wip: UI refactoring

* Per object permissions
* Faster identities listing
* Possibility to filter on alias names
* fixes

see #204
This commit is contained in:
Antoine Nguyen
2012-05-02 17:11:29 +02:00
parent 32b3959f8e
commit d1b543c25d
10 changed files with 219 additions and 217 deletions
+1 -1
View File
@@ -1 +1 @@
[{"pk": 1, "model": "auth.group", "fields": {"name": "DomainAdmins", "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"], ["add_mailbox", "admin", "mailbox"], ["change_mailbox", "admin", "mailbox"], ["delete_mailbox", "admin", "mailbox"], ["add_alias", "admin", "alias"], ["change_alias", "admin", "alias"], ["delete_alias", "admin", "alias"], ["view_mailboxes", "admin", "mailbox"], ["view_aliases", "admin", "alias"], ["view_domaliases", "admin", "domainalias"], ["add_domainalias", "admin", "domainalias"], ["change_domainalias", "admin", "domainalias"], ["delete_domainalias", "admin", "domainalias"]]}},{"pk": 2, "model": "auth.group", "fields": {"name": "SimpleUsers", "permissions": []}},{"pk": 1, "model": "auth.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": false, "last_login": "2012-01-26 15:19:25", "groups": [], "user_permissions": [], "password": "{CRYPT}dTTsGDkA5ZHKg", "email": "", "date_joined": "2012-01-26 15:19:25"}}]
[{"pk": 1, "model": "auth.group", "fields": {"name": "DomainAdmins", "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"], ["add_mailbox", "admin", "mailbox"], ["change_mailbox", "admin", "mailbox"], ["delete_mailbox", "admin", "mailbox"], ["add_alias", "admin", "alias"], ["change_alias", "admin", "alias"], ["delete_alias", "admin", "alias"], ["view_mailboxes", "admin", "mailbox"], ["view_aliases", "admin", "alias"], ["view_domaliases", "admin", "domainalias"], ["add_domainalias", "admin", "domainalias"], ["change_domainalias", "admin", "domainalias"], ["delete_domainalias", "admin", "domainalias"]]}},{"pk": 2, "model": "auth.group", "fields": {"name": "SimpleUsers", "permissions": []}},{"pk": 1, "model": "auth.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": false, "last_login": "2012-01-26 15:19:25", "groups": [], "user_permissions": [], "password": "{CRYPT}dTTsGDkA5ZHKg", "email": "", "date_joined": "2012-01-26 15:19:25"}},{"pk": 1, "model": "admin.objectaccess", "fields": {"is_owner": false, "user": 1, "content_type": ["admin", "user"], "object_id": 1}}]
+47 -25
View File
@@ -95,8 +95,6 @@ class DomainForm(forms.ModelForm, DynamicForm):
for dalias in d.domainalias_set.all():
if not len(filter(lambda name: self.cleaned_data[name] == dalias.name,
self.cleaned_data.keys())):
events.raiseEvent("DomainAliasDeleted", dalias)
ungrant_access_to_object(dalias)
dalias.delete()
return d
@@ -114,7 +112,8 @@ class DlistForm(forms.ModelForm, DynamicForm):
model = Alias
fields = ("enabled",)
def __init__(self, *args, **kwargs):
def __init__(self, user, *args, **kwargs):
self.user = user
super(DlistForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = ['email', 'recipients', 'enabled']
@@ -138,12 +137,14 @@ class DlistForm(forms.ModelForm, DynamicForm):
def clean_email(self):
localpart, domname = split_mailbox(self.cleaned_data["email"])
try:
Domain.objects.get(name=domname)
domain = Domain.objects.get(name=domname)
except Domain.DoesNotExist:
raise forms.ValidationError(_("Domain does not exist"))
if not self.user.can_access(domain):
raise forms.ValidationError(_("You don't have access to this domain"))
return self.cleaned_data["email"]
def set_recipients(self, user):
def set_recipients(self):
"""Recipients dispatching
We make a difference between 'local' recipients (the ones hosted
@@ -166,7 +167,7 @@ class DlistForm(forms.ModelForm, DynamicForm):
except Domain.DoesNotExist:
domain = None
if domain:
if not user.can_access(domain):
if not self.user.can_access(domain):
raise PermDeniedException(v)
try:
mb = Mailbox.objects.get(domain=domain, address=local_part)
@@ -209,7 +210,8 @@ class ForwardForm(forms.ModelForm):
model = Alias
fields = ("enabled",)
def __init__(self, *args, **kwargs):
def __init__(self, user, *args, **kwargs):
self.user = user
super(ForwardForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = ['email', 'recipient', 'enabled']
if kwargs.has_key("instance"):
@@ -220,9 +222,11 @@ class ForwardForm(forms.ModelForm):
def clean_email(self):
localpart, domname = split_mailbox(self.cleaned_data["email"])
try:
Domain.objects.get(name=domname)
domain = Domain.objects.get(name=domname)
except Domain.DoesNotExist:
raise forms.ValidationError(_("Domain does not exist"))
if not self.user.can_access(domain):
raise forms.ValidationError(_("You don't have access to this domain"))
return self.cleaned_data["email"]
def clean_recipient(self):
@@ -235,7 +239,7 @@ class ForwardForm(forms.ModelForm):
raise forms.ValidationError(_("Local addresses are forbidden"))
return self.cleaned_data["recipient"]
def set_recipients(self, user):
def set_recipients(self):
pass
def save(self, commit=True):
@@ -286,32 +290,33 @@ class AccountFormGeneral(forms.ModelForm):
self.user = user
if user.group == "DomainAdmins":
del self.fields["role"]
return
else:
self.fields["role"].choices = \
[('', ugettext_lazy("Choose"))] + get_account_roles(user)
self.fields["role"].choices = \
[('', ugettext_lazy("Choose"))] + get_account_roles(user)
if kwargs.has_key("instance"):
if len(args) \
and (args[0].get("password1", "") == "" \
and args[0].get("password2", "") == ""):
self.fields["password1"].required = False
self.fields["password2"].required = False
u = kwargs["instance"]
if u.is_superuser:
role = "SuperAdmins"
else:
try:
role = u.groups.all()[0].name
except IndexError:
pass
self.fields["role"].initial = role
if user.group != "DomainAdmins":
u = kwargs["instance"]
if u.is_superuser:
role = "SuperAdmins"
else:
try:
role = u.groups.all()[0].name
except IndexError:
pass
self.fields["role"].initial = role
def clean_username(self):
from django.core.validators import validate_email
if not self.cleaned_data.has_key("role"):
return self.cleaned_data["username"]
if self.cleaned_data["role"] != "SimpleUsers":
return self.cleaned_data
return self.cleaned_data["username"]
validate_email(self.cleaned_data["username"])
return self.cleaned_data["username"]
@@ -326,7 +331,7 @@ class AccountFormGeneral(forms.ModelForm):
def save(self, commit=True):
account = super(AccountFormGeneral, self).save(commit=False)
if commit:
if self.cleaned_data.has_key("password1"):
if self.cleaned_data["password1"] != "":
account.set_password(self.cleaned_data["password1"])
account.save()
role = None
@@ -396,6 +401,10 @@ class AccountFormMail(forms.Form, DynamicForm):
self.cleaned_data["quota"])
grant_access_to_object(user, self.mb, is_owner=True)
events.raiseEvent("CreateMailbox", user, self.mb)
if user.is_superuser:
for admin in self.mb.domain.admins:
grant_access_to_object(admin, self.mb)
else:
if self.cleaned_data["email"] != self.mb.full_address:
if self.mb.rename_dir(domname, locpart):
@@ -426,6 +435,9 @@ class AccountFormMail(forms.Form, DynamicForm):
al.save([self.mb], [])
grant_access_to_object(user, al, is_owner=True)
events.raiseEvent("MailboxAliasCreated", user, al)
if user.is_superuser:
for admin in al.domain.admins:
grant_access_to_object(admin, al)
for alias in self.mb.alias_set.all():
if len(alias.get_recipients()) >= 2:
@@ -470,11 +482,21 @@ class AccountPermissionsForm(forms.Form, DynamicForm):
if not value in current_domains:
domain = Domain.objects.get(name=value)
grant_access_to_object(self.account, domain)
for mb in domain.mailbox_set.all():
grant_access_to_object(self.account, mb)
grant_access_to_object(self.account, mb.user)
for al in Alias.objects.filter(domain=domain):
grant_access_to_object(self.account, al)
for domain in self.account.get_domains():
if not len(filter(lambda name: self.cleaned_data[name] == domain.name,
self.cleaned_data.keys())):
ungrant_access_to_object(domain, self.account)
for mb in domain.mailbox_set.all():
ungrant_access_to_object(mb, self.account)
ungrant_access_to_object(mb.user, self.account)
for al in Alias.objects.filter(domain=domain):
ungrant_access_to_object(al, self.account)
class AccountForm(TabForms):
+47 -33
View File
@@ -7,20 +7,21 @@ from django.core.exceptions import ObjectDoesNotExist
class Migration(DataMigration):
def grant_access(self, orm, user, ct, obj, is_owner=False):
objaccess = orm["admin.ObjectAccess"](
user=user, content_type=ct, object_id=obj.id
)
objaccess.is_owner = is_owner
objaccess.save()
def forwards(self, orm):
"Write your forwards methods here."
superusers = orm.User.objects.filter(is_superuser=True)
superusers = orm["auth.User"].objects.filter(is_superuser=True)
if not len(superusers):
# Empty db, nothing to do
return
domadmins = orm.User.objects.filter(groups__name='DomainAdmins')
domains = orm.Domain.objects.all()
deferred_admin = []
domct = orm['contenttypes.ContentType'].objects.get(
app_label='admin', model='domain'
)
# 1: all superadmins must be able to access every defined
# object. (user, domain, domain alias, mailbox, alias)
try:
uct = orm['contenttypes.ContentType'].objects.get(
app_label='admin', model='user'
@@ -30,35 +31,48 @@ class Migration(DataMigration):
name='user', app_label='admin', model='user'
)
uct.save()
for account in orm["admin.User"].objects.all():
for i, su in enumerate(superusers):
self.grant_access(orm, su, uct, account, i == 0)
domct = orm['contenttypes.ContentType'].objects.get(
app_label='admin', model='domain'
)
for dom in orm["admin.Domain"].objects.all():
for i, su in enumerate(superusers):
self.grant_access(orm, su, domct, dom, i == 0)
dalct = orm['contenttypes.ContentType'].objects.get(
app_label='admin', model='domainalias'
)
for domalias in orm["admin.DomainAlias"].objects.all():
for i, su in enumerate(superusers):
self.grant_access(orm, su, dalct, domalias, i == 0)
mbct = orm['contenttypes.ContentType'].objects.get(
app_label='admin', model='mailbox'
)
for mb in orm["admin.Mailbox"].objects.all():
for i, su in enumerate(superusers):
self.grant_access(orm, su, mbct, mb, i == 0)
alct = orm['contenttypes.ContentType'].objects.get(
app_label='admin', model='alias'
)
for alias in orm["admin.Alias"].objects.all():
for i, su in enumerate(superusers):
self.grant_access(orm, su, alct, alias, i == 0)
for da in domadmins:
for i, su in enumerate(superusers):
objaccess = orm.ObjectAccess(
user=su, content_type=uct, object_id=da.id
)
if i == 0:
objaccess.is_owner = True
objaccess.save()
# 2: domain admins must have access to their domain's content
for da in orm["admin.User"].objects.filter(groups__name='DomainAdmins'):
dom = da.mailbox_set.all()[0].domain
objaccess = orm.ObjectAccess(
user=da, content_type=domct, object_id=dom.id, is_owner=True
)
objaccess.save()
deferred_admin += [dom]
for dom in domains:
for i, su in enumerate(superusers):
objaccess = orm.ObjectAccess(
user=su, content_type=domct, object_id=dom.id
)
if not dom in deferred_admin:
objaccess.is_owner = True
objaccess.save()
self.grant_access(orm, da, domct, dom)
for mb in dom.mailbox_set.all():
self.grant_access(orm, da, mbct, mb)
self.grant_access(orm, da, uct, mb.user)
for al in dom.alias_set.all():
self.grant_access(orm, da, alct, al)
def backwards(self, orm):
"Write your backwards methods here."
raise RuntimeError("Cannot revert this migration")
models = {
'admin.alias': {
+57 -40
View File
@@ -69,24 +69,19 @@ class User(DUser):
if fromuser == self:
raise AdminError(_("You can't delete your own account"))
if not fromuser.can_access(self):
raise PermDeniedException("You don't have access to this account")
if self.has_mailbox:
mb = self.mailbox_set.all()[0]
if not fromuser.can_access(mb.domain):
raise PermDeniedException(_("You don't have access to this domain"))
events.raiseEvent("DeleteMailbox", mb)
ungrant_access_to_object(mb)
if not fromuser.can_access(mb):
raise PermDeniedException(_("You don't have access to this mailbox"))
mb.delete(keepdir=keep_mb_dir)
elif not fromuser.can_access(self):
raise PermDeniedException(_("You don't have access to this account"))
owner = get_object_owner(self)
for ooentry in self.objectaccess_set.all():
if ooentry.is_owner:
if ooentry.content_object is not None:
grant_access_to_object(owner, ooentry.content_object, True)
else:
print "ORPHELIN!!!"
ooentry.delete()
for ooentry in self.objectaccess_set.filter(is_owner=True):
if ooentry.content_object is not None:
grant_access_to_object(owner, ooentry.content_object, True)
events.raiseEvent("AccountDeleted", self)
ungrant_access_to_object(self)
@@ -204,24 +199,22 @@ class User(DUser):
return False
return True
def get_identities(self):
from modoboa.lib.permissions import get_content_type
userct = get_content_type(self)
alct = get_content_type(Alias)
return self.objectaccess_set.filter(content_type__in=[userct, alct])
def get_domains(self):
"""Return the domains belonging to this user
The result is a ``QuerySet`` object, so this function can be used
to fill ``ModelChoiceField`` objects.
:param user: a ``User`` object
"""
if self.is_superuser:
return Domain.objects.all()
result = Domain.objects.filter(owners__user=self).distinct()
userct = self.get_content_type()
for entry in self.objectaccess_set.filter(content_type=userct):
if not entry.content_object.belongs_to_group('DomainAdmins'):
continue
result |= entry.content_object.get_domains().distinct()
return result
return Domain.objects.filter(owners__user=self)
def get_domaliases(self):
"""Return the domain aliases that belong to this user
@@ -327,6 +320,9 @@ class ObjectAccess(models.Model):
class Meta:
unique_together = (("user", "content_type", "object_id"),)
def __unicode__(self):
return "%s => %s (%s)" % (self.user, self.content_object, self.content_type)
class ObjectDates(models.Model):
"""Dates recording for admin objects
@@ -400,6 +396,10 @@ class Domain(DatesAware):
def mbalias_count(self):
return len(self.alias_set.all())
@property
def admins(self):
return [oa.user for oa in self.owners.filter(user__is_superuser=False)]
def create_dir(self):
if parameters.get_admin("CREATE_DIRECTORIES") == "yes":
path = "%s/%s" % (parameters.get_admin("STORAGE_PATH"), self.name)
@@ -421,17 +421,21 @@ class Domain(DatesAware):
self.name))
return True
def delete(self, *args, **kwargs):
keepdir = False
if kwargs.has_key("keepdir"):
keepdir = kwargs["keepdir"]
del kwargs["keepdir"]
# Not very optimized but currently, this is the simple way
# I've found to delete all related objects (mailboxes, users
# and aliases)!
# for mb in self.mailbox_set.all():
# mb.delete(keepdir=keepdir)
super(Domain, self).delete(*args, **kwargs)
def delete(self, keepdir=False):
from modoboa.lib.permissions import ungrant_access_to_object, ungrant_access_to_objects
if len(self.domainalias_set.all()):
events.raiseEvent("DomainAliasDeleted", self.domainalias_set.all())
ungrant_access_to_objects(self.domainalias_set.all())
if len(self.mailbox_set.all()):
events.raiseEvent("DeleteMailbox", self.mailbox_set.all())
ungrant_access_to_objects(self.mailbox_set.all())
if len(self.alias_set.all()):
events.raiseEvent("MailboxAliasDelete", self.alias_set.all())
ungrant_access_to_objects(self.alias_set.all())
events.raiseEvent("DeleteDomain", self)
ungrant_access_to_object(self)
super(Domain, self).delete()
if not keepdir:
self.delete_dir()
@@ -469,6 +473,12 @@ class DomainAlias(DatesAware):
def __unicode__(self):
return self.name
def delete(self):
from modoboa.lib.permissions import ungrant_access_to_object
events.raiseEvent("DomainAliasDeleted", self)
ungrant_access_to_object(self)
super(DomainAlias, self).delete()
class Mailbox(DatesAware):
address = models.CharField(
ugettext_lazy('address'), max_length=100,
@@ -668,16 +678,16 @@ class Mailbox(DatesAware):
self.save(username=line[1].strip(), name=name,
password=line[2].strip(), enabled=True)
def delete(self, *args, **kwargs):
keepdir = False
if kwargs.has_key("keepdir"):
keepdir = kwargs["keepdir"]
del kwargs["keepdir"]
def delete(self, keepdir=False):
from modoboa.lib.permissions import ungrant_access_to_object
events.raiseEvent("DeleteMailbox", self)
ungrant_access_to_object(self)
for alias in self.alias_set.all():
alias.mboxes.remove(self)
if len(alias.mboxes.all()) == 0:
alias.delete()
super(Mailbox, self).delete(*args, **kwargs)
super(Mailbox, self).delete()
if not keepdir:
self.delete_dir()
@@ -731,6 +741,13 @@ class Alias(DatesAware):
if not t in int_rcpts:
self.mboxes.remove(t)
def delete(self):
from modoboa.lib.permissions import ungrant_access_to_object
events.raiseEvent("MailboxAliasDeleted", self)
ungrant_access_to_object(self)
super(Alias, self).delete()
def get_recipients(self):
"""Return the recipients list
+15 -4
View File
@@ -183,6 +183,11 @@ class PermissionsTestCase(ModoTestCase):
fixtures = ["test_content.json"]
def setUp(self):
"""
FIXME: je n'arrive pas à générer des données de test incluant
déjà les permissions (cf. table ObjectAccess). C'est pour
cette raison que j'assigne le domaine test.com ici...
"""
from modoboa.lib.permissions import grant_access_to_object
super(PermissionsTestCase, self).setUp()
@@ -191,9 +196,13 @@ class PermissionsTestCase(ModoTestCase):
username=self.user.username, role="DomainAdmins",
is_active=self.user.is_active, email="user@test.com"
)
grant_access_to_object(User.objects.get(username="admin@test.com"),
Domain.objects.get(name="test.com"))
self.admin = User.objects.get(username="admin@test.com")
self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % self.admin.id, dict(
username=self.admin.username, role="DomainAdmins",
is_active=self.admin.is_active, email="admin@test.com",
password1="", password2="", domains="test.com"
))
def tearDown(self):
self.clt.logout()
@@ -224,7 +233,7 @@ class PermissionsTestCase(ModoTestCase):
self.assertEqual(self.clt.login(username="admin@test.com", password="toto"),
True)
admin = User.objects.get(username="admin@test.com")
values = dict(username="admin@test.com", first_name="Admin",
values = dict(username="admin@test.com", first_name="Admin", password1="", password2="",
is_active=True, email="admin@test.com")
self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % admin.id, values)
self.assertEqual(admin.group, "DomainAdmins")
@@ -247,4 +256,6 @@ class PermissionsTestCase(ModoTestCase):
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertNotEqual(response["Content-Type"], "application/json")
-3
View File
@@ -10,15 +10,12 @@ urlpatterns = patterns(
(r'^domains/delete/$', 'deldomain'),
(r'^domains/import/$', 'import_domains'),
(r'^mailboxes/search/$', 'mailboxes_search'),
(r'^settings/$', 'viewparameters'),
(r'^settings/parameters/$', 'viewparameters'),
(r'^settings/parameters/save/$', 'saveparameters'),
(r'^settings/extensions/$', 'viewextensions'),
(r'^settings/extensions/save/$', 'saveextensions'),
(r'^permissions/searchaccount/$', 'search_account'),
(r'^permissions/remove/$', 'remove_permission'),
(r'^identities/$', 'identities'),
+32 -82
View File
@@ -97,10 +97,9 @@ def editdomain(request, dom_id, tplname="admin/editdomainform.html"):
if not request.user.can_access(domain):
raise PermDeniedException(_("You can't edit this domain"))
domadmins = map(lambda oaccess: oaccess.user, domain.owners.all())
domadmins = filter(
lambda u: request.user.can_access(u) and not u.is_superuser,
domadmins
domain.admins
)
if not request.user.is_superuser:
domadmins = filter(lambda u: u.group == "DomainAdmins", domadmins)
@@ -137,37 +136,12 @@ def deldomain(request):
raise PermDeniedException(_("You can't delete this domain"))
if mb and mb.domain == dom:
raise AdminError(_("You can't delete your own domain"))
if len(dom.domainalias_set.all()):
events.raiseEvent("DomainAliasDeleted", dom.domainalias_set.all())
if len(dom.mailbox_set.all()):
events.raiseEvent("DeleteMailbox", dom.mailbox_set.all())
events.raiseEvent("DeleteDomain", dom)
ungrant_access_to_object(dom)
dom.delete(keepdir=keepdir)
msg = ungettext("Domain deleted", "Domains deleted", len(selection))
messages.info(request, msg, fail_silently=True)
return ajax_response(request)
@login_required
@permission_required("admin.view_mailboxes")
@check_domain_access
def mailboxes_search(request):
if request.method != "POST":
return
local_part, domain = split_mailbox(request.POST["search"])
query = Q(address__startswith=local_part)
if domain is not None and domain != "":
query &= Q(domain__name__startswith=domain)
if request.GET.has_key("domid"):
query = Q(domain=request.GET["domid"]) & query
elif not request.user.is_superuser:
query = Q(domain__in=request.user.get_domains()) & query
mboxes = Mailbox.objects.filter(query)
result = map(lambda mb: mb.full_address, mboxes)
return ajax_simple_response(result)
def _validate_alias(request, form, successmsg, tplname, commonctx, callback=None):
"""Alias validation
@@ -175,7 +149,7 @@ def _validate_alias(request, form, successmsg, tplname, commonctx, callback=None
"""
error = None
if form.is_valid():
form.set_recipients(request.user)
form.set_recipients()
try:
alias = form.save()
except IntegrityError:
@@ -202,11 +176,14 @@ def _new_alias(request, tplname, formclass, ctx, successmsg):
def callback(user, alias):
grant_access_to_object(user, alias, is_owner=True)
events.raiseEvent("MailboxAliasCreated", user, alias)
if user.is_superuser:
for admin in alias.domain.admins:
grant_access_to_object(admin, alias)
form = formclass(request.POST)
form = formclass(request.user, request.POST)
return _validate_alias(request, form, successmsg, tplname, ctx, callback)
form = formclass()
form = formclass(request.user)
ctx["form"] = form
return _render(request, tplname, ctx)
@@ -231,15 +208,15 @@ def newforward(request):
ForwardForm, ctx, _("Forward created"))
def _edit_alias(request, alias, tplname, formclass, ctx, successmsg):
if not request.user.can_access(alias.domain):
raise PermDeniedException(_("You do not have access to this domain"))
if not request.user.can_access(alias):
raise PermDeniedException(_("You do not have access to this alias"))
ctx.update(title=alias.full_address, action_label=_("Update"),
action_classes="submit")
if request.method == "POST":
form = formclass(request.POST, instance=alias)
form = formclass(request.user, request.POST, instance=alias)
return _validate_alias(request, form, successmsg, tplname, ctx)
form = formclass(instance=alias)
form = formclass(request.user, instance=alias)
ctx["form"] = form
return _render(request, tplname, ctx)
@@ -264,10 +241,8 @@ def _del_alias(request, msg, msgs):
selection = request.GET["selection"].split(",")
for alid in selection:
alias = Alias.objects.get(pk=alid)
if not request.user.can_access(alias.domain):
raise PermDeniedException(_("You do not have access to this domain"))
events.raiseEvent("MailboxAliasDeleted", alias)
ungrant_access_to_object(alias)
if not request.user.can_access(alias):
raise PermDeniedException(_("!"))
alias.delete()
msg = ungettext(msg, msgs, len(selection))
@@ -289,32 +264,29 @@ def delforward(request):
@login_required
@user_passes_test(lambda u: u.has_perm("auth.add_user") or u.has_perm("admin.add_alias"))
def identities(request, tplname='admin/identities.html'):
accounts_list = []
idents_list = request.user.get_identities()
squery = request.GET.get("searchquery", None)
mbalias_q = Q(domain__in=request.user.get_domains())
if squery:
accounts = User.objects.filter(username__contains=squery)
uct = get_content_type(User)
uids = idents_list.filter(content_type=uct).values_list("object_id", flat=True)
objects = [u for u in User.objects.filter(pk__in=uids, username__contains=squery)]
alct = get_content_type(Alias)
alids = idents_list.filter(content_type=alct).values_list("object_id", flat=True)
if squery.find('@') != -1:
local_part, domname = split_mailbox(squery)
mbaliases = Alias.objects.filter(address__contains=local_part,
domain__name__contains=domname)
q = Q(address__contains=local_part, domain__name__contains=domname)
else:
mbaliases = Alias.objects.filter(mbalias_q & Q(address__contains=squery))
q = Q(address__contains=squery)
objects += [al for al in Alias.objects.filter(Q(pk__in=alids) & q)]
else:
accounts = User.objects.all()
mbaliases = Alias.objects.filter(mbalias_q)
for account in accounts:
if request.user.can_access(account) or \
account.has_mailbox and request.user.can_access(account.mailbox_set.all()[0].domain):
accounts_list += [account]
for mbalias in mbaliases:
if len(mbalias.get_recipients()) >= 2 or \
not len(mbalias.mboxes.all()):
accounts_list += [mbalias]
objects = []
for oa in idents_list:
if oa.content_object:
objects.append(oa.content_object)
return render_listing(request, "identities", tplname,
objects=accounts_list, squery=squery)
objects=objects, squery=squery)
@login_required
@permission_required("auth.add_user")
@@ -332,7 +304,7 @@ def newaccount(request, tplname='admin/newaccount.html'):
def create_account(steps):
"""Account creation callback
Called when all the creation steps have been validated.
Called when all creation steps have been validated.
:param steps: the steps data
"""
@@ -343,7 +315,7 @@ def newaccount(request, tplname='admin/newaccount.html'):
events.raiseEvent("AccountCreated", account)
mailform = steps[1]["form"]
mailform.save(request.user, account)
mb = mailform.save(request.user, account)
ctx = dict(
title=_("New account"),
@@ -386,14 +358,11 @@ def newaccount(request, tplname='admin/newaccount.html'):
@transaction.commit_on_success
def editaccount(request, accountid, tplname="common/tabforms.html"):
account = User.objects.get(pk=accountid)
if not request.user.can_access(account):
raise PermDeniedException(_("You can't access this account"))
mb = None
if account.has_mailbox:
mb = account.mailbox_set.all()[0]
if not request.user.can_access(mb.domain):
raise PermDeniedException(_("You don't have access to this domain"))
else:
if not request.user.can_access(account):
raise PermDeniedException(_("You can't access this account"))
mb = None
instances = dict(general=account, mail=mb, perms=account)
events.raiseEvent("FillAccountInstances", request.user, account, instances)
@@ -440,25 +409,6 @@ def delaccount(request):
messages.info(request, msg, fail_silently=True)
return ajax_response(request)
@login_required
@permission_required("auth.add_account")
@check_domain_access
def search_account(request):
search = request.POST.get("search", None)
if search is None:
return ajax_simple_response([])
query = Q(username__startswith=search)
query &= Q(is_superuser=False)
if not request.user.has_perm("admin.add_domain"):
query &= Q(groups__name="SimpleUsers")
else:
query &= ~Q(groups__name__in=["DomainAdmins"])
users = User.objects.filter(query)
result = map(lambda u: u.username, users.all())
return ajax_simple_response(result)
@login_required
@permission_required("admin.add_domain")
def remove_permission(request):
+9 -2
View File
@@ -113,10 +113,17 @@ def modify_user_record(mailbox, oldmailbox):
u.save()
@events.observe("DeleteMailbox")
def remove_user_record(mailbox):
def remove_user_record(mailboxes):
from models import Users
from modoboa.admin.models import Mailbox
Users.objects.get(email=mailbox.full_address).delete()
if isinstance(mailboxes, Mailbox):
mailboxes = [mailboxes]
for mailbox in mailboxes:
try:
Users.objects.get(email=mailbox.full_address).delete()
except Users.DoesNotExist:
pass
@events.observe("GetStaticContent")
def extra_static_content(user):
+2 -1
View File
@@ -32,6 +32,8 @@ def inc_limit(user, lname):
pass
def dec_limit(user, lname):
if user is None:
return
try:
user.limitspool.dec_curvalue(lname)
except LimitsPool.DoesNotExist:
@@ -96,7 +98,6 @@ def dec_nb_mailboxes(mailboxes):
for mailbox in mailboxes:
owner = get_object_owner(mailbox)
dec_limit(owner, 'mailboxes_limit')
# FIXME: Gestion des alias ici
@events.observe('MailboxAliasCreated')
def inc_nb_mbaliases(user, mailboxalias):
+9 -26
View File
@@ -78,6 +78,15 @@ def ungrant_access_to_object(obj, user=None):
else:
ObjectAccess.objects.filter(content_type=ct, object_id=obj.id).delete()
def ungrant_access_to_objects(objects):
"""Cancel all accesses for a given objects list
:param objects: a list of objects inheriting from ``model.Model``
"""
for obj in objects:
ct = get_content_type(obj)
ObjectAccess.objects.filter(content_type=ct, object_id=obj.id).delete()
def get_object_owner(obj):
"""Return the unique owner of this object
@@ -90,29 +99,3 @@ def get_object_owner(obj):
except ObjectAccess.DoesNotExist:
return None
return entry.user
def check_domain_access(f):
"""Decorator to check if the current user can access a domain
This decorator only applies to url that contain a 'domid' or
'mbid' parameter. (for a direct access)
Raise a ``PermDeniedError`` if the current user can't view the
requested object.
"""
@wraps(f)
def dec(request, **kwargs):
if not request.user.is_superuser:
domain = None
domid = request.GET.get("domid", None)
if domid:
domain = Domain.objects.get(pk=domid)
else:
mbid = request.GET.get("mbid", None)
if mbid:
domain = Mailbox.objects.get(pk=mbid).domain
if domain and not request.user.can_access(domain):
raise PermDeniedError(_("You can't access this domain"))
return f(request, **kwargs)
return dec