wip: big refactoring

old userprefs application removed.
This commit is contained in:
Antoine Nguyen
2013-08-23 11:39:03 +02:00
parent 1353fe979c
commit 93d7cb50c3
27 changed files with 159 additions and 431 deletions
-4
View File
@@ -181,10 +181,6 @@ class User(AbstractBaseUser, PermissionsMixin):
return [{"name": "account", "label": _("account"), "type": "idt"},
{"name": self.group, "label": self.group, "type": "grp", "color": "info"}]
# @property
# def has_mailbox(self):
# return self.mailbox_set.count() != 0
@property
def fullname(self):
if self.first_name != u"":
+1 -1
View File
@@ -1,7 +1,7 @@
{% extends "twocols.html" %}{% load i18n core_tags libextras %}
{% block pagetitle %}{% trans "Settings" %}{% endblock %}
{% block html_head %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}userprefs/css/userprefs.css" />
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}core/css/userprefs.css" />
<script type="text/javascript" src="{{ STATIC_URL }}js/history.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/listing.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/twocols_nav.js"></script>
-6
View File
@@ -135,12 +135,6 @@ def uprefs_menu(selection, user):
"url": "preferences/",
"label": _("Preferences")},
]
# if user.has_mailbox:
# entries.insert(0, {"name": "forward",
# "class": "ajaxlink",
# "url": "forward/",
# "label": _("Forward")})
entries += events.raiseQueryEvent("UserMenuDisplay", "uprefs_menu", user)
entries = sorted(entries, key=lambda e: e["label"])
return render_to_string('common/menu.html', {
+1
View File
@@ -23,6 +23,7 @@ def dologin(request):
login(request, user)
if not form.cleaned_data["rememberme"]:
request.session.set_expiry(0)
events.raiseEvent("UserLoggedIn", request, form)
# if request.user.has_mailbox:
# request.session["password"] = encrypt(form.cleaned_data["password"])
+19 -15
View File
@@ -6,27 +6,29 @@ from django.template.loader import render_to_string
from modoboa.lib import events
from modoboa.lib.webutils import static_url
@events.observe("UserMenuDisplay")
def menu(target, user):
if target != "top_menu_middle":
return []
if not user.has_mailbox:
if not user.mailbox_set.count():
return []
return [
{"name" : "demo",
"label" : _("Test messages"),
"img" : static_url("pics/demo.png"),
"class" : "topdropdown",
"menu" : [
{"name" : "sendvirus",
"label" : _("Send virus"),
"url" : reverse("modoboa.demo.views.send_virus")},
{"name" : "sendspam",
"label" : _("Send spam"),
"url" : reverse("modoboa.demo.views.send_spam")}
]
{"name": "demo",
"label": _("Test messages"),
"img": static_url("pics/demo.png"),
"class": "topdropdown",
"menu": [
{"name": "sendvirus",
"label": _("Send virus"),
"url": reverse("modoboa.demo.views.send_virus")},
{"name": "sendspam",
"label": _("Send spam"),
"url": reverse("modoboa.demo.views.send_spam")}
]
}
]
]
@events.observe("GetAnnouncement")
def announcement(target):
@@ -35,13 +37,15 @@ def announcement(target):
return [txt]
return ""
@events.observe("PasswordChange")
def password_change(user):
return [user.id == 1]
@events.observe("GetStaticContent")
def get_static_content(user):
if not user.has_mailbox:
if not user.mailbox_set.count():
return []
return """<script type="text/javascript">
$(document).ready(function() {
+21 -1
View File
@@ -53,8 +53,14 @@ class AdminConsole(ModoExtension):
exts_pool.register_extension(AdminConsole, show=False)
@events.observe("ExtraUprefsRoutes")
def extra_routes():
return [(r'^user/forward/',
'modoboa.extensions.admin.views.user.forward'), ]
@events.observe("AdminMenuDisplay")
def menu(target, user):
def admin_menu(target, user):
if target != "top_menu":
return []
entries = []
@@ -73,6 +79,20 @@ def menu(target, user):
return entries
@events.observe("UserMenuDisplay")
def user_menu(target, user):
if target != "uprefs_menu":
return []
if not user.mailbox_set.count():
return []
return [
{"name": "forward",
"class": "ajaxlink",
"url": "forward/",
"label": ugettext_lazy("Forward")}
]
@events.observe("RoleChanged")
def grant_access_to_all_objects(user, role):
from django.contrib.contenttypes.models import ContentType
+4
View File
@@ -13,3 +13,7 @@ class AdminError(ModoboaException):
application.
"""
pass
class BadDestination(Exception):
pass
+36 -3
View File
@@ -6,12 +6,15 @@ from django.http import QueryDict
from modoboa.lib import events, parameters
from modoboa.lib.emailutils import split_mailbox
from modoboa.lib.permissions import get_account_roles
from modoboa.lib.formutils import *
from modoboa.lib.formutils import (
DomainNameField, YesNoField, DynamicForm, TabForms
)
from modoboa.lib.exceptions import PermDeniedException
from modoboa.core.models import User
from modoboa.extensions.admin.templatetags.admin_tags import gender
from modoboa.extensions.admin.exceptions import AdminError
from modoboa.extensions.admin.exceptions import AdminError, BadDestination
from modoboa.extensions.admin.models import (
Domain, DomainAlias, Mailbox, Alias
Domain, DomainAlias, Mailbox, Alias, Quota
)
@@ -670,3 +673,33 @@ class AccountForm(TabForms):
return
for f in self.forms[2:]:
f["instance"].save()
class ForwardForm(forms.Form):
dest = forms.CharField(
label=ugettext_lazy("Recipient(s)"),
widget=forms.Textarea,
required=False,
help_text=ugettext_lazy("Indicate one or more recipients separated by a ','")
)
keepcopies = forms.BooleanField(
label=ugettext_lazy("Keep local copies"),
required=False,
help_text=ugettext_lazy("Forward messages and store copies into your local mailbox")
)
def parse_dest(self):
self.dests = []
rawdata = self.cleaned_data["dest"].strip()
if rawdata == "":
return
for d in rawdata.split(","):
local_part, domname = split_mailbox(d)
if not local_part or not domname or not len(domname):
raise BadDestination("Invalid mailbox syntax for %s" % d)
try:
mb = Domain.objects.get(name=domname)
except Domain.DoesNotExist:
self.dests += [d]
else:
raise BadDestination(_("You can't define a forward to a local destination. Please ask your administrator to create an alias instead."))
@@ -1,7 +1,7 @@
{% load i18n libextras %}{% load url from future %}
<h2>{% trans "Forward" %} <small>{% trans "Automatically forward emails to another address" %}</small></h2>
<hr>
<form class="form-horizontal" method="POST" action="{% url 'modoboa.userprefs.views.forward' %}"
<form class="form-horizontal" method="POST" action="{% url 'modoboa.extensions.admin.views.user.forward' %}"
id="uprefs_form">{% csrf_token %}
{% render_form form %}
<div class="form-actions">
+68
View File
@@ -0,0 +1,68 @@
from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _
from modoboa.lib.exceptions import ModoboaException
from modoboa.lib.webutils import (
ajax_response, ajax_simple_response, _render_to_string
)
from modoboa.extensions.admin.lib import needs_mailbox
from modoboa.extensions.admin.exceptions import BadDestination
from modoboa.extensions.admin.models import Alias, Mailbox
from modoboa.extensions.admin.forms import ForwardForm
@login_required
@needs_mailbox()
def forward(request, tplname='admin/forward.html'):
try:
mb = request.user.mailbox_set.all()[0]
except IndexError:
raise ModoboaException(
_("You need a mailbox in order to define a forward")
)
try:
al = Alias.objects.get(address=mb.address,
domain__name=mb.domain.name)
except Alias.DoesNotExist:
al = None
if request.method == "POST":
form = ForwardForm(request.POST)
error = None
if form.is_valid():
try:
if al is None:
al = Alias()
al.address = mb.address
al.domain = mb.domain
al.enabled = mb.user.is_active
intdests = []
if form.cleaned_data["keepcopies"]:
intdests += [mb]
form.parse_dest()
al.save(intdests, form.dests)
if request.user.group != "SimpleUsers":
al.post_create(request.user)
return ajax_response(request, respmsg=_("Forward updated"))
except BadDestination, e:
error = str(e)
return ajax_simple_response(dict(
status="ko",
errors=form.errors,
respmsg=error
))
form = ForwardForm()
if al is not None:
form.fields["dest"].initial = al.extmboxes
try:
selfmb = al.mboxes.get(pk=mb.id)
except Mailbox.DoesNotExist:
pass
else:
form.fields["keepcopies"].initial = True
return ajax_simple_response({
"status": "ok",
"content": _render_to_string(request, tplname, {
"form": form
})
})
@@ -71,7 +71,7 @@ class Command(BaseCommand):
self.listingurl = self.baseurl + reverse("modoboa.extensions.amavis.views._listing") + "?viewrequests=1"
for da in User.objects.filter(groups__name="DomainAdmins"):
if not da.has_mailbox:
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())
@@ -84,7 +84,7 @@ class Command(BaseCommand):
print "No release request currently pending"
return
for su in User.objects.filter(is_superuser=True):
if not su.has_mailbox:
if not su.mailbox_set.count():
continue
rcpt = su.mailbox_set.all()[0].full_address
self.send_pr_notification(rcpt, reqs)
+1 -1
View File
@@ -155,7 +155,7 @@ def viewmail(request, mail_id):
else:
rcpt = None
if request.user.has_mailbox:
if request.user.mailbox_set.count():
mb = Mailbox.objects.get(user=request.user)
if not rcpt or rcpt == mb.full_address:
msgrcpt = get_wrapper().get_recipient_message(mb.full_address, mail_id)
+2 -2
View File
@@ -33,7 +33,7 @@ def menu(target, user):
return [
{"name": "sievefilters",
"label": _("Message filters"),
"url": reverse("modobooa.extensions.sievefilters.views.index"),
"url": reverse("modoboa.extensions.sievefilters.views.index"),
"img": "icon-check"}
]
@@ -42,7 +42,7 @@ def menu(target, user):
def userlogout(request):
from .lib import SieveClient
if not request.user.has_mailbox:
if not request.user.mailbox_set.count():
return
try:
sc = SieveClient(user=request.user.username,
+1 -1
View File
@@ -43,7 +43,7 @@ def userlogout(request):
from .lib import IMAPconnector
from .exceptions import ImapError
if not request.user.has_mailbox:
if not request.user.mailbox_set.count():
return
try:
m = IMAPconnector(user=request.user.username,
+1 -1
View File
@@ -142,4 +142,4 @@ class UserSettings(UserParametersForm):
@staticmethod
def has_access(user):
return user.has_mailbox
return user.mailbox_set.count() != 0
+1 -1
View File
@@ -32,7 +32,7 @@ TwocolsNav.prototype = {
},
display_errors: function(data) {
if (data.errors == undefined) {
if (data.errors === undefined || !data.errors.length) {
if (data.respmsg) {
$("body").notify("error", data.respmsg);
}
-20
View File
@@ -1,20 +0,0 @@
# coding: utf-8
from django.utils.translation import ugettext_lazy
from modoboa.extensions import ModoExtension, exts_pool
from modoboa.lib import parameters
class UserPreferences(ModoExtension):
name = "userprefs"
label = ugettext_lazy("User preferences")
version = "1.0"
description = ugettext_lazy("Per-user settings")
always_active = True
def load(self):
from app_settings import UserSettings
parameters.register(UserSettings, ugettext_lazy("General"))
def destroy(self):
parameters.unregister()
exts_pool.register_extension(UserPreferences, show=False)
-28
View File
@@ -1,28 +0,0 @@
# coding: utf-8
from django import forms
from django.utils.translation import ugettext_lazy
from django.conf import settings
from modoboa.lib.parameters import UserParametersForm
from modoboa.lib.formutils import SeparatorField
def translate_language_code(value):
if "-" in value:
return value.split("-")[0]
return value
class UserSettings(UserParametersForm):
app = "general"
sep = SeparatorField(label=ugettext_lazy("Display"))
lang = forms.ChoiceField(
initial=translate_language_code(settings.LANGUAGE_CODE),
label=ugettext_lazy("Prefered language"),
choices=[("de", "deutsch"), ("en", "english"),
("es", "español"), ("fr", "français"),
("it", "italiano"), ("pt", "português"),
("sv", "svenska"),],
help_text=ugettext_lazy("Prefered language to display pages")
)
-85
View File
@@ -1,85 +0,0 @@
# coding: utf-8
from django import forms
from django.utils.translation import ugettext as _, ugettext_lazy
from modoboa.admin.models import User, Domain
from modoboa.lib.emailutils import split_mailbox
from modoboa.lib import parameters
class BadDestination(Exception):
pass
class ProfileForm(forms.ModelForm):
oldpassword = forms.CharField(label=ugettext_lazy("Old password"), required=False,
widget=forms.PasswordInput)
newpassword = forms.CharField(label=ugettext_lazy("New password"), required=False,
widget=forms.PasswordInput)
confirmation = forms.CharField(label=ugettext_lazy("Confirmation"), required=False,
widget=forms.PasswordInput)
class Meta:
model = User
fields = ("first_name", "last_name")
def __init__(self, update_password, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
if not update_password:
del self.fields["oldpassword"]
del self.fields["newpassword"]
del self.fields["confirmation"]
def clean_oldpassword(self):
if self.cleaned_data["oldpassword"] == "":
return self.cleaned_data["oldpassword"]
if parameters.get_admin("AUTHENTICATION_TYPE", app="admin") != "local":
return self.cleaned_data["oldpassword"]
if not self.instance.check_password(self.cleaned_data["oldpassword"]):
raise forms.ValidationError(_("Old password mismatchs"))
return self.cleaned_data["oldpassword"]
def clean_confirmation(self):
if self.cleaned_data["newpassword"] != self.cleaned_data["confirmation"]:
raise forms.ValidationError(_("Passwords mismatch"))
return self.cleaned_data["confirmation"]
def save(self, commit=True):
user = super(ProfileForm, self).save(commit=False)
if commit:
if self.cleaned_data.has_key("confirmation") and \
self.cleaned_data["confirmation"] != "":
user.set_password(self.cleaned_data["confirmation"], self.cleaned_data["oldpassword"])
user.save()
return user
class ForwardForm(forms.Form):
dest = forms.CharField(
label=ugettext_lazy("Recipient(s)"),
widget=forms.Textarea,
required=False,
help_text=ugettext_lazy("Indicate one or more recipients separated by a ','")
)
keepcopies = forms.BooleanField(
label=ugettext_lazy("Keep local copies"),
required=False,
help_text=ugettext_lazy("Forward messages and store copies into your local mailbox")
)
def parse_dest(self):
self.dests = []
rawdata = self.cleaned_data["dest"].strip()
if rawdata == "":
return
for d in rawdata.split(","):
local_part, domname = split_mailbox(d)
if not local_part or not domname or not len(domname):
raise BadDestination("Invalid mailbox syntax for %s" % d)
try:
mb = Domain.objects.get(name=domname)
except Domain.DoesNotExist:
self.dests += [d]
else:
raise BadDestination(_("You can't define a forward to a local destination. Please ask your administrator to create an alias instead."))
@@ -1,21 +0,0 @@
{% extends "twocols.html" %}{% load i18n uprefs_extras libextras %}
{% block pagetitle %}{% trans "Settings" %}{% endblock %}
{% block html_head %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}userprefs/css/userprefs.css" />
<script type="text/javascript" src="{{ STATIC_URL }}js/history.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/listing.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/twocols_nav.js"></script>
<script type="text/javascript">
{{ extrajs|safe }}
$(document).ready(function() {
var userprefs = new TwocolsNav({
deflocation: "profile/",
formid: "uprefs_form",
divid: "uprefs_content",
reload_exceptions: ["profile"]
});
});
</script>
{% endblock %}
{% block leftcol %}<div class="well sidebar-nav">{% uprefs_menu left_selection user %}</div>{% endblock %}
{% block apparea %}<div id="uprefs_content"></div>{% endblock %}
@@ -1,9 +0,0 @@
{% load i18n %}{% load url from future %}
<h2>{% trans "Preferences" %} <small>{% trans "Customize Modoboa" %}</small></h2>
<hr>
<form class="form-horizontal" method="POST" action="{% url 'modoboa.userprefs.views.preferences' %}"
id="uprefs_form">{% csrf_token %}
{% include "common/parameters.html" %}
<hr>
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Save' %}</button>
</form>
@@ -1,10 +0,0 @@
{% load i18n libextras %}{% load url from future %}
<h2>{% trans "Profile" %} <small>{% trans "Update your personal information" %}</small></h2>
<hr>
<form class="form-horizontal" method="POST" action="{% url 'modoboa.userprefs.views.profile' %}"
id="uprefs_form">{% csrf_token %}
{% render_form form %}
<div class="form-actions">
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Update' %}</button>
</div>
</form>
@@ -1,70 +0,0 @@
# coding: utf-8
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 import events
register = template.Library()
@register.simple_tag
def uprefs_menu(selection, user):
entries = [
{"name": "profile",
"class": "ajaxlink",
"url": "profile/",
"label": _("Profile")},
{"name": "preferences",
"class": "ajaxlink",
"url": "preferences/",
"label": _("Preferences")},
]
if user.has_mailbox:
entries.insert(0, {"name": "forward",
"class": "ajaxlink",
"url": "forward/",
"label": _("Forward")})
entries += events.raiseQueryEvent("UserMenuDisplay", "uprefs_menu", user)
entries = sorted(entries, key=lambda e: e["label"])
return render_to_string('common/menu.html', {
"entries": entries,
"css": "nav nav-list",
"selection": selection,
"user": user
})
@register.simple_tag
def user_menu(user, selection):
entries = [
{"name": "user",
"img": "icon-user icon-white",
"label": user.fullname,
"menu": [
{"name": "settings",
"img": "icon-list",
"label": _("Settings"),
"url": reverse("modoboa.userprefs.views.index")}
]}
]
entries[0]["menu"] += \
events.raiseQueryEvent("UserMenuDisplay", "options_menu", user) \
+ [{"name": "logout",
"url": reverse("modoboa.auth.views.dologout"),
"label": _("Logout"),
"img": "icon-off"}]
return render_to_string("common/menulist.html", {
"selection": selection, "entries": entries, "user": user
})
@register.simple_tag
def loadextmenu(selection, user):
menu = events.raiseQueryEvent("UserMenuDisplay", "top_menu", user)
return render_to_string('common/menulist.html', {
"selection": selection, "entries": menu, "user": user
})
-14
View File
@@ -1,14 +0,0 @@
# coding: utf-8
from django.conf.urls import patterns, url
from modoboa.lib import events
urlpatterns = patterns('modoboa.userprefs.views',
url(r'^$', 'index'),
(r'^preferences/$', 'preferences'),
(r'^profile/$', 'profile'),
(r'^forward/$', 'forward'),
)
urlpatterns += patterns('',
*events.raiseQueryEvent("ExtraUprefsRoutes")
)
-135
View File
@@ -1,135 +0,0 @@
# coding: utf-8
from django.shortcuts import render
from django.contrib.auth.decorators import login_required, user_passes_test
from django.utils.translation import ugettext as _
from modoboa.lib import parameters, events
from modoboa.lib.decorators import needs_mailbox
from modoboa.lib.exceptions import ModoboaException
from modoboa.lib.webutils import (
ajax_response, ajax_simple_response, _render_to_string
)
from modoboa.admin.models import Mailbox, Alias
from modoboa.auth.lib import encrypt
from forms import ForwardForm, BadDestination, ProfileForm
@login_required
def index(request, tplname="userprefs/index.html"):
extrajs = events.raiseQueryEvent("ExtraUprefsJS", request.user)
return render(request, tplname, {
"selection": "user",
"extrajs": "".join(extrajs)
})
@login_required
@needs_mailbox()
def forward(request, tplname='userprefs/forward.html'):
try:
mb = request.user.mailbox_set.all()[0]
except IndexError:
raise ModoboaException(
_("You need a mailbox in order to define a forward")
)
try:
al = Alias.objects.get(address=mb.address,
domain__name=mb.domain.name)
except Alias.DoesNotExist:
al = None
if request.method == "POST":
form = ForwardForm(request.POST)
error = None
if form.is_valid():
try:
if al is None:
al = Alias()
al.address = mb.address
al.domain = mb.domain
al.enabled = mb.user.is_active
intdests = []
if form.cleaned_data["keepcopies"]:
intdests += [mb]
form.parse_dest()
al.save(intdests, form.dests)
if request.user.group != "SimpleUsers":
al.post_create(request.user)
return ajax_response(request, respmsg=_("Forward updated"))
except BadDestination, e:
error = str(e)
return ajax_simple_response(dict(
status="ko",
errors=form.errors,
respmsg=error
))
form = ForwardForm()
if al is not None:
form.fields["dest"].initial = al.extmboxes
try:
selfmb = al.mboxes.get(pk=mb.id)
except Mailbox.DoesNotExist:
pass
else:
form.fields["keepcopies"].initial = True
return ajax_simple_response({
"status": "ok",
"content": _render_to_string(request, tplname, {
"form": form
})
})
@login_required
def profile(request, tplname='userprefs/profile.html'):
update_password = True
if True in events.raiseQueryEvent("PasswordChange", request.user):
update_password = False
if request.method == "POST":
form = ProfileForm(
update_password, request.POST, instance=request.user
)
if form.is_valid():
form.save()
if update_password and form.cleaned_data["confirmation"] != "":
request.session["password"] = encrypt(form.cleaned_data["confirmation"])
return ajax_simple_response(dict(
status="ok", respmsg=_("Profile updated")
))
return ajax_simple_response({
"status": "ko",
"errors": form.errors
})
form = ProfileForm(update_password, instance=request.user)
return ajax_simple_response({
"status": "ok",
"content": _render_to_string(request, tplname, {
"form": form
})
})
@login_required
def preferences(request):
if request.method == "POST":
for formdef in parameters.get_user_forms(request.user, request.POST)():
form = formdef["form"]
if form.is_valid():
form.save()
continue
return ajax_simple_response({
"status": "ko", "prefix": form.app, "errors": form.errors
})
return ajax_simple_response({
"status": "ok", "respmsg": _("Preferences saved")
})
return ajax_simple_response({
"status": "ok",
"content": _render_to_string(request, "userprefs/preferences.html", {
"forms": parameters.get_user_forms(request.user)
})
})