wip: Limits and resellers

* refactoring, limits are working pretty well
* domain admins can now create domains (under control) when the limits extension is enabled

see #105
This commit is contained in:
Antoine Nguyen
2012-01-24 11:23:31 +01:00
parent 3681bb4198
commit 1c51e97179
18 changed files with 300 additions and 88 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ def loadextensions(prefix):
try:
ext = Extension.objects.get(name=f)
if ext.enabled:
module.main.init()
ext.load()
except Extension.DoesNotExist:
pass
u = module.main.urls(prefix)
+44 -6
View File
@@ -5,6 +5,7 @@
"""
from modoboa.admin.models import Mailbox
from modoboa.admin.lib import get_object_owner, set_object_ownership
from modoboa.lib import events
from lib import *
from models import *
@@ -48,8 +49,15 @@ def inc_nb_domains(user, domain):
inc_limit(user, 'domains_limit')
@events.observe('DeleteDomain')
def dec_nb_domains(user, domain):
dec_limit(user, 'domains_limit')
def dec_nb_domains(domain):
owner = get_object_owner(domain)
dec_limit(owner, 'domains_limit')
for domalias in domain.domainalias_set.all():
dec_nb_domaliases(domalias)
for mailbox in domain.mailbox_set.all():
dec_nb_mailboxes(mailbox)
for mbalias in domain.alias_set.all():
dec_nb_mbaliases(mbalias)
@events.observe('CanCreateDomainAlias')
def check_domaliases_limit(user):
@@ -60,8 +68,9 @@ def inc_nb_domaliases(user, domalias):
inc_limit(user, 'domain_aliases_limit')
@events.observe('DomainAliasDeleted')
def dec_nb_domaliases(user, domainalias):
dec_limit(user, 'domain_aliases_limit')
def dec_nb_domaliases(domainalias):
owner = get_object_owner(domainalias)
dec_limit(owner, 'domain_aliases_limit')
@events.observe('CanCreateMailbox')
def check_mboxes_limit(user):
@@ -72,8 +81,9 @@ def inc_nb_mailboxes(user, mailbox):
inc_limit(user, 'mailboxes_limit')
@events.observe('DeleteMailbox')
def dec_nb_mailboxes(user, mailbox):
dec_limit(user, 'mailboxes_limit')
def dec_nb_mailboxes(mailbox):
owner = get_object_owner(mailbox)
dec_limit(owner, 'mailboxes_limit')
@events.observe('CanCreateMailboxAlias')
def check_mbaliases_limit(user):
@@ -82,3 +92,31 @@ def check_mbaliases_limit(user):
@events.observe('MailboxAliasCreated')
def inc_nb_mbaliases(user, mailboxalias):
inc_limit(user, 'mailbox_aliases_limit')
@events.observe('MailboxAliasDeleted')
def dec_nb_mbaliases(mailboxalias):
owner = get_object_owner(mailboxalias)
dec_limit(owner, 'mailbox_aliases_limit')
@events.observe("DomainAdminCreated")
def create_pool(user):
p = LimitsPool(user=user)
p.save()
p.create_limits()
@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)
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()
+24 -7
View File
@@ -4,7 +4,9 @@ from django import forms
from django.utils.translation import ugettext_noop as _
from django.contrib.auth.models import User, Group
from modoboa.admin.forms import UserForm, UserWithPasswordForm
from modoboa.admin.lib import get_object_owner
from models import *
from lib import *
class ResellerForm(UserForm):
def __init__(self, *args, **kwargs):
@@ -19,14 +21,8 @@ class ResellerForm(UserForm):
except LimitsPool.DoesNotExist:
pool = LimitsPool()
pool.user = user
print pool.user
pool.save()
for lname in reseller_limits_tpl:
l = Limit()
l.name = lname
l.pool = pool
l.save()
pool.create_limits()
return user
@@ -64,9 +60,30 @@ class ResellerPoolForm(forms.Form):
for l in reseller_limits_tpl:
self.fields[l].initial = user.limitspool.getmaxvalue(l)
def allocate_from_pool(self, limit, pool):
ol = pool.get_limit(limit.name)
if ol.maxvalue == -2:
raise BadLimitValue(_("Your pool is not initialized yet"))
newvalue = self.cleaned_data[limit.name]
if newvalue == -1 and ol.maxvalue != -1:
raise BadLimitValue(_("You're not allowed to define unlimited values"))
if limit.maxvalue > -1:
newvalue -= limit.maxvalue
if newvalue == 0:
return
remain = ol.maxvalue - ol.curvalue
if newvalue > remain:
raise UnsifficientResource(ol)
ol.maxvalue -= newvalue
ol.save()
def save_new_limits(self, pool):
owner = get_object_owner(pool.user)
for lname in reseller_limits_tpl:
l = pool.limit_set.get(name=lname)
if not owner.is_superuser:
self.allocate_from_pool(l, owner.limitspool)
l.maxvalue = self.cleaned_data[lname]
l.save()
+8
View File
@@ -5,6 +5,7 @@
"""
from django.contrib.auth.models import Group
from django.utils.translation import ugettext as _
from modoboa.lib.exceptions import ModoboaException
class LimitReached(ModoboaException):
@@ -14,6 +15,13 @@ class LimitReached(ModoboaException):
def __str__(self):
return "%s reached" % self.limit.name
class UnsifficientResource(ModoboaException):
def __init__(self, limit):
self.limit = limit
def __str__(self):
return _("Not enough resource into your pool")
class BadLimitValue(ModoboaException):
pass
+25 -2
View File
@@ -6,6 +6,8 @@ The *limits* extension
"""
from django.contrib.auth.models import Permission, Group
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_noop as _, ugettext
from django.core.urlresolvers import reverse
from django.conf.urls.defaults import include
@@ -14,14 +16,25 @@ from modoboa.lib.webutils import static_url
from models import *
import permissions
import controls
import views
baseurl = "limits"
def init():
pass
ct = ContentType.objects.get(app_label="admin", model="domain")
grp = Group.objects.get(name="DomainAdmins")
for pname in ["view_domains", "add_domain", "change_domain", "delete_domain"]:
perm = Permission.objects.get(content_type=ct, codename=pname)
grp.permissions.add(perm)
grp.save()
def destroy():
pass
ct = ContentType.objects.get(app_label="admin", model="domain")
grp = Group.objects.get(name="DomainAdmins")
for pname in ["view_domains", "add_domain", "change_domain", "delete_domain"]:
perm = Permission.objects.get(content_type=ct, codename=pname)
grp.permissions.remove(perm)
grp.save()
def infos():
return {
@@ -53,3 +66,13 @@ def display_pool_usage(user, objtype):
label = str(l.maxvalue)
return [_("Pool usage: %s / %s") % (l.curvalue, label)]
@events.observe("DomainAdminActions")
def get_da_actions(user):
return [
{"name" : "editpool",
"url" : reverse(views.edit_limits_pool, args=[user.id]),
"img" : static_url("pics/settings.png"),
"title" : _("Edit limits allocated to this domain admin"),
"class" : "boxed",
"rel" : "{handler:'iframe',size:{x:330,y:280}}"},
]
+9
View File
@@ -16,6 +16,13 @@ reseller_limits_tpl = [
class LimitsPool(models.Model):
user = models.OneToOneField(User)
def create_limits(self):
for lname in reseller_limits_tpl:
l = Limit()
l.name = lname
l.pool = self
l.save()
def getcurvalue(self, lname):
l = self.limit_set.get(name=lname)
return l.curvalue
@@ -56,3 +63,5 @@ class Limit(models.Model):
maxvalue = models.IntegerField(default=-2)
pool = models.ForeignKey(LimitsPool)
class Meta:
unique_together = (("name", "pool"),)
+12 -2
View File
@@ -3,6 +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.lib import events
from modoboa.lib.webutils import _render, _render_to_string
from tables import *
@@ -21,13 +23,21 @@ class ResellersPerms(Permissions):
form = ResellerWithPasswordForm(request.POST)
error = None
if form.is_valid():
form.save(group="Resellers")
r = form.save(group="Resellers")
set_object_ownership(request.user, r)
return True, None
content = self._render_form(request, form, True)
return False, dict(status="ko", content=content)
def delete(self, selection):
User.objects.filter(id__in=selection).delete()
ct = ContentType.objects.get_for_model(User)
for u in User.objects.filter(id__in=selection):
try:
ObjectOwner.objects.get(content_type=ct, object_id=u.id).delete()
except ObjectOwner.DoesNotExist:
pass
u.delete()
def get(self, request):
resellers = User.objects.filter(groups__name="Resellers")
+1 -1
View File
@@ -10,7 +10,7 @@ window.addEvent("domready", function() {
{% endblock %}
{% block content %}
<div class="title"><h1>{% trans "Limits pool for" %} {{ reseller.username }}</h1></div>
{% if error %}<div class="error">{{ error }}</div>{% endif %}
<div class="error">{% if error %}{{ error }}{% endif %}</div>
<form action="{% url extensions.limits.views.edit_limits_pool reseller.id %}"
method="POST" id="limits_pool_form" name="limits_pool_form">
{% include "common/genericform.html" %}
+4 -3
View File
@@ -1,10 +1,10 @@
# coding: utf-8
from django.utils.translation import ugettext as _
from django.db import IntegrityError
from django.db import IntegrityError, transaction
from django.contrib.auth.models import *
from django.contrib import messages
from django.contrib.auth.decorators \
import login_required, user_passes_test
import login_required, user_passes_test, permission_required
from django.core.urlresolvers import reverse
from forms import *
from modoboa.lib.webutils import _render, ajax_response
@@ -39,7 +39,8 @@ def edit_reseller(request, resid, tplname="admin/add_permission.html"):
return _render(request, tplname, ctx)
@login_required
@user_passes_test(lambda u: u.is_superuser)
@permission_required("auth.view_permissions")
@transaction.commit_on_success
def edit_limits_pool(request, resid, tplname="limits/pool.html"):
reseller = User.objects.get(pk=resid)
ctx = dict(reseller=reseller)