Fixes onmailbox filtering

This commit is contained in:
Marc Aymerich 2015-04-29 10:51:30 +00:00
parent 948a4ced8f
commit 52be2e3bb1
11 changed files with 87 additions and 77 deletions

View file

@ -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
```

13
TODO.md
View file

@ -170,14 +170,11 @@ require_once(/etc/moodles/.$moodle_host.config.php);``` moodle/drupl
* budgets: no undo feature
* Autocomplete admin fields like <site_name>.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 ?

View file

@ -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,19 +21,24 @@ 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':
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': '/admin/settings/',
'app_name': 'settings',
'change_url': '/admin/settings/setting/',
'name': 'setting',
'title': "Settings" }],
'name': 'settings',
'title': 'Settings',
'url': '/admin/settings/'
'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)

View file

@ -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

View file

@ -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):

View file

@ -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&ge;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&ge;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;
}""")),

View file

@ -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.<br>"
"metric_storage new value: <tt>lastvalue*(1+threshold) > currentvalue or lastvalue*threshold < currentvalue</tt>."),
)

View file

@ -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))
)

View file

@ -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"))

View file

@ -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

View file

@ -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: