From 52be2e3bb112c267671acd71b9eba670d3e6494a Mon Sep 17 00:00:00 2001 From: Marc Aymerich Date: Wed, 29 Apr 2015 10:51:30 +0000 Subject: [PATCH] Fixes onmailbox filtering --- README.md | 4 +- TODO.md | 13 +++--- orchestra/admin/dashboard.py | 40 +++++++++++------ orchestra/contrib/mailboxes/backends.py | 55 ++++++++++++----------- orchestra/contrib/mailboxes/models.py | 2 +- orchestra/contrib/mailboxes/settings.py | 11 +++-- orchestra/contrib/orders/settings.py | 2 +- orchestra/contrib/services/settings.py | 3 +- orchestra/contrib/settings/admin.py | 2 + orchestra/contrib/systemusers/backends.py | 16 +------ orchestra/contrib/webapps/types/php.py | 16 +++---- 11 files changed, 87 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index fb18a9e9..a79eb745 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ If you are planing to do some development or perhaps just checking out this proj 1. Create a basic [LXC](http://linuxcontainers.org/) container, start it and get inside. ```bash wget -O /tmp/create.sh \ - https://raw2.github.com/glic3rinu/django-orchestra/master/scripts/container/create.sh + https://raw.github.com/glic3rinu/django-orchestra/master/scripts/container/create.sh sudo bash /tmp/create.sh sudo lxc-start -n orchestra ``` @@ -45,7 +45,7 @@ If you are planing to do some development or perhaps just checking out this proj 2. Deploy Django-orchestra development environment inside the container ```bash wget -O /tmp/deploy.sh \ - https://raw2.github.com/glic3rinu/django-orchestra/master/scripts/container/deploy.sh + https://raw.github.com/glic3rinu/django-orchestra/master/scripts/container/deploy.sh cd /tmp/ # Moving away from /root before running deploy.sh bash /tmp/deploy.sh ``` diff --git a/TODO.md b/TODO.md index 8696a41d..3b030a97 100644 --- a/TODO.md +++ b/TODO.md @@ -170,14 +170,11 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl * budgets: no undo feature * Autocomplete admin fields like .phplist... with js -* autoexpand mailbox.filter according to filtering options (js) * allow empty metric pack for default rates? changes on rating algo # don't produce lines with cost == 0 or quantity 0 ? maybe minimal quantity for billing? like 0.1 ? or minimal price? per line or per bill? # lines too long on invoice, double lines or cut, and make margin wider -* PHP_TIMEOUT env variable in sync with fcgid idle timeout - http://foaa.de/old-blog/2010/11/php-apache-and-fastcgi-a-comprehensive-overview/trackback/index.html#pni-top0 * payment methods icons * use server.name | server.address on python backends, like gitlab instead of settings? @@ -243,14 +240,11 @@ https://code.djangoproject.com/ticket/24576 # FIXME address name change does not remove old one :P, readonly or perhaps we can regenerate all addresses using backend.prepare()? * read https://docs.djangoproject.com/en/dev/releases/1.8/ and fix deprecation warnings -* remove admin object display_links , like contents webapps -* SaaS and WebApp types and services fieldsets, and helptexts ! +* create nice fieldsets for SaaS, WebApp types and services, and helptexts too! * replace make_option in management commands -* welcome, pangea linke doesnt work - # FIXME model contact info and account info (email, name, etc) correctly/unredundant/dry * Use the new django.contrib.admin.RelatedOnlyFieldListFilter in ModelAdmin.list_filter to limit the list_filter choices to foreign objects which are attached to those from the ModelAdmin. @@ -296,3 +290,8 @@ https://code.djangoproject.com/ticket/24576 # @ something database names # password validation cracklib on change password form=????? # reset setting buton + +# periodic cleaning of spam mailboxes + +# admin edit relevant djanog settings +# django SITE_NAME vs ORCHESTRA_SITE_NAME ? diff --git a/orchestra/admin/dashboard.py b/orchestra/admin/dashboard.py index 6e79015a..88e30b60 100644 --- a/orchestra/admin/dashboard.py +++ b/orchestra/admin/dashboard.py @@ -1,3 +1,4 @@ +from django.core.urlresolvers import reverse from fluent_dashboard import dashboard from fluent_dashboard.modules import CmsAppIconList @@ -5,6 +6,14 @@ from orchestra.core import services class OrchestraIndexDashboard(dashboard.FluentIndexDashboard): + _registry = {} + + @classmethod + def register_link(cls, module, view_name, title): + registered = cls._registry.get(module, []) + registered.append((view_name, title)) + cls._registry[module] = registered + def get_application_modules(self): modules = super(OrchestraIndexDashboard, self).get_application_modules() models = [] @@ -12,20 +21,25 @@ class OrchestraIndexDashboard(dashboard.FluentIndexDashboard): if options.get('menu', True): models.append("%s.%s" % (model.__module__, model._meta.object_name)) - # TODO make this dynamic for module in modules: - if module.title == 'Administration': - module.children.append({ - 'models': [{ - 'add_url': '/admin/settings/', - 'app_name': 'settings', - 'change_url': '/admin/settings/setting/', - 'name': 'setting', - 'title': "Settings" }], - 'name': 'settings', - 'title': 'Settings', - 'url': '/admin/settings/' - }) + registered = self._registry.get(module.title, None) + if registered: + for view_name, title in registered: + # This values are shit, but it is how fluent dashboard will look for the icon + app_name, name = view_name.split('_')[:-1] + url = reverse('admin:' + view_name) + add_url = '/'.join(url.split('/')[:-2]) + module.children.append({ + 'models': [{ + 'add_url': add_url, + 'app_name': app_name, + 'change_url': url, + 'name': name, + 'title': title }], + 'name': app_name, + 'title': title, + 'url': add_url, + }) service_icon_list = CmsAppIconList('Services', models=models, collapsible=True) modules.append(service_icon_list) return modules diff --git a/orchestra/contrib/mailboxes/backends.py b/orchestra/contrib/mailboxes/backends.py index c9b1dcd2..f1fbde23 100644 --- a/orchestra/contrib/mailboxes/backends.py +++ b/orchestra/contrib/mailboxes/backends.py @@ -1,4 +1,5 @@ import logging +import os import re import textwrap @@ -24,14 +25,25 @@ class SieveFilteringMixin(object): def generate_filter(self, mailbox, context): name, content = mailbox.get_filtering() for box in re.findall(r'fileinto\s+"([^"]+)"', content): + # create mailboxes if fileinfo is provided witout ':create' option context['box'] = box - # TODO create mailbox without doveadm (not always installed) - self.append("doveadm mailbox create -u %(user)s %(box)s" % context) + self.append(textwrap.dedent("""\ + mkdir -p %(maildir)s/.%(box)s + chown %(user)s:%(group)s %(maildir)s/.%(box)s + if [[ ! $(grep '%(box)s' %(maildir)s/subscriptions) ]]; then + echo '%(box)s' >> %(maildir)s/subscriptions + fi + """) % context + ) context['filtering_path'] = settings.MAILBOXES_SIEVE_PATH % context if content: - context['filtering'] = ('# %(banner)s\n' + filtering) % context - self.append("mkdir -p $(dirname '%(filtering_path)s')" % context) - self.append("echo '%(filtering)s' > %(filtering_path)s" % context) + context['filtering'] = ('# %(banner)s\n' + content) % context + self.append(textwrap.dedent("""\ + mkdir -p $(dirname '%(filtering_path)s') + echo '%(filtering)s' > %(filtering_path)s + chown %(user)s:%(group)s %(filtering_path)s + """) % context + ) else: self.append("echo '' > %(filtering_path)s" % context) @@ -41,6 +53,8 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController): Assumes that all system users on this servers all mail accounts. If you want to have system users AND mailboxes on the same server you should consider using virtual mailboxes """ + SHELL = '/dev/null' + verbose_name = _("UNIX maildir user") model = 'mailboxes.Mailbox' @@ -64,13 +78,13 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController): context['quota'] = mailbox.resources.disk.allocated * mailbox.resources.disk.resource.get_scale() #unit_to_bytes(mailbox.resources.disk.unit) self.append(textwrap.dedent(""" - mkdir -p %(home)s/Maildir - chown %(user)s:%(group)s %(home)s/Maildir - if [[ ! -f %(home)s/Maildir/maildirsize ]]; then - echo "%(quota)iS" > %(home)s/Maildir/maildirsize - chown %(user)s:%(group)s %(home)s/Maildir/maildirsize + mkdir -p %(maildir)s + chown %(user)s:%(group)s %(maildir)s + if [[ ! -f %(maildir)s/maildirsize ]]; then + echo "%(quota)iS" > %(maildir)s/maildirsize + chown %(user)s:%(group)s %(maildir)s/maildirsize else - sed -i '1s/.*/%(quota)iS/' %(home)s/Maildir/maildirsize + sed -i '1s/.*/%(quota)iS/' %(maildir)s/maildirsize fi""") % context ) @@ -91,7 +105,8 @@ class UNIXUserMaildirBackend(SieveFilteringMixin, ServiceController): 'name': mailbox.name, 'password': mailbox.password if mailbox.active else '*%s' % mailbox.password, 'home': mailbox.get_home(), - 'initial_shell': '/dev/null', + 'maildir': os.path.join(mailbox.get_home(), 'Maildir'), + 'initial_shell': self.SHELL, 'banner': self.get_banner(), } return replace(context, "'", '"') @@ -363,20 +378,8 @@ class PostfixMailscannerTraffic(ServiceMonitor): maillogs = {mail_logs} end_datetime = to_local_timezone('{current_date}') end_date = int(end_datetime.strftime('%Y%m%d%H%M%S')) - months = {{ - "Jan": "01", - "Feb": "02", - "Mar": "03", - "Apr": "04", - "May": "05", - "Jun": "06", - "Jul": "07", - "Aug": "08", - "Sep": "09", - "Oct": "10", - "Nov": "11", - "Dec": "12", - }} + months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') + months = dict((m, '%02d' % n) for n, m in enumerate(months, 1)) def inside_period(month, day, time, ini_date): global months diff --git a/orchestra/contrib/mailboxes/models.py b/orchestra/contrib/mailboxes/models.py index d70a6227..7a3811f6 100644 --- a/orchestra/contrib/mailboxes/models.py +++ b/orchestra/contrib/mailboxes/models.py @@ -61,7 +61,7 @@ class Mailbox(models.Model): def get_filtering(self): name, content = settings.MAILBOXES_MAILBOX_FILTERINGS[self.filtering] if callable(content): - return content(self) + content = content(self) return (name, content) def delete(self, *args, **kwargs): diff --git a/orchestra/contrib/mailboxes/settings.py b/orchestra/contrib/mailboxes/settings.py index 91d977e0..bf69ae13 100644 --- a/orchestra/contrib/mailboxes/settings.py +++ b/orchestra/contrib/mailboxes/settings.py @@ -1,6 +1,8 @@ import os import textwrap +from django.utils.functional import lazy +from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from orchestra.core.validators import validate_name @@ -9,6 +11,7 @@ from orchestra.settings import ORCHESTRA_BASE_DOMAIN, Setting _names = ('name', 'username',) _backend_names = _names + ('user', 'group', 'home') +mark_safe_lazy = lazy(mark_safe, str) MAILBOXES_DOMAIN_MODEL = Setting('MAILBOXES_DOMAIN_MODEL', 'domains.Domain', @@ -72,15 +75,15 @@ MAILBOXES_MAILBOX_FILTERINGS = Setting('MAILBOXES_MAILBOX_FILTERINGS', { # value: (verbose_name, filter) 'DISABLE': (_("Disable"), ''), - 'REJECT': (_("Reject spam"), textwrap.dedent(""" + 'REJECT': (mark_safe_lazy(_("Reject spam (X-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" "5" { + if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "9" { discard; stop; }""")), - 'REDIRECT': (_("Archive spam"), textwrap.dedent(""" + 'REDIRECT': (mark_safe_lazy(_("Archive spam (X-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" "5" { + if header :value "ge" :comparator "i;ascii-numeric" "X-Spam-Score" "9" { fileinto "Spam"; stop; }""")), diff --git a/orchestra/contrib/orders/settings.py b/orchestra/contrib/orders/settings.py index 0d171638..c3030c2c 100644 --- a/orchestra/contrib/orders/settings.py +++ b/orchestra/contrib/orders/settings.py @@ -32,7 +32,7 @@ ORDERS_EXCLUDED_APPS = Setting('ORDERS_EXCLUDED_APPS', ORDERS_METRIC_ERROR = Setting('ORDERS_METRIC_ERROR', - 0.01, + 0.05, help_text=("Only account for significative changes.
" "metric_storage new value: lastvalue*(1+threshold) > currentvalue or lastvalue*threshold < currentvalue."), ) diff --git a/orchestra/contrib/services/settings.py b/orchestra/contrib/services/settings.py index e97fabb0..ceda0b90 100644 --- a/orchestra/contrib/services/settings.py +++ b/orchestra/contrib/services/settings.py @@ -20,7 +20,8 @@ SERVICES_SERVICE_DEFAULT_TAX = Setting('SERVICES_SERVICE_DEFAULT_TAX', SERVICES_SERVICE_ANUAL_BILLING_MONTH = Setting('SERVICES_SERVICE_ANUAL_BILLING_MONTH', 1, - choices=tuple((n, n) for n in range(1, 13)) + choices=tuple(enumerate( + ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), 1)) ) diff --git a/orchestra/contrib/settings/admin.py b/orchestra/contrib/settings/admin.py index 7b6b9f4c..c4f30d28 100644 --- a/orchestra/contrib/settings/admin.py +++ b/orchestra/contrib/settings/admin.py @@ -6,6 +6,7 @@ from django.shortcuts import render_to_response from django.views import generic from django.utils.translation import ngettext, ugettext_lazy as _ +from orchestra.admin.dashboard import OrchestraIndexDashboard from orchestra.settings import Setting from orchestra.utils import sys, paths @@ -104,4 +105,5 @@ class SettingFileView(generic.TemplateView): admin.site.register_url(r'^settings/setting/view/$', SettingFileView.as_view(), 'settings_setting_view') admin.site.register_url(r'^settings/setting/$', SettingView.as_view(), 'settings_setting_change') +OrchestraIndexDashboard.register_link('Administration', 'settings_setting_change', _("Settings")) diff --git a/orchestra/contrib/systemusers/backends.py b/orchestra/contrib/systemusers/backends.py index 83caaa1c..1914f874 100644 --- a/orchestra/contrib/systemusers/backends.py +++ b/orchestra/contrib/systemusers/backends.py @@ -237,20 +237,8 @@ class VsFTPdTraffic(ServiceMonitor): end_date = to_local_timezone('{current_date}') end_date = int(end_date.strftime('%Y%m%d%H%M%S')) users = {{}} - months = {{ - 'Jan': '01', - 'Feb': '02', - 'Mar': '03', - 'Apr': '04', - 'May': '05', - 'Jun': '06', - 'Jul': '07', - 'Aug': '08', - 'Sep': '09', - 'Oct': '10', - 'Nov': '11', - 'Dec': '12', - }} + months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') + months = dict((m, '%02d' % n) for n, m in enumerate(months, 1)) def prepare(object_id, username, ini_date): global users diff --git a/orchestra/contrib/webapps/types/php.py b/orchestra/contrib/webapps/types/php.py index 0a093250..44f41f61 100644 --- a/orchestra/contrib/webapps/types/php.py +++ b/orchestra/contrib/webapps/types/php.py @@ -81,15 +81,15 @@ class PHPApp(AppType): if webapp.type_instance.get_php_version() == php_version: options += list(webapp.options.all()) init_vars = OrderedDict((opt.name, opt.value) for opt in options) - # Enabled functions - enabled_functions = init_vars.pop('enabled_functions', None) - if enabled_functions: - enabled_functions = set(enabled_functions.split(',')) - disabled_functions = [] + # Enable functions + enable_functions = init_vars.pop('enable_functions', None) + if enable_functions: + enable_functions = set(enable_functions.split(',')) + disable_functions = [] for function in self.PHP_DISABLED_FUNCTIONS: - if function not in enabled_functions: - disabled_functions.append(function) - init_vars['disable_functions'] = ','.join(disabled_functions) + if function not in enable_functions: + disable_functions.append(function) + init_vars['disable_functions'] = ','.join(disable_functions) # process timeout timeout = self.instance.options.filter(name='timeout').first() if timeout: