wip: big refactoring

* sieve extension still needs work
* auth application removed
This commit is contained in:
Antoine Nguyen
2013-08-23 10:09:16 +02:00
parent 2147d87127
commit 932431da42
16 changed files with 244 additions and 353 deletions
View File
-17
View File
@@ -1,17 +0,0 @@
# coding: utf-8
from django import forms
from django.utils.translation import ugettext_lazy as _
class LoginForm(forms.Form):
username = forms.CharField(
label=_("Username"),
widget=forms.TextInput(attrs={"class": "input-block-level"})
)
password = forms.CharField(
label=_("Password"),
widget=forms.PasswordInput(attrs={"class": "input-block-level"})
)
rememberme = forms.BooleanField(
initial=False,
required=False
)
-41
View File
@@ -1,41 +0,0 @@
# coding: utf-8
from Crypto.Cipher import AES
import base64
import random
import string
from modoboa.lib import parameters
def random_key(l=16):
"""Generate a random key
:param integer l: the key's length
:return: a string
"""
char_set = string.digits + string.letters + string.punctuation
return ''.join(random.sample(char_set * l, l))
def encrypt(clear):
key = parameters.get_admin("SECRET_KEY", app="admin")
obj = AES.new(key, AES.MODE_ECB)
if type(clear) is unicode:
clear = clear.encode("utf-8")
if len(clear) % AES.block_size:
clear += " " * (AES.block_size - len(clear) % AES.block_size)
ciph = obj.encrypt(clear)
ciph = base64.b64encode(ciph)
return ciph
def decrypt(ciph):
obj = AES.new(
parameters.get_admin("SECRET_KEY", app="admin"), AES.MODE_ECB
)
ciph = base64.b64decode(ciph)
clear = obj.decrypt(ciph)
return clear.rstrip(' ')
def get_password(request):
return decrypt(request.session["password"])
-3
View File
@@ -1,3 +0,0 @@
from django.db import models
# Create your models here.
-23
View File
@@ -1,23 +0,0 @@
# coding: utf-8
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-69
View File
@@ -1,69 +0,0 @@
# coding: utf-8
import logging
from django.views.decorators.cache import never_cache
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from modoboa.lib import events, parameters
from modoboa.lib.webutils import _render_to_string
from forms import LoginForm
from modoboa.auth.lib import encrypt
def dologin(request):
error = None
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
logger = logging.getLogger('modoboa.auth')
user = authenticate(username=form.cleaned_data["username"],
password=form.cleaned_data["password"])
if user and user.is_active:
login(request, user)
if not form.cleaned_data["rememberme"]:
request.session.set_expiry(0)
if request.user.has_mailbox:
request.session["password"] = encrypt(form.cleaned_data["password"])
request.session["django_language"] = \
parameters.get_user(request.user, "LANG", app="general")
logger.info(_("User '%s' successfully logged in" % user.username))
events.raiseEvent("UserLogin", request,
form.cleaned_data["username"],
form.cleaned_data["password"])
nextlocation = request.POST.get("next", None)
if nextlocation is None or nextlocation == "None":
if user.group == "SimpleUsers":
nextlocation = reverse("modoboa.lib.webutils.topredirection")
else:
nextlocation = reverse("domains")
return HttpResponseRedirect(nextlocation)
error = _("Your username and password didn't match. Please try again.")
logger.warning("Failed connection attempt from '%(addr)s' as user '%(user)s'" \
% {"addr": request.META["REMOTE_ADDR"],
"user": form.cleaned_data["username"]})
nextlocation = request.POST.get("next", None)
httpcode = 401
else:
form = LoginForm()
nextlocation = request.GET.get("next", None)
httpcode = 200
return HttpResponse(_render_to_string(request, "registration/login.html", {
"form": form, "error": error, "next": nextlocation,
"annoucements": events.raiseQueryEvent("GetAnnouncement", "loginpage")
}), status=httpcode)
dologin = never_cache(dologin)
def dologout(request):
events.raiseEvent("UserLogout", request)
logger = logging.getLogger("modoboa.auth")
logger.info(_("User '%s' logged out" % request.user.username))
logout(request)
return HttpResponseRedirect(reverse(dologin))
+1 -1
View File
@@ -4,8 +4,8 @@ from django.conf import settings
from django.utils.translation import ugettext as _, ugettext_lazy
from modoboa.lib.formutils import YesNoField, SeparatorField, InlineRadioSelect
from modoboa.lib.sysutils import exec_cmd
from modoboa.lib.cryptutils import random_key
from modoboa.lib import parameters
from modoboa.auth.lib import random_key
def enabled_applications():
+1 -1
View File
@@ -7,8 +7,8 @@ from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from modoboa.lib import events, parameters
from modoboa.lib.webutils import _render_to_string
from modoboa.lib.cryptutils import encrypt
from modoboa.core.forms import LoginForm
from modoboa.auth.lib import encrypt
def dologin(request):
+12 -12
View File
@@ -2,7 +2,7 @@
from django.utils.translation import ugettext as _, ugettext_lazy
from django.core.urlresolvers import reverse
from modoboa.lib import events, parameters
from modoboa.extensions import ModoExtension, exts_pool
from modoboa.core.extensions import ModoExtension, exts_pool
class SieveFilters(ModoExtension):
@@ -13,7 +13,7 @@ class SieveFilters(ModoExtension):
url = "sfilters"
def load(self):
from app_settings import ParametersForm, UserSettings
from .app_settings import ParametersForm, UserSettings
parameters.register(ParametersForm, ugettext_lazy("Sieve filters"))
parameters.register(UserSettings, ugettext_lazy("Message filters"))
@@ -23,31 +23,31 @@ class SieveFilters(ModoExtension):
exts_pool.register_extension(SieveFilters)
@events.observe("UserMenuDisplay")
def menu(target, user):
import views
if target != "options_menu":
return []
if not user.has_mailbox:
if not user.mailbox_set.count():
return []
return [
{"name" : "sievefilters",
"label" : _("Message filters"),
"url" : reverse(views.index),
"img" : "icon-check"}
]
{"name": "sievefilters",
"label": _("Message filters"),
"url": reverse("modobooa.extensions.sievefilters.views.index"),
"img": "icon-check"}
]
@events.observe("UserLogout")
def userlogout(request):
from lib import SieveClient
from .lib import SieveClient
if not request.user.has_mailbox:
return
try:
sc = SieveClient(user=request.user.username,
password=request.session["password"])
except Exception, e:
except Exception:
pass
else:
sc.logout()
@@ -29,7 +29,7 @@ class ParametersForm(AdminParametersForm):
initial=4190,
help_text=_("Listening port of your MANAGESIEVE server")
)
starttls = YesNoField(
label=_("Connect using STARTTLS"),
initial="no",
@@ -59,4 +59,4 @@ class UserSettings(UserParametersForm):
@staticmethod
def has_access(user):
return user.has_mailbox
return user.mailbox_set.count() != 0
+50 -39
View File
@@ -7,11 +7,15 @@ from django.utils.html import conditional_escape
from django.utils.encoding import force_unicode
from modoboa.extensions.admin.templatetags.admin_tags import gender
class FiltersSetForm(forms.Form):
name = forms.CharField()
active = forms.BooleanField(label=gender("Active", "m"), required=False,
initial=False,
help_text=ugettext_lazy("Check to activate this filters set"))
active = forms.BooleanField(
label=gender("Active", "m"), required=False,
initial=False,
help_text=ugettext_lazy("Check to activate this filters set")
)
class CustomRadioInput(RadioInput):
def __unicode__(self):
@@ -27,15 +31,16 @@ class CustomRadioInput(RadioInput):
label_for = ''
choice_label = conditional_escape(force_unicode(self.choice_label))
return mark_safe(
u'<label%s class="radio inline">%s %s</label>' \
% (label_for, self.tag(), choice_label)
)
u'<label%s class="radio inline">%s %s</label>'
% (label_for, self.tag(), choice_label)
)
class CustomRadioFieldRenderer(RadioFieldRenderer):
def __iter__(self):
for i, choice in enumerate(self.choices):
yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i)
def __getitem__(self, idx):
choice = self.choices[idx]
return CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
@@ -43,9 +48,11 @@ class CustomRadioFieldRenderer(RadioFieldRenderer):
def render(self):
return mark_safe(u'\n'.join([force_unicode(w) for w in self]))
class CustomRadioSelect(RadioSelect):
renderer = CustomRadioFieldRenderer
class FilterForm(forms.Form):
def __init__(self, conditions, actions, request, *args, **kwargs):
super(FilterForm, self).__init__(*args, **kwargs)
@@ -56,30 +63,32 @@ class FilterForm(forms.Form):
("anyof", _("Any of the following")),
("all", _("All messages"))],
initial="anyof",
widget=CustomRadioSelect(attrs={"class" : "radio inline"})
)
self.header_operators = [("contains", _("contains"), "string"),
("notcontains", _("does not contain"), "string"),
("is", _("is"), "string"),
("isnot", _("is not"), "string")]
widget=CustomRadioSelect(attrs={"class": "radio inline"})
)
self.header_operators = [
("contains", _("contains"), "string"),
("notcontains", _("does not contain"), "string"),
("is", _("is"), "string"),
("isnot", _("is not"), "string")
]
self.cond_templates = [
{"name" : "Subject", "label" : _("Subject"), "operators" : self.header_operators},
{"name" : "From", "label" : _("Sender"), "operators" : self.header_operators},
{"name" : "To", "label" : _("Recipient"), "operators" : self.header_operators},
{"name" : "Cc", "label" : _("Cc"), "operators" : self.header_operators},
{"name" : "size", "label" : _("Size"),
"operators" : [("over", _("is greater than"), "number"),
("under", _("is less than"), "number")]},
]
{"name": "Subject", "label": _("Subject"), "operators": self.header_operators},
{"name": "From", "label": _("Sender"), "operators": self.header_operators},
{"name": "To", "label": _("Recipient"), "operators": self.header_operators},
{"name": "Cc", "label": _("Cc"), "operators": self.header_operators},
{"name": "size", "label": _("Size"),
"operators": [("over", _("is greater than"), "number"),
("under", _("is less than"), "number")]},
]
self.action_templates = [
{"name" : "fileinto", "label" : _("Move message to"),
"args" : [{"type" : "list", "vloader" : "userfolders"}]},
{"name" : "redirect", "label" : _("Redirect message to"),
"args" : [{"type" : "string"}]},
]
{"name": "fileinto", "label": _("Move message to"),
"args": [{"type": "list", "vloader": "userfolders"}]},
{"name": "redirect", "label": _("Redirect message to"),
"args": [{"type": "string"}]},
]
self.conds_cnt = 0
for c in conditions:
@@ -93,7 +102,7 @@ class FilterForm(forms.Form):
ops = []
vfield = None
for tpl in self.cond_templates:
targets += [(tpl["name"], tpl["label"]),]
targets += [(tpl["name"], tpl["label"]), ]
if tpl["name"] != name:
continue
for opdef in tpl["operators"]:
@@ -109,7 +118,7 @@ class FilterForm(forms.Form):
forms.ChoiceField(initial=op, choices=ops)
self.fields["cond_value_%d" % self.conds_cnt] = vfield
self.conds_cnt += 1
def _build_Subject_field(self, op, value):
self._build_header_field("Subject", op, value)
@@ -129,7 +138,7 @@ class FilterForm(forms.Form):
actions = []
args = None
for tpl in self.action_templates:
actions += [(tpl["name"], tpl["label"]),]
actions += [(tpl["name"], tpl["label"]), ]
if name == tpl["name"]:
args = tpl["args"]
self.fields["action_name_%d" % self.actions_cnt] = \
@@ -153,12 +162,12 @@ class FilterForm(forms.Form):
def __build_folders_list(self, folders, user, imapc, parentmb=None):
ret = []
for fd in folders:
value = fd["path"] if fd.has_key("path") else fd["name"]
value = fd["path"] if "path" in fd else fd["name"]
if parentmb:
ret += [(value, fd["name"].replace("%s." % parentmb, ""))]
else:
ret += [(value, fd["name"])]
if fd.has_key("sub"):
if "sub" in fd:
submboxes = imapc.getmboxes(user, value, unseen_messages=False)
ret += self.__build_folders_list(submboxes, user, imapc, value)
return ret
@@ -191,7 +200,8 @@ class FilterForm(forms.Form):
actions += [naction]
return (conditions, actions)
def build_filter_form_from_qdict(request):
conditions = []
actions = []
@@ -204,7 +214,7 @@ def build_filter_form_from_qdict(request):
while True:
if cpt == int(request.POST["conds"]):
break
if request.POST.has_key("cond_target_%d" % i):
if "cond_target_%d" % i in request.POST:
qdict["cond_target_%d" % cpt] = request.POST["cond_target_%d" % i]
qdict["cond_operator_%d" % cpt] = request.POST["cond_operator_%d" % i]
qdict["cond_value_%d" % cpt] = request.POST["cond_value_%d" % i]
@@ -219,7 +229,7 @@ def build_filter_form_from_qdict(request):
while True:
if cpt == int(request.POST["actions"]):
break
if request.POST.has_key("action_name_%d" % i):
if "action_name_%d" % i in request.POST:
qdict["action_name_%d" % cpt] = request.POST["action_name_%d" % i]
action = request.POST["action_name_%d" % i]
argcpt = 0
@@ -239,6 +249,7 @@ def build_filter_form_from_qdict(request):
return FilterForm(conditions, actions, request, qdict)
def build_filter_form_from_filter(request, name, fobj):
from sievelib.commands import SizeCommand, TrueCommand
@@ -252,8 +263,8 @@ def build_filter_form_from_filter(request, name, fobj):
elif isinstance(t, SizeCommand):
conditions += [("size", t["comparator"][1:], t["limit"])]
else:
conditions += [(t["header-names"].strip('"'),
t["match-type"][1:],
conditions += [(t["header-names"].strip('"'),
t["match-type"][1:],
t["key-list"].strip('"'))]
actions = []
for c in fobj.children:
+6 -4
View File
@@ -7,9 +7,11 @@ from sievelib.factory import FiltersSet
from modoboa.lib import parameters
from modoboa.lib.connections import ConnectionsManager, ConnectionError
class SieveClientError(Exception):
pass
class SieveClient(object):
__metaclass__ = ConnectionsManager
@@ -22,7 +24,7 @@ class SieveClient(object):
raise ConnectionError(msg)
def login(self, user, password):
self.msc = Client(parameters.get_admin("SERVER"),
self.msc = Client(parameters.get_admin("SERVER"),
int(parameters.get_admin("PORT")),
debug=False)
use_starttls = True if parameters.get_admin("STARTTLS") == "yes" else False
@@ -31,7 +33,7 @@ class SieveClient(object):
authmech = None
try:
ret = self.msc.connect(user, password, use_starttls, authmech)
except Error, e:
except Error:
ret = False
if not ret:
return False, _("Connection to MANAGESIEVE server failed, check your configuration")
@@ -40,7 +42,7 @@ class SieveClient(object):
def logout(self):
self.msc.logout()
self.msc = None
def refresh(self, user, password):
import ssl
@@ -85,7 +87,7 @@ class SieveClient(object):
raise SieveClientError(self.msc.errmsg)
if active and not self.msc.setactive(name):
raise SieveClientError(self.msc.errmsg)
def deletescript(self, name):
if not self.msc.deletescript(name):
raise SieveClientError(self.msc.errmsg)
@@ -2,106 +2,108 @@ from django import template
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from modoboa.lib.webutils import render_actions
from modoboa.lib.webutils import render_actions, static_url
register = template.Library()
from modoboa.lib.webutils import static_url
@register.simple_tag
def sfilters_menu(user):
entries = [
{"name" : "newfilterset",
"img" : "icon-plus",
"label" : _("New filters set"),
"url" : reverse("modoboa.extensions.sievefilters.views.new_filters_set"),
"modal" : True,
"modalcb" : "filtersetform_cb"
{"name": "newfilterset",
"img": "icon-plus",
"label": _("New filters set"),
"url": reverse("modoboa.extensions.sievefilters.views.new_filters_set"),
"modal": True,
"modalcb": "filtersetform_cb"
}
]
]
return render_to_string('common/menulist.html',
{"entries": entries, "user": user})
return render_to_string('common/menulist.html',
{"entries" : entries, "user" : user})
@register.simple_tag
def fset_menu(mode, setname):
entries = []
if mode == "gui":
entries += [
{"name" : "newfilter",
"img" : "icon-plus",
"label" : _("New filter"),
"url" : reverse("modoboa.extensions.sievefilters.views.newfilter",
{"name": "newfilter",
"img": "icon-plus",
"label": _("New filter"),
"url": reverse("modoboa.extensions.sievefilters.views.newfilter",
args=[setname]),
"modal" : True,
"autowidth" : True,
"modalcb" : "filterform_cb"}
]
"modal": True,
"autowidth": True,
"modalcb": "filterform_cb"}
]
if mode == "raw":
entries += [
{"name" : "savefs",
"img" : "icon-download-alt",
"label" : _("Save filters set"),
"url" : reverse("modoboa.extensions.sievefilters.views.savefs",
{"name": "savefs",
"img": "icon-download-alt",
"label": _("Save filters set"),
"url": reverse("modoboa.extensions.sievefilters.views.savefs",
args=[setname])},
]
entries += [
{"name" : "activatefs",
"img" : "icon-ok",
"label" : _("Activate filters set"),
"url" : reverse("modoboa.extensions.sievefilters.views.activate_filters_set",
args=[setname])},
{"name" : "removefs",
"img" : "icon-trash",
"label" : _("Remove filters set"),
"url" : reverse("modoboa.extensions.sievefilters.views.remove_filters_set",
args=[setname])},
{"name" : "downloadfs",
"img" : "icon-download",
"label" : _("Download"),
"url" : reverse("modoboa.extensions.sievefilters.views.download_filters_set",
args=[setname])}
]
return render_to_string('common/menulist.html',
{"entries" : entries})
entries += [
{"name": "activatefs",
"img": "icon-ok",
"label": _("Activate filters set"),
"url": reverse("modoboa.extensions.sievefilters.views.activate_filters_set",
args=[setname])},
{"name": "removefs",
"img": "icon-trash",
"label": _("Remove filters set"),
"url": reverse("modoboa.extensions.sievefilters.views.remove_filters_set",
args=[setname])},
{"name": "downloadfs",
"img": "icon-download",
"label": _("Download"),
"url": reverse("modoboa.extensions.sievefilters.views.download_filters_set",
args=[setname])}
]
return render_to_string('common/menulist.html',
{"entries": entries})
@register.simple_tag
def filter_actions(setname, f, position, islast):
actions = [
{"name" : "editfilter",
"url" : reverse("modoboa.extensions.sievefilters.views.editfilter",
{"name": "editfilter",
"url": reverse("modoboa.extensions.sievefilters.views.editfilter",
args=[setname, f["name"]]),
"img" : "icon-edit",
"title" : _("Edit filter"),
"modal" : True,
"autowidth" : True,
"modalcb" : "filterform_cb"},
{"name" : "removefilter",
"url" : reverse("modoboa.extensions.sievefilters.views.removefilter",
"img": "icon-edit",
"title": _("Edit filter"),
"modal": True,
"autowidth": True,
"modalcb": "filterform_cb"},
{"name": "removefilter",
"url": reverse("modoboa.extensions.sievefilters.views.removefilter",
args=[setname, f["name"]]),
"img" : "icon-trash",
"title" : _("Remove this filter")}
]
"img": "icon-trash",
"title": _("Remove this filter")}
]
if position != 1:
actions += [
{"name" : "movefilter_up",
"url" : reverse("modoboa.extensions.sievefilters.views.move_filter_up",
{"name": "movefilter_up",
"url": reverse("modoboa.extensions.sievefilters.views.move_filter_up",
args=[setname, f["name"]]),
"img" : "icon-arrow-up",
"title" : _("Move this filter up")}
]
"img": "icon-arrow-up",
"title": _("Move this filter up")}
]
if not islast:
actions += [
{"name" : "movefilter_down",
"url" : reverse("modoboa.extensions.sievefilters.views.move_filter_down",
{"name": "movefilter_down",
"url": reverse("modoboa.extensions.sievefilters.views.move_filter_down",
args=[setname, f["name"]]),
"img" : "icon-arrow-down",
"title" : _("Move this filter down")},
]
"img": "icon-arrow-down",
"title": _("Move this filter down")},
]
return render_actions(actions)
@register.simple_tag
def display_errors(errors):
if not len(errors):
@@ -114,8 +116,9 @@ def display_errors(errors):
</ul>
""")
return t.render(template.Context({
"errors" : errors
}))
"errors": errors
}))
@register.simple_tag
def display_condition(form, cnt):
@@ -128,12 +131,13 @@ def display_condition(form, cnt):
</div>
""")
return t.render(template.Context({
"idx" : cnt,
"tfield" : target,
"ofield" : operator,
"vfield" : value,
"verrors" : display_errors(value.errors)
}))
"idx": cnt,
"tfield": target,
"ofield": operator,
"vfield": value,
"verrors": display_errors(value.errors)
}))
@register.simple_tag
def display_action(form, cnt):
@@ -155,7 +159,7 @@ def display_action(form, cnt):
</div>
""")
return t.render(template.Context({
"idx" : cnt,
"afield" : action, "values" : values,
"verrors" : display_errors(verrors)
}))
"idx": cnt,
"afield": action, "values": values,
"verrors": display_errors(verrors)
}))
+82 -57
View File
@@ -1,45 +1,51 @@
# coding: utf-8
from sievelib.managesieve import Error
from django.shortcuts import render
from django.http import HttpResponse
from django.template.loader import render_to_string
from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from modoboa.lib import parameters
from modoboa.lib.webutils import _render, _render_to_string, _render_error, \
from modoboa.lib.webutils import _render_to_string, _render_error, \
ajax_response, ajax_simple_response
from modoboa.lib.decorators import needs_mailbox
from modoboa.lib.connections import ConnectionError
from modoboa.auth.lib import get_password
from lib import *
from forms import *
from modoboa.lib.cryptutils import get_password
from modoboa.extensions.admin.lib import needs_mailbox
from .lib import SieveClient, SieveClientError
from .forms import (
FilterForm, build_filter_form_from_qdict, build_filter_form_from_filter,
FiltersSetForm
)
from templatetags.sfilters_tags import fset_menu
@login_required
@needs_mailbox()
def index(request, tplname="sievefilters/index.html"):
try:
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
except ConnectionError, e:
return _render_error(request, user_context={"error" : e})
return _render_error(request, user_context={"error": e})
try:
active_script, scripts = sc.listscripts()
except Error, e:
return _render_error(request, user_context={"error" : e})
return _render_error(request, user_context={"error": e})
if active_script is None:
active_script = ""
default_script = "%s/" % scripts[0] if len(scripts) else ""
else:
default_script = "%s/" % active_script
return _render(request, tplname, {
"selection" : "user",
"active_script" : active_script,
"default_script" : default_script,
"scripts" : sorted(scripts),
})
return render(request, tplname, {
"selection": "user",
"active_script": active_script,
"default_script": default_script,
"scripts": sorted(scripts),
})
@login_required
@needs_mailbox()
@@ -48,10 +54,11 @@ def get_templates(request, ftype):
return ajax_simple_response(FilterForm([], [], request).cond_templates)
return ajax_simple_response(FilterForm([], [], request).action_templates)
@login_required
@needs_mailbox()
def getfs(request, name):
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
editormode = parameters.get_user(request.user, "EDITOR_MODE")
error = None
@@ -67,30 +74,32 @@ def getfs(request, name):
return ajax_response(request, "ko", respmsg=error)
if editormode == "raw":
htmlcontent = render_to_string("sievefilters/rawfilter.html", dict(
name=name, scriptcontent=content
))
htmlcontent = render_to_string("sievefilters/rawfilter.html", dict(
name=name, scriptcontent=content
))
else:
htmlcontent = render_to_string("sievefilters/guieditor.html", dict(
fs=content
))
fs=content
))
menu = '<ul id="fsetmenu" class="nav nav-list"><li class="nav-header">%s</li>%s</ul>' % \
(_("Actions"), fset_menu(editormode, name))
(_("Actions"), fset_menu(editormode, name))
resp = dict(status="ok", menu=menu, content=htmlcontent)
return ajax_simple_response(resp)
def build_filter_ctx(ctx, form):
ctx["form"] = form
ctx["conds_nb"] = range(form.conds_cnt)
ctx["actions_nb"] = range(form.actions_cnt)
return ctx
def submitfilter(request, setname, okmsg, tplname, tplctx, update=False, sc=None):
form = build_filter_form_from_qdict(request)
if form.is_valid():
if sc is None:
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
fset = sc.getscript(setname, format="fset")
conditions, actions = form.tofilter()
@@ -110,6 +119,7 @@ def submitfilter(request, setname, okmsg, tplname, tplctx, update=False, sc=None
tplctx = build_filter_ctx(tplctx, form)
return ajax_response(request, status="ko", template=tplname, **tplctx)
@login_required
@needs_mailbox()
def newfilter(request, setname, tplname="sievefilters/filter.html"):
@@ -119,15 +129,18 @@ def newfilter(request, setname, tplname="sievefilters/filter.html"):
action=reverse(newfilter, args=[setname]),
action_label=_("Create"),
action_classes="submit"
)
)
if request.method == "POST":
return submitfilter(request, setname, _("Filter created"), tplname, ctx)
return submitfilter(
request, setname, _("Filter created"), tplname, ctx
)
conds = [("Subject", "contains", "")]
actions = [("fileinto", "")]
form = FilterForm(conds, actions, request)
ctx = build_filter_ctx(ctx, form)
return _render(request, tplname, ctx)
return render(request, tplname, ctx)
@login_required
@needs_mailbox()
@@ -138,13 +151,13 @@ def editfilter(request, setname, fname, tplname="sievefilters/filter.html"):
action=reverse(editfilter, args=[setname, fname]),
action_label=_("Update"),
action_classes="submit"
)
sc = SieveClient(user=request.user.username,
)
sc = SieveClient(user=request.user.username,
password=request.session["password"])
if request.method == "POST":
return submitfilter(request, setname, _("Filter modified"), tplname, ctx,
update=True, sc=sc)
fset = sc.getscript(setname, format="fset")
f = fset.getfilter(fname)
form = build_filter_form_from_filter(request, fname, f)
@@ -152,12 +165,13 @@ def editfilter(request, setname, fname, tplname="sievefilters/filter.html"):
ctx["oldname"] = fname
ctx["hidestyle"] = "none" \
if form.fields["match_type"].initial == "all" else "block"
return _render(request, tplname, ctx)
return render(request, tplname, ctx)
@login_required
@needs_mailbox()
def removefilter(request, setname, fname):
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
fset = sc.getscript(setname, format="fset")
if fset.removefilter(fname):
@@ -165,12 +179,13 @@ def removefilter(request, setname, fname):
return ajax_response(request, respmsg=_("Filter removed"))
return ajax_response(request, "ko", respmsg=_("Failed to remove filter"))
@login_required
@needs_mailbox()
def savefs(request, name):
if not request.POST.has_key("scriptcontent"):
if not "scriptcontent" in request.POST:
return
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
try:
sc.pushscript(name, request.POST["scriptcontent"])
@@ -178,22 +193,23 @@ def savefs(request, name):
error = str(e)
return ajax_response(request, "ko", respmsg=error)
return ajax_response(request, respmsg=_("Filters set saved"))
@login_required
@needs_mailbox()
def new_filters_set(request, tplname="common/generic_modal_form.html"):
ctx = {"title" : _("Create a new filters set"),
"formid" : "newfiltersset",
"action_label" : _("Create"),
"action_classes" : "submit",
"action" : reverse(new_filters_set),
"withmenu" : False,
"withunseen" : False}
ctx = {"title": _("Create a new filters set"),
"formid": "newfiltersset",
"action_label": _("Create"),
"action_classes": "submit",
"action": reverse(new_filters_set),
"withmenu": False,
"withunseen": False}
if request.method == "POST":
form = FiltersSetForm(request.POST)
error = None
if form.is_valid():
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
try:
sc.pushscript(form.cleaned_data["name"], "# Empty script",
@@ -202,7 +218,7 @@ def new_filters_set(request, tplname="common/generic_modal_form.html"):
error = str(e)
else:
return ajax_simple_response({
"status": "ok",
"status": "ok",
"url": form.cleaned_data["name"],
"active": form.cleaned_data["active"],
"respmsg": _("Filters set created")
@@ -213,12 +229,13 @@ def new_filters_set(request, tplname="common/generic_modal_form.html"):
return ajax_response(request, status="ko", template=tplname, **ctx)
ctx["form"] = FiltersSetForm()
return _render(request, tplname, ctx)
return render(request, tplname, ctx)
@login_required
@needs_mailbox()
def remove_filters_set(request, name):
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
try:
sc.deletescript(name)
@@ -226,13 +243,14 @@ def remove_filters_set(request, name):
return ajax_simple_response(dict(status="ko", respmsg=str(e)))
acs, scripts = sc.listscripts()
return ajax_simple_response(dict(
status="ok", respmsg=_("Filters set deleted"), newfs=acs
))
status="ok", respmsg=_("Filters set deleted"), newfs=acs
))
@login_required
@needs_mailbox()
def activate_filters_set(request, name):
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
try:
sc.activatescript(name)
@@ -240,10 +258,11 @@ def activate_filters_set(request, name):
return ajax_response(request, "ko", respmsg=str(e))
return ajax_response(request, respmsg=_("Filters set activated"))
@login_required
@needs_mailbox()
def download_filters_set(request, name):
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
try:
script = sc.getscript(name)
@@ -256,10 +275,11 @@ def download_filters_set(request, name):
resp["Content-Disposition"] = 'attachment; filename="%s.txt"' % name
return resp
@login_required
@needs_mailbox()
def toggle_filter_state(request, setname, fname):
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
try:
fset = sc.getscript(setname, format="fset")
@@ -276,15 +296,16 @@ def toggle_filter_state(request, setname, fname):
sc.pushscript(setname, str(fset))
except SieveClientError, e:
return ajax_response(request, "ko", respmsg=str(e))
return ajax_simple_response({
"status" : "ok",
"label" : newstate,
"color" : color
})
"status": "ok",
"label": newstate,
"color": color
})
def move_filter(request, setname, fname, direction):
sc = SieveClient(user=request.user.username,
sc = SieveClient(user=request.user.username,
password=request.session["password"])
try:
fset = sc.getscript(setname, format="fset")
@@ -292,13 +313,17 @@ def move_filter(request, setname, fname, direction):
sc.pushscript(setname, str(fset))
except (SieveClientError), e:
return ajax_response(request, "ko", respmsg=str(e))
return ajax_response(request, template="sievefilters/guieditor.html", fs=fset)
return ajax_response(
request, template="sievefilters/guieditor.html", fs=fset
)
@login_required
@needs_mailbox()
def move_filter_up(request, setname, fname):
return move_filter(request, setname, fname, "up")
@login_required
@needs_mailbox()
def move_filter_down(request, setname, fname):
+1 -1
View File
@@ -644,7 +644,7 @@ def send_mail(request, posturl=None):
from email.mime.multipart import MIMEMultipart
from .forms import ComposeMailForm
from modoboa.lib.webutils import _render_to_string
from modoboa.auth.lib import get_password
from modoboa.lib.cryptutils import get_password
form = ComposeMailForm(request.POST)
editormode = parameters.get_user(request.user, "EDITOR")
+8 -6
View File
@@ -1,23 +1,24 @@
from modoboa.auth.lib import decrypt
from modoboa.lib.cryptutils import decrypt
class ConnectionsManager(type):
"""Singleton pattern implementation
This class is specialized in connection management.
"""
def __init__(cls, name, bases, dict):
super(ConnectionsManager, cls).__init__(name, bases, dict)
def __init__(cls, name, bases, ctx):
super(ConnectionsManager, cls).__init__(name, bases, ctx)
cls.instances = {}
def __call__(cls, **kwargs):
key = None
if kwargs.has_key("user"):
if "user" in kwargs:
key = kwargs["user"]
else:
return None
if not cls.instances.has_key(key):
if not key in cls.instances:
cls.instances[key] = None
if kwargs.has_key("password"):
if "password" in kwargs:
kwargs["password"] = decrypt(kwargs["password"])
if cls.instances[key] is None:
@@ -27,5 +28,6 @@ class ConnectionsManager(type):
cls.instances[key].refresh(key, kwargs["password"])
return cls.instances[key]
class ConnectionError(Exception):
pass