mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-21 06:18:45 +02:00
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:
+2
-2
@@ -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 @@
|
||||
[{"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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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")
|
||||
|
||||
@@ -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
@@ -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
@@ -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"])
|
||||
|
||||
Reference in New Issue
Block a user