diff --git a/modoboa/bin/modoboa-admin.py b/bin/modoboa-admin.py similarity index 100% rename from modoboa/bin/modoboa-admin.py rename to bin/modoboa-admin.py diff --git a/modoboa/core/__init__.py b/modoboa/core/__init__.py index cf4bc5c04..824c49add 100644 --- a/modoboa/core/__init__.py +++ b/modoboa/core/__init__.py @@ -1,11 +1,47 @@ from django.utils.translation import ugettext_lazy from modoboa.lib import parameters, events +base_events = [ + "CanCreate", + + "AccountCreated", + "AccountAutoCreated", + "AccountModified", + "AccountDeleted", + "AccountExported", + "AccountImported", + "PasswordUpdated", + "ExtraAccountActions", + "RoleChanged", + "GetExtraRoles", + "PasswordChange", + + "UserMenuDisplay", + "AdminMenuDisplay", + "GetStaticContent", + + "ExtEnabled", + "ExtDisabled", + + "UserLogin", + "UserLogout", + + "GetAnnouncement", + + "TopNotifications", + "ExtraAdminContent", + + "ExtraUprefsRoutes", + "ExtraUprefsJS" +] + def load_settings(): - from app_settings import GeneralParametersForm, UserSettings + from .app_settings import GeneralParametersForm, UserSettings + parameters.register(GeneralParametersForm, ugettext_lazy("General")) parameters.register(UserSettings, ugettext_lazy("General")) + events.declare(base_events) @events.observe("ExtDisabled") diff --git a/modoboa/lib/management/__init__.py b/modoboa/core/management/__init__.py similarity index 100% rename from modoboa/lib/management/__init__.py rename to modoboa/core/management/__init__.py diff --git a/modoboa/lib/management/commands/__init__.py b/modoboa/core/management/commands/__init__.py similarity index 100% rename from modoboa/lib/management/commands/__init__.py rename to modoboa/core/management/commands/__init__.py diff --git a/modoboa/lib/management/commands/cleanlogs.py b/modoboa/core/management/commands/cleanlogs.py similarity index 91% rename from modoboa/lib/management/commands/cleanlogs.py rename to modoboa/core/management/commands/cleanlogs.py index e25ba7604..3da28798f 100644 --- a/modoboa/lib/management/commands/cleanlogs.py +++ b/modoboa/core/management/commands/cleanlogs.py @@ -1,13 +1,12 @@ #!/usr/bin/env python # coding: utf-8 - import datetime from optparse import make_option from django.core.management.base import BaseCommand from django.utils import timezone +from modoboa.core import load_settings +from modoboa.core.models import Log from modoboa.lib import parameters -from modoboa.lib.models import Log -from modoboa.admin import AdminConsole class Command(BaseCommand): @@ -38,8 +37,8 @@ class Command(BaseCommand): l.addHandler(logging.StreamHandler()) self.verbose = options["verbose"] - AdminConsole().load() - log_maximum_age = int(parameters.get_admin("LOG_MAXIMUM_AGE", app="admin")) + load_settings() + log_maximum_age = int(parameters.get_admin("LOG_MAXIMUM_AGE")) self.__vprint("Deleting logs older than %d days..." % log_maximum_age) limit = timezone.now() - datetime.timedelta(log_maximum_age) Log.objects.filter(date_created__lt=limit).delete() diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 71364982d..6d51a3aac 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -358,6 +358,26 @@ class User(AbstractBaseUser, PermissionsMixin): reversion.register(User) +def populate_callback(user): + """Populate callback + + If the LDAP authentication backend is in use, this callback will + be called each time a new user authenticates succesfuly to + Modoboa. This function is in charge of creating the mailbox + associated to the provided ``User`` object. + + :param user: a ``User`` instance + """ + from modoboa.lib.permissions import grant_access_to_object + + sadmins = User.objects.filter(is_superuser=True) + user.set_role("SimpleUsers") + user.post_create(sadmins[0]) + for su in sadmins[1:]: + grant_access_to_object(su, user) + events.raiseEvent("AccountAutoCreated", user) + + class ObjectAccess(models.Model): user = models.ForeignKey(User) content_type = models.ForeignKey(ContentType) diff --git a/modoboa/core/templates/core/information.html b/modoboa/core/templates/core/information.html index 80f7500a3..8dcdf1a52 100644 --- a/modoboa/core/templates/core/information.html +++ b/modoboa/core/templates/core/information.html @@ -1,4 +1,4 @@ -{% load i18n libextras %} +{% load i18n core_tags libextras %}

{% trans "Information" %} {% trans "Various information about Modoboa" %}


Modoboa {% get_version %} {% trans "is currently in use." %}
diff --git a/modoboa/core/templates/core/parameters.html b/modoboa/core/templates/core/parameters.html index c425d0e60..02e5e792d 100644 --- a/modoboa/core/templates/core/parameters.html +++ b/modoboa/core/templates/core/parameters.html @@ -1,5 +1,4 @@ {% load i18n libextras %}{% load url from future %} -{% url "modoboa.admin.views.saveparameters" as action %}

{% trans "Parameters" %} {% trans "Configure Modoboa" %}


{% csrf_token %} {% include "common/parameters.html" %} diff --git a/modoboa/core/templatetags/core_tags.py b/modoboa/core/templatetags/core_tags.py index 53ff25b7d..940aecff2 100644 --- a/modoboa/core/templatetags/core_tags.py +++ b/modoboa/core/templatetags/core_tags.py @@ -1,8 +1,10 @@ import re from django import template from django.template.loader import render_to_string +from django.utils import timezone from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse +from django.contrib.sessions.models import Session from modoboa.lib import events @@ -160,3 +162,117 @@ def colorize_level(level): @register.filter def tohtml(message): return re.sub("'(.*?)'", "\g<1>", message) + + +@register.simple_tag +def visirule(field): + if not hasattr(field.form, "visirules") or not field.html_name in field.form.visirules: + return "" + rule = field.form.visirules[field.html_name] + return " data-visibility-field='%s' data-visibility-value='%s' " \ + % (rule["field"], rule["value"]) + + +@register.simple_tag +def get_version(): + import pkg_resources + return pkg_resources.get_distribution("modoboa").version + + +class ConnectedUsers(template.Node): + def __init__(self, varname): + self.varname = varname + + def render(self, context): + from modoboa.core.models import User + + sessions = Session.objects.filter(expire_date__gte=timezone.now()) + uid_list = [] + # Build a list of user ids from that query + for session in sessions: + data = session.get_decoded() + uid = data.get('_auth_user_id', None) + if uid: + uid_list.append(uid) + + # Query all logged in users based on id list + context[self.varname] = [] + for uid in uid_list: + try: + context[self.varname].append(User.objects.get(pk=uid)) + except User.DoesNotExist: + pass + return '' + + +@register.tag +def connected_users(parser, token): + try: + tag, a, varname = token.split_contents() + except ValueError: + raise template.TemplateSyntaxError( + 'connected_users usage: {% connected_users as users %}' + ) + return ConnectedUsers(varname) + + +@register.simple_tag +def get_modoboa_logo(): + import os + from django.conf import settings + + try: + logo = settings.MODOBOA_CUSTOM_LOGO + except AttributeError: + logo = None + if logo is None: + return os.path.join(settings.STATIC_URL, "css/modoboa.png") + return logo + + +@register.simple_tag +def extra_head_content(user): + tpl = Template("{% for sc in static_content %}{{ sc|safe }}{% endfor %}") + return tpl.render( + Context( + dict(static_content=events.raiseQueryEvent("GetStaticContent", user)) + ) + ) + + +@register.simple_tag +def load_optionalmenu(user): + menu = events.raiseQueryEvent("UserMenuDisplay", "top_menu_middle", user) + return template.loader.render_to_string( + 'common/menulist.html', + {"entries" : menu, "user" : user} + ) + + +@register.simple_tag +def load_notifications(user): + content = events.raiseQueryEvent("TopNotifications", user) + return "".join(content) + + +@register.simple_tag +def display_messages(msgs): + text = "" + level = "info" + for m in msgs: + level = m.tags + text += unicode(m) + "\\\n" + + if level == "info": + level = "success" + timeout = "2000" + else: + timeout = "undefined" + + return """ + +""" % (level, text, timeout) diff --git a/modoboa/extensions/admin/__init__.py b/modoboa/extensions/admin/__init__.py index 763ff5054..79c8fad5d 100644 --- a/modoboa/extensions/admin/__init__.py +++ b/modoboa/extensions/admin/__init__.py @@ -157,6 +157,32 @@ def import_account_mailbox(user, account, row): dom.add_admin(account) +@events.observe("AccountAutoCreated") +def account_auto_created(user): + from modoboa.core.models import User + from modoboa.lib.permissions import grant_access_to_object + + sadmins = User.objects.filter(is_superuser=True) + localpart, domname = split_mailbox(user.username) + try: + domain = Domain.objects.get(name=domname) + except Domain.DoesNotExist: + domain = Domain(name=domname, enabled=True, quota=0) + domain.save(creator=sadmins[0]) + for su in sadmins[1:]: + grant_access_to_object(su, domain) + try: + mb = Mailbox.objects.get(domain=domain, address=localpart) + except Mailbox.DoesNotExist: + mb = Mailbox( + address=localpart, domain=domain, user=user, use_domain_quota=True + ) + mb.set_quota(override_rules=True) + mb.save(creator=sadmins[0]) + for su in sadmins[1:]: + grant_access_to_object(su, mb) + + @events.observe("UserLogin") def user_logged_in(request, username, password): from modoboa.lib.cryptutils import encrypt diff --git a/modoboa/extensions/admin/models/alias.py b/modoboa/extensions/admin/models/alias.py index ada1cfa19..c59b5b083 100644 --- a/modoboa/extensions/admin/models/alias.py +++ b/modoboa/extensions/admin/models/alias.py @@ -139,14 +139,6 @@ class Alias(DatesAware): total += len(self.extmboxes.split(',')) return total + self.aliases.count() + self.mboxes.count() - def ui_disabled(self, user): - if user.is_superuser: - return False - for mb in self.mboxes.all(): - if not user.is_owner(mb.domain): - return True - return False - def from_csv(self, user, row, expected_elements=5): """Create a new alias from a CSV file entry diff --git a/modoboa/extensions/admin/templates/admin/extensions.html b/modoboa/extensions/admin/templates/admin/extensions.html deleted file mode 100644 index a419d20ad..000000000 --- a/modoboa/extensions/admin/templates/admin/extensions.html +++ /dev/null @@ -1,6 +0,0 @@ -{% load i18n %}{% load url from future %} -

{% trans "Extensions" %} {% trans "Choose the extension(s) to use" %}


-{% csrf_token %} - {{ extensions|safe }} -
-{% trans 'Save' %} diff --git a/modoboa/extensions/admin/templates/admin/information.html b/modoboa/extensions/admin/templates/admin/information.html deleted file mode 100644 index 80f7500a3..000000000 --- a/modoboa/extensions/admin/templates/admin/information.html +++ /dev/null @@ -1,17 +0,0 @@ -{% load i18n libextras %} -

{% trans "Information" %} {% trans "Various information about Modoboa" %}


-
Modoboa {% get_version %} {% trans "is currently in use." %}
- -

{% trans "Active users" %}

- - - - - - - {% connected_users as users %}{% for u in users %} - - - - {% endfor %} -
{% trans "Name" %}{% trans "Group name" %}{% trans "Last login" %}
{{ u.username }}{{ u.group }}{{ u.last_login }}
diff --git a/modoboa/extensions/admin/templates/admin/parameters.html b/modoboa/extensions/admin/templates/admin/parameters.html deleted file mode 100644 index 0ae46dfc2..000000000 --- a/modoboa/extensions/admin/templates/admin/parameters.html +++ /dev/null @@ -1,8 +0,0 @@ -{% load i18n libextras %}{% load url from future %} -{% url "modoboa.admin.views.saveparameters" as action %} -

{% trans "Parameters" %} {% trans "Configure Modoboa" %}


-
{% csrf_token %} - {% include "common/parameters.html" %} -
-
-{% trans 'Save' %} diff --git a/modoboa/extensions/admin/templatetags/admin_tags.py b/modoboa/extensions/admin/templatetags/admin_tags.py index 59a68b63c..ed2747e22 100644 --- a/modoboa/extensions/admin/templatetags/admin_tags.py +++ b/modoboa/extensions/admin/templatetags/admin_tags.py @@ -177,82 +177,6 @@ def domadmin_actions(daid, domid): return render_actions(actions) -@register.simple_tag -def loadadminextmenu(user): - menu = events.raiseQueryEvent("AdminMenuDisplay", "admin_menu_box", user) - return render_to_string('common/menulist.html', - {"entries": menu, "user": user}) - - -@register.simple_tag -def param(app, definition): - name = "%s.%s" % (app, definition["name"]) - value = definition["value"] \ - if "value" in definition else definition["deflt"] - - if definition["type"] == "separator": - return "
%s
" % (unicode(definition["label"])) - - extratags = "" - if "visible_if" in definition: - vfield, vvalue = definition["visible_if"].split("=") - extratags = "data-visibility-field='%s.%s' data-visibility-value='%s'" \ - % (app, vfield, vvalue) - - result = """
- -""" % (extratags, name, - _(definition["label"]) if "label" in definition else definition["name"]) - - result += "
" - if definition["type"] in ["string", "int"]: - result += """ - """ % (name, name, value) - - if definition["type"] == "text": - result += "" \ - % (name, name, value) - - if definition["type"] == "list_yesno": - for idx, v in enumerate([("yes", _("Yes")), ("no", _("No"))]): - checked = "checked" if value == v[0] else "" - result += """ -""" % dict(id="%s_%d" % (name, idx), name=name, value=v[0], - label=v[1], checked=checked) - - if definition["type"] == "list": - result += """ - -""" - - if "help" in definition: - result += """ - -""" % (unicode(definition["help"]), _("Help")) -# result += """ -# %s -# """ % _(definition["help"]) - - result += """ -
-
-""" - return result - - @register.filter def gender(value, target): if value in genders: diff --git a/modoboa/extensions/admin/views/domain.py b/modoboa/extensions/admin/views/domain.py index 737d19bde..7989ebcb3 100644 --- a/modoboa/extensions/admin/views/domain.py +++ b/modoboa/extensions/admin/views/domain.py @@ -60,7 +60,7 @@ def domains(request, tplname="admin/domains.html"): if not request.user.has_perm("admin.view_domains"): if request.user.has_perm("admin.view_mailboxes"): return HttpResponseRedirect(reverse(identities)) - return HttpResponseRedirect(reverse("modoboa.userprefs.views.index")) + return HttpResponseRedirect(reverse("modoboa.core.views.user.index")) return render(request, tplname, {"selection": "domains"}) diff --git a/modoboa/extensions/amavis/management/commands/amnotify.py b/modoboa/extensions/amavis/management/commands/amnotify.py index 083cce65f..b90046869 100644 --- a/modoboa/extensions/amavis/management/commands/amnotify.py +++ b/modoboa/extensions/amavis/management/commands/amnotify.py @@ -8,9 +8,10 @@ from django.core.management.base import BaseCommand, CommandError from django.template.loader import render_to_string from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ +from modoboa.core.models import User from modoboa.lib import parameters from modoboa.lib.emailutils import sendmail_simple -from modoboa.admin.models import User, Domain +from modoboa.extensions.admin.models import Domain from modoboa.extensions.amavis import Amavis from modoboa.extensions.amavis.models import ( Msgrcpt @@ -68,13 +69,17 @@ class Command(BaseCommand): self.sender = parameters.get_admin("NOTIFICATIONS_SENDER", app="amavis") self.baseurl = self.options["baseurl"].strip("/") - self.listingurl = self.baseurl + reverse("modoboa.extensions.amavis.views._listing") + "?viewrequests=1" + self.listingurl = self.baseurl \ + + reverse("modoboa.extensions.amavis.views._listing") \ + + "?viewrequests=1" for da in User.objects.filter(groups__name="DomainAdmins"): if not da.mailbox_set.count(): continue rcpt = da.mailbox_set.all()[0].full_address - reqs = get_wrapper().get_domains_pending_requests(da.get_domains()) + reqs = get_wrapper().get_domains_pending_requests( + Domain.objects.get_for_admin(da) + ) if reqs.count(): self.send_pr_notification(rcpt, reqs) diff --git a/modoboa/extensions/stats/management/commands/logparser.py b/modoboa/extensions/stats/management/commands/logparser.py index cbc5c2151..b6df503c3 100644 --- a/modoboa/extensions/stats/management/commands/logparser.py +++ b/modoboa/extensions/stats/management/commands/logparser.py @@ -26,7 +26,7 @@ import string from django.core.management.base import BaseCommand, CommandError from optparse import make_option from modoboa.lib import parameters -from modoboa.admin.models import Domain +from modoboa.extensions.admin.models import Domain from modoboa.extensions.stats import Stats from modoboa.extensions.stats.grapher import str2Time, Grapher from modoboa.extensions.stats.graph_templates import MailTraffic diff --git a/modoboa/extensions/webmail/middleware.py b/modoboa/extensions/webmail/middleware.py deleted file mode 100644 index e5693f318..000000000 --- a/modoboa/extensions/webmail/middleware.py +++ /dev/null @@ -1,15 +0,0 @@ -# coding: utf-8 -from modoboa.lib.webutils import ajax_response, _render_error -from modoboa.extensions.webmail.exceptions import WebmailError, ImapError - - -class WebmailErrorMiddleware(object): - def process_exception(self, request, exception): - if not isinstance(exception, (WebmailError, ImapError)): - return None - json = request.GET.get("json", False) if request.method == "GET" \ - else request.POST.get("json", False) - if json: - return ajax_response(request, status="ko", - respmsg=str(exception), norefresh=True) - return _render_error(request, user_context=dict(error=str(exception))) diff --git a/modoboa/lib/authbackends.py b/modoboa/lib/authbackends.py index 325dc361d..3e9663604 100644 --- a/modoboa/lib/authbackends.py +++ b/modoboa/lib/authbackends.py @@ -25,21 +25,22 @@ try: from django_auth_ldap.backend import ( LDAPBackend as orig_LDAPBackend, _LDAPUser ) - from modoboa.admin.models import populate_callback + from modoboa.core.models import populate_callback class LDAPBackend(orig_LDAPBackend): def get_or_create_user(self, username, ldap_user): """ - This must return a (User, created) 2-tuple for the given LDAP user. - username is the Django-friendly username of the user. ldap_user.dn is - the user's DN and ldap_user.attrs contains all of their LDAP attributes. + This must return a (User, created) 2-tuple for the given + LDAP user. username is the Django-friendly username of + the user. ldap_user.dn is the user's DN and + ldap_user.attrs contains all of their LDAP attributes. """ lpart, domain = split_mailbox(username) if domain is None: return None user, created = User.objects.get_or_create( - username__iexact=username, + username__iexact=username, defaults={'username': username.lower(), 'is_local': False} ) if created: @@ -50,7 +51,7 @@ try: user = None try: user = User.objects.get(pk=user_id) - _LDAPUser(self, user=user) # This sets user.ldap_user + _LDAPUser(self, user=user) # This sets user.ldap_user except User.DoesNotExist: pass return user diff --git a/modoboa/lib/emailutils.py b/modoboa/lib/emailutils.py index a10381ffe..7a6795d8b 100644 --- a/modoboa/lib/emailutils.py +++ b/modoboa/lib/emailutils.py @@ -1,16 +1,16 @@ # coding: utf-8 - +import time import re import lxml -from django.template import Template, Context -from django.template.loader import render_to_string -from django.conf import settings -import u2u_decode import smtplib from email.header import Header, decode_header from email.mime.text import MIMEText from email.utils import make_msgid, formatdate, parseaddr -import time +from django.template import Template, Context +from django.template.loader import render_to_string +from django.conf import settings +import u2u_decode + class EmailAddress(object): def __init__(self, address): @@ -18,14 +18,15 @@ class EmailAddress(object): (self.name, self.address) = parseaddr(self.fulladdress) if self.name == "": self.fulladdress = self.address - + def __str__(self): return self.fulladdress + class Email(object): def __init__(self, msg, mformat="plain", dformat="plain", links=0): self.attached_map = {} - self.contents = {"html" : "", "plain" : ""} + self.contents = {"html": "", "plain": ""} self.headers = [] self.attachments = {} self.mformat = mformat @@ -34,7 +35,7 @@ class Email(object): self.__parse(msg) - if not self.contents.has_key(mformat) or self.contents[mformat] == "": + if not mformat in self.contents or self.contents[mformat] == "": # Fallback self.mformat = mformat == "html" and "plain" or "html" @@ -68,7 +69,7 @@ class Email(object): target = "plain" else: target = msg.get_content_subtype() - self.contents[target] += decode(msg.get_payload(decode=True), + self.contents[target] += decode(msg.get_payload(decode=True), charset=msg.get_content_charset()) def _parse_image(self, msg, level): @@ -97,7 +98,7 @@ class Email(object): self.attached_map[cid] = re.match("^http:", fname) and fname \ or self.__save_image(fname, msg) return - self.__parse_default(msg, level) + self.__parse_default(msg, level) def __parse(self, msg, level=None): """Recursive email parser @@ -121,7 +122,7 @@ class Email(object): cpt += 1 return - if level is None: + if level is None: level = "1" try: getattr(self, "_parse_%s" % msg.get_content_maintype())(msg, level) @@ -148,19 +149,17 @@ class Email(object): return path def map_cid(self, url): - import re - m = re.match(".*cid:(.+)", url) if m: - if self.attached_map.has_key(m.group(1)): + if m.group(1) in self.attached_map: return self.attached_map[m.group(1)] return url def render_headers(self, **kwargs): return render_to_string("common/mailheaders.html", { - "headers" : self.headers, - }) - + "headers": self.headers, + }) + def viewmail_plain(self, content, **kwargs): return "
%s
" % content @@ -181,6 +180,7 @@ class Email(object): body = re.sub("<(/?)body", lambda m: "<%sdiv" % m.group(1), body) return body + def split_mailbox(mailbox): """Tries to split a mailbox in two parts (local part and domain name) @@ -199,6 +199,7 @@ def split_mailbox(mailbox): address = "@".join(parts[:-1]) return (address, domain) + def decode(s, encodings=('utf8', 'latin1', 'windows-1252', 'ascii'), charset=None): if charset is not None: try: @@ -270,6 +271,7 @@ def __sendmail(sender, rcpt, msgstring, server='localhost', port=25): return False, "SMTP error: %s" % str(e) return True, None + def sendmail_simple(sender, rcpt, subject="Sample message", content="", **kwargs): """Simple way to send a text message @@ -288,9 +290,10 @@ def sendmail_simple(sender, rcpt, subject="Sample message", content="", **kwargs set_email_headers(msg, subject, sender, rcpt) return __sendmail(sender, rcpt, msg.as_string(), **kwargs) + def sendmail_fromfile(sender, rcpt, fname): """Send a message contained within a file - + The given file name must represent a valid message structure. It must not include the From: and To: headers, they are automatically added by the function. @@ -312,4 +315,3 @@ To: %s fp.close() return __sendmail(sender, rcpt, content) - diff --git a/modoboa/lib/events.py b/modoboa/lib/events.py index 85284b1f2..5abb9df6d 100644 --- a/modoboa/lib/events.py +++ b/modoboa/lib/events.py @@ -13,39 +13,7 @@ import inspect import re from django.conf import settings -events = [ - "CanCreate", - - "AccountCreated", - "AccountModified", - "AccountDeleted", - "AccountExported", - "AccountImported", - "PasswordUpdated", - "ExtraAccountActions", - "RoleChanged", - "GetExtraRoles", - "PasswordChange", - - "UserMenuDisplay", - "AdminMenuDisplay", - "GetStaticContent", - - "ExtEnabled", - "ExtDisabled", - - "UserLogin", - "UserLogout", - - "GetAnnouncement", - - "TopNotifications", - "ExtraAdminContent", - - "ExtraUprefsRoutes", - "ExtraUprefsJS" -] - +events = [] callbacks = {} diff --git a/modoboa/lib/templatetags/libextras.py b/modoboa/lib/templatetags/libextras.py index 7c8f9cc81..904f9d4a2 100644 --- a/modoboa/lib/templatetags/libextras.py +++ b/modoboa/lib/templatetags/libextras.py @@ -1,14 +1,10 @@ # coding: utf-8 -import os -from django.utils import timezone -from django.conf import settings +from datetime import datetime from django import template from django.contrib import messages from django.template import Template, Context from django.template.loader import render_to_string from django.core.urlresolvers import reverse -from django.contrib.sessions.models import Session -from datetime import datetime from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib import events from modoboa.lib.sysutils import exec_cmd @@ -17,10 +13,6 @@ from modoboa.lib.formutils import SeparatorField register = template.Library() -@register.simple_tag -def get_version(): - import pkg_resources - return pkg_resources.get_distribution("modoboa").version @register.simple_tag def join(items, sep=','): @@ -31,53 +23,11 @@ def join(items, sep=','): res += "%s : '%s'" % (k, v) return res + @register.simple_tag def tolist(values): - return "[%s]" % ",".join(map(lambda v: '"%s"' % v, values)) + return "[%s]" % ",".join(['"%s"' % v for v in values]) -@register.simple_tag -def display_messages(msgs): - from django.contrib import messages - - text = "" - level = "info" - for m in msgs: - level = m.tags - text += unicode(m) + "\\\n" - - if level == "info": - level = "success" - timeout = "2000" - else: - timeout = "undefined" - - return """ - -""" % (level, text, timeout) - -@register.simple_tag -def extra_head_content(user): - tpl = Template("{% for sc in static_content %}{{ sc|safe }}{% endfor %}") - return tpl.render( - Context( - dict(static_content=events.raiseQueryEvent("GetStaticContent", user)) - ) - ) - -@register.simple_tag -def load_optionalmenu(user): - menu = events.raiseQueryEvent("UserMenuDisplay", "top_menu_middle", user) - return template.loader.render_to_string('common/menulist.html', - {"entries" : menu, "user" : user}) - -@register.simple_tag -def load_notifications(user): - content = events.raiseQueryEvent("TopNotifications", user) - return "".join(content) @register.simple_tag def render_form(form, tpl=None): @@ -89,20 +39,25 @@ def render_form(form, tpl=None): ret += "%s\n" % render_field(field) return ret + @register.simple_tag def render_field(field, help_display_mode="tooltip"): + from modoboa.core.templatetags.core_tags import visirule + if type(field.form.fields[field.name]) is SeparatorField: return "%s" % (visirule(field), unicode(field.label)) return render_to_string("common/generic_field.html", dict( - field=field, help_display_mode=help_display_mode - )) + field=field, help_display_mode=help_display_mode + )) + @register.simple_tag def render_field_appended(field, text): return render_to_string("common/generic_field.html", dict( - field=field, help_display_mode="tooltip", appended_text=text - )) + field=field, help_display_mode="tooltip", appended_text=text + )) + @register.simple_tag def render_field_with_activator(field, activator_label=ugettext_lazy("activate")): @@ -111,11 +66,13 @@ def render_field_with_activator(field, activator_label=ugettext_lazy("activate") "activator_label": activator_label, "deactivate_if_empty": True }) + @register.simple_tag def render_and_hide_field(field): return render_to_string("common/generic_field.html", dict( - field=field, hidden=True - )) + field=field, hidden=True + )) + @register.simple_tag def render_fields_group(form, pattern): @@ -128,7 +85,7 @@ def render_fields_group(form, pattern): haserror = len(first.errors) != 0 while True: fname = "%s_%d" % (pattern, cpt) - if not form.fields.has_key(fname): + if not fname in form.fields: break bfield = forms.BoundField(form, form.fields[fname], fname) if len(bfield.errors): @@ -137,14 +94,16 @@ def render_fields_group(form, pattern): cpt += 1 return render_to_string("common/generic_fields_group.html", dict( - label=label, help_text=first.help_text, group=group, haserror=haserror - )) + label=label, help_text=first.help_text, group=group, haserror=haserror + )) + @register.simple_tag def pagination_bar(page): return render_to_string("common/pagination_bar.html", dict( - page=page, baseurl="?" - )) + page=page, baseurl="?" + )) + @register.simple_tag def alert(msg, typ): @@ -154,6 +113,7 @@ def alert(msg, typ): """) return t.render(Context(dict(type=typ, msg=msg))) + @register.simple_tag def render_link(linkdef, mdclass=""): t = Template("""""") return t.render(Context(dict(link=linkdef, mdclass=mdclass))) + @register.simple_tag def progress_color(value): value = int(value) @@ -175,54 +136,12 @@ def progress_color(value): return "progress-warning" return "progress-danger" + @register.filter def fromunix(value): - return datetime.datetime.fromtimestamp(int(value)) + return datetime.fromtimestamp(int(value)) -@register.simple_tag -def visirule(field): - if not hasattr(field.form, "visirules") or not field.html_name in field.form.visirules: - return "" - rule = field.form.visirules[field.html_name] - return " data-visibility-field='%s' data-visibility-value='%s' " \ - % (rule["field"], rule["value"]) - - -class ConnectedUsers(template.Node): - def __init__(self, varname): - self.varname = varname - - def render(self, context): - from modoboa.core.models import User - - sessions = Session.objects.filter(expire_date__gte=timezone.now()) - uid_list = [] - - # Build a list of user ids from that query - for session in sessions: - data = session.get_decoded() - uid = data.get('_auth_user_id', None) - if uid: - uid_list.append(uid) - - # Query all logged in users based on id list - context[self.varname] = [] - for uid in uid_list: - try: - context[self.varname].append(User.objects.get(pk=uid)) - except User.DoesNotExist: - pass - return '' - -@register.tag -def connected_users(parser, token): - try: - tag, a, varname = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError('connected_users usage: {% connected_users as users %}') - return ConnectedUsers(varname) - @register.simple_tag def render_tags(tags): t = Template("""{% for tag in tags %} @@ -231,16 +150,4 @@ def render_tags(tags): {% endfor %} """) - return t.render(Context({"tags" : tags})) - - -@register.simple_tag -def get_modoboa_logo(): - try: - logo = settings.MODOBOA_CUSTOM_LOGO - except AttributeError: - logo = None - if logo is None: - return os.path.join(settings.STATIC_URL, "css/modoboa.png") - return logo - + return t.render(Context({"tags": tags})) diff --git a/modoboa/lib/webutils.py b/modoboa/lib/webutils.py index c9977d244..a8eb58180 100644 --- a/modoboa/lib/webutils.py +++ b/modoboa/lib/webutils.py @@ -41,14 +41,6 @@ def render_actions(actions): return t.render(template.Context(dict(actions=actions))) -def _ctx_ok(url): - return {"status": "ok", "url": url} - - -def _ctx_ko(tpl, ctx): - return {"status": "ko", "content": render_to_string(tpl, ctx)} - - def getctx(status, level=1, callback=None, **kwargs): if not callback: callername = sys._getframe(level).f_code.co_name diff --git a/modoboa/templates/common/generic_field.html b/modoboa/templates/common/generic_field.html index 5c3ea7ec1..82acbf87b 100644 --- a/modoboa/templates/common/generic_field.html +++ b/modoboa/templates/common/generic_field.html @@ -1,4 +1,4 @@ -{% load i18n libextras %} +{% load i18n core_tags libextras %}