From 7386b89be63f7ed366a878c0419bb28be50de72b Mon Sep 17 00:00:00 2001 From: Marc Aymerich Date: Mon, 25 May 2015 19:16:07 +0000 Subject: [PATCH] Custom mailbox filters and other random inprovements0 --- TODO.md | 26 +++- orchestra/api/options.py | 2 +- orchestra/contrib/mailboxes/api.py | 1 + orchestra/contrib/mailboxes/backends.py | 6 +- orchestra/contrib/mailboxes/settings.py | 119 +++++++++++++----- orchestra/contrib/orders/actions.py | 7 +- orchestra/contrib/orders/forms.py | 1 + .../orders/order/bill_selected_options.html | 14 +++ orchestra/contrib/plans/ratings.py | 10 +- orchestra/contrib/resources/admin.py | 7 +- orchestra/contrib/services/handlers.py | 4 +- .../tests/functional_tests/test_domain.py | 2 +- .../tests/functional_tests/test_traffic.py | 1 + orchestra/contrib/settings/admin.py | 3 +- orchestra/contrib/settings/parser.py | 6 +- .../templates/admin/settings/reload.html | 8 +- orchestra/contrib/webapps/backends/php.py | 6 +- orchestra/contrib/websites/api.py | 2 +- orchestra/contrib/websites/backends/apache.py | 16 ++- orchestra/utils/sys.py | 2 +- 20 files changed, 175 insertions(+), 68 deletions(-) diff --git a/TODO.md b/TODO.md index a16e0a27..6dd5925e 100644 --- a/TODO.md +++ b/TODO.md @@ -60,7 +60,7 @@ * print open invoices as proforma? -* env ORCHESTRA_MASTER_SERVER='test1.orchestra.lan' ORCHESTRA_SECOND_SERVER='test2.orchestra.lan' ORCHESTRA_SLAVE_SERVER='test3.orchestra.lan' python3 manage.py test orchestra.contrib.domains.tests.functional_tests.tests:AdminBind9BackendDomainTest --nologcapture +* env ORCHESTRA_MASTER_SERVER='test1.orchestra.lan' ORCHESTRA_SECOND_SERVER='test2.orchestra.lan' ORCHESTRA_SLAVE_SERVER='test3.orchestra.lan' python3 manage.py test orchestra.contrib.domains.tests.functional_tests.tests:AdminBind9BackendDomainTest --nologcapture --keepdb * ForeignKey.swappable * Field.editable @@ -386,4 +386,26 @@ http://wiki2.dovecot.org/Pigeonhole/Sieve/Examples Bash/Python/PHPBackend -# Gandi sync domains cancelled +# bill action view on a separate process. check memory consumption without debug (236m) + +# services.handler as generator in order to save memory? not swell like a balloon +# mailboxes group username instead of mainuser + +import uwsgi +from uwsgidecorators import timer +from django.utils import autoreload + +@timer(3) +def change_code_gracefull_reload(sig): + if autoreload.code_changed(): + uwsgi.reload() +# using kill to send the signal +kill -HUP `cat /tmp/project-master.pid` +# or the convenience option --reload +uwsgi --reload /tmp/project-master.pid +# or if uwsgi was started with touch-reload=/tmp/somefile +touch /tmp/somefile + + + +# Pending vs bill(): get_billing_point() returns the next billing point, no matter if nbp > now(). pending filter filters by billed_until < now() diff --git a/orchestra/api/options.py b/orchestra/api/options.py index 1dc864db..060121ef 100644 --- a/orchestra/api/options.py +++ b/orchestra/api/options.py @@ -78,7 +78,7 @@ class LinkHeaderRouter(DefaultRouter): return viewset msg = "%s does not have a regiestered viewset" % prefix_or_model raise KeyError(msg) - + def insert(self, prefix_or_model, name, field, **kwargs): """ Dynamically add new fields to an existing serializer """ viewset = self.get_viewset(prefix_or_model) diff --git a/orchestra/contrib/mailboxes/api.py b/orchestra/contrib/mailboxes/api.py index 2d498f1e..16d926d3 100644 --- a/orchestra/contrib/mailboxes/api.py +++ b/orchestra/contrib/mailboxes/api.py @@ -10,6 +10,7 @@ from .serializers import AddressSerializer, MailboxSerializer class AddressViewSet(LogApiMixin, AccountApiMixin, viewsets.ModelViewSet): queryset = Address.objects.select_related('domain').prefetch_related('mailboxes').all() serializer_class = AddressSerializer + filter_fields = ('domain', 'mailboxes__name') class MailboxViewSet(LogApiMixin, SetPasswordApiMixin, AccountApiMixin, viewsets.ModelViewSet): diff --git a/orchestra/contrib/mailboxes/backends.py b/orchestra/contrib/mailboxes/backends.py index ccb77011..4de35c93 100644 --- a/orchestra/contrib/mailboxes/backends.py +++ b/orchestra/contrib/mailboxes/backends.py @@ -60,9 +60,6 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController): verbose_name = _("UNIX maildir user") model = 'mailboxes.Mailbox' - doc_settings = (settings, - ('MAILBOXES_USE_ACCOUNT_AS_GROUP',) - ) def save(self, mailbox): context = self.get_context(mailbox) @@ -123,10 +120,9 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController): super(UNIXUserMaildirBackend, self).commit() def get_context(self, mailbox): - account_as_group = settings.MAILBOXES_USE_ACCOUNT_AS_GROUP context = { 'user': mailbox.name, - 'group': mailbox.account.username if account_as_group else mailbox.name, + 'group': mailbox.name, 'name': mailbox.name, 'password': mailbox.password if mailbox.active else '*%s' % mailbox.password, 'home': mailbox.get_home(), diff --git a/orchestra/contrib/mailboxes/settings.py b/orchestra/contrib/mailboxes/settings.py index 49aa1361..150f9d0b 100644 --- a/orchestra/contrib/mailboxes/settings.py +++ b/orchestra/contrib/mailboxes/settings.py @@ -48,12 +48,6 @@ MAILBOXES_SIEVETEST_BIN_PATH = Setting('MAILBOXES_SIEVETEST_BIN_PATH', ) -MAILBOXES_USE_ACCOUNT_AS_GROUP = Setting('MAILBOXES_USE_ACCOUNT_AS_GROUP', - False, - help_text="Group used for system user based mailboxes. If False mailbox.name will be used as group." -) - - MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH = Setting('MAILBOXES_VIRTUAL_MAILBOX_MAPS_PATH', '/etc/postfix/virtual_mailboxes' ) @@ -81,34 +75,99 @@ MAILBOXES_PASSWD_PATH = Setting('MAILBOXES_PASSWD_PATH', ) +MAILBOXES_SPAM_SCORE_HEADER = Setting('MAILBOXES_SPAM_SCORE_HEADER', + 'X-Spam-Score' +) + + +MAILBOXES_SPAM_SCORE_SYMBOL = Setting('MAILBOXES_SPAM_SCORE_SYMBOL', + '', + help_text="Blank for numeric spam score.", +) + + MAILBOXES_MAILBOX_FILTERINGS = Setting('MAILBOXES_MAILBOX_FILTERINGS', { # value: (verbose_name, filter) 'DISABLE': (_("Disable"), ''), - 'REJECT': (mark_safe_lazy(_("Reject spam (Score≥9)")), textwrap.dedent("""\ - require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"]; - if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "9" { - discard; - stop; - }""")), - 'REJECT5': (mark_safe_lazy(_("Reject spam (Score≥5)")), textwrap.dedent("""\ - require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"]; - if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" { - discard; - stop; - }""")), - 'REDIRECT': (mark_safe_lazy(_("Archive spam (Score≥9)")), textwrap.dedent("""\ - require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"]; - if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "9" { - fileinto "Spam"; - stop; - }""")), - 'REDIRECT5': (mark_safe_lazy(_("Archive spam (Score≥5)")), textwrap.dedent("""\ - require ["fileinto","regex","envelope","vacation","reject","relational","comparator-i;ascii-numeric"]; - if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "5" { - fileinto "Spam"; - stop; - }""")), + 'REJECT': (mark_safe_lazy(_("Reject spam (Score≥8)")), ( + textwrap.dedent("""\ + if header :contains "%(score_header)s" "%(score_value)s" { + discard; + stop; + }""") if MAILBOXES_SPAM_SCORE_SYMBOL else + textwrap.dedent("""\ + require ["relational","comparator-i;ascii-numeric"]; + if allof ( + not header :matches "%(score_header)s" "-*", + header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "8" ) + { + discard; + stop; + }""")) % { + 'score_header': MAILBOXES_SPAM_SCORE_HEADER, + 'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*8 + } + ), + 'REJECT5': (mark_safe_lazy(_("Reject spam (Score≥5)")), ( + textwrap.dedent("""\ + if header :contains "%(score_header)s" "%(score_value)s" { + discard; + stop; + }""") if MAILBOXES_SPAM_SCORE_SYMBOL else + textwrap.dedent("""\ + require ["relational","comparator-i;ascii-numeric"]; + if allof ( + not header :matches "%(score_header)s" "-*", + header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "5" ) + { + discard; + stop; + }""")) % { + 'score_header': MAILBOXES_SPAM_SCORE_HEADER, + 'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*5 + } + ), + 'REDIRECT': (mark_safe_lazy(_("Archive spam (Score≥8)")), ( + textwrap.dedent("""\ + require "fileinto"; + if header :contains "%(score_header)s" "%(score_value)s" { + fileinto "Spam"; + stop; + }""") if MAILBOXES_SPAM_SCORE_SYMBOL else + textwrap.dedent("""\ + require ["fileinto","relational","comparator-i;ascii-numeric"]; + if allof ( + not header :matches "%(score_header)s" "-*", + header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "8" ) + { + fileinto "Spam"; + stop; + }""")) % { + 'score_header': MAILBOXES_SPAM_SCORE_HEADER, + 'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*8 + } + ), + 'REDIRECT5': (mark_safe_lazy(_("Archive spam (Score≥5)")), ( + textwrap.dedent("""\ + require "fileinto"; + if header :contains "%(score_header)s" "%(score_value)s" { + fileinto "Spam"; + stop; + }""") if MAILBOXES_SPAM_SCORE_SYMBOL else + textwrap.dedent("""\ + require ["fileinto","relational","comparator-i;ascii-numeric"]; + if allof ( + not header :matches "%(score_header)s" "-*", + header :value "ge" :comparator "i;ascii-numeric" "%(score_header)s" "5" ) + { + fileinto "Spam"; + stop; + }""")) % { + 'score_header': MAILBOXES_SPAM_SCORE_HEADER, + 'score_value': MAILBOXES_SPAM_SCORE_SYMBOL*5 + } + ), 'CUSTOM': (_("Custom filtering"), lambda mailbox: mailbox.custom_filtering), } ) diff --git a/orchestra/contrib/orders/actions.py b/orchestra/contrib/orders/actions.py index 090baa9b..0965d302 100644 --- a/orchestra/contrib/orders/actions.py +++ b/orchestra/contrib/orders/actions.py @@ -29,7 +29,10 @@ class BillSelectedOrders(object): 'queryset': queryset, 'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME, } - return self.set_options(request) + ret = self.set_options(request) + del(self.queryset) + del(self.context) + return ret def set_options(self, request): form = BillSelectedOptionsForm() @@ -42,7 +45,6 @@ class BillSelectedOrders(object): proforma=form.cleaned_data['proforma'], new_open=form.cleaned_data['new_open'], ) - print(self.options) if int(request.POST.get('step')) != 3: return self.select_related(request) else: @@ -142,4 +144,3 @@ def mark_as_not_ignored(modeladmin, request, queryset): _("%i selected orders have been marked as not ignored.") % num, num) modeladmin.message_user(request, msg) - diff --git a/orchestra/contrib/orders/forms.py b/orchestra/contrib/orders/forms.py index 2cdde9f8..c0d436bf 100644 --- a/orchestra/contrib/orders/forms.py +++ b/orchestra/contrib/orders/forms.py @@ -44,6 +44,7 @@ class BillSelectRelatedForm(AdminFormMixin, forms.Form): # initial=False, required=False, help_text=_("The price may vary " # "depending on the billed orders. This options designates whether " # "all existing orders will be used for price computation or not.")) + select_all = forms.BooleanField(label=_("Select all"), required=False) selected_related = forms.ModelMultipleChoiceField(label=_("Related orders"), queryset=Order.objects.none(), widget=forms.CheckboxSelectMultiple, required=False) diff --git a/orchestra/contrib/orders/templates/admin/orders/order/bill_selected_options.html b/orchestra/contrib/orders/templates/admin/orders/order/bill_selected_options.html index 18222cad..0408c3c1 100644 --- a/orchestra/contrib/orders/templates/admin/orders/order/bill_selected_options.html +++ b/orchestra/contrib/orders/templates/admin/orders/order/bill_selected_options.html @@ -12,6 +12,20 @@ {% endblock %} +{% block extrahead %} +{{ block.super }} + + + +{% endblock %} {% block breadcrumbs %}