Refactoring and Shorcuts added:

* Possibility to create an administrator with a new domain
* Possibility to create default aliases with a new domain

fixes #344
This commit is contained in:
Antoine Nguyen
2013-04-30 15:39:08 +02:00
parent 538c0a406f
commit efc851d57b
11 changed files with 371 additions and 181 deletions
+67 -67
View File
@@ -8,7 +8,6 @@ from modoboa.admin.templatetags.admin_extras import gender
from modoboa.lib.emailutils import split_mailbox
from modoboa.lib.permissions import get_account_roles
from modoboa.lib.formutils import *
from modoboa.lib.permissions import *
class DomainFormGeneral(forms.ModelForm, DynamicForm):
@@ -101,9 +100,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
continue
events.raiseEvent("CanCreate", user, "domain_aliases")
al = DomainAlias(name=v, target=d, enabled=d.enabled)
al.save()
grant_access_to_object(user, al, is_owner=True)
events.raiseEvent("DomainAliasCreated", user, al)
al.save(creator=user)
for dalias in d.domainalias_set.all():
if not len(filter(lambda name: self.cleaned_data[name] == dalias.name,
@@ -112,6 +109,67 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
return d
class DomainFormOptions(forms.Form):
create_dom_admin = YesNoField(
label=ugettext_lazy("Create a domain administrator"),
initial="no",
help_text=ugettext_lazy("Automatically create an administrator for this domain")
)
dom_admin_username = forms.CharField(
label=ugettext_lazy("Name"),
initial="admin",
help_text=ugettext_lazy("The administrator's name. Don't include the domain's name here, it will be automatically appended."),
widget=forms.widgets.TextInput(attrs={"class": "input-small"}),
required=False
)
create_aliases = YesNoField(
label=ugettext_lazy("Create aliases"),
initial="yes",
help_text=ugettext_lazy("Automatically create standard aliases for this domain"),
required=False
)
def __init__(self, *args, **kwargs):
super(DomainFormOptions, self).__init__(*args, **kwargs)
if args:
if args[0].get("create_dom_admin", "no") == "yes":
self.fields["dom_admin_username"].required = True
self.fields["create_aliases"].required = True
def clean_dom_admin_username(self):
if '@' in self.cleaned_data["dom_admin_username"]:
raise forms.ValidationError(_("Invalid format"))
return self.cleaned_data["dom_admin_username"]
def save(self, user, domain):
if self.cleaned_data["create_dom_admin"] == "no":
return
username = "%s@%s" % (self.cleaned_data["dom_admin_username"], domain.name)
try:
da = User.objects.get(username=username)
except User.DoesNotExist:
pass
else:
raise AdminError(_("User '%s' already exists" % username))
da = User(username=username, email=username, is_active=True)
da.set_password("password")
da.save()
da.set_role("DomainAdmins")
da.post_create(user)
mb = Mailbox(address=self.cleaned_data["dom_admin_username"], domain=domain,
user=da, use_domain_quota=True)
mb.set_quota()
mb.save(creator=user)
if self.cleaned_data["create_aliases"] == "yes":
al = Alias(address="postmaster", domain=domain, enabled=True)
al.save([mb], [], creator=user)
domain.add_admin(da)
class DomainForm(TabForms):
def __init__(self, user, *args, **kwargs):
self.user = user
@@ -464,19 +522,6 @@ class AccountFormGeneral(forms.ModelForm):
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
def give_all_accesses(self, account):
"""Give access to all objects defined in the database
Must be used when an account is promoted as a super user.
:param account: a ``User`` instance
"""
grant_access_to_objects(account, User.objects.all(), get_content_type(User))
grant_access_to_objects(account, Domain.objects.all(), get_content_type(Domain))
grant_access_to_objects(account, DomainAlias.objects.all(), get_content_type(DomainAlias))
grant_access_to_objects(account, Mailbox.objects.all(), get_content_type(Mailbox))
grant_access_to_objects(account, Alias.objects.all(), get_content_type(Alias))
def save(self, commit=True):
account = super(AccountFormGeneral, self).save(commit=False)
if self.user == account and not self.cleaned_data["is_active"]:
@@ -490,20 +535,7 @@ class AccountFormGeneral(forms.ModelForm):
role = self.cleaned_data["role"]
elif self.user.group == "DomainAdmins" and self.user != account:
role = "SimpleUsers"
if role is None or account.group == role:
return account
account.groups.clear()
if role == "SuperAdmins":
account.is_superuser = True
self.give_all_accesses(account)
else:
if account.is_superuser:
ObjectAccess.objects.filter(user=account).delete()
account.is_superuser = False
account.groups.add(Group.objects.get(name=role))
account.save()
account.set_role(role)
return account
@@ -576,18 +608,7 @@ class AccountFormMail(forms.Form, DynamicForm):
use_domain_quota=self.cleaned_data["quota_act"])
self.mb.set_quota(self.cleaned_data["quota"],
user.has_perm("admin.add_domain"))
self.mb.save()
grant_access_to_object(user, self.mb, is_owner=True)
events.raiseEvent("CreateMailbox", user, self.mb)
if user.is_superuser and not self.mb.user.has_perm("admin.add_domain"):
# A super user is creating a new mailbox. Give
# access to that mailbox (and the associated
# account) to the appropriate domain admins,
# except if the new account has a more important
# role (SuperAdmin, Reseller)
for admin in self.mb.domain.admins:
grant_access_to_object(admin, self.mb)
grant_access_to_object(admin, self.mb.user)
self.mb.save(creator=user)
else:
newaddress = None
if self.cleaned_data["email"] != self.mb.full_address:
@@ -627,20 +648,13 @@ class AccountFormMail(forms.Form, DynamicForm):
events.raiseEvent("CanCreate", user, "mailbox_aliases")
al = Alias(address=local_part, enabled=account.is_active)
al.domain = Domain.objects.get(name=domname)
al.save([self.mb], [])
grant_access_to_object(user, al, is_owner=True)
events.raiseEvent("MailboxAliasCreated", user, al)
if user.is_superuser:
for admin in al.domain.admins:
grant_access_to_object(admin, al)
al.save([self.mb], [], creator=user)
for alias in self.mb.alias_set.all():
if len(alias.get_recipients()) >= 2:
continue
if not len(filter(lambda name: self.cleaned_data[name] == alias.full_address,
self.cleaned_data.keys())):
events.raiseEvent("MailboxAliasDeleted", alias)
ungrant_access_to_object(alias)
alias.delete()
return self.mb
@@ -677,26 +691,12 @@ class AccountPermissionsForm(forms.Form, DynamicForm):
continue
if not value in current_domains:
domain = Domain.objects.get(name=value)
grant_access_to_object(self.account, domain)
for mb in domain.mailbox_set.all():
if mb.user.has_perm("admin.add_domain"):
continue
grant_access_to_object(self.account, mb)
grant_access_to_object(self.account, mb.user)
for al in Alias.objects.filter(domain=domain):
grant_access_to_object(self.account, al)
domain.add_admin(self.account)
for domain in self.account.get_domains():
if not len(filter(lambda name: self.cleaned_data[name] == domain.name,
self.cleaned_data.keys())):
ungrant_access_to_object(domain, self.account)
for mb in domain.mailbox_set.all():
if mb.user.has_perm("admin.add_domain"):
continue
ungrant_access_to_object(mb, self.account)
ungrant_access_to_object(mb.user, self.account)
for al in Alias.objects.filter(domain=domain):
ungrant_access_to_object(al, self.account)
domain.remove_admin(self.account)
class AccountForm(TabForms):
+193 -56
View File
@@ -14,8 +14,9 @@ from modoboa.lib.exceptions import PermDeniedException
from modoboa.lib.sysutils import exec_cmd, exec_as_vuser
from modoboa.lib.emailutils import split_mailbox
from modoboa.extensions import exts_pool
from exceptions import *
import os, sys
from exceptions import AdminError
import os
import sys
import pwd
import re
import crypt, hashlib, string, base64
@@ -27,6 +28,7 @@ try:
except ImportError:
ldap_available = False
class User(DUser):
"""Proxy for the ``User`` model.
@@ -216,7 +218,7 @@ class User(DUser):
return self.groups.all()[0].name
except IndexError:
return "?"
@property
def enabled(self):
return self.is_active
@@ -269,7 +271,7 @@ class User(DUser):
else:
q &= Q(groups__name__in=grpfilter)
accounts = User.objects.select_related().filter(q)
aliases = []
if not idtfilter or ("alias" in idtfilter
or "forward" in idtfilter
@@ -290,7 +292,6 @@ class User(DUser):
return chain(accounts, aliases)
def get_domains(self):
"""Return the domains belonging to this user
@@ -408,6 +409,54 @@ class User(DUser):
return True
return False
def grant_access_to_all_objects(self):
"""Give access to all objects defined in the database
Must be used when an account is promoted as a super user.
"""
from modoboa.lib.permissions import grant_access_to_objects, get_content_type
grant_access_to_objects(self, User.objects.all(), get_content_type(User))
grant_access_to_objects(self, Domain.objects.all(), get_content_type(Domain))
grant_access_to_objects(self, DomainAlias.objects.all(), get_content_type(DomainAlias))
grant_access_to_objects(self, Mailbox.objects.all(), get_content_type(Mailbox))
grant_access_to_objects(self, Alias.objects.all(), get_content_type(Alias))
def set_role(self, role):
"""Set administrative role for this account
:param string role: the role to set
"""
if role is None or self.group == role:
return
self.groups.clear()
if role == "SuperAdmins":
self.is_superuser = True
self.grant_access_to_all_objects()
else:
if self.is_superuser:
ObjectAccess.objects.filter(user=self).delete()
self.is_superuser = False
try:
self.groups.add(Group.objects.get(name=role))
except Group.DoesNotExist:
self.groups.add(Group.objects.get(name="SimpleUsers"))
self.save()
def post_create(self, creator):
from modoboa.lib.permissions import grant_access_to_object
grant_access_to_object(creator, self, is_owner=True)
events.raiseEvent("AccountCreated", self)
def save(self, *args, **kwargs):
if "creator" in kwargs:
creator = kwargs["creator"]
del kwargs["creator"]
else:
creator = None
super(User, self).save(*args, **kwargs)
if creator is not None:
self.post_create(creator)
def from_csv(self, user, row, crypt_password=True):
"""Create a new account from a CSV file entry
@@ -419,8 +468,6 @@ class User(DUser):
:param row: a list containing the expected information
:param crypt_password:
"""
from modoboa.lib.permissions import grant_access_to_object
if len(row) < 6:
raise AdminError(_("Invalid line"))
self.username = row[1].strip()
@@ -431,17 +478,8 @@ class User(DUser):
self.first_name = row[3].strip()
self.last_name = row[4].strip()
self.is_active = (row[5].strip() == 'True')
grpname = row[6].strip()
if grpname == "SuperAdmins":
self.is_superuser = True
self.save()
else:
self.save()
try:
self.groups.add(Group.objects.get(name=grpname))
except Group.DoesNotExist:
self.groups.add(Group.objects.get(name="SimpleUsers"))
self.save()
self.save(creator=user)
self.set_role(row[6].strip())
self.email = row[7].strip()
if self.email != "":
@@ -454,12 +492,11 @@ class User(DUser):
raise PermDeniedException
mb = Mailbox(address=mailbox, domain=domain, user=self, use_domain_quota=True)
mb.set_quota(override_rules=user.has_perm("admin.change_domain"))
mb.save()
self.save()
if grpname == "DomainAdmins":
mb.save(creator=user)
if self.group == "DomainAdmins":
for domname in row[8:]:
try:
grant_access_to_object(self, Domain.objects.get(name=domname))
Domain.objects.get(name=domname).add_admin(self)
except Domain.DoesNotExist:
pass
@@ -470,7 +507,8 @@ class User(DUser):
if self.group == "DomainAdmins":
row += [dom.name for dom in self.get_domains()]
csvwriter.writerow(row)
class ObjectAccess(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
@@ -483,7 +521,8 @@ class ObjectAccess(models.Model):
def __unicode__(self):
return "%s => %s (%s)" % (self.user, self.content_object, self.content_type)
class ObjectDates(models.Model):
"""Dates recording for admin objects
@@ -530,21 +569,26 @@ class DatesAware(models.Model):
def last_modification(self):
return self.dates.last_modification
class Domain(DatesAware):
name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True,
help_text=ugettext_lazy("The domain name"))
quota = models.IntegerField(help_text=ugettext_lazy("Default quota in MB applied to mailboxes"))
enabled = models.BooleanField(ugettext_lazy('enabled'),
help_text=ugettext_lazy("Check to activate this domain"))
quota = models.IntegerField(
help_text=ugettext_lazy("Default quota in MB applied to mailboxes")
)
enabled = models.BooleanField(
ugettext_lazy('enabled'),
help_text=ugettext_lazy("Check to activate this domain")
)
owners = generic.GenericRelation(ObjectAccess)
class Meta:
permissions = (
("view_domain", "View domain"),
("view_domains", "View domains"),
)
)
ordering = ["name"]
@property
def domainalias_count(self):
return self.domainalias_set.count()
@@ -559,8 +603,42 @@ class Domain(DatesAware):
@property
def admins(self):
"""Return the domain administrators of this domain
:return: a list of User objects
"""
return [oa.user for oa in self.owners.filter(user__is_superuser=False)]
def add_admin(self, account):
"""Add a new administrator for this domain
:param User account: the administrotor to add
"""
from modoboa.lib.permissions import grant_access_to_object
grant_access_to_object(account, self)
for mb in self.mailbox_set.all():
if mb.user.has_perm("admin.add_domain"):
continue
grant_access_to_object(account, mb)
grant_access_to_object(account, mb.user)
for al in self.alias_set.all():
grant_access_to_object(account, al)
def remove_admin(self, account):
"""Remove an administrator for this domain
:param User account: the administrotor to remove
"""
from modoboa.lib.permissions import ungrant_access_to_object
ungrant_access_to_object(account, self)
for mb in self.mailbox_set.all():
if mb.user.has_perm("admin.add_domain"):
continue
ungrant_access_to_object(mb, account)
ungrant_access_to_object(mb.user, account)
for al in self.alias_set.all():
ungrant_access_to_object(al, account)
def delete(self, fromuser, keepdir=False):
from modoboa.lib.permissions import ungrant_access_to_object, ungrant_access_to_objects
@@ -588,13 +666,28 @@ class Domain(DatesAware):
def __str__(self):
return self.name
def post_create(self, creator):
from modoboa.lib.permissions import grant_access_to_object
grant_access_to_object(creator, self, is_owner=True)
events.raiseEvent("CreateDomain", creator, self)
def save(self, *args, **kwargs):
if "creator" in kwargs:
creator = kwargs["creator"]
del kwargs["creator"]
else:
creator = None
super(Domain, self).save(*args, **kwargs)
if creator is not None:
self.post_create(creator)
def from_csv(self, user, row):
if len(row) < 4:
raise AdminError(_("Invalid line"))
self.name = row[1].strip()
self.quota = int(row[2].strip())
self.enabled = (row[3].strip() == 'True')
self.save()
self.save(creator=user)
def to_csv(self, csvwriter):
csvwriter.writerow(["domain", self.name, self.quota, self.enabled])
@@ -603,21 +696,38 @@ class Domain(DatesAware):
class DomainAlias(DatesAware):
name = models.CharField(ugettext_lazy("name"), max_length=100, unique=True,
help_text=ugettext_lazy("The alias name"))
target = models.ForeignKey(Domain, verbose_name=ugettext_lazy('target'),
help_text=ugettext_lazy("The domain this alias points to"))
target = models.ForeignKey(
Domain, verbose_name=ugettext_lazy('target'),
help_text=ugettext_lazy("The domain this alias points to")
)
enabled = models.BooleanField(
ugettext_lazy('enabled'),
help_text=ugettext_lazy("Check to activate this alias")
)
)
class Meta:
permissions = (
("view_domaliases", "View domain aliases"),
)
)
def __unicode__(self):
return self.name
def post_create(self, creator):
from modoboa.lib.permissions import grant_access_to_object
grant_access_to_object(creator, self, is_owner=True)
events.raiseEvent("DomainAliasCreated", creator, self)
def save(self, *args, **kwargs):
if "creator" in kwargs:
creator = kwargs["creator"]
del kwargs["creator"]
else:
creator = None
super(DomainAlias, self).save(*args, **kwargs)
if creator is not None:
self.post_create(creator)
def delete(self):
from modoboa.lib.permissions import ungrant_access_to_object
events.raiseEvent("DomainAliasDeleted", self)
@@ -628,7 +738,7 @@ class DomainAlias(DatesAware):
"""Create a domain alias from a CSV row
Expected format: ["domainalias", domain alias name, targeted domain, enabled]
:param user: a ``User`` object
:param row: a list containing the alias definition
"""
@@ -641,7 +751,7 @@ class DomainAlias(DatesAware):
except Domain.DoesNotExist:
raise AdminError(_("Unknown domain %s" % domname))
self.enabled = row[3].strip() == 'True'
self.save()
self.save(creator=user)
def to_csv(self, csvwriter):
"""Export a domain alias using CSV format
@@ -650,11 +760,12 @@ class DomainAlias(DatesAware):
"""
csvwriter.writerow(["domainalias", self.name, self.target.name, self.enabled])
class Mailbox(DatesAware):
address = models.CharField(
ugettext_lazy('address'), max_length=100,
help_text=ugettext_lazy("Mailbox address (without the @domain.tld part)")
)
)
quota = models.PositiveIntegerField()
use_domain_quota = models.BooleanField(default=False)
domain = models.ForeignKey(Domain)
@@ -671,10 +782,10 @@ class Mailbox(DatesAware):
def __str__(self):
return self.full_address
def __full_address(self, localpart):
return "%s@%s" % (localpart, self.domain.name)
@property
def full_address(self):
return self.__full_address(self.address)
@@ -776,8 +887,29 @@ class Mailbox(DatesAware):
q = Quota.objects.get(username=self.full_address)
return int(q.bytes / float(self.quota * 1048576) * 100)
def post_create(self, creator):
from modoboa.lib.permissions import grant_access_to_object
grant_access_to_object(creator, self, True)
events.raiseEvent("CreateMailbox", creator, self)
if creator.is_superuser and not self.user.has_perm("admin.add_domain"):
# A super user is creating a new mailbox. Give
# access to that mailbox (and the associated
# account) to the appropriate domain admins,
# except if the new account has a more important
# role (SuperAdmin, Reseller)
for admin in self.domain.admins:
grant_access_to_object(admin, self)
grant_access_to_object(admin, self.user)
def save(self, *args, **kwargs):
if "creator" in kwargs:
creator = kwargs["creator"]
del kwargs["creator"]
else:
creator = None
super(Mailbox, self).save(*args, **kwargs)
if creator is not None:
self.post_create(creator)
try:
q = self.quota_value
except Quota.DoesNotExist:
@@ -889,12 +1021,27 @@ class Alias(DatesAware):
altype = self.type
return [{"name" : altype, "label" : labels[altype], "type" : "idt"}]
def post_create(self, creator):
from modoboa.lib.permissions import grant_access_to_object
grant_access_to_object(creator, self, is_owner=True)
events.raiseEvent("MailboxAliasCreated", creator, self)
if creator.is_superuser:
for admin in self.domain.admins:
grant_access_to_object(admin, self)
def save(self, int_rcpts, ext_rcpts, *args, **kwargs):
if len(ext_rcpts):
self.extmboxes = ",".join(ext_rcpts)
else:
self.extmboxes = ""
if "creator" in kwargs:
creator = kwargs["creator"]
del kwargs["creator"]
else:
creator = None
super(Alias, self).save(*args, **kwargs)
if creator is not None:
self.post_create(creator)
curmboxes = self.mboxes.all()
for t in int_rcpts:
if not t in curmboxes:
@@ -961,7 +1108,7 @@ class Alias(DatesAware):
domain__name=domname)]
except Mailbox.DoesNotExist:
raise AdminError(_("Mailbox %s does not exist" % rcpt))
self.save(int_rcpts, ext_rcpts)
self.save(int_rcpts, ext_rcpts, creator=user)
def to_csv(self, csvwriter):
row = [self.type, self.full_address, self.enabled]
@@ -1032,11 +1179,8 @@ def populate_callback(user):
from modoboa.lib.permissions import grant_access_to_object
sadmins = User.objects.filter(is_superuser=True)
user.groups.add(Group.objects.get(name="SimpleUsers"))
user.save()
events.raiseEvent("AccountCreated", user)
grant_access_to_object(sadmins[0], user, True)
user.set_role("SimpleUsers")
user.post_create(sadmins[0])
for su in sadmins[1:]:
grant_access_to_object(su, user)
@@ -1044,13 +1188,8 @@ def populate_callback(user):
try:
domain = Domain.objects.get(name=domname)
except Domain.DoesNotExist:
domain = Domain()
domain.name = domname
domain.enabled = True
domain.quota = 0
domain.save()
events.raiseEvent("CreateDomain", sadmins[0], domain)
grant_access_to_object(sadmins[0], domain, True)
domain = Domain(name=domname, enabled=True, quota=0)
domain.save(creator=sadmin[0])
for su in sadmins[1:]:
grant_access_to_object(su, domain)
try:
@@ -1058,8 +1197,6 @@ def populate_callback(user):
except Mailbox.DoesNotExist:
mb = Mailbox(address=localpart, domain=domain, user=user, use_domain_quota=True)
mb.set_quota()
mb.save()
events.raiseEvent("CreateMailbox", sadmins[0], mb)
grant_access_to_object(sadmins[0], mb, True)
mb.save(creator=sadmins[0])
for su in sadmins[1:]:
grant_access_to_object(su, domain)
grant_access_to_object(su, mb)
+56 -9
View File
@@ -161,17 +161,35 @@ Domains.prototype = {
});
},
domainform_cb: function() {
change_inputs_state: function(value) {
$("#id_dom_admin_username").attr("disabled", value);
$("input[name=create_aliases]").attr("disabled", value);
},
create_dom_admin_changed: function(e) {
var $target = $(e.target);
this.change_inputs_state(($target.attr("value") == "yes") ? false : true);
},
generalform_init: function() {
$('input:text:visible:first').focus();
$("#id_aliases").dynamic_input();
$(".submit").one('click', $.proxy(function(e) {
simple_ajax_form_post(e, {
formid: "domform",
error_cb: $.proxy(this.domainform_cb, this),
reload_on_success: false,
success_cb: $.proxy(this.reload_listing, this)
});
}, this));
},
optionsform_init: function() {
$("input[name=create_dom_admin]").click($.proxy(this.create_dom_admin_changed, this));
this.change_inputs_state(
$("input[name=create_dom_admin]:checked").attr("value") == "yes" ? false : true
);
this.optionsform_prefill();
},
optionsform_prefill: function() {
var $span = $("#id_dom_admin_username").next("span");
$span.html("@" + $("#id_name").attr("value"));
},
domadminsform_init: function() {
$("a[name=removeperm]").click(function(e) {
var $tr = $(this).parent().parent();
simple_ajax_request.apply(this, [e, {
@@ -184,6 +202,35 @@ Domains.prototype = {
}
}]);
});
},
newdomain_cb: function() {
this.generalform_init();
this.optionsform_init();
$("#wizard").cwizard({
formid: "domform",
transition_callbacks: {
1: this.optionsform_prefill
},
error_callbacks: {
1: this.generalform_init,
2: $.proxy(this.optionsform_init, this)
},
success_callback: $.proxy(this.reload_listing, this)
});
},
domainform_cb: function() {
this.generalform_init();
this.domadminsform_init();
$(".submit").one('click', $.proxy(function(e) {
simple_ajax_form_post(e, {
formid: "domform",
error_cb: $.proxy(this.domainform_cb, this),
reload_on_success: false,
success_cb: $.proxy(this.reload_listing, this)
});
}, this));
$(document).trigger('domform_init');
}
@@ -0,0 +1,4 @@
{% load i18n libextras %}
{% render_field form.create_dom_admin %}
{% render_field_appended form.dom_admin_username "@" %}
{% render_field form.create_aliases %}
@@ -2,10 +2,7 @@
{% block pagetitle %}{% trans "Identities" %}{% endblock %}
{% block html_head %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/jquery.sortable.css" />
<script type="text/javascript" src="{{ STATIC_URL }}js/creation_wizard.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/autocompleter.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/jquery.sortable.js"></script>
<script type="text/javascript">
function get_domains_list(container) {
$.getJSON("{% url 'modoboa.admin.views.domains_list' %}", function(data) {
@@ -1,7 +1,10 @@
{% extends "admin/header.html" %}{% load i18n admin_extras libextras %}
{% block html_head %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/jquery.sortable.css" />
<script type="text/javascript" src="{{ STATIC_URL }}js/creation_wizard.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/dynamic_input.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/jquery.sortable.js"></script>
<script type="text/javascript">
var admin;
</script>
+1 -1
View File
@@ -76,7 +76,7 @@ def domains_menu(selection, user):
"label" : _("Add domain"),
"img" : "icon-plus",
"modal" : True,
"modalcb" : "admin.domainform_cb",
"modalcb" : "admin.newdomain_cb",
"url" : reverse("modoboa.admin.views.newdomain")},
{"name" : "import",
"label" : _("Import"),
+41 -38
View File
@@ -20,7 +20,8 @@ from modoboa.lib.webutils \
import _render, ajax_response, ajax_simple_response, _render_to_string
from modoboa.lib.emailutils import split_mailbox
from modoboa.lib.models import Parameter
from modoboa.lib.permissions import *
from modoboa.lib.formutils import CreationWizard
@login_required
def index(request):
@@ -67,8 +68,6 @@ def _validate_domain(request, form, successmsg, commonctx, tplname,
domain = form.save(request.user)
except AdminError, e:
error = str(e)
# except IntegrityError:
# error = _("An alias with this name already exists")
else:
if callback is not None:
callback(request.user, domain)
@@ -81,23 +80,49 @@ def _validate_domain(request, form, successmsg, commonctx, tplname,
@login_required
@permission_required("admin.add_domain")
@transaction.commit_on_success
def newdomain(request, tplname="admin/newdomainform.html"):
def newdomain(request, tplname="common/wizard_forms.html"):
events.raiseEvent("CanCreate", request.user, "domains")
def newdomain_cb(user, domain):
grant_access_to_object(user, domain, is_owner=True)
events.raiseEvent("CreateDomain", user, domain)
def newdomain_cb(steps):
genform = steps[0]["form"]
genform.is_valid()
domain = genform.save(request.user)
domain.post_create(request.user)
steps[1]["form"].save(request.user, domain)
commonctx = {"title" : _("New domain"),
"action_label" : _("Create"),
"action_classes" : "submit",
"action" : reverse(newdomain),
"formid" : "domform"}
cwizard = CreationWizard(newdomain_cb)
cwizard.add_step(DomainFormGeneral, _("General"),
[dict(classes="btn-inverse next", label=_("Next"))],
formtpl="admin/domain_general_form.html")
cwizard.add_step(DomainFormOptions, _("Options"),
[dict(classes="btn-primary submit", label=_("Create")),
dict(classes="btn-inverse prev", label=_("Previous"))],
formtpl="admin/domain_options_form.html")
if request.method == "POST":
form = DomainFormGeneral(request.POST)
return _validate_domain(request, form, _("Domain created"), commonctx,
tplname, callback=newdomain_cb)
form = DomainFormGeneral()
commonctx["form"] = form
retcode, data = cwizard.validate_step(request)
if retcode == -1:
raise AdminError(data)
if retcode == 1:
return ajax_simple_response(dict(
status="ok", title=cwizard.get_title(data + 1), stepid=data
))
if retcode == 2:
return ajax_simple_response(dict(status="ok", respmsg=_("Domain created")))
from modoboa.lib.templatetags.libextras import render_form
return ajax_simple_response(dict(
status="ko", stepid=data, form=render_form(cwizard.steps[data]["form"])
))
cwizard.create_forms()
commonctx.update(steps=cwizard.steps)
commonctx.update(subtitle="1. %s" % cwizard.steps[0]['title'])
return render(request, tplname, commonctx)
@login_required
@@ -188,11 +213,7 @@ def _new_alias(request, tplname, formclass, ctx, successmsg):
ctx.update(action_label=_("Create"), action_classes="submit")
if request.method == "POST":
def callback(user, alias):
grant_access_to_object(user, alias, is_owner=True)
events.raiseEvent("MailboxAliasCreated", user, alias)
if user.is_superuser:
for admin in alias.domain.admins:
grant_access_to_object(admin, alias)
alias.post_create(user)
form = formclass(request.user, request.POST)
return _validate_alias(request, form, successmsg, tplname, ctx, callback)
@@ -382,9 +403,7 @@ def list_quotas(request, tplname="admin/quotas.html"):
@login_required
@permission_required("auth.add_user")
@transaction.commit_on_success
def newaccount(request, tplname='admin/newaccount.html'):
from modoboa.lib.formutils import CreationWizard
def newaccount(request, tplname='common/wizard_forms.html'):
def create_account(steps):
"""Account creation callback
@@ -395,8 +414,7 @@ def newaccount(request, tplname='admin/newaccount.html'):
genform = steps[0]["form"]
genform.is_valid()
account = genform.save()
grant_access_to_object(request.user, account, is_owner=True)
events.raiseEvent("AccountCreated", account)
account.post_create(request.user)
mailform = steps[1]["form"]
mb = mailform.save(request.user, account)
@@ -508,7 +526,7 @@ def remove_permission(request):
raise AdminError(_("Invalid request"))
if not request.user.can_access(account) or not request.user.can_access(domain):
raise PermDeniedException
ungrant_access_to_object(domain, account)
domain.remove_admin(account)
return ajax_simple_response(dict(status="ok"))
@login_required
@@ -598,39 +616,24 @@ def import_domain(user, row, formopts):
"""Specific code for domains import"""
dom = Domain()
dom.from_csv(user, row)
grant_access_to_object(user, dom, is_owner=True)
events.raiseEvent("CreateDomain", user, dom)
@transaction.commit_on_success
def import_domainalias(user, row, formopts):
"""Specific code for domain aliases import"""
domalias = DomainAlias()
domalias.from_csv(user, row)
grant_access_to_object(user, domalias, is_owner=True)
events.raiseEvent("DomainAliasCreated", user, domalias)
@transaction.commit_on_success
def import_account(user, row, formopts):
"""Specific code for accounts import"""
account = User()
account.from_csv(user, row, formopts["crypt_password"])
grant_access_to_object(user, account, is_owner=True)
if account.is_superuser:
# Give access to the existing user
grant_access_to_object(account, user)
events.raiseEvent("AccountCreated", account)
if account.mailbox_set.count():
mb = account.mailbox_set.all()[0]
grant_access_to_object(user, mb, is_owner=True)
events.raiseEvent("CreateMailbox", user, mb)
@transaction.commit_on_success
def _import_alias(user, row, **kwargs):
"""Specific code for aliases import"""
alias = Alias()
alias.from_csv(user, row, **kwargs)
grant_access_to_object(user, alias, is_owner=True)
events.raiseEvent("MailboxAliasCreated", user, alias)
def import_alias(user, row, formopts):
_import_alias(user, row, expected_elements=4)
+3 -2
View File
@@ -3,7 +3,7 @@ from functools import wraps
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext as _
from django.db import IntegrityError
from modoboa.admin.models import ObjectAccess, IntegrityError
from modoboa.admin.models import ObjectAccess
import events
from exceptions import ModoboaException
@@ -89,7 +89,8 @@ def grant_access_to_objects(user, objects, ct):
ObjectAccess.objects.create(user=user, content_type=ct, object_id=obj.id)
except IntegrityError:
pass
def ungrant_access_to_object(obj, user=None):
"""Ungrant access to an object for a specific user
+1 -1
View File
@@ -98,7 +98,7 @@
};
$.fn.cwizard.defaults = {
transition_callbacks: {}
};
})(jQuery);
@@ -7,13 +7,11 @@
<form class="form-horizontal" action="{{ action }}" enctype="{{ enctype }}"
method="POST" id="{{ formid }}" name="{{ formid }}">
<div id="wizard" class="carousel">
<div class="carousel-inner">
{% for step in steps %}
<div class="carousel-inner">{% for step in steps %}
<div id="step{{ forloop.counter }}"
class="item{% if forloop.first %} active{% endif %}">
{% if step.formtpl %}{% render_form step.form step.formtpl %}{% else %}{% render_form step.form %}{% endif %}
</div>
{% endfor %}
</div>{% endfor %}
</div>
</div>
</form>