mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
wip: Resellers and limits
* We now make a difference between users that own a specific object and users that have access to a specific object * Limits are not moved anymore (from one reseller to a domain admin) when we grant access to a domain see #105
This commit is contained in:
@@ -264,6 +264,20 @@ class DomainAdminPromotionForm(forms.Form):
|
||||
raise forms.ValidationError(_("Unknown user"))
|
||||
return self.cleaned_data["name"]
|
||||
|
||||
class AssignDomainsForm(forms.Form):
|
||||
domains = forms.ModelMultipleChoiceField(
|
||||
queryset=None,
|
||||
label=ugettext_noop("Domains"),
|
||||
required=True,
|
||||
help_text=ugettext_noop("Select one or more domains in the list")
|
||||
)
|
||||
|
||||
def __init__(self, user, domadmin, *args, **kwargs):
|
||||
super(AssignDomainsForm, self).__init__(*args, **kwargs)
|
||||
self.fields["domains"].queryset = get_user_domains_qs(user)
|
||||
self.fields["domains"].initial = get_user_domains_qs(domadmin)
|
||||
|
||||
|
||||
class ImportDataForm(forms.Form):
|
||||
sourcefile = forms.FileField(label=_("Select a file"))
|
||||
sepcar = forms.CharField(label=_("Separator"), max_length=1, required=False)
|
||||
|
||||
+73
-32
@@ -115,35 +115,59 @@ def render_listing(request, objtype, tplname="admin/listing.html",
|
||||
|
||||
return _render(request, tplname, kwargs)
|
||||
|
||||
def set_object_ownership(user, obj):
|
||||
"""Simple shorcut to associate an object to a user
|
||||
def grant_access_to_object(user, obj, is_owner=False):
|
||||
"""Grant access to an object for a given user
|
||||
|
||||
There are two different cases where we want to grant access to an
|
||||
object for a specific user:
|
||||
|
||||
* He is the owner (he's just created the object)
|
||||
* He is going to administrate the object (but he is not the owner)
|
||||
|
||||
:param user: a ``User`` object
|
||||
:param obj: an admin. object (Domain, Mailbox, ...)
|
||||
:param is_owner: the user is the unique object's owner
|
||||
"""
|
||||
try:
|
||||
ct = ContentType.objects.get_for_model(obj)
|
||||
obj_owner = user.objectowner_set.get(content_type=ct, object_id=obj.id)
|
||||
except ObjectOwner.DoesNotExist:
|
||||
obj_owner = ObjectOwner(user=user, content_object=obj)
|
||||
obj_owner.save()
|
||||
entry = user.objectaccess_set.get(content_type=ct, object_id=obj.id)
|
||||
entry.is_owner = is_owner
|
||||
entry.save()
|
||||
except ObjectAccess.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
return
|
||||
|
||||
def unset_object_ownership(obj):
|
||||
"""Remove the ownership of the given object
|
||||
try:
|
||||
objaccess = ObjectAccess(user=user, content_object=obj, is_owner=is_owner)
|
||||
objaccess.save()
|
||||
except IntegrityError, e:
|
||||
raise AdminError(_("Failed to grant access (%s)" % str(e)))
|
||||
|
||||
def ungrant_access_to_object(obj, user=None):
|
||||
"""Ungrant access to an object for a specific user
|
||||
|
||||
If no user is provided, all entries referencing this object are
|
||||
deleted from the database.
|
||||
|
||||
:param obj: an object inheriting from ``models.Model``
|
||||
:param user: a ``User`` object
|
||||
"""
|
||||
ct = ContentType.objects.get_for_model(obj)
|
||||
ObjectOwner.objects.get(content_type=ct, object_id=obj.id).delete()
|
||||
if user:
|
||||
try:
|
||||
ObjectAccess.objects.get(user=user, content_type=ct, object_id=obj.id).delete()
|
||||
except ObjectAccess.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
ObjectAccess.objects.filter(content_type=ct, object_id=obj.id).delete()
|
||||
|
||||
def is_object_owner(user, obj):
|
||||
"""Check if a user is the object's owner
|
||||
def can_access_object(user, obj):
|
||||
"""Check if a user can access a specific object
|
||||
|
||||
An object can only belongs to one user.
|
||||
|
||||
This function is recursive : if the given user is not the owner
|
||||
and if he owns other ``User`` objects, we also check if one of
|
||||
those users owns the object.
|
||||
This function is recursive : if the given user hasn't got direct
|
||||
access to this object and if he has got access other ``User``
|
||||
objects, we check if one of those users owns the object.
|
||||
|
||||
:param user: a ``User`` object
|
||||
:param obj: a admin object
|
||||
@@ -154,35 +178,52 @@ def is_object_owner(user, obj):
|
||||
|
||||
ct = ContentType.objects.get_for_model(obj)
|
||||
try:
|
||||
ooentry = user.objectowner_set.get(content_type=ct, object_id=obj.id)
|
||||
except ObjectOwner.DoesNotExist:
|
||||
ooentry = user.objectaccess_set.get(content_type=ct, object_id=obj.id)
|
||||
except ObjectAccess.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
return True
|
||||
if ct.model == "user":
|
||||
return False
|
||||
if directowner:
|
||||
return False
|
||||
|
||||
ct = ContentType.objects.get_for_model(User)
|
||||
qs = user.objectowner_set.filter(content_type=ct)
|
||||
qs = user.objectaccess_set.filter(content_type=ct)
|
||||
for ooentry in qs.all():
|
||||
if is_object_owner(ooentry.content_object, obj):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_object_owner(user, obj):
|
||||
"""Tell is the user is the unique owner of this object
|
||||
|
||||
:param user: a ``User`` object
|
||||
:param obj: an object inheriting from ``models.Model``
|
||||
:return: a boolean
|
||||
"""
|
||||
ct = ContentType.objects.get_for_model(obj)
|
||||
try:
|
||||
ooentry = user.objectaccess_set.get(content_type=ct, object_id=obj.id)
|
||||
except ObjectAccess.DoesNotExist:
|
||||
return False
|
||||
return ooentry.is_owner
|
||||
|
||||
def get_object_owner(obj):
|
||||
"""Return this object's owner
|
||||
"""Return the unique owner of this object
|
||||
|
||||
:param obj: an object inheriting from ``model.Model``
|
||||
:return: a ``User`` object
|
||||
"""
|
||||
ct = ContentType.objects.get_for_model(obj)
|
||||
res = ObjectOwner.objects.filter(content_type=ct, object_id=obj.id)
|
||||
if not len(res):
|
||||
try:
|
||||
entry = ObjectAccess.objects.get(content_type=ct, object_id=obj.id, is_owner=True)
|
||||
except ObjectAccess.DoesNotExist:
|
||||
return None
|
||||
return res[0].user
|
||||
return entry.user
|
||||
|
||||
def check_domain_ownership(f):
|
||||
"""Decorator to check if the current user can access to a domain
|
||||
def check_domain_access(f):
|
||||
"""Decorator to check if the current user can access a domain
|
||||
|
||||
This decorator only applies to url that contain a 'domid' or
|
||||
'mbid' parameter. (for a direct access)
|
||||
@@ -201,7 +242,7 @@ def check_domain_ownership(f):
|
||||
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):
|
||||
if domain and not can_access_object(request.user, domain):
|
||||
raise PermDeniedError(_("You can't access this domain"))
|
||||
|
||||
return f(request, **kwargs)
|
||||
@@ -212,13 +253,13 @@ def get_user_domains(user):
|
||||
return Domain.objects.all()
|
||||
|
||||
domct = ContentType.objects.get_for_model(Domain)
|
||||
qs = user.objectowner_set.filter(content_type=domct)
|
||||
qs = user.objectaccess_set.filter(content_type=domct)
|
||||
domains = []
|
||||
for entry in qs.all():
|
||||
domains += [entry.content_object]
|
||||
|
||||
userct = ContentType.objects.get_for_model(User)
|
||||
qs = user.objectowner_set.filter(content_type=userct)
|
||||
qs = user.objectaccess_set.filter(content_type=userct)
|
||||
for entry in qs:
|
||||
if not is_domain_admin(entry.content_object):
|
||||
continue
|
||||
@@ -235,13 +276,13 @@ def get_user_domains_qs(user):
|
||||
"""
|
||||
if user.is_superuser:
|
||||
return Domain.objects.all()
|
||||
result = Domain.objects.filter(owners__user=user)
|
||||
|
||||
result = Domain.objects.filter(owners__user=user).distinct()
|
||||
|
||||
userct = ContentType.objects.get_for_model(User)
|
||||
for entry in user.objectowner_set.filter(content_type=userct):
|
||||
for entry in user.objectaccess_set.filter(content_type=userct):
|
||||
if not is_domain_admin(entry.content_object):
|
||||
continue
|
||||
result |= get_user_domains_qs(entry.content_object)
|
||||
result |= get_user_domains_qs(entry.content_object).distinct()
|
||||
return result
|
||||
|
||||
def get_user_domaliases(user):
|
||||
|
||||
+20
-12
@@ -8,20 +8,27 @@ class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'ObjectOwner'
|
||||
db.create_table('admin_objectowner', (
|
||||
# Adding model 'ObjectAccess'
|
||||
db.create_table('admin_objectaccess', (
|
||||
('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')()),
|
||||
('is_owner', self.gf('django.db.models.fields.BooleanField')(default=False)),
|
||||
))
|
||||
db.send_create_signal('admin', ['ObjectOwner'])
|
||||
db.send_create_signal('admin', ['ObjectAccess'])
|
||||
|
||||
# Adding unique constraint on 'ObjectAccess', fields ['user', 'content_type', 'object_id']
|
||||
db.create_unique('admin_objectaccess', ['user_id', 'content_type_id', 'object_id'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'ObjectOwner'
|
||||
db.delete_table('admin_objectowner')
|
||||
# Removing unique constraint on 'ObjectAccess', fields ['user', 'content_type', 'object_id']
|
||||
db.delete_unique('admin_objectaccess', ['user_id', 'content_type_id', 'object_id'])
|
||||
|
||||
# Deleting model 'ObjectAccess'
|
||||
db.delete_table('admin_objectaccess')
|
||||
|
||||
|
||||
models = {
|
||||
@@ -71,19 +78,20 @@ class Migration(SchemaMigration):
|
||||
'uid': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'admin.objectaccess': {
|
||||
'Meta': {'unique_together': "(('user', 'content_type', 'object_id'),)", 'object_name': 'ObjectAccess'},
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_owner': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
|
||||
'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'}),
|
||||
+4
-3
@@ -18,14 +18,15 @@ try:
|
||||
except ImportError:
|
||||
ldap_available = False
|
||||
|
||||
class ObjectOwner(models.Model):
|
||||
class ObjectAccess(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
content_type = models.ForeignKey(ContentType)
|
||||
object_id = models.PositiveIntegerField()
|
||||
content_object = generic.GenericForeignKey('content_type', 'object_id')
|
||||
is_owner = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
unique_together = (("content_type", "object_id"),)
|
||||
unique_together = (("user", "content_type", "object_id"),)
|
||||
|
||||
class ObjectDates(models.Model):
|
||||
"""Dates recording for admin objects
|
||||
@@ -80,7 +81,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)
|
||||
owners = generic.GenericRelation(ObjectAccess)
|
||||
|
||||
class Meta:
|
||||
permissions = (
|
||||
|
||||
@@ -7,7 +7,7 @@ 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
|
||||
from lib import grant_access_to_object, ungrant_access_to_object
|
||||
|
||||
class Permissions(object):
|
||||
submit_label = ugettext_noop("Add")
|
||||
@@ -101,20 +101,24 @@ 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)
|
||||
#set_object_ownership(mb.user, mb.domain)
|
||||
return True, None
|
||||
content = self._render_form(request, form, True)
|
||||
return False, getctx("ko", content=content)
|
||||
|
||||
def delete(self, selection):
|
||||
grp = Group.objects.get(name="DomainAdmins")
|
||||
dagrp = Group.objects.get(name="DomainAdmins")
|
||||
sugrp = Group.objects.get(name="SimpleUsers")
|
||||
for uid in selection:
|
||||
u = User.objects.get(pk=uid)
|
||||
u.groups.remove(grp)
|
||||
u.groups.remove(dagrp)
|
||||
u.save()
|
||||
events.raiseEvent("DomainAdminDeleted", u)
|
||||
if not len(u.mailbox_set.all()):
|
||||
ungrant_access_to_object(u)
|
||||
u.delete()
|
||||
else:
|
||||
u.groups.add(sugrp)
|
||||
|
||||
def get(self, request):
|
||||
#domadmins = Mailbox.objects.filter(user__groups__name="DomainAdmins")
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ class DomainAdminsTable(tables.Table):
|
||||
date_joined = tables.Column("date_joined", label=ugettext_noop("Defined"))
|
||||
enabled = tables.Column("is_active", label=gender("Enabled", "m"), width="10%")
|
||||
actions = tables.ActionColumn("actions", label=ugettext_noop("Actions"),
|
||||
width="50px", align="center",
|
||||
width="70px", align="center",
|
||||
defvalue=domain_admin_actions)
|
||||
|
||||
cols_order = ["selection", "username", "first_name",
|
||||
|
||||
@@ -209,6 +209,12 @@ def domain_admin_actions(user, daid):
|
||||
"title" : _("Edit domain admin"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:350,y:320}}"},
|
||||
{"name" : "assigndomains",
|
||||
"url" : reverse(admin.views.assign_domains_to_admin, args=[daid]),
|
||||
"img" : static_url("pics/domains.png"),
|
||||
"title" : _("Assign domain(s) to this administrator"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:350,y:320}}"},
|
||||
]
|
||||
actions += events.raiseQueryEvent("DomainAdminActions", User.objects.get(pk=daid))
|
||||
return render_actions(actions)
|
||||
|
||||
@@ -38,6 +38,7 @@ urlpatterns = patterns(
|
||||
(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/domainadmin/assign/(?P<da_id>\d+)/$', 'assign_domains_to_admin'),
|
||||
(r'^permissions/searchaccount/$', 'search_account'),
|
||||
(r'^permissions/delete/$', 'delete_permissions'),
|
||||
)
|
||||
|
||||
+55
-18
@@ -32,7 +32,7 @@ def domains(request):
|
||||
|
||||
return HttpResponseRedirect(reverse(userprefs.views.preferences))
|
||||
|
||||
domains = get_user_domains(request.user)
|
||||
domains = get_user_domains_qs(request.user)
|
||||
for dom in domains:
|
||||
dom.mbalias_counter = len(Alias.objects.filter(domain=dom.id))
|
||||
deloptions = {"keepdir" : _("Do not delete domain directory")}
|
||||
@@ -73,7 +73,7 @@ def _validate_domain(request, form, successmsg, commonctx,
|
||||
def newdomain(request, tplname="admin/adminform.html"):
|
||||
events.raiseEvent("CanCreateDomain", request.user)
|
||||
def newdomain_cb(user, domain):
|
||||
set_object_ownership(user, domain)
|
||||
grant_access_to_object(user, domain, is_owner=True)
|
||||
events.raiseEvent("CreateDomain", user, domain)
|
||||
|
||||
commonctx = {"title" : _("New domain"),
|
||||
@@ -127,7 +127,7 @@ def deldomain(request):
|
||||
raise AdminError(_("You can't delete your own domain"))
|
||||
|
||||
events.raiseEvent("DeleteDomain", dom)
|
||||
unset_object_ownership(dom)
|
||||
ungrant_access_to_object(dom)
|
||||
dom.delete(keepdir=keepdir)
|
||||
|
||||
msg = ungettext("Domain deleted", "Domains deleted", len(selection))
|
||||
@@ -136,7 +136,7 @@ def deldomain(request):
|
||||
|
||||
@login_required
|
||||
@permission_required("admin.view_domaliases")
|
||||
@check_domain_ownership
|
||||
@check_domain_access
|
||||
def domaliases(request):
|
||||
if request.GET.has_key("domid"):
|
||||
domain = Domain.objects.get(pk=request.GET["domid"])
|
||||
@@ -171,7 +171,7 @@ def newdomalias(request, tplname="admin/adminform.html"):
|
||||
except IntegrityError:
|
||||
error = _("Alias with this name already exists")
|
||||
else:
|
||||
set_object_ownership(request.user, domalias)
|
||||
grant_access_to_object(request.user, domalias, is_owner=True)
|
||||
events.raiseEvent("DomainAliasCreated", request.user, domalias)
|
||||
messages.info(request, _("Domain alias created"), fail_silently=True)
|
||||
return ajax_response(request, url=reverse(admin.views.domaliases))
|
||||
@@ -230,7 +230,7 @@ def deldomalias(request):
|
||||
if not is_object_owner(request.user, domalias.target):
|
||||
raise PermDeniedException(_("You don't have acces to this domain"))
|
||||
events.raiseEvent("DomainAliasDeleted", domalias)
|
||||
unset_object_ownership(domalias)
|
||||
ungrant_access_to_object(domalias)
|
||||
domalias.delete()
|
||||
msg = ungettext("Domain alias deleted", "Domain aliases deleted", len(selection))
|
||||
messages.info(request, msg, fail_silently=True)
|
||||
@@ -238,7 +238,7 @@ def deldomalias(request):
|
||||
|
||||
@login_required
|
||||
@permission_required("admin.view_mailboxes")
|
||||
@check_domain_ownership
|
||||
@check_domain_access
|
||||
def mailboxes(request):
|
||||
title = _("Available mailboxes")
|
||||
if request.GET.has_key("domid"):
|
||||
@@ -270,7 +270,7 @@ def mailboxes_raw(request, dom_id=None):
|
||||
|
||||
@login_required
|
||||
@permission_required("admin.view_mailboxes")
|
||||
@check_domain_ownership
|
||||
@check_domain_access
|
||||
def mailboxes_search(request):
|
||||
if request.method != "POST":
|
||||
return
|
||||
@@ -300,7 +300,7 @@ def newmailbox(request, tplname="admin/adminform.html"):
|
||||
error = None
|
||||
if form.is_valid():
|
||||
if not request.user.is_superuser:
|
||||
if not is_object_owner(request.user, form.cleaned_data["domain"]):
|
||||
if not can_access_object(request.user, form.cleaned_data["domain"]):
|
||||
raise PermDeniedException(_("You do not have access to this domain"))
|
||||
|
||||
try:
|
||||
@@ -308,7 +308,8 @@ def newmailbox(request, tplname="admin/adminform.html"):
|
||||
except AdminError as e:
|
||||
error = str(e)
|
||||
else:
|
||||
set_object_ownership(request.user, mb)
|
||||
grant_access_to_object(request.user, mb, is_owner=True)
|
||||
grant_access_to_object(request.user, mb.user, is_owner=True)
|
||||
events.raiseEvent("CreateMailbox", request.user, mb)
|
||||
messages.info(request, _("Mailbox created"),
|
||||
fail_silently=True)
|
||||
@@ -370,12 +371,13 @@ def delmailbox(request):
|
||||
if len(request.user.mailbox_set.all()) else None
|
||||
|
||||
for mb in Mailbox.objects.filter(id__in=selection):
|
||||
if not is_object_owner(request.user, mb.domain):
|
||||
if not can_access_object(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", mb)
|
||||
unset_object_ownership(mb)
|
||||
ungrant_access_to_object(mb)
|
||||
ungrant_access_to_object(mb.user)
|
||||
mb.delete(keepdir=keepdir)
|
||||
|
||||
msg = ungettext("Mailbox deleted", "Mailboxes deleted", len(selection))
|
||||
@@ -384,7 +386,7 @@ def delmailbox(request):
|
||||
|
||||
@login_required
|
||||
@permission_required("admin.view_aliases")
|
||||
@check_domain_ownership
|
||||
@check_domain_access
|
||||
def mbaliases(request):
|
||||
if request.GET.has_key("domid"):
|
||||
aliases = Alias.objects.filter(domain=request.GET["domid"])
|
||||
@@ -438,7 +440,7 @@ def newmbalias(request, tplname="admin/mbaliasform.html"):
|
||||
"formid" : "mbaliasform"}
|
||||
if request.method == "POST":
|
||||
def callback(user, mbalias):
|
||||
set_object_ownership(user, mbalias)
|
||||
grant_access_to_object(user, mbalias, is_owner=True)
|
||||
events.raiseEvent("MailboxAliasCreated", user, mbalias)
|
||||
|
||||
form = AliasForm(request.user, request.POST)
|
||||
@@ -480,7 +482,7 @@ def delmbalias(request):
|
||||
if not is_object_owner(request.user, mbalias.domain):
|
||||
raise PermDeniedException(_("You do not have access to this domain"))
|
||||
events.raiseEvent("MailboxAliasDeleted", mbalias)
|
||||
unset_object_ownership(mbalias)
|
||||
ungrant_access_to_object(mbalias)
|
||||
mbalias.delete()
|
||||
|
||||
msg = ungettext("Alias deleted", "Aliases deleted", len(selection))
|
||||
@@ -541,7 +543,7 @@ def create_domain_admin(request, tplname="admin/create_domain_admin.html"):
|
||||
form = UserWithPasswordForm(request.POST)
|
||||
if form.is_valid():
|
||||
user = form.save(group="DomainAdmins")
|
||||
set_object_ownership(request.user, user)
|
||||
grant_access_to_object(request.user, user, is_owner=True)
|
||||
events.raiseEvent("DomainAdminCreated", user)
|
||||
messages.info(request, _("Domain admin created"), fail_silently=True)
|
||||
return ajax_response(request, url=reverse(admin.views.permissions))
|
||||
@@ -588,7 +590,11 @@ def domain_admin_promotion(request):
|
||||
u = User.objects.get(username=form.cleaned_data["name"])
|
||||
u.groups.add(Group.objects.get(name="DomainAdmins"))
|
||||
u.save()
|
||||
set_object_ownership(request.user, u)
|
||||
if not can_access_object(request.user, u):
|
||||
# The only case where we need to grant access to the
|
||||
# object is when ``u`` has been create by a super
|
||||
# admin
|
||||
grant_access_to_object(request.user, u, is_owner=True)
|
||||
events.raiseEvent("DomainAdminCreated", u)
|
||||
messages.info(request, _("Domain admin added"), fail_silently=True)
|
||||
return ajax_response(request, url=reverse(admin.views.permissions))
|
||||
@@ -599,7 +605,38 @@ def domain_admin_promotion(request):
|
||||
|
||||
@login_required
|
||||
@permission_required("auth.view_permissions")
|
||||
@check_domain_ownership
|
||||
@transaction.commit_on_success
|
||||
def assign_domains_to_admin(request, da_id, tplname="admin/adminform.html"):
|
||||
da = User.objects.get(pk=da_id)
|
||||
ctx = dict(title=_("Assign domains to %s" % da.username),
|
||||
action=reverse(assign_domains_to_admin, args=[da_id]),
|
||||
formid="assignform",
|
||||
submit_label=_("Assign"))
|
||||
if request.method == "POST":
|
||||
form = AssignDomainsForm(request.user, da, request.POST)
|
||||
if form.is_valid():
|
||||
current_domains = get_user_domains(da)
|
||||
for domain in form.cleaned_data["domains"]:
|
||||
if not domain in current_domains:
|
||||
grant_access_to_object(da, domain)
|
||||
else:
|
||||
current_domains.remove(domain)
|
||||
for domain in current_domains:
|
||||
ungrant_access_to_object(domain, da)
|
||||
msg = ungettext("Domain assigned", "Domains assigned",
|
||||
len(form.cleaned_data["domains"]))
|
||||
messages.info(request, msg)
|
||||
return ajax_response(request, url=reverse(admin.views.permissions))
|
||||
ctx.update(form=form)
|
||||
return ajax_response(request, status="ko", template=tplname, **ctx)
|
||||
|
||||
form = AssignDomainsForm(request.user, da)
|
||||
ctx.update(form=form)
|
||||
return _render(request, tplname, ctx)
|
||||
|
||||
@login_required
|
||||
@permission_required("auth.view_permissions")
|
||||
@check_domain_access
|
||||
def search_account(request):
|
||||
search = request.POST.get("search", None)
|
||||
if search is None:
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
"""
|
||||
from modoboa.admin.models import Mailbox
|
||||
from modoboa.admin.lib import get_object_owner, set_object_ownership
|
||||
from modoboa.admin.lib import \
|
||||
get_object_owner, grant_access_to_object, is_object_owner, \
|
||||
ungrant_access_to_object
|
||||
from modoboa.lib import events
|
||||
from lib import *
|
||||
from models import *
|
||||
@@ -20,8 +22,6 @@ def check_limit(user, lname):
|
||||
|
||||
:param user: a ``User`` object
|
||||
"""
|
||||
if not is_reseller(user):
|
||||
return
|
||||
try:
|
||||
if user.limitspool.will_be_reached(lname):
|
||||
raise LimitReached(user.limitspool.get_limit(lname))
|
||||
@@ -107,16 +107,17 @@ def create_pool(user):
|
||||
@events.observe("DomainAdminDeleted")
|
||||
def move_pool_resource(domadmin):
|
||||
owner = get_object_owner(domadmin)
|
||||
for ooentry in domadmin.objectowner_set.all():
|
||||
obj = ooentry.content_object
|
||||
ooentry.delete()
|
||||
set_object_ownership(owner, obj)
|
||||
if not owner.is_superuser:
|
||||
for ooentry in domadmin.objectaccess_set.all():
|
||||
if ooentry.is_owner:
|
||||
grant_access_to_object(owner, ooentry.content_object, True)
|
||||
ooentry.delete()
|
||||
|
||||
for lname in reseller_limits_tpl:
|
||||
l = domadmin.limitspool.get_limit(lname)
|
||||
ol = owner.limitspool.get_limit(lname)
|
||||
ol.curvalue += l.curvalue
|
||||
ol.maxvalue += l.maxvalue
|
||||
ol.save()
|
||||
for lname in reseller_limits_tpl:
|
||||
l = domadmin.limitspool.get_limit(lname)
|
||||
ol = owner.limitspool.get_limit(lname)
|
||||
ol.curvalue += l.curvalue
|
||||
ol.maxvalue += l.maxvalue
|
||||
ol.save()
|
||||
|
||||
domadmin.limitspool.delete()
|
||||
|
||||
@@ -43,6 +43,20 @@ class LimitsPool(models.Model):
|
||||
l.curvalue -= nb
|
||||
l.save()
|
||||
|
||||
def dec_limit(self, lname, nb=1):
|
||||
l = self.limit_set.get(name=lname)
|
||||
l.curvalue -= nb
|
||||
if l.maxvalue > -1:
|
||||
l.maxvalue -= nb
|
||||
l.save()
|
||||
|
||||
def inc_limit(self, lname, nb=1):
|
||||
l = self.limit_set.get(name=lname)
|
||||
l.curvalue += nb
|
||||
if l.maxvalue > -1:
|
||||
l.maxvalue += nb
|
||||
l.save()
|
||||
|
||||
def will_be_reached(self, lname, nb=1):
|
||||
l = self.limit_set.get(name=lname)
|
||||
if l.maxvalue <= -1:
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
from django.utils.translation import ugettext as _, ugettext_noop
|
||||
from django.contrib.auth.models import User
|
||||
from modoboa.admin.permissions import Permissions
|
||||
from modoboa.admin.lib import set_object_ownership
|
||||
from modoboa.admin.models import ObjectOwner
|
||||
from modoboa.admin.lib import grant_access_to_object
|
||||
from modoboa.admin.models import ObjectAccess
|
||||
from modoboa.lib import events
|
||||
from modoboa.lib.webutils import _render, _render_to_string
|
||||
from tables import *
|
||||
@@ -24,7 +24,7 @@ class ResellersPerms(Permissions):
|
||||
error = None
|
||||
if form.is_valid():
|
||||
r = form.save(group="Resellers")
|
||||
set_object_ownership(request.user, r)
|
||||
grant_access_to_object(request.user, r, True)
|
||||
return True, None
|
||||
content = self._render_form(request, form, True)
|
||||
return False, dict(status="ko", content=content)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
import rrdtool
|
||||
#import rrdtool
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib import parameters
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ events = [
|
||||
"CanCreateDomain",
|
||||
"CreateDomain",
|
||||
"DeleteDomain",
|
||||
"DomainAssigned",
|
||||
|
||||
"CanCreateDomainAlias",
|
||||
"DomainAliasCreated",
|
||||
|
||||
@@ -188,4 +188,12 @@ html[xmlns] .clearfix {
|
||||
|
||||
#permform > #id_name {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assign domains form
|
||||
*/
|
||||
#assignform #id_domains {
|
||||
width: 310px;
|
||||
height: 200px;
|
||||
}
|
||||
Reference in New Issue
Block a user