wip: resellers and limits

I've finally started to rethink the database structure. The goal I'm trying to reach: only use User objects to manage permissions and accesses to the webui and associate other objects to them if needed (like mailboxes).

see #105
This commit is contained in:
Antoine Nguyen
2012-01-20 17:33:05 +01:00
parent 2a0e9fdf3a
commit 3681bb4198
41 changed files with 1311 additions and 478 deletions
+2 -2
View File
@@ -51,13 +51,13 @@ parameters.register_admin("DEFAULT_TOP_REDIRECTION", type="list", deflt="admin",
values=enabled_applications(),
help=_("The default redirection used when no application is specified"))
def unset_default_topredirection(**kwargs):
def unset_default_topredirection(extension):
"""
Simple callback to change the default redirection if the
corresponding extension is being disabled.
"""
topredirection = parameters.get_admin("DEFAULT_TOP_REDIRECTION", app="general")
if topredirection == kwargs["ext"].name:
if topredirection == extension.name:
parameters.save_admin("DEFAULT_TOP_REDIRECTION", "userprefs", app="general")
def update_available_applications(extension):
+1 -1
View File
@@ -1 +1 @@
[{"pk": 1, "model": "auth.group", "fields": {"name": "DomainAdmins", "permissions": [["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_domain", "admin", "domain"], ["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": 1, "model": "auth.group", "fields": {"name": "DomainAdmins", "permissions": [["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_domain", "admin", "domain"], ["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": []}}]
+112 -48
View File
@@ -7,6 +7,7 @@ from django.contrib.auth.models import User
from modoboa.admin.templatetags.admin_extras import gender
from modoboa.lib import tables
from modoboa.lib.emailutils import split_mailbox
from lib import get_user_domains
class DomainForm(forms.ModelForm):
class Meta:
@@ -32,10 +33,10 @@ class ProxyForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super(ProxyForm, self).__init__(*args, **kwargs)
if user.is_superuser:
self._domain = None
if not user.is_superuser:
self._domains = Domain.objects.filter(owners__user=user)
else:
self._domain = user.mailbox_set.all()[0].domain
self._domains = None
class DomainAliasForm(ProxyForm):
class Meta:
@@ -44,8 +45,9 @@ class DomainAliasForm(ProxyForm):
def __init__(self, *args, **kwargs):
super(DomainAliasForm, self).__init__(*args, **kwargs)
if self._domain is not None:
self.fields["target"].queryset = Domain.objects.filter(pk=self._domain.id)
if self._domains is not None:
#self.fields["target"].queryset = Domain.objects.filter(pk=self._domain.id)
self.fields["target"].queryset = self._domains
class MailboxForm(ProxyForm):
quota = forms.IntegerField(label=ugettext_noop("Quota"), required=False,
@@ -68,9 +70,10 @@ class MailboxForm(ProxyForm):
super(MailboxForm, self).__init__(*args, **kwargs)
for f in ['name', 'address', 'quota', 'password1', 'password2']:
self.fields[f].widget.attrs['size'] = 14
if self._domain is not None:
self.fields["domain"].queryset = Domain.objects.filter(pk=self._domain.id)
self.fields["domain"].initial = self._domain
if self._domains is not None:
self.fields["domain"].queryset = self._domains
#self.fields["domain"].queryset = Domain.objects.filter(pk=self._domain.id)
#self.fields["domain"].initial = self._domain
if kwargs.has_key("instance"):
self.fields['quota'].initial = kwargs["instance"].quota
@@ -111,22 +114,26 @@ class AliasForm(ProxyForm):
# member of Alias, we need to fill it manually. if
# self._domain exists, it means a DomainAdmin is going to
# create a new alias, we know how to fill the fields.
if self._domain is not None:
self.fields["domain"].queryset = Domain.objects.filter(pk=self._domain.id)
# if self._domain is not None:
# self.fields["domain"].queryset = Domain.objects.filter(pk=self._domain.id)
if self._domains is not None:
self.fields["domain"].queryset = self._domains
# if 'instance' exists, it means we are modifying an existing
# record, we need to select the right value for 'domain' and
# to fill the first "targets" input (because it is created by the
# Form object, not by us).
domain = None
if self._domain:
domain = self._domain
#domain = None
# if self._domain:
# domain = self._domain
if kwargs.has_key("instance"):
if self._domain is None:
domain = kwargs["instance"].domain
# if self._domain is None:
# domain = kwargs["instance"].domain
self.fields["targets"].initial = kwargs["instance"].first_target()
if domain is not None:
self.fields["domain"].initial = domain
# if domain is not None:
# self.fields["domain"].initial = domain
self.fields.keyOrder = ['address', 'domain', 'enabled', 'targets']
@@ -140,33 +147,37 @@ class AliasForm(ProxyForm):
return self.cleaned_data["address"]
def set_targets(self, user, values):
"""Targets dispatching
We make a difference between 'local' targets (the ones hosted
by Modoboa) and 'external targets.
"""
from modoboa.admin.lib import is_object_owner
self.ext_targets = []
self.int_targets = []
if user.id != 1:
umb = Mailbox.objects.get(user=user)
for addr in values:
if addr == "":
continue
local_part, domain = split_mailbox(addr)
if domain is None:
local_part, domname = split_mailbox(addr)
if domname is None:
raise AdminError("%s %s" % (_("Invalid mailbox"), addr))
if is_domain_admin(user) and umb.domain.name != domain:
try:
d = Domain.objects.get(name=domain)
except Domain.DoesNotExist:
pass
else:
raise AdminError("%s %s" % (_("Access denied for"), addr))
try:
mb = Mailbox.objects.get(address=local_part, domain__name=domain)
except Mailbox.DoesNotExist:
self.ext_targets += [addr]
else:
if not user.is_superuser:
usermb = Mailbox.objects.get(user=user.id)
if usermb.domain.id != mb.domain.id:
raise AdminError("%s %s" % (_("Permission denied on"), addr))
domain = Domain.objects.get(name=domname)
except Domain.DoesNotExist:
domain = None
if domain:
if not is_object_owner(user, domain):
raise PermDeniedException(addr)
try:
mb = Mailbox.objects.get(domain=domain, address=local_part)
except Mailbox.DoesNotExist:
raise AdminError(_("Mailbox %s does not exist" % addr))
self.int_targets += [mb]
continue
self.ext_targets += [addr]
def save(self, force_insert=False, force_update=False, commit=True):
a = super(AliasForm, self).save(commit=False)
@@ -186,19 +197,72 @@ class SuperAdminForm(forms.Form):
self.fields["user"].queryset = User.objects.exclude(pk__in=[1, user.id])
class DomainAdminForm(forms.Form):
def __init__(self, *args, **kwargs):
super(DomainAdminForm, self).__init__(*args, **kwargs)
createfrom = forms.ChoiceField(
choices=[("new", ugettext_noop("Create a new account")),
("select", ugettext_noop("Promote an existing account"))],
widget=forms.RadioSelect)
self.fields["domain"] = \
forms.ModelChoiceField(queryset=Domain.objects.all(),
label=_("Domain"),
required=True,
empty_label=_("Select a domain"),
help_text=_("Select a domain in the list"))
self.fields["user"] = \
forms.ChoiceField(label=_("User"), required=True,
choices=[("", _("Empty"))],
help_text=_("Select a user in the list"))
domain = forms.ModelChoiceField(
queryset=Domain.objects.all(),
label=_("Domain"),
required=True,
empty_label=ugettext_noop("Select a domain"),
help_text=ugettext_noop("Select a domain in the list")
)
user = forms.ChoiceField(
label=ugettext_noop("User"), required=True,
choices=[("", ugettext_noop("Empty"))],
help_text=ugettext_noop("Select a user in the list"))
class UserForm(forms.ModelForm):
createmb = forms.BooleanField(
label=ugettext_noop("Create mailbox"), required=False,
help_text=ugettext_noop("Create a mailbox for this user using the given address")
)
class Meta:
model = User
fields = ("username", "first_name", "last_name", "email")
def save(self, commit=True, group=None):
user = super(UserForm, self).save(commit=False)
if self.cleaned_data.has_key("password1"):
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
if group:
user.groups.add(Group.objects.get(name=group))
user.save()
return user
class UserWithPasswordForm(UserForm):
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(
label=ugettext_noop("Confirmation"),
widget=forms.PasswordInput,
help_text=ugettext_noop("Enter the same password as above, for verification.")
)
def clean_password2(self):
password1 = self.cleaned_data.get("password1", "")
password2 = self.cleaned_data["password2"]
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
class DomainAdminPromotionForm(forms.Form):
name = forms.CharField(
label=ugettext_noop("Name"),
help_text=ugettext_noop("The username/email address/name of the account to promote")
)
def clean_name(self):
try:
u = User.objects.get(username=self.cleaned_data["name"])
except User.DoesNotExist:
raise forms.ValidationError(_("Unknown user"))
return self.cleaned_data["name"]
class ImportDataForm(forms.Form):
sourcefile = forms.FileField(label=_("Select a file"))
+112
View File
@@ -1,12 +1,21 @@
# coding: utf-8
from functools import wraps
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.models import User, Group
from django.utils.translation import ugettext as _
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from models import *
from modoboa.lib.exceptions import ModoboaException
from modoboa.lib.webutils import _render_error, _render
from modoboa.admin.tables import *
class AdminError(ModoboaException):
"""
Just a Custom exception to identify errors coming from the admin
application.
"""
pass
def is_not_localadmin(errortpl="error"):
def dec(f):
def wrapped_f(request, *args, **kwargs):
@@ -46,6 +55,7 @@ def good_domain(f):
def dec(request, **kwargs):
if request.user.is_superuser:
return f(request, **kwargs)
if is_domain_admin(request.user):
mb = Mailbox.objects.get(user=request.user.id)
access = True
@@ -67,6 +77,18 @@ def good_domain(f):
return HttpResponseRedirect("%s?next=%s" % (login_url, path))
return dec
# def has_access_to_domain(user, domain):
# """
# """
# access = events.raiseQueryEvent("CanViewDomain", user, domain)
# if True in access:
# return True
# if is_domain_admin(user):
# mb = Mailbox.objects.get(user=request.user.id)
# if mb.domain == domain:
# return True
# return False
def render_listing(request, objtype, tplname="admin/listing.html",
**kwargs):
"""Common function to render a listing
@@ -103,3 +125,93 @@ def render_listing(request, objtype, tplname="admin/listing.html",
kwargs["table"] = tblclass(request, kwargs["objects"].object_list)
return _render(request, tplname, kwargs)
def set_object_ownership(user, obj):
"""Simple shorcut to associate an object to a user
:param user: a ``User`` object
:param obj: an admin. object (Domain, Mailbox, ...)
"""
obj_owner = ObjectOwner(user=user, content_object=obj)
obj_owner.save()
def is_object_owner(user, obj):
"""Check if a user is the object's owner
An object can have multiple owners but this function only
concerns one given user.
:param user: a ``User`` object
:param obj: a admin object
:return: a boolean
"""
if user.is_superuser:
return True
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model=obj._meta.module_name)
for entry in qs.all():
if entry.content_object == obj:
return True
return False
def check_domain_ownership(f):
@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 is_object_owner(request.user, domain):
raise PermDeniedError(_("You can't access this domain"))
return f(request, **kwargs)
return dec
def get_user_domains(user):
if user.is_superuser:
return Domain.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
domains = []
for entry in qs.all():
domains += [entry.content_object]
return domains
def get_user_domaliases(user):
if user.is_superuser:
return DomainAlias.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
domaliases = []
for entry in qs.all():
domaliases += entry.content_object.domainalias_set.all()
return domaliases
def get_user_mailboxes(user):
if user.is_superuser:
return Mailbox.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
mboxes = []
for ro in qs.all():
mboxes += Mailbox.objects.filter(domain=ro.content_object)
return mboxes
def get_user_mbaliases(user):
if user.is_superuser:
return Alias.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
mbaliases = []
for ro in qs.all():
mbaliases += Alias.objects.filter(domain=ro.content_object)
return mbaliases
@@ -0,0 +1,125 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'ObjectOwner'
db.create_table('admin_objectowner', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),
))
db.send_create_signal('admin', ['ObjectOwner'])
def backwards(self, orm):
# Deleting model 'ObjectOwner'
db.delete_table('admin_objectowner')
models = {
'admin.alias': {
'Meta': {'object_name': 'Alias'},
'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'extmboxes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mboxes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['admin.Mailbox']", 'symmetrical': 'False'})
},
'admin.domain': {
'Meta': {'object_name': 'Domain'},
'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'quota': ('django.db.models.fields.IntegerField', [], {})
},
'admin.domainalias': {
'Meta': {'object_name': 'DomainAlias'},
'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"})
},
'admin.extension': {
'Meta': {'object_name': 'Extension'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '150'})
},
'admin.mailbox': {
'Meta': {'object_name': 'Mailbox'},
'address': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"}),
'gid': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'quota': ('django.db.models.fields.IntegerField', [], {}),
'uid': ('django.db.models.fields.IntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'admin.objectdates': {
'Meta': {'object_name': 'ObjectDates'},
'creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'admin.objectowner': {
'Meta': {'object_name': 'ObjectOwner'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['admin']
+23 -18
View File
@@ -1,31 +1,28 @@
# coding: utf-8
from django.db import models, IntegrityError
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.contrib.auth.models import User, Group
from django.utils.translation import ugettext as _, ugettext_noop
from django.conf import settings
from modoboa.lib import parameters, events
from modoboa.lib.sysutils import exec_cmd, exec_as_vuser
from modoboa.lib.emailutils import split_mailbox
from modoboa.lib.ldaputils import *
from modoboa.auth.lib import crypt_password
import os
import pwd
class AdminError(Exception):
"""Custom exception
try:
from modoboa.lib.ldaputils import *
ldap_available = True
except ImportError:
ldap_available = False
"""
def __init__(self, value):
"""Constructor
:param value: the information contained in this exception.
"""
self.value = str(value)
def __str__(self):
"""String representation"""
return self.value
class ObjectOwner(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class ObjectDates(models.Model):
"""Dates recording for admin objects
@@ -80,6 +77,7 @@ class Domain(DatesAware):
quota = models.IntegerField(help_text=ugettext_noop("Default quota in MB applied to mailboxes"))
enabled = models.BooleanField(ugettext_noop('enabled'),
help_text=ugettext_noop("Check to activate this domain"))
owners = generic.GenericRelation(ObjectOwner)
class Meta:
permissions = (
@@ -265,6 +263,10 @@ class Mailbox(DatesAware):
raise AdminError(_("Mailbox with this address already exists"))
self.user = user
if len(user.groups.all()) == 0:
user.groups.add(Group.objects.get(name="SimpleUsers"))
user.save()
if kwargs.has_key("password") and kwargs["password"] != u"é":
self.password = crypt_password(kwargs["password"])
# If we ever had numerical uid, don't resolve it
@@ -305,6 +307,8 @@ class Mailbox(DatesAware):
self.password = crypt_password(newvalue)
self.save()
return
if not ldap_available:
raise AdminError(_("Failed to update password: LDAP module not installed"))
ab = LDAPAuthBackend()
try:
@@ -456,11 +460,12 @@ class Alias(DatesAware):
return "<br/>".join(self.extmboxes.split(","))
def ui_disabled(self, user):
from modoboa.admin.lib import is_object_owner
if user.is_superuser:
return False
usermb = Mailbox.objects.get(user=user.id)
for mb in self.mboxes.all():
if mb.domain.id != usermb.domain.id:
if not is_object_owner(user, mb.domain):
return True
return False
+35 -38
View File
@@ -7,11 +7,15 @@ from modoboa.lib.webutils import _render, getctx, _render_to_string
from modoboa.lib import events
from forms import *
from tables import SuperAdminsTable, DomainAdminsTable
from lib import set_object_ownership
class Permissions(object):
submit_label = ugettext_noop("Add")
formtpl = 'admin/add_permission.html'
@staticmethod
def is_authorized(user):
return True
return user.is_superuser
def get_add_form(self, request):
raise NotImplementedError
@@ -25,21 +29,20 @@ class Permissions(object):
def get(self, request):
raise NotImplementedError
def _render_form(self, request, form, instring=False):
ctx = dict(form=form, title=self.title, submit_label=self.submit_label,
role=self.role)
if instring:
return _render_to_string(request, self.formtpl, ctx)
return _render(request, self.formtpl, ctx)
class SuperAdminsPerms(Permissions):
title = ugettext_noop("Add super administrator")
role = "super_admins"
@staticmethod
def is_authorized(user):
return user.is_superuser
def get_add_form(self, request):
form = SuperAdminForm(request.user)
return _render(request, 'admin/add_permission.html', {
"form" : form,
"title" : _(self.title),
"role": self.role
})
return self._render_form(request, form)
def add(self, request):
form = SuperAdminForm(request.user, request.POST)
@@ -51,11 +54,7 @@ class SuperAdminsPerms(Permissions):
user.save()
return True, None
content = _render_to_string(request, "admin/add_permission.html", {
"form" : form,
"title" : _(self.title),
"role" : self.role
})
content = self._render_form(request, form, True)
return False, getctx("ko", content=content)
def delete(self, selection):
@@ -81,22 +80,19 @@ class SuperAdminsPerms(Permissions):
class DomainAdminsPerms(Permissions):
title = ugettext_noop("Add domain administrator")
role = "domain_admins"
formtpl = 'admin/add_domain_admin.html'
@staticmethod
def is_authorized(user):
return user.has_perm("admin.view_domains")
def get_add_form(self, request):
form = DomainAdminForm()
return _render(request, 'admin/add_domain_admin.html', {
"form" : form,
"title" : _(self.title),
"role" : self.role
})
return self._render_form(request, form)
def add(self, request):
form = DomainAdminForm(request.POST)
if request.POST.has_key("user") and request.POST["user"] != "":
if request.POST.get("user", "") != "":
mboxid = request.POST['user']
mb = Mailbox.objects.get(pk=mboxid)
form.fields["user"].choices = [(mboxid, mb),]
@@ -105,27 +101,28 @@ class DomainAdminsPerms(Permissions):
mb.user.date_joined = datetime.datetime.now()
mb.user.groups.add(Group.objects.get(name="DomainAdmins"))
mb.user.save()
set_object_ownership(mb.user, mb.domain)
return True, None
content = _render_to_string(request, "admin/add_domain_admin.html", {
"form" : form,
"title" : _(self.title),
"role" : self.role
})
content = self._render_form(request, form, True)
return False, getctx("ko", content=content)
def delete(self, selection):
for s in selection:
mbox = Mailbox.objects.get(pk=int(s))
grp = Group.objects.get(name="DomainAdmins")
mbox.user.groups.remove(grp)
mbox.user.save()
User.objects.filter(id__in=selection).delete()
# for s in selection:
# user.delete()
# try:
# mbox = Mailbox.objects.get(pk=int(s))
# grp = Group.objects.get(name="DomainAdmins")
# mbox.user.groups.remove(grp)
# mbox.user.save()
def get(self, request):
domadmins = Mailbox.objects.filter(user__groups__name="DomainAdmins")
domadmins_list = []
for admin in domadmins:
domadmins_list += [admin.tohash()]
return DomainAdminsTable(request, domadmins_list).render()
#domadmins = Mailbox.objects.filter(user__groups__name="DomainAdmins")
domainadmins = User.objects.filter(groups__name="DomainAdmins")
# domadmins_list = []
# for admin in domadmins:
# domadmins_list += [admin.tohash()]
return DomainAdminsTable(request, domainadmins).render()
def get_perms_class(user, role):
"""Retrieves the class associated to a given role
@@ -150,7 +147,7 @@ def get_perms_class(user, role):
if globals()[cname].is_authorized(user):
return globals()[cname]
return None
res = events.raiseQueryEvent("PermsGetClass", role=role)
res = events.raiseQueryEvent("PermsGetClass", role)
if not len(res):
return None
return res[0]
+16 -5
View File
@@ -142,11 +142,22 @@ class SuperAdminsTable(tables.Table):
class DomainAdminsTable(tables.Table):
idkey = "id"
selection = tables.SelectionColumn("selection", width="4%", first=True)
domain = tables.Column("domain", label=ugettext_noop("Domain"))
full_name = tables.Column("full_name", label=ugettext_noop("Full name"))
selection = tables.SelectionColumn("selection", width="4%")
username = tables.Column("username", label=ugettext_noop("User name"))
first_name = tables.Column("first_name", label=ugettext_noop("First name"))
last_name = tables.Column("last_name", label=ugettext_noop("Last name"))
date_joined = tables.Column("date_joined", label=ugettext_noop("Defined"))
enabled = tables.Column("enabled", label=gender("Enabled", "m"), width="10%")
enabled = tables.Column("is_active", label=gender("Enabled", "m"), width="10%")
actions = tables.ActionColumn("actions", label=ugettext_noop("Actions"),
width="50px", align="center",
defvalue=domain_admin_actions)
cols_order = ["selection", "domain", "full_name", "date_joined", "enabled"]
cols_order = ["selection", "username", "first_name",
"last_name", "date_joined", "enabled", "actions"]
def __init__(self, request, users):
super(DomainAdminsTable, self).__init__(request)
self.populate(self._rows_from_model(users))
def parse_is_active(self, value):
return _("yes") if value else _("no")
+17
View File
@@ -199,6 +199,18 @@ def mailbox_actions(user, mboxid):
]
return render_actions(actions)
@register.simple_tag
def domain_admin_actions(user, daid):
actions = [
{"name" : "editdomainadmin",
"url" : reverse(admin.views.edit_domain_admin, args=[daid]),
"img" : static_url("pics/edit.png"),
"title" : _("Edit domain admin"),
"class" : "boxed",
"rel" : "{handler:'iframe',size:{x:350,y:320}}"},
]
return render_actions(actions)
@register.simple_tag
def mbalias_actions(user, aliasid):
from modoboa.admin.models import Alias
@@ -274,3 +286,8 @@ def gender(value, target):
if trans.find("_") == -1:
return trans
return value
@register.simple_tag
def get_footer_content(user, objtype):
res = events.raiseQueryEvent("AdminFooterDisplay", user, objtype)
return "".join(res)
+41 -36
View File
@@ -1,38 +1,43 @@
from django.conf.urls.defaults import *
urlpatterns = patterns('modoboa.admin.views',
url(r'^$', 'domains', name="index"),
url(r'^domains/$', 'domains', name="domains"),
(r'^domains/new/', 'newdomain'),
(r'^domains/(?P<dom_id>\d+)/edit/$', 'editdomain'),
(r'^domains/delete/$', 'deldomain'),
(r'^domains/import/$', 'importdata'),
(r'^domaliases/$', "domaliases"),
(r'^domaliases/new/', 'newdomalias'),
(r'^domaliases/edit/(?P<alias_id>\d+)/', 'editdomalias'),
(r'^domaliases/delete/$', 'deldomalias'),
(r'^mailboxes/$', 'mailboxes'),
(r'^mailboxes/new/$', 'newmailbox'),
(r'^mailboxes/edit/(?P<mbox_id>\d+)/$', 'editmailbox'),
(r'^mailboxes/delete/$', 'delmailbox'),
(r'^mailboxes/search/$', 'mailboxes_search'),
(r'^mbaliases/$', 'mbaliases'),
(r'^mbaliases/new/$', 'newmbalias'),
(r'^mbaliases/edit/(?P<alias_id>\d+)/$', 'editmbalias'),
(r'^mbaliases/delete/$', 'delmbalias'),
(r'^domains/(?P<dom_id>\d+)/rawmboxes/$', 'mailboxes_raw'),
(r'^settings/$', 'viewparameters'),
(r'^settings/parameters/$', 'viewparameters'),
(r'^settings/parameters/save/$', 'saveparameters'),
(r'^settings/extensions/$', 'viewextensions'),
(r'^settings/extensions/save/$', 'saveextensions'),
(r'^permissions/$', 'permissions'),
(r'^permissions/add/$', 'add_permission'),
(r'^permissions/delete/$', 'delete_permissions'),
)
urlpatterns = patterns(
'modoboa.admin.views',
url(r'^$', 'domains', name="index"),
url(r'^domains/$', 'domains', name="domains"),
(r'^domains/new/', 'newdomain'),
(r'^domains/(?P<dom_id>\d+)/edit/$', 'editdomain'),
(r'^domains/delete/$', 'deldomain'),
(r'^domains/import/$', 'importdata'),
(r'^domaliases/$', "domaliases"),
(r'^domaliases/new/', 'newdomalias'),
(r'^domaliases/edit/(?P<alias_id>\d+)/', 'editdomalias'),
(r'^domaliases/delete/$', 'deldomalias'),
(r'^mailboxes/$', 'mailboxes'),
(r'^mailboxes/new/$', 'newmailbox'),
(r'^mailboxes/edit/(?P<mbox_id>\d+)/$', 'editmailbox'),
(r'^mailboxes/delete/$', 'delmailbox'),
(r'^mailboxes/search/$', 'mailboxes_search'),
(r'^mbaliases/$', 'mbaliases'),
(r'^mbaliases/new/$', 'newmbalias'),
(r'^mbaliases/edit/(?P<alias_id>\d+)/$', 'editmbalias'),
(r'^mbaliases/delete/$', 'delmbalias'),
(r'^domains/(?P<dom_id>\d+)/rawmboxes/$', 'mailboxes_raw'),
(r'^settings/$', 'viewparameters'),
(r'^settings/parameters/$', 'viewparameters'),
(r'^settings/parameters/save/$', 'saveparameters'),
(r'^settings/extensions/$', 'viewextensions'),
(r'^settings/extensions/save/$', 'saveextensions'),
(r'^permissions/$', 'permissions'),
(r'^permissions/add/$', 'add_permission'),
(r'^permissions/domainadmin/new/$', 'create_domain_admin'),
(r'^permissions/domainadmin/edit/(?P<da_id>\d+)/$', 'edit_domain_admin'),
(r'^permissions/domainadmin/promote/$', 'domain_admin_promotion'),
(r'^permissions/searchaccount/$', 'search_account'),
(r'^permissions/delete/$', 'delete_permissions'),
)
+182 -72
View File
@@ -16,6 +16,7 @@ from models import *
from modoboa.admin.permissions import *
from modoboa.admin.tables import *
from modoboa.lib import events, parameters
from modoboa.lib.exceptions import *
from modoboa.auth.lib import crypt_password
from modoboa.lib.webutils \
import _render, ajax_response, ajax_simple_response, getctx
@@ -31,10 +32,7 @@ def domains(request):
return HttpResponseRedirect(reverse(userprefs.views.preferences))
if request.user.is_superuser:
domains = Domain.objects.all()
else:
domains = events.raiseQueryEvent("GetUserDomains", request.user)
domains = get_user_domains(request.user)
for dom in domains:
dom.mbalias_counter = len(Alias.objects.filter(domain=dom.id))
deloptions = {"keepdir" : _("Do not delete domain directory")}
@@ -53,7 +51,6 @@ def _validate_domain(request, form, successmsg, commonctx,
"""
error = None
if form.is_valid():
events.raiseEvent("CanCreateDomain", request.user)
try:
domain = form.save()
except AdminError, e:
@@ -74,7 +71,9 @@ def _validate_domain(request, form, successmsg, commonctx,
@permission_required("admin.add_domain")
@transaction.commit_on_success
def newdomain(request, tplname="admin/adminform.html"):
events.raiseEvent("CanCreateDomain", request.user)
def newdomain_cb(user, domain):
set_object_ownership(user, domain)
events.raiseEvent("CreateDomain", user, domain)
commonctx = {"title" : _("New domain"),
@@ -94,6 +93,9 @@ def newdomain(request, tplname="admin/adminform.html"):
@permission_required("admin.change_domain")
def editdomain(request, dom_id, tplname="admin/adminform.html"):
domain = Domain.objects.get(pk=dom_id)
if not is_object_owner(request.user, domain):
raise PermDeniedException(_("You can't edit this domain"))
commonctx = {"title" : _("Domain editing"),
"submit_label" : _("Update"),
"action" : reverse(editdomain, args=[dom_id]),
@@ -108,47 +110,47 @@ def editdomain(request, dom_id, tplname="admin/adminform.html"):
@login_required
@permission_required("admin.delete_domain")
@transaction.commit_on_success
def deldomain(request):
selection = request.GET["selection"].split(",")
error = None
keepdir = True if request.GET.get("keepdir", "false") == "true" else False
try:
mb = Mailbox.objects.get(user__id=request.user.id)
except Mailbox.DoesNotExist:
pass
else:
if str(mb.domain.id) in selection:
error = _("You can't delete your own domain")
mb = None
if error is None:
if request.GET.has_key("keepdir") and request.GET["keepdir"] == "true":
keepdir = True
else:
keepdir = False
for dom in Domain.objects.filter(id__in=selection):
events.raiseEvent("DeleteDomain", dom)
dom.delete(keepdir=keepdir)
msg = ungettext("Domain deleted", "Domains deleted", len(selection))
messages.info(request, msg, fail_silently=True)
return ajax_response(request)
return ajax_response(request, status="ko", respmsg=error)
for dom in Domain.objects.filter(id__in=selection):
if not is_object_owner(request.user, dom):
raise PermDeniedException(_("You can't delete this domain"))
if mb and mb.domain == dom:
raise AdminError(_("You can't delete your own domain"))
events.raiseEvent("DeleteDomain", request.user, 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_domaliases")
@check_domain_ownership
def domaliases(request):
if request.GET.has_key("domid"):
domain = Domain.objects.get(pk=request.GET["domid"])
domaliases = DomainAlias.objects.filter(target=request.GET["domid"])
else:
domain = None
domaliases = DomainAlias.objects.all()
domaliases = get_user_domaliases(request.user)
return render_listing(request, "domaliases",
title=_("Domain aliases"),
rel="310 190",
objects=domaliases)
@login_required
@good_domain
@permission_required("admin.add_domainalias")
@transaction.commit_on_success
def newdomalias(request, tplname="admin/adminform.html"):
commonctx = {"title" : _("New domain alias"),
"submit_label" : _("Create"),
@@ -158,6 +160,7 @@ def newdomalias(request, tplname="admin/adminform.html"):
form = DomainAliasForm(request.user, request.POST)
error = None
if form.is_valid():
events.raiseEvent("CanCreateDomainAlias", request.user)
domalias = form.save(commit=False)
if Domain.objects.filter(name=domalias.name):
error = _("A domain with this name already exists")
@@ -167,6 +170,7 @@ def newdomalias(request, tplname="admin/adminform.html"):
except IntegrityError:
error = _("Alias with this name already exists")
else:
events.raiseEvent("DomainAliasCreated", request.user, domalias)
messages.info(request, _("Domain alias created"), fail_silently=True)
return ajax_response(request, url=reverse(admin.views.domaliases))
@@ -181,10 +185,12 @@ def newdomalias(request, tplname="admin/adminform.html"):
return _render(request, tplname, commonctx)
@login_required
@good_domain
@permission_required("admin.change_domainalias")
def editdomalias(request, alias_id, tplname="admin/adminform.html"):
domalias = DomainAlias.objects.get(pk=alias_id)
if not is_object_owner(request.user, domalias.target):
raise PermDeniedException(_("You do not have access to this domain"))
commonctx = {"title" : _("Domain alias editing"),
"submit_label" : _("Update"),
"action" : reverse(editdomalias, args=[alias_id]),
@@ -213,18 +219,23 @@ def editdomalias(request, alias_id, tplname="admin/adminform.html"):
return _render(request, tplname, commonctx)
@login_required
@good_domain
@permission_required("admin.delete_domainalias")
@transaction.commit_on_success
def deldomalias(request):
selection = request.GET["selection"].split(",")
DomainAlias.objects.filter(id__in=selection).delete()
for daid in selection:
domalias = DomainAlias.objects.get(pk=daid)
if not is_object_owner(request.user, domalias.target):
raise PermDeniedException(_("You don't have acces to this domain"))
events.raiseEvent("DomainAliasDeleted", request.user, domalias)
domalias.delete()
msg = ungettext("Domain alias deleted", "Domain aliases deleted", len(selection))
messages.info(request, msg, fail_silently=True)
return ajax_response(request)
@login_required
@good_domain
@permission_required("admin.view_mailboxes")
@check_domain_ownership
def mailboxes(request):
title = _("Available mailboxes")
if request.GET.has_key("domid"):
@@ -232,7 +243,7 @@ def mailboxes(request):
mboxes = Mailbox.objects.filter(domain=domain.id)
title += " (%s)" % domain.name
else:
mboxes = Mailbox.objects.all()
mboxes = get_user_mailboxes(request.user)
domain = None
deloptions = {"keepdir" : _("Do not delete mailbox directory")}
return render_listing(request, "mailboxes",
@@ -255,8 +266,8 @@ def mailboxes_raw(request, dom_id=None):
})
@login_required
@good_domain
@permission_required("admin.view_mailboxes")
@check_domain_ownership
def mailboxes_search(request):
if request.method != "POST":
return
@@ -266,13 +277,15 @@ def mailboxes_search(request):
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=get_user_domains(request.user)) & query
mboxes = Mailbox.objects.filter(query)
result = map(lambda mb: mb.full_address, mboxes)
return ajax_simple_response(result)
@login_required
@good_domain
@permission_required("admin.add_mailbox")
@transaction.commit_on_success
def newmailbox(request, tplname="admin/adminform.html"):
commonctx = {"title" : _("New mailbox"),
"submit_label" : _("Create"),
@@ -282,12 +295,17 @@ def newmailbox(request, tplname="admin/adminform.html"):
form = MailboxForm(request.user, request.POST)
error = None
if form.is_valid():
if not request.user.is_superuser:
if not is_object_owner(request.user, form.cleaned_data["domain"]):
raise PermDeniedException(_("You do not have access to this domain"))
events.raiseEvent("CanCreateMailbox", request.user)
try:
mb = form.save()
except AdminError as e:
error = str(e)
else:
events.raiseEvent("CreateMailbox", mb)
events.raiseEvent("CreateMailbox", request.user, mb)
messages.info(request, _("Mailbox created"),
fail_silently=True)
return ajax_response(request, url=reverse(admin.views.mailboxes) + "?domid=%d" % mb.domain.id)
@@ -301,10 +319,12 @@ def newmailbox(request, tplname="admin/adminform.html"):
return _render(request, tplname, commonctx)
@login_required
@good_domain
@permission_required("admin.change_mailbox")
def editmailbox(request, mbox_id=None, tplname="admin/adminform.html"):
mb = Mailbox.objects.get(pk=mbox_id)
if not is_object_owner(request.user, mb.domain):
raise PermDeniedException(_("You do not have access to this domain"))
commonctx = {"title" : _("Mailbox editing"),
"submit_label" : _("Create"),
"action" : reverse(editmailbox, args=[mbox_id]),
@@ -336,66 +356,63 @@ def editmailbox(request, mbox_id=None, tplname="admin/adminform.html"):
return _render(request, tplname, commonctx)
@login_required
@good_domain
@permission_required("admin.delete_mailbox")
@transaction.commit_on_success
def delmailbox(request):
selection = request.GET["selection"].split(",")
error = None
if not request.user.is_superuser:
mb = Mailbox.objects.get(user__pk=request.user.id)
if str(mb.id) in selection:
error = _("You can't delete your own mailbox")
keepdir = True if request.GET.get("keepdir", "false") == "true" else False
usermb = request.user.mailbox_set.all()[0] \
if len(request.user.mailbox_set.all()) else None
if error is None:
if request.GET.has_key("keepdir") and request.GET["keepdir"] == "true":
keepdir = True
else:
keepdir = False
for mb in Mailbox.objects.filter(id__in=selection):
events.raiseEvent("DeleteMailbox", mb)
mb.delete(keepdir=keepdir)
msg = ungettext("Mailbox deleted", "Mailboxes deleted", len(selection))
messages.info(request, msg, fail_silently=True)
return ajax_response(request)
for mb in Mailbox.objects.filter(id__in=selection):
if not is_object_owner(request.user, mb.domain):
raise PermDeniedException(_("You don't have access to this domain"))
if usermb and usermb == mb:
raise AdminError(_("You can't delete your own mailbox"))
events.raiseEvent("DeleteMailbox", request.user, mb)
mb.delete(keepdir=keepdir)
return ajax_response(request, status="ko", error=error)
msg = ungettext("Mailbox deleted", "Mailboxes deleted", len(selection))
messages.info(request, msg, fail_silently=True)
return ajax_response(request)
@login_required
@good_domain
@permission_required("admin.view_aliases")
@check_domain_ownership
def mbaliases(request):
if request.GET.has_key("domid"):
aliases = Alias.objects.filter(domain=request.GET["domid"])
elif request.GET.has_key("mbid"):
aliases = Alias.objects.filter(mboxes__id=request.GET["mbid"]).distinct()
else:
aliases = Alias.objects.all()
aliases = get_user_mbaliases(request.user)
return render_listing(request, "mbaliases",
title=_("Mailbox aliases"),
rel="320 300",
objects=aliases)
def _validate_mbalias(request, form, successmsg, tplname, commonctx):
def _validate_mbalias(request, form, successmsg, tplname, commonctx, callback=None):
"""Mailbox alias validation
Common function shared between creation and modification actions.
"""
error = None
if form.is_valid():
if not request.POST.has_key("targets"):
raise AdminError(_("No target defined"))
form.set_targets(request.user, request.POST.getlist("targets"))
try:
if not request.POST.has_key("targets"):
raise AdminError(_("No target defined"))
form.set_targets(request.user, request.POST.getlist("targets"))
try:
alias = form.save()
except IntegrityError:
raise AdminError(_("Alias with this name already exists"))
alias = form.save()
except IntegrityError:
raise AdminError(_("Alias with this name already exists"))
messages.info(request, successmsg, fail_silently=True)
return ajax_response(request, url=reverse(admin.views.mbaliases))
except AdminError, e:
error = str(e)
if callback:
callback(request.user, alias)
messages.info(request, successmsg, fail_silently=True)
return ajax_response(request, url=reverse(admin.views.mbaliases))
if request.POST.has_key("targets"):
targets = request.POST.getlist("targets")
@@ -406,17 +423,21 @@ def _validate_mbalias(request, form, successmsg, tplname, commonctx):
return ajax_response(request, status="ko", template=tplname, **commonctx)
@login_required
@good_domain
@permission_required("admin.add_alias")
@transaction.commit_on_success
def newmbalias(request, tplname="admin/mbaliasform.html"):
events.raiseEvent("CanCreateMailboxAlias", request.user)
commonctx = {"title" : _("New mailbox alias"),
"submit_label" : _("Create"),
"action" : reverse(newmbalias),
"formid" : "mbaliasform"}
if request.method == "POST":
def callback(user, mbalias):
events.raiseEvent("MailboxAliasCreated", user, mbalias)
form = AliasForm(request.user, request.POST)
return _validate_mbalias(request, form, _("Mailbox alias created"),
tplname, commonctx)
tplname, commonctx, callback)
form = AliasForm(request.user)
commonctx["form"] = form
@@ -424,10 +445,11 @@ def newmbalias(request, tplname="admin/mbaliasform.html"):
return _render(request, tplname, commonctx)
@login_required
@good_domain
@permission_required("admin.change_alias")
def editmbalias(request, alias_id, tplname="admin/mbaliasform.html"):
alias = Alias.objects.get(pk=alias_id)
if not is_object_owner(request.user, alias.domain):
raise PermDeniedException(_("You do not have access to this domain"))
commonctx = {"title" : _("Mailbox alias editing"),
"submit_label" : _("Update"),
"action" : reverse(editmbalias, args=[alias.id]),
@@ -443,11 +465,17 @@ def editmbalias(request, alias_id, tplname="admin/mbaliasform.html"):
return _render(request, tplname, commonctx)
@login_required
@good_domain
@permission_required("admin.delete_alias")
@transaction.commit_on_success
def delmbalias(request):
selection = request.GET["selection"].split(",")
Alias.objects.filter(id__in=selection).delete()
for mbaid in selection:
mbalias = Alias.objects.get(pk=mbaid)
if not is_object_owner(request.user, mbalias.domain):
raise PermDeniedException(_("You do not have access to this domain"))
events.raiseEvent("MailboxAliasDeleted", request.user, mbalias)
mbalias.delete()
msg = ungettext("Alias deleted", "Aliases deleted", len(selection))
messages.info(request, msg, fail_silently=True)
return ajax_response(request)
@@ -464,12 +492,12 @@ def permissions(request, tplname='admin/permissions.html'):
"content" : SuperAdminsPerms().get(request)}
]
permtables += events.raiseQueryEvent("PermsGetTables", user=request.user)
permtables += events.raiseQueryEvent("PermsGetTables", request)
permtables += [
{"id" : "domain_admins",
"title" : _("Domain administrators"),
"rel" : "310 180",
"rel" : "350 250",
"content" : DomainAdminsPerms().get(request)}
]
@@ -492,10 +520,92 @@ def add_permission(request):
status, data = pobj.add(request)
if not status:
return HttpResponse(simplejson.dumps(data), mimetype="application/json")
messages.info(request, _("Permission added."),
fail_silently=True)
try:
msg = pobj.add_success_msg
except AttributeError:
msg = _("Permission added")
messages.info(request, msg, fail_silently=True)
return ajax_response(request, url=reverse(admin.views.permissions))
@login_required
@permission_required("auth.view_permissions")
def create_domain_admin(request, tplname="admin/create_domain_admin.html"):
if request.method == "POST":
form = UserWithPasswordForm(request.POST)
if form.is_valid():
user = form.save(group="DomainAdmins")
events.raiseEvent("DomainAdminCreated", user)
messages.info(request, _("Domain admin created"), fail_silently=True)
return ajax_response(request, url=reverse(admin.views.permissions))
return ajax_response(request, status="ko", template=tplname, form=form)
form = UserWithPasswordForm()
return ajax_response(request, tplname, form=form)
@login_required
@permission_required("auth.view_permissions")
def edit_domain_admin(request, da_id, tplname="admin/adminform.html"):
ctx = dict(title=_("Edit domain admin"),
action=reverse(edit_domain_admin, args=[da_id]),
formid="eda_form",
submit_label=_("Update"))
u = User.objects.get(pk=da_id, groups__name="DomainAdmins")
if request.method == "POST":
if request.POST.get("password1", "") != "" and \
request.POST.get("password2", "") != "":
form = UserWithPasswordForm(request.POST, instance=u)
else:
form = UserForm(request.POST, instance=u)
if form.is_valid():
form.save()
if form.cleaned_data["createmb"]:
pass
messages.info(request, _("Domain admin updated"), fail_silently=True)
return ajax_response(request,
url=reverse("modoboa.admin.views.permissions"))
ctx.update(form=form)
return ajax_response(request, status="ko", template=tplname, **ctx)
form = UserWithPasswordForm(instance=u)
ctx.update(form=form)
return _render(request, tplname, ctx)
@login_required
@permission_required("auth.view_permissions")
def domain_admin_promotion(request):
if request.method == "POST":
form = DomainAdminPromotionForm(request.POST)
if form.is_valid():
u = User.objects.get(username=form.cleaned_data["name"])
u.groups.add(Group.objects.get(name="DomainAdmins"))
u.save()
messages.info(request, _("Domain admin added"), fail_silently=True)
return ajax_response(request, url=reverse(admin.views.permissions))
form = DomainAdminPromotionForm()
return ajax_response(request, template="admin/domain_admin_promotion.html",
form=form)
@login_required
@permission_required("admin.view_permissions")
@check_domain_ownership
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
def delete_permissions(request):
pclass = get_perms_class(request.user, request.GET["role"])