diff --git a/admin/models.py b/admin/models.py index 2e381e7a7..278f792c7 100644 --- a/admin/models.py +++ b/admin/models.py @@ -112,56 +112,3 @@ class Alias(models.Model): ("view_aliases", "View aliases"), ) -class Extension(models.Model): - name = models.CharField(max_length=150) - enabled = models.BooleanField(_('enabled'), - help_text=_("Check to enable this extension")) - has_templates = models.BooleanField() - - def on(self): - from django.core.management import sql, color - from django.db import connection, models - - style = color.no_style() - cursor = connection.cursor() - module = __import__("mailng.extensions.%s" % self.name, - globals(), locals(), ['main', 'models']) - try: - extmodels = module.models - except AttributeError: - extmodels = None - if extmodels is not None: - mods = [] - for k, v in extmodels.__dict__.iteritems(): - try: - if not issubclass(v, models.Model): - continue - statements, pending = \ - connection.creation.sql_create_model(v, style) - try: - for sql in statements: - cursor.execute(sql) - except Exception, msg: - pass - except TypeError: - pass - if self.has_templates: - code, output = exec_cmd("ln -s ../extensions/%s/templates templates/%s" \ - % (self.name, self.name)) - if os.path.exists("extensions/%s/scripts" % self.name): - code, output = exec_cmd("ln -s ../extensions/%s/scripts scripts/%s" \ - % (self.name, self.name)) - module.main.init() - self.enabled = True - self.save() - - def off(self): - if self.has_templates: - code, output = exec_cmd("rm -f templates/%s" % self.name) - print output - self.enabled = False - self.save() - module = __import__("mailng.extensions.%s" % self.name, - globals(), locals(), ['main', 'models']) - module.main.destroy() - diff --git a/admin/templatetags/admin_extras.py b/admin/templatetags/admin_extras.py index 62f7fe16e..7b78e65ea 100644 --- a/admin/templatetags/admin_extras.py +++ b/admin/templatetags/admin_extras.py @@ -62,9 +62,6 @@ def settings_menu(selection, user): "url" : reverse(admin.views.viewparameters), "img" : "/static/pics/domains.png", "label" : _("Parameters")}, - {"name" : "extensions", - "url" : reverse(admin.views.viewextensions), - "label" : _("Extensions")}, ] return render_to_string('common/menu.html', {"selection" : selection, "entries" : entries, diff --git a/admin/urls.py b/admin/urls.py index 8855e8f0d..6c8a9f53f 100644 --- a/admin/urls.py +++ b/admin/urls.py @@ -19,8 +19,6 @@ urlpatterns = patterns('mailng.admin.views', (r'^settings/$', 'settings'), (r'^settings/addperm/$', 'addpermission'), (r'^settings/delperm/(?P\d+)/(?P\w+)/$', 'deletepermission'), - (r'^settings/extensions/$', 'viewextensions'), - (r'^settings/extensions/save/$', 'saveextensions'), (r'^settings/parameters/$', 'viewparameters'), (r'^settings/parameters/save/$', 'saveparameters'), ) diff --git a/admin/views.py b/admin/views.py index 41f53e746..ca6848ed0 100644 --- a/admin/views.py +++ b/admin/views.py @@ -12,7 +12,7 @@ from django.contrib.auth.decorators \ import login_required, permission_required, user_passes_test from django.contrib.auth.models import User, Group from mailng import admin, userprefs -from mailng.admin.models import Domain, Mailbox, Alias, Extension +from mailng.admin.models import Domain, Mailbox, Alias from forms import MailboxForm, DomainForm, AliasForm, PermissionForm from mailng.lib.authbackends import crypt_password from mailng.lib import _render, _ctx_ok, _ctx_ko @@ -440,55 +440,3 @@ def saveparameters(request): parameters.save(app, name, v) request.user.message_set.create(message=_("Configuration saved.")) return HttpResponseRedirect(reverse(admin.views.viewparameters)) - -@login_required -@user_passes_test(lambda u: u.is_superuser) -def viewextensions(request): - from mailng.extensions import list_extensions - from mailng.lib import tables - - class ExtensionsTable(tables.Table): - idkey = "id" - selection = tables.SelectionColumn("selection", width="4%", first=True) - _1_name = tables.Column("name", label=_("Name"), width="15%") - _2_version = tables.Column("version", label=_("Version"), width="6%") - _3_descr = tables.Column("description", label=_("Description")) - - exts = list_extensions() - for ext in exts: - try: - dbext = Extension.objects.get(name=ext["id"]) - ext["selection"] = dbext.enabled - except Extension.DoesNotExist: - dbext = Extension() - dbext.name = ext["id"] - dbext.enabled = False - dbext.has_templates = ext["templates"] - dbext.save() - ext["selection"] = False - - tbl = ExtensionsTable(exts) - return _render(request, 'admin/extensions.html', { - "extensions" : tbl.render(request) - }) - -@login_required -@user_passes_test(lambda u: u.is_superuser) -def saveextensions(request): - from mailng import extensions - - actived_exts = Extension.objects.filter(enabled=True) - found = [] - for k, v in request.POST.iteritems(): - if k.startswith("select_"): - parts = k.split("_", 1) - dbext = Extension.objects.get(name=parts[1]) - if not dbext in actived_exts: - dbext.on() - else: - found += [dbext] - for ext in actived_exts: - if not ext in found: - ext.off() - - return HttpResponseRedirect(reverse(admin.views.viewextensions)) diff --git a/extensions/__init__.py b/extensions/__init__.py index 4cccb3b59..d9d5b7ce9 100644 --- a/extensions/__init__.py +++ b/extensions/__init__.py @@ -1,61 +1,23 @@ # -*- coding: utf-8 -*- import os import re - -extensions = {} +from django.conf import settings def loadextensions(): - from admin.models import Extension - from django.template import add_to_builtins - - exts = Extension.objects.filter(enabled=True) - for ext in exts: - tagsdir = "extensions/%s/templatetags" % ext.name - if os.path.isdir("extensions/%s/templatetags" % ext.name): - for f in os.listdir(tagsdir): - if f in ["__init__.py", "__init__.pyc"]: - continue - parts = f.split('.') - if len(parts) == 2 and parts[1] == "py": - add_to_builtins("extensions.%s.templatetags.%s" \ - % (ext.name, parts[0])) - module = __import__(ext.name, globals(), locals(), ['main']) - module.main.init() - globals()['extensions'][ext] = module - -def loadmenus(): + basedir = "%s/extensions" % settings.MAILNG_DIR result = [] - for name, mod in extensions.iteritems(): - u = mod.main.urls() + for f in os.listdir(basedir): + if not os.path.isdir("%s/%s" % (basedir, f)): + continue + if not isenabled(f): + continue + module = __import__(f, globals(), locals(), ['main']) + module.main.init() + u = module.main.urls() if u == (): continue - result += (u,) + result += [u] return result def isenabled(ext): - return extensions.has_key(ext) - -def list_extensions(): - basedir = "extensions" - result = [] - for d in os.listdir(basedir): - if not os.path.isdir("%s/%s" % (basedir, d)): - continue - isvalid = True - for f in ['urls.py', 'main.py', '__init__.py']: - if not os.path.exists("%s/%s/%s" % (basedir, d, f)): - isvalid = False - break - if isvalid: - module = __import__(d, globals(), locals(), ['main']) - try: - infos = module.main.infos() - infos["id"] = d - if os.path.isdir("%s/%s/templates" % (basedir, d)): - infos["templates"] = True - else: - infos["templates"] = False - result += [infos] - except AttributeError: - pass - return result + return "mailng.extensions.%s" % ext in settings.INSTALLED_APPS diff --git a/extensions/amavis_quarantine/main.py b/extensions/amavis_quarantine/main.py index f5b734a6b..9028ada12 100644 --- a/extensions/amavis_quarantine/main.py +++ b/extensions/amavis_quarantine/main.py @@ -44,7 +44,7 @@ def menu(**kwargs): return [ {"name" : "quarantine", "label" : _("Quarantine"), - "url" : reverse(views.index), + "url" : reverse(views.index, urlconf='mailng.extensions.amavis_quarantine.exturls'), "img" : "/static/pics/quarantine.png"} ] return [] diff --git a/extensions/amavis_quarantine/urls.py b/extensions/amavis_quarantine/urls.py index 2d33d8d6d..936e2d9cf 100644 --- a/extensions/amavis_quarantine/urls.py +++ b/extensions/amavis_quarantine/urls.py @@ -1,12 +1,16 @@ from django.conf.urls.defaults import * +extpatterns = [ + (r'^$', 'index'), + (r'^listing/$', '_listing'), + (r'^getmailcontent/(?P[\w\-\+]+)/$', 'getmailcontent'), + (r'^(?P[\w\-\+]+)/headers/$', 'viewheaders'), + (r'^process/$', 'process'), + (r'^delete/(?P[\w\-\+]+)/$', 'delete'), + (r'^release/(?P[\w\-\+]+)/$', 'release'), + (r'^(?P[\w\-\+]+)/$', 'viewmail') + ] + urlpatterns = patterns('mailng.extensions.amavis_quarantine.views', - (r'^$', 'index'), - (r'^listing/$', '_listing'), - (r'^getmailcontent/(?P[\w\-\+]+)/$', 'getmailcontent'), - (r'^(?P[\w\-\+]+)/headers/$', 'viewheaders'), - (r'^process/$', 'process'), - (r'^delete/(?P[\w\-\+]+)/$', 'delete'), - (r'^release/(?P[\w\-\+]+)/$', 'release'), - (r'^(?P[\w\-\+]+)/$', 'viewmail'), + *extpatterns ) diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py index c98835d9c..d57eb6e74 100644 --- a/extensions/webmail/main.py +++ b/extensions/webmail/main.py @@ -46,7 +46,7 @@ def menu(**kwargs): return [ {"name" : "webmail", "label" : _("Webmail"), - "url" : reverse(views.index), + "url" : reverse(views.index, urlconf='mailng.urls'), "img" : "/static/pics/webmail.png"} ] diff --git a/lib/__init__.py b/lib/__init__.py index c9d7cbfc5..cad017020 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -63,3 +63,4 @@ class Singleton(type): if cls.instance is None: cls.instance = super(Singleton, cls).__call__(*args, **kwargs) return cls.instance + diff --git a/lib/events.py b/lib/events.py index 5fe839387..bb9e1ce36 100644 --- a/lib/events.py +++ b/lib/events.py @@ -24,7 +24,8 @@ def register(event, callback): return 0 if not event in callbacks.keys(): callbacks[event] = [] - callbacks[event].append(callback) + if not callback in callbacks[event]: + callbacks[event].append(callback) return 1 def unregister(event, callback): @@ -32,7 +33,10 @@ def unregister(event, callback): return False if not callbacks.has_key(event): return False - callbacks[event].remove(callback) + try: + callbacks[event].remove(callback) + except ValueError: + pass def raiseEvent(event, **kwargs): if not event in events or not event in callbacks.keys(): diff --git a/scripts/extension.py b/scripts/extension.py new file mode 100755 index 000000000..3b98ce22b --- /dev/null +++ b/scripts/extension.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os, sys +from django.conf import settings + +def usage(): + print "Usage: extension.py " + sys.exit(1) + +def update_extension(name, extdir, state): + for d in ['templates', 'scripts']: + if not os.path.isdir("%s/%s" % (extdir, d)): + continue + cmd = state == "on" \ + and "ln -s %s/%s %s/%s" % (extdir, d, d, name) \ + or "rm %s/%s" % (d, name) + os.system(cmd) + +if __name__ == "__main__": + if len(sys.argv) != 3: + usage() + extdir = "%s/extensions/%s" % (settings.MAILNG_DIR, sys.argv[1]) + if not os.path.isdir(extdir): + print "Extension not found" + sys.exit(1) + extname = "mailng.extensions.%s" % sys.argv[1] + update_extension(sys.argv[1], extdir, sys.argv[2]) + if sys.argv[2] == "on": + print "Make sure you have added '%s' to INSTALLED_APPS (inside settings.py)" % extname + elif sys.argv[2] == "off": + print "Make sure you have remove '%s' from INSTALLED_APPS (inside settings.py)" % extname + diff --git a/settings_sample.py b/settings_sample.py index 8306d8d91..256158ac5 100644 --- a/settings_sample.py +++ b/settings_sample.py @@ -68,11 +68,13 @@ MIDDLEWARE_CLASSES = ( ROOT_URLCONF = 'mailng.urls' +MAILNG_DIR = os.path.dirname(__file__) +STATIC_ROOTDIR = os.path.join(MAILNG_DIR, 'static') TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. - os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), + os.path.join(os.path.dirname(__file__), 'templates'), ) INSTALLED_APPS = ( @@ -82,7 +84,7 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'mailng.lib', 'mailng.admin', - 'mailng.main' + 'mailng.main', # MailNG extensions here. # 'mailng.extensions.postfix_autoreply' @@ -93,6 +95,3 @@ AUTHENTICATION_BACKENDS = ( 'mailng.lib.authbackends.SimpleBackend' ) -# Autoreplies sending timeout (default: 86400s) -# AUTOREPLIES_TIMEOUT = - diff --git a/templates/admin/extensions.html b/templates/admin/extensions.html deleted file mode 100644 index 7b86890c7..000000000 --- a/templates/admin/extensions.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends "admin/settings_header.html" %} -{% block menu %} -{% load admin_extras %} -{% settings_menu "extensions" user %} -{% endblock %} -{% block setcontent %} -{% load i18n %} -
- {{ extensions }} -
- -
-{% endblock %} diff --git a/urls.py b/urls.py index ab1c39c1f..cf830bfdc 100644 --- a/urls.py +++ b/urls.py @@ -5,9 +5,8 @@ from django.conf import settings # from django.contrib import admin # admin.autodiscover() -from mailng.extensions import loadextensions, loadmenus, isenabled +from mailng.extensions import * from mailng.lib import parameters -loadextensions() urlpatterns = patterns('', # Example: @@ -25,12 +24,10 @@ urlpatterns = patterns('', (r'^accounts/login/$', 'mailng.auth.views.dologin'), (r'^accounts/logout/$', 'django.contrib.auth.views.logout_then_login'), (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', - {'packages': ('mailng',),}) -) + {'packages': ('mailng',),}), -menus = loadmenus() -if menus != (): - urlpatterns += patterns('', *menus) + *loadextensions() +) if settings.DEBUG: urlpatterns += patterns(