mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
see #103
Work in progress: * New domains admin page, all menus are now at the same level, * Views, models and forms partial refactoring (better code organization).
This commit is contained in:
+16
-1
@@ -32,7 +32,7 @@ class MailboxForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Mailbox
|
||||
fields = ('name', 'address')
|
||||
fields = ('domain', 'name', 'address')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MailboxForm, self).__init__(*args, **kwargs)
|
||||
@@ -49,6 +49,13 @@ class MailboxForm(forms.ModelForm):
|
||||
raise forms.ValidationError(_("Passwords mismatch"))
|
||||
return self.cleaned_data["password2"]
|
||||
|
||||
def save(self, force_insert=False, force_update=False, commit=True):
|
||||
m = super(MailboxForm, self).save(commit=False)
|
||||
if commit:
|
||||
m.save(enabled=self.cleaned_data["enabled"],
|
||||
password=self.cleaned_data["password1"])
|
||||
return m
|
||||
|
||||
class AliasForm(forms.ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
domain = None
|
||||
@@ -70,6 +77,14 @@ class AliasForm(forms.ModelForm):
|
||||
return self.cleaned_data["address"].rsplit("@", 1)[0]
|
||||
return self.cleaned_data["address"]
|
||||
|
||||
def save(self, force_insert=False, force_update=False, commit=True):
|
||||
a = super(AliasForm, self).save(commit=False)
|
||||
if commit:
|
||||
domain = self.cleaned_data["mboxes"][0].domain
|
||||
a.full_address = "%s@%s" % (a.address, domain.name)
|
||||
a.save()
|
||||
return a
|
||||
|
||||
class SuperAdminForm(forms.Form):
|
||||
user = forms.ModelChoiceField([], label=_("User"), required=True,
|
||||
empty_label=_("Select a user"),
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.db import models
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
db.alter_column("auth_user", "username", models.CharField(max_length=254))
|
||||
db.alter_column("auth_user", "username", models.CharField(unique=True, max_length=254))
|
||||
db.alter_column("auth_user", "email", models.CharField(max_length=254))
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# 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):
|
||||
db.alter_column("admin_alias", "full_address",
|
||||
models.CharField(unique=True, max_length=254))
|
||||
|
||||
def backwards(self, orm):
|
||||
db.alter_column("admin_alias", "full_address",
|
||||
models.CharField(max_length=150))
|
||||
|
||||
models = {
|
||||
'admin.alias': {
|
||||
'Meta': {'object_name': 'Alias'},
|
||||
'address': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'full_address': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '150'}),
|
||||
'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'},
|
||||
'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': '100'}),
|
||||
'quota': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'admin.domainalias': {
|
||||
'Meta': {'object_name': 'DomainAlias'},
|
||||
'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'}),
|
||||
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"}),
|
||||
'full_address': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
|
||||
'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']"})
|
||||
},
|
||||
'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']
|
||||
+71
-16
@@ -1,10 +1,28 @@
|
||||
from django.db import models
|
||||
# coding: utf8
|
||||
from django.db import models, IntegrityError
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.conf import settings
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib import exec_cmd, exec_as_vuser
|
||||
from modoboa.lib import exec_cmd, exec_as_vuser, crypt_password
|
||||
import os
|
||||
import pwd
|
||||
|
||||
class AdminError(Exception):
|
||||
"""Custom exception
|
||||
|
||||
|
||||
"""
|
||||
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 Domain(models.Model):
|
||||
name = models.CharField(_('name'), max_length=100,
|
||||
@@ -70,28 +88,29 @@ class Mailbox(models.Model):
|
||||
self.mdirroot = parameters.get_admin("MAILDIR_ROOT")
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % (self.address)
|
||||
return "%s" % (self.full_address)
|
||||
|
||||
def create_dir(self, domain):
|
||||
path = "%s/%s/%s" % (parameters.get_admin("STORAGE_PATH"),
|
||||
domain.name, self.address)
|
||||
if os.path.exists(path):
|
||||
def create_dir(self):
|
||||
relpath = "%s/%s" % (self.domain.name, self.address)
|
||||
abspath = os.path.join(parameters.get_admin("STORAGE_PATH"), relpath)
|
||||
if self.mbtype == "mbox":
|
||||
self.path = "%s/Inbox" % relpath
|
||||
else:
|
||||
self.path = "%s/%s" % (relpath, self.mdirroot)
|
||||
if os.path.exists(abspath):
|
||||
return True
|
||||
if not exec_as_vuser("mkdir -p %s" % path):
|
||||
if not exec_as_vuser("mkdir -p %s" % abspath):
|
||||
return False
|
||||
if self.mbtype == "mbox":
|
||||
template = ["Inbox", "Drafts", "Sent", "Trash", "Junk"]
|
||||
for dir in template:
|
||||
exec_as_vuser("touch %s/%s" % (path, dir))
|
||||
|
||||
self.path = "%s/%s/Inbox" % (domain.name, self.address)
|
||||
for f in template:
|
||||
exec_as_vuser("touch %s/%s" % (abspath, f))
|
||||
else:
|
||||
template = [".Drafts/", ".Sent/", ".Trash/", ".Junk/"]
|
||||
for dir in template:
|
||||
for sdir in ["cur", "new", "tmp"]:
|
||||
exec_as_vuser("mkdir -p %s/%s/%s/%s" \
|
||||
% (path, self.mdirroot, dir, sdir))
|
||||
self.path = "%s/%s/%s/" % (domain.name, self.address, self.mdirroot)
|
||||
% (abspath, self.mdirroot, dir, sdir))
|
||||
return True
|
||||
|
||||
def rename_dir(self, domain, newaddress):
|
||||
@@ -109,6 +128,42 @@ class Mailbox(models.Model):
|
||||
% (parameters.get_admin("STORAGE_PATH"),
|
||||
self.domain.name, self.address))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.create_dir():
|
||||
raise AdminError(_("Failed to initialise mailbox, check permissions"))
|
||||
try:
|
||||
user = getattr(self, "user")
|
||||
except User.DoesNotExist:
|
||||
user = User()
|
||||
user.username = user.email = "%s@%s" % (self.address, self.domain.name)
|
||||
user.set_unusable_password()
|
||||
user.is_active = kwargs["enabled"]
|
||||
try:
|
||||
fname, lname = self.name.split()
|
||||
except ValueError:
|
||||
fname = self.name
|
||||
lname = ""
|
||||
user.first_name = fname
|
||||
user.last_name = lname
|
||||
try:
|
||||
user.save()
|
||||
except IntegrityError:
|
||||
raise AdminError(_("Mailbox with this address already exists"))
|
||||
self.user = user
|
||||
if kwargs["password"] != u"é":
|
||||
self.password = crypt_password(kwargs["password"])
|
||||
self.uid = pwd.getpwnam(parameters.get_admin("VIRTUAL_UID")).pw_uid
|
||||
self.gid = pwd.getpwnam(parameters.get_admin("VIRTUAL_GID")).pw_gid
|
||||
if not self.quota:
|
||||
self.quota = self.domain.quota
|
||||
self.full_address = self.user.email
|
||||
try:
|
||||
del kwargs["enabled"]
|
||||
del kwargs["password"]
|
||||
except KeyError:
|
||||
pass
|
||||
super(Mailbox, self).save(*args, **kwargs)
|
||||
|
||||
def tohash(self):
|
||||
return {
|
||||
"id" : self.id,
|
||||
@@ -120,7 +175,7 @@ class Mailbox(models.Model):
|
||||
class Alias(models.Model):
|
||||
address = models.CharField(_('address'), max_length=100,
|
||||
help_text=_("The alias address (without the domain part)"))
|
||||
full_address = models.CharField(max_length=150)
|
||||
full_address = models.CharField(max_length=254, unique=True)
|
||||
mboxes = models.ManyToManyField(Mailbox, verbose_name=_('mailboxes'),
|
||||
help_text=_("The mailboxes this alias points to"))
|
||||
enabled = models.BooleanField(_('enabled'),
|
||||
|
||||
@@ -62,17 +62,17 @@ def admin_menu(user):
|
||||
def domain_menu(domain_id, selection, user):
|
||||
entries = [
|
||||
{"name" : "",
|
||||
"url" : reverse(admin.views.newmailbox, args=[domain_id]),
|
||||
"url" : reverse(admin.views.newmailbox),
|
||||
"label" : _("New mailbox"),
|
||||
"img" : static_url("pics/add.png"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:300,y:280}}"},
|
||||
{"name" : "mailboxes",
|
||||
"url" : reverse(admin.views.mailboxes, args=[domain_id]),
|
||||
"url" : reverse(admin.views.mailboxes),
|
||||
"img" : static_url("pics/mailbox.png"),
|
||||
"label" : _("Mailboxes")},
|
||||
{"name" : "aliases",
|
||||
"url" : reverse("full-aliases", args=[domain_id]),
|
||||
"url" : reverse("full-aliases"),
|
||||
"img" : static_url("/pics/alias.png"),
|
||||
"label" : _("Aliases")},
|
||||
]
|
||||
@@ -108,34 +108,47 @@ def settings_menu(selection, user):
|
||||
{"selection" : selection, "entries" : entries,
|
||||
"user" : user})
|
||||
|
||||
def dommenu_entry(name, label, img, listurl, newurl):
|
||||
result = {"name" : name,
|
||||
"label" : label,
|
||||
"img" : img,
|
||||
"url" : listurl,
|
||||
"class" : "menubardropdown",
|
||||
"menu" : [{"name" : "%s_new" % name,
|
||||
"url" : newurl,
|
||||
"label" : _("New"),
|
||||
"img" : static_url("pics/add.png"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:300,y:200}}"}
|
||||
]
|
||||
}
|
||||
return result
|
||||
|
||||
@register.simple_tag
|
||||
def domains_menu(selection, user):
|
||||
entries = [
|
||||
{"name" : "newdomain",
|
||||
"url" : reverse(admin.views.newdomain),
|
||||
"label" : _("New domain"),
|
||||
"img" : static_url("pics/add.png"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:300,y:200}}"},
|
||||
{"name" : "domains",
|
||||
"url" : reverse(admin.views.domains),
|
||||
"label" : _("Domains"),
|
||||
"img" : static_url("pics/domains.png")},
|
||||
{"name" : "newdomalias",
|
||||
"url" : reverse(admin.views.newdomalias),
|
||||
"label" : _("New domain alias"),
|
||||
"img" : static_url("pics/add.png"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:300,y:200}}"},
|
||||
{"name" : "domaliases",
|
||||
"url" : reverse(admin.views.domaliases),
|
||||
"label" : _("Domain aliases"),
|
||||
"img" : static_url("pics/alias.png")}
|
||||
def domains_menu(selection, user, domid):
|
||||
args = domid != "" and ("?domid=%s" % domid) or ""
|
||||
entries = []
|
||||
if user.has_perm("admin.view_domains"):
|
||||
entries += dommenu_entry("domains", _("Domains"),
|
||||
static_url("pics/domains.png"),
|
||||
reverse(admin.views.domains),
|
||||
reverse(admin.views.newdomain)),
|
||||
entries += [
|
||||
dommenu_entry("domaliases", _("Domain aliases"), static_url("pics/alias.png"),
|
||||
reverse(admin.views.domaliases) + args,
|
||||
reverse(admin.views.newdomalias) + args),
|
||||
dommenu_entry("mailboxes", _("Mailboxes"), static_url("pics/mailbox.png"),
|
||||
reverse(admin.views.mailboxes) + args,
|
||||
reverse(admin.views.newmailbox) + args),
|
||||
dommenu_entry("mbaliases", _("Mailbox aliases"), static_url("pics/alias.png"),
|
||||
reverse(admin.views.mbaliases) + args,
|
||||
reverse(admin.views.newmbalias) + args),
|
||||
]
|
||||
entries += events.raiseQueryEvent("AdminMenuDisplay", target="admin_menu_box",
|
||||
user=user)
|
||||
return render_to_string('common/menu.html',
|
||||
{"entries" : entries, "selection" : selection,
|
||||
{"entries" : entries,
|
||||
"selection" : selection,
|
||||
"user" : user})
|
||||
|
||||
@register.simple_tag
|
||||
@@ -156,7 +169,8 @@ def permissions_menu(user):
|
||||
def render_actions(actions):
|
||||
t = template.Template("""
|
||||
{% for a in actions %}
|
||||
<a href="{{ a.url }}" name="{{ a.name }}" class="{{ a.class }}" rel="{{ a.rel }}">
|
||||
<a href="{{ a.url }}" name="{{ a.name }}" class="{{ a.class }}" rel="{{ a.rel }}"
|
||||
{% if a.confirm %}onclick="return confirm('{{ a.confirm }}')"{% endif %}>
|
||||
<img src="{{ a.img }}" border="0" title="{{ a.title }}" />
|
||||
</a>
|
||||
{% endfor %}
|
||||
@@ -177,7 +191,8 @@ def domain_actions(user, domid):
|
||||
{"name" : "deldomain",
|
||||
"url" : reverse(admin.views.deldomain, args=[domid]),
|
||||
"img" : static_url("pics/remove.png"),
|
||||
"title" : _("Delete domain")},
|
||||
"title" : _("Delete domain"),
|
||||
"confirm" : _("Delete this domain?")},
|
||||
{"name" : "domaliases",
|
||||
"url" : reverse(admin.views.domaliases) + "?domid=%s" % domid,
|
||||
"img" : static_url("pics/alias.png"),
|
||||
@@ -198,25 +213,42 @@ def domalias_actions(user, aid):
|
||||
return render_actions(actions)
|
||||
|
||||
@register.simple_tag
|
||||
def mailbox_actions(user, domid, mid):
|
||||
def mailbox_actions(user, mbox):
|
||||
actions = [
|
||||
{"name" : "editmailbox",
|
||||
"url" : reverse(admin.views.editmailbox, args=[domid, mid]),
|
||||
"url" : reverse(admin.views.editmailbox, args=[mbox.id]),
|
||||
"img" : static_url("pics/edit.png"),
|
||||
"title" : _("Edit mailbox"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:300,y:280}}"},
|
||||
{"name" : "deleteMb",
|
||||
"url" : reverse(admin.views.delmailbox, args=[domid, mid]),
|
||||
"url" : reverse(admin.views.delmailbox, args=[mbox.id]),
|
||||
"img" : static_url("pics/remove.png"),
|
||||
"title" : _("Delete mailbox")},
|
||||
{"name" : "aliases",
|
||||
"url" : reverse("mbox-aliases", args=[domid, mid]),
|
||||
"url" : reverse(admin.views.mbaliases) + "?mbid=%d" % mbox.id,
|
||||
"img" : static_url("pics/alias.png"),
|
||||
"title" : _("View this mailbox aliases")},
|
||||
]
|
||||
return render_actions(actions)
|
||||
|
||||
@register.simple_tag
|
||||
def mbalias_actions(user, alias):
|
||||
actions = [
|
||||
{"name" : "editmbalias",
|
||||
"url" : reverse(admin.views.editmbalias, args=[alias.id]),
|
||||
"img" : static_url("pics/edit.png"),
|
||||
"title" : _("Edit mailbox alias"),
|
||||
"class" : "boxed",
|
||||
"rel" : "{handler:'iframe',size:{x:300,y:250}}"},
|
||||
{"name" : "dembalias",
|
||||
"url" : reverse(admin.views.delmbalias, args=[alias.id]),
|
||||
"img" : static_url("pics/remove.png"),
|
||||
"title" : _("Delete mailbox alias"),
|
||||
"confirm" : _("Delete this alias?")},
|
||||
]
|
||||
return render_actions(actions)
|
||||
|
||||
@register.simple_tag
|
||||
def loadadminextmenu(user):
|
||||
menu = events.raiseQueryEvent("AdminMenuDisplay", target="admin_menu_box",
|
||||
|
||||
+12
-9
@@ -11,16 +11,19 @@ urlpatterns = patterns('modoboa.admin.views',
|
||||
(r'^domaliases/new/', 'newdomalias'),
|
||||
(r'^domaliases/edit/(?P<alias_id>\d+)/', 'editdomalias'),
|
||||
|
||||
(r'^domains/(?P<dom_id>\d+)/newmailbox/$', 'newmailbox'),
|
||||
(r'^domains/(?P<dom_id>\d+)/editmailbox/(?P<mbox_id>\d+)/$', 'editmailbox'),
|
||||
(r'^domains/(?P<dom_id>\d+)/deletemailbox/(?P<mbox_id>\d+)/$', 'delmailbox'),
|
||||
(r'^domains/(?P<dom_id>\d+)/newalias/$', 'newalias'),
|
||||
(r'^domains/(?P<dom_id>\d+)/editalias/(?P<alias_id>\d+)/$', 'editalias'),
|
||||
(r'^domains/(?P<dom_id>\d+)/$', 'mailboxes'),
|
||||
(r'^mailboxes/$', 'mailboxes'),
|
||||
(r'^mailboxes/new/$', 'newmailbox'),
|
||||
(r'^mailboxes/edit/(?P<mbox_id>\d+)/$', 'editmailbox'),
|
||||
(r'^mailboxes/delete/(?P<mbox_id>\d+)/$', 'delmailbox'),
|
||||
|
||||
(r'^mbaliases/$', 'mbaliases'),
|
||||
(r'^mbaliases/new/$', 'newmbalias'),
|
||||
(r'^mbaliases/edit/(?P<alias_id>\d+)/$', 'editmbalias'),
|
||||
(r'^mbaliases/delete/(?P<alias_id>\d+)/$', 'delmbalias'),
|
||||
|
||||
(r'^domains/(?P<dom_id>\d+)/raw/$', 'mailboxes_raw'),
|
||||
url(r'^domains/(?P<dom_id>\d+)/aliases/$', "aliases", name="full-aliases"),
|
||||
url(r'^domains/(?P<dom_id>\d+)/aliases/(?P<mbox_id>\d+)/$', "aliases", name="mbox-aliases"),
|
||||
(r'^domains/(?P<dom_id>\d+)/delalias/(?P<alias_id>\d+)/$', 'delalias'),
|
||||
#url(r'^domains/(?P<dom_id>\d+)/aliases/$', "aliases", name="full-aliases"),
|
||||
#url(r'^domains/(?P<dom_id>\d+)/aliases/(?P<mbox_id>\d+)/$', "aliases", name="mbox-aliases"),
|
||||
|
||||
(r'^settings/$', 'viewparameters'),
|
||||
(r'^settings/parameters/$', 'viewparameters'),
|
||||
|
||||
+98
-130
@@ -13,22 +13,28 @@ from django.db import transaction, IntegrityError
|
||||
from modoboa import admin, userprefs
|
||||
from models import *
|
||||
from admin.permissions import *
|
||||
from modoboa.lib.authbackends import crypt_password
|
||||
from modoboa.lib import crypt_password
|
||||
from modoboa.lib import _render, _render_to_string, _ctx_ok, \
|
||||
getctx, events, parameters
|
||||
from modoboa.lib.models import Parameter
|
||||
import copy
|
||||
import pwd
|
||||
|
||||
def good_domain(f):
|
||||
def dec(request, dom_id, **kwargs):
|
||||
def dec(request, **kwargs):
|
||||
if request.user.is_superuser:
|
||||
return f(request, dom_id, **kwargs)
|
||||
return f(request, **kwargs)
|
||||
mb = Mailbox.objects.get(user=request.user.id)
|
||||
if isinstance(dom_id, str) or isinstance(dom_id, unicode):
|
||||
dom_id = int(dom_id)
|
||||
if dom_id == mb.domain.id:
|
||||
return f(request, dom_id, **kwargs)
|
||||
access = True
|
||||
if request.GET.has_key("domid"):
|
||||
dom_id = int(request.GET["domid"])
|
||||
if dom_id != mb.domain.id:
|
||||
access = False
|
||||
else:
|
||||
q = request.GET.copy()
|
||||
q["domid"] = mb.domain.id
|
||||
request.GET = q
|
||||
if access:
|
||||
return f(request, **kwargs)
|
||||
|
||||
from django.conf import settings
|
||||
path = urlquote(request.get_full_path())
|
||||
@@ -36,12 +42,20 @@ def good_domain(f):
|
||||
return HttpResponseRedirect("%s?next=%s" % (login_url, path))
|
||||
return dec
|
||||
|
||||
def render_domains_page(request, page, **kwargs):
|
||||
template = "admin/%s.html" % page
|
||||
if request.GET.has_key("domid"):
|
||||
kwargs["domid"] = request.GET["domid"]
|
||||
else:
|
||||
kwargs["domid"] = ""
|
||||
kwargs["selection"] = page
|
||||
return _render(request, template, kwargs)
|
||||
|
||||
@login_required
|
||||
def domains(request):
|
||||
if not request.user.has_perm("admin.view_domains"):
|
||||
if request.user.has_perm("admin.view_mailboxes"):
|
||||
mb = Mailbox.objects.get(user=request.user.id)
|
||||
return mailboxes(request, dom_id=mb.domain.id)
|
||||
return HttpResponseRedirect(reverse(mailboxes))
|
||||
|
||||
return HttpResponseRedirect(reverse(userprefs.views.preferences))
|
||||
|
||||
@@ -49,9 +63,8 @@ def domains(request):
|
||||
counters = {}
|
||||
for dom in domains:
|
||||
dom.mboxcounter = len(dom.mailbox_set.all())
|
||||
return _render(request, 'admin/domains.html', {
|
||||
"domains" : domains, "counters" : counters
|
||||
})
|
||||
return render_domains_page(request, "domains",
|
||||
domains=domains, counter=counters)
|
||||
|
||||
@login_required
|
||||
def domaliases(request):
|
||||
@@ -61,9 +74,8 @@ def domaliases(request):
|
||||
else:
|
||||
domain = None
|
||||
domaliases = DomainAlias.objects.all()
|
||||
return _render(request, 'admin/domaliases.html', {
|
||||
"domaliases" : domaliases, "domain" : domain
|
||||
})
|
||||
return render_domains_page(request, "domaliases",
|
||||
domaliases=domaliases, domain=domain)
|
||||
|
||||
@login_required
|
||||
def newdomalias(request):
|
||||
@@ -199,12 +211,15 @@ def deldomain(request, dom_id):
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.view_mailboxes")
|
||||
def mailboxes(request, dom_id=None):
|
||||
domain = Domain.objects.get(pk=dom_id)
|
||||
mailboxes = Mailbox.objects.filter(domain=dom_id)
|
||||
return _render(request, 'admin/mailboxes.html', {
|
||||
"mailboxes" : mailboxes, "domain" : domain
|
||||
})
|
||||
def mailboxes(request):
|
||||
if request.GET.has_key("domid"):
|
||||
domain = Domain.objects.get(pk=request.GET["domid"])
|
||||
mailboxes = Mailbox.objects.filter(domain=domain.id)
|
||||
else:
|
||||
mailboxes = Mailbox.objects.all()
|
||||
domain = None
|
||||
return render_domains_page(request, "mailboxes",
|
||||
mailboxes=mailboxes, domain=domain)
|
||||
|
||||
@login_required
|
||||
@good_domain
|
||||
@@ -218,102 +233,60 @@ def mailboxes_raw(request, dom_id=None):
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.add_mailbox")
|
||||
def newmailbox(request, dom_id=None):
|
||||
domain = Domain.objects.get(pk=dom_id)
|
||||
def newmailbox(request):
|
||||
if request.method == "POST":
|
||||
form = MailboxForm(request.POST)
|
||||
error = None
|
||||
if form.is_valid():
|
||||
mb = form.save(commit=False)
|
||||
if mb.create_dir(domain):
|
||||
from django.conf import settings
|
||||
|
||||
user = User()
|
||||
user.username = user.email = "%s@%s" % (mb.address, domain.name)
|
||||
user.set_unusable_password()
|
||||
user.is_active = request.POST.has_key("enabled") \
|
||||
and True or False
|
||||
try:
|
||||
fname, lname = mb.name.split()
|
||||
except ValueError:
|
||||
fname = mb.name
|
||||
lname = ""
|
||||
user.first_name = fname
|
||||
user.last_name = lname
|
||||
try:
|
||||
user.save()
|
||||
except IntegrityError:
|
||||
error = _("Mailbox with this address already exists")
|
||||
else:
|
||||
mb.user = user
|
||||
mb.password = crypt_password(request.POST["password1"])
|
||||
mb.uid = pwd.getpwnam(parameters.get_admin("VIRTUAL_UID")).pw_uid
|
||||
mb.gid = pwd.getpwnam(parameters.get_admin("VIRTUAL_GID")).pw_gid
|
||||
mb.domain = domain
|
||||
mb.quota = request.POST["quota"]
|
||||
if not mb.quota:
|
||||
mb.quota = domain.quota
|
||||
mb.full_address = user.email
|
||||
mb.save()
|
||||
|
||||
events.raiseEvent("CreateMailbox", mbox=mb)
|
||||
|
||||
messages.info(request, _("Mailbox created."),
|
||||
fail_silently=True)
|
||||
ctx = _ctx_ok(reverse(admin.views.mailboxes, args=[domain.id]))
|
||||
return HttpResponse(simplejson.dumps(ctx),
|
||||
mimetype="application/json")
|
||||
try:
|
||||
mb = form.save()
|
||||
except AdminError as e:
|
||||
error = str(e)
|
||||
else:
|
||||
error = _("Failed to initialise mailbox, check permissions")
|
||||
content = _render_to_string("ko", "admin/newmailbox.html", {
|
||||
"form" : form, "domain" : domain, "error" : error
|
||||
events.raiseEvent("CreateMailbox", mbox=mb)
|
||||
messages.info(request, _("Mailbox created"),
|
||||
fail_silently=True)
|
||||
ctx = _ctx_ok(reverse(admin.views.mailboxes) + "?domid=%d" % mb.domain.id)
|
||||
return HttpResponse(simplejson.dumps(ctx),
|
||||
mimetype="application/json")
|
||||
content = _render_to_string(request, "admin/newmailbox.html", {
|
||||
"form" : form, "error" : error
|
||||
})
|
||||
ctx = getctx("ko", content=content)
|
||||
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
|
||||
|
||||
form = MailboxForm()
|
||||
if request.GET.has_key("domid"):
|
||||
form.fields["domain"].initial = request.GET["domid"]
|
||||
return _render(request, "admin/newmailbox.html", {
|
||||
"domain" : domain, "form" : form
|
||||
"form" : form
|
||||
})
|
||||
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.change_mailbox")
|
||||
@transaction.commit_manually
|
||||
def editmailbox(request, dom_id, mbox_id=None):
|
||||
def editmailbox(request, mbox_id=None):
|
||||
mb = Mailbox.objects.get(pk=mbox_id)
|
||||
if request.method == "POST":
|
||||
oldmb = copy.deepcopy(mb)
|
||||
form = MailboxForm(request.POST, instance=mb)
|
||||
error = None
|
||||
if form.is_valid():
|
||||
mb = form.save(commit=False)
|
||||
mb.user.is_active = request.POST.has_key("enabled") \
|
||||
and request.POST["enabled"] or False
|
||||
mb.user.username = mb.user.email = \
|
||||
"%s@%s" % (mb.address, mb.domain.name)
|
||||
try:
|
||||
mb.user.save()
|
||||
except IntegrityError:
|
||||
error = _("Mailbox with this address already exists")
|
||||
mb = form.save()
|
||||
except AdminError, inst:
|
||||
error = str(inst)
|
||||
else:
|
||||
if not oldmb.rename_dir(mb.domain.name, mb.address):
|
||||
error = _("Failed to rename mailbox, check permissions")
|
||||
else:
|
||||
if request.POST["password1"] != u"é":
|
||||
mb.password = crypt_password(request.POST["password1"])
|
||||
mb.quota = request.POST["quota"]
|
||||
if not mb.quota:
|
||||
mb.quota = mb.domain.quota
|
||||
mb.full_address = mb.user.email
|
||||
mb.save()
|
||||
if oldmb.rename_dir(mb.domain.name, mb.address):
|
||||
transaction.commit()
|
||||
events.raiseEvent("ModifyMailbox", mbox=mb, oldmbox=oldmb)
|
||||
messages.info(request, _("Mailbox modified"),
|
||||
fail_silently=True)
|
||||
ctx = _ctx_ok(reverse(admin.views.mailboxes, args=[dom_id]))
|
||||
ctx = _ctx_ok(reverse(admin.views.mailboxes) + "?domid=%d" % mb.domain.id)
|
||||
return HttpResponse(simplejson.dumps(ctx),
|
||||
mimetype="application/json")
|
||||
error = _("Failed to rename mailbox, check permissions")
|
||||
if error is not None:
|
||||
transaction.rollback()
|
||||
ctx = getctx("ko", content=_render_to_string(request, "admin/editmailbox.html", {
|
||||
@@ -333,7 +306,7 @@ def editmailbox(request, dom_id, mbox_id=None):
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.delete_mailbox")
|
||||
def delmailbox(request, dom_id, mbox_id=None):
|
||||
def delmailbox(request, mbox_id=None):
|
||||
mb = Mailbox.objects.get(pk=mbox_id)
|
||||
if mb.user.id != request.user.id:
|
||||
events.raiseEvent("DeleteMailbox", mbox=mb)
|
||||
@@ -351,90 +324,85 @@ def delmailbox(request, dom_id, mbox_id=None):
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.view_aliases")
|
||||
def aliases(request, dom_id=None, mbox_id=None):
|
||||
domain = Domain.objects.get(pk=dom_id)
|
||||
if not mbox_id:
|
||||
aliases = Alias.objects.filter(mboxes__domain__id=dom_id).distinct()
|
||||
def mbaliases(request):
|
||||
if request.GET.has_key("domid"):
|
||||
aliases = Alias.objects.filter(mboxes__domain__id=request.GET["domid"]).distinct()
|
||||
if request.GET.has_key("mbid"):
|
||||
aliases = Alias.objects.filter(mboxes__id=request.GET["mbid"]).distinct()
|
||||
else:
|
||||
aliases = Alias.objects.filter(mboxes__id=mbox_id)
|
||||
return _render(request, 'admin/aliases.html', {
|
||||
"aliases" : aliases, "domain" : domain
|
||||
})
|
||||
aliases = Alias.objects.all()
|
||||
return render_domains_page(request, "mbaliases", aliases=aliases)
|
||||
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.add_alias")
|
||||
def newalias(request, dom_id):
|
||||
domain = Domain.objects.get(pk=dom_id)
|
||||
def newmbalias(request):
|
||||
if request.method == "POST":
|
||||
form = AliasForm(request.POST, domain=domain)
|
||||
form = AliasForm(request.POST)
|
||||
error = None
|
||||
if form.is_valid():
|
||||
if Alias.objects.filter(address=request.POST["address"]):
|
||||
try:
|
||||
alias = form.save()
|
||||
except IntegrityError:
|
||||
error = _("Alias with this name already exists")
|
||||
else:
|
||||
alias = form.save(commit=False)
|
||||
alias.full_address = "%s@%s" % (alias.address, domain.name)
|
||||
alias.save()
|
||||
form.save_m2m()
|
||||
ctx = _ctx_ok(reverse(admin.views.aliases, args=[dom_id]))
|
||||
messages.info(request, _("Alias created"), fail_silently=True)
|
||||
ctx = _ctx_ok(reverse(admin.views.mbaliases) )
|
||||
messages.info(request, _("Mailbox alias created"), fail_silently=True)
|
||||
return HttpResponse(simplejson.dumps(ctx),
|
||||
mimetype="application/json")
|
||||
content = _render_to_string(request, "admin/newalias.html", {
|
||||
"domain" : dom_id, "form" : form, "error" : error
|
||||
content = _render_to_string(request, "admin/newmbalias.html", {
|
||||
"form" : form, "error" : error
|
||||
})
|
||||
ctx = getctx("ko", content=content)
|
||||
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
|
||||
|
||||
form = AliasForm(domain=domain)
|
||||
return _render(request, 'admin/newalias.html', {
|
||||
"domain" : dom_id, "form" : form, "noerrors" : True
|
||||
if request.GET.has_key("domid"):
|
||||
form = AliasForm(domain=Domain.objects.get(pk=request.GET["domid"]))
|
||||
else:
|
||||
form = AliasForm()
|
||||
return _render(request, 'admin/newmbalias.html', {
|
||||
"form" : form, "noerrors" : True
|
||||
})
|
||||
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.change_alias")
|
||||
def editalias(request, dom_id, alias_id):
|
||||
def editmbalias(request, alias_id):
|
||||
alias = Alias.objects.get(pk=alias_id)
|
||||
if request.method == "POST":
|
||||
form = AliasForm(request.POST, instance=alias)
|
||||
error = None
|
||||
if form.is_valid():
|
||||
if alias.address != request.POST["address"] \
|
||||
and Alias.objects.filter(address=request.POST["address"]):
|
||||
try:
|
||||
alias = form.save()
|
||||
except IntegrityError:
|
||||
error = _("Alias with this name already exists")
|
||||
else:
|
||||
domain = Domain.objects.get(pk=dom_id)
|
||||
alias = form.save(commit=False)
|
||||
alias.full_address = "%s@%s" % (alias.address,
|
||||
domain.name)
|
||||
alias.save()
|
||||
form.save_m2m()
|
||||
ctx = _ctx_ok(reverse(admin.views.aliases, args=[dom_id]))
|
||||
messages.info(request, _("Alias modified"),
|
||||
ctx = _ctx_ok(reverse(admin.views.mbaliases))
|
||||
messages.info(request, _("Mailbox alias modified"),
|
||||
fail_silently=True)
|
||||
return HttpResponse(simplejson.dumps(ctx),
|
||||
mimetype="application/json")
|
||||
content = _render_to_string(request, "admin/editalias.html", {
|
||||
"domain" : dom_id, "alias" : alias, "form" : form, "error" : error
|
||||
content = _render_to_string(request, "admin/editmbalias.html", {
|
||||
"alias" : alias, "form" : form, "error" : error
|
||||
})
|
||||
ctx = getctx("ko", content=content)
|
||||
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
|
||||
form = AliasForm(instance=alias)
|
||||
return _render(request, 'admin/editalias.html', {
|
||||
"form" : form, "alias" : alias, "domain" : dom_id
|
||||
return _render(request, 'admin/editmbalias.html', {
|
||||
"form" : form, "alias" : alias
|
||||
})
|
||||
|
||||
@login_required
|
||||
@good_domain
|
||||
@permission_required("admin.delete_alias")
|
||||
def delalias(request, dom_id, alias_id):
|
||||
def delmbalias(request, alias_id):
|
||||
alias = Alias.objects.get(pk=alias_id)
|
||||
alias.delete()
|
||||
messages.info(request, _("Alias deleted"), fail_silently=True)
|
||||
return HttpResponseRedirect(reverse(admin.views.aliases,
|
||||
args=[dom_id]))
|
||||
return HttpResponseRedirect(reverse(admin.views.mbaliases))
|
||||
|
||||
@login_required
|
||||
@permission_required("auth.view_permissions")
|
||||
@@ -530,8 +498,8 @@ def saveparameters(request):
|
||||
@login_required
|
||||
@user_passes_test(lambda u: u.is_superuser)
|
||||
def viewextensions(request):
|
||||
from extensions import list_extensions
|
||||
from lib import tables
|
||||
from modoboa.extensions import list_extensions
|
||||
from modoboa.lib import tables
|
||||
|
||||
class ExtensionsTable(tables.Table):
|
||||
idkey = "id"
|
||||
@@ -560,7 +528,7 @@ def viewextensions(request):
|
||||
@login_required
|
||||
@user_passes_test(lambda u: u.is_superuser)
|
||||
def saveextensions(request):
|
||||
import extensions
|
||||
from modoboa import extensions
|
||||
|
||||
actived_exts = Extension.objects.filter(enabled=True)
|
||||
found = []
|
||||
|
||||
@@ -9,7 +9,7 @@ from modoboa.admin.views import good_domain
|
||||
from modoboa.admin.models import Domain, Mailbox
|
||||
from django.contrib.auth.decorators \
|
||||
import login_required, user_passes_test, permission_required
|
||||
from extensions.stats.grapher import *
|
||||
from modoboa.extensions.stats.grapher import *
|
||||
|
||||
graph_types = ['AVERAGE', 'MAX']
|
||||
graph_list = [{"name" : "traffic", "label" : _("Average normal traffic")},
|
||||
|
||||
@@ -156,6 +156,7 @@ textarea {
|
||||
background-color: #eee;
|
||||
width: 80%;
|
||||
height: 30px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
textarea:hover {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import hashlib, crypt, string
|
||||
from random import Random
|
||||
from django.conf import settings
|
||||
from django.template import RequestContext
|
||||
from django.shortcuts import render_to_response
|
||||
@@ -118,3 +120,20 @@ class Singleton(type):
|
||||
cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
|
||||
return cls.instance
|
||||
|
||||
|
||||
def _check_password(password, crypted):
|
||||
scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin")
|
||||
if scheme == "crypt":
|
||||
return crypt.crypt(password, crypted) == crypted
|
||||
if scheme == "md5":
|
||||
return hashlib.md5(password).hexdigest() == crypted
|
||||
return password
|
||||
|
||||
def crypt_password(password):
|
||||
scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin")
|
||||
if scheme == "crypt":
|
||||
salt = ''.join(Random().sample(string.letters + string.digits, 2))
|
||||
return crypt.crypt(password, salt)
|
||||
if scheme == "md5":
|
||||
return hashlib.md5(password).hexdigest()
|
||||
return password
|
||||
|
||||
+1
-21
@@ -1,10 +1,6 @@
|
||||
from django.contrib.auth.models import User
|
||||
from modoboa.admin.models import Mailbox
|
||||
import hashlib
|
||||
import crypt
|
||||
import string
|
||||
from random import Random
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib import _check_password
|
||||
|
||||
class SimpleBackend:
|
||||
def authenticate(self, username=None, password=None):
|
||||
@@ -26,19 +22,3 @@ class SimpleBackend:
|
||||
except User.DoesNotExist:
|
||||
return None
|
||||
|
||||
def _check_password(password, crypted):
|
||||
scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin")
|
||||
if scheme == "crypt":
|
||||
return crypt.crypt(password, crypted) == crypted
|
||||
if scheme == "md5":
|
||||
return hashlib.md5(password).hexdigest() == crypted
|
||||
return password
|
||||
|
||||
def crypt_password(password):
|
||||
scheme = parameters.get_admin("PASSWORD_SCHEME", app="admin")
|
||||
if scheme == "crypt":
|
||||
salt = ''.join(Random().sample(string.letters + string.digits, 2))
|
||||
return crypt.crypt(password, salt)
|
||||
if scheme == "md5":
|
||||
return hashlib.md5(password).hexdigest()
|
||||
return password
|
||||
|
||||
@@ -177,6 +177,11 @@ div#footer {
|
||||
border-left: 5px solid #ccc;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
}
|
||||
|
||||
.menubardropdown label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.left {
|
||||
|
||||
+4
-1
@@ -288,7 +288,10 @@ setDivHeight = function(id, extrah, modulo) {
|
||||
bindRows = function(rooturl, page) {
|
||||
$$("tr").addEvent("click", function(event) {
|
||||
if (event.target.parentNode.id) {
|
||||
var url = rooturl + event.target.parentNode.id + "?page=" + page;
|
||||
var url = rooturl + "?domid=" + event.target.parentNode.id;
|
||||
if (page != "") {
|
||||
url += "?page=" + page;
|
||||
}
|
||||
event.target.parentNode.setStyle("background", "#ffffcc");
|
||||
location.href = url;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
{% extends "nlayout.html" %}
|
||||
{% extends "admin/domains_header.html" %}
|
||||
{% load i18n admin_extras libextras %}
|
||||
{% block html_head %}
|
||||
<script src="{{ MEDIA_URL }}js/domains.js" type="text/javascript"></script>
|
||||
{{ block.super }}
|
||||
<script type="text/javascript">
|
||||
window.addEvent('domready', function() {
|
||||
{% url admin.views.domains as view_url %}
|
||||
{% url admin.views.mailboxes as view_url %}
|
||||
bindRows("{{ view_url }}", "{{ current_page }}");
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block middletitle %}{% trans "Available domains" %}{% endblock %}
|
||||
{% block menu %}{% domains_menu "domains" user %}{% endblock %}
|
||||
{% block content %}
|
||||
{% if messages %}
|
||||
{% display_messages messages %}
|
||||
{% endif %}
|
||||
<div id="domcontent">
|
||||
{% block subcontent %}
|
||||
{% if not domains %}<div class="info">{% trans "No domain defined." %}</div>
|
||||
{% else %}
|
||||
<table>
|
||||
@@ -37,5 +32,4 @@
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends "nlayout.html" %}
|
||||
{% load i18n admin_extras libextras %}
|
||||
{% block html_head %}
|
||||
<script src="{{ MEDIA_URL }}js/domains.js" type="text/javascript"></script>
|
||||
{% endblock %}
|
||||
{% block middletitle %}
|
||||
{% block pagetitle %}{% endblock %}{% if domain %} ({% trans "for" %} {{ domain.name }}){% endif %}
|
||||
{% endblock %}
|
||||
{% block menu %}{% domains_menu selection user domid %}{% endblock %}
|
||||
{% block content %}
|
||||
{% if messages %}
|
||||
{% display_messages messages %}
|
||||
{% endif %}
|
||||
<div id="subcontent">
|
||||
{% block subcontent %}{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,17 +1,7 @@
|
||||
{% extends "nlayout.html" %}
|
||||
{% extends "admin/domains_header.html" %}
|
||||
{% load i18n admin_extras libextras %}
|
||||
{% block html_head %}
|
||||
<script src="{{ MEDIA_URL }}js/domains.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block middletitle %}
|
||||
{% trans "Domain aliases" %}{% if domain %} ({% trans "for" %} {{ domain.name }}){% endif %}
|
||||
{% endblock %}
|
||||
{% block menu %}{% domains_menu "domaliases" user %}{% endblock %}
|
||||
{% block content %}
|
||||
{% if messages %}{% display_messages messages %}{% endif %}
|
||||
<div id="domcontent">
|
||||
{% block pagetitle %}{% trans "Domain aliases" %}{% endblock %}
|
||||
{% block subcontent %}
|
||||
{% if not domaliases %}
|
||||
<div class="info">{% trans "No domain alias defined." %}</div>
|
||||
{% else %}
|
||||
@@ -32,5 +22,4 @@
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{% block content %}
|
||||
<div class="title"><h1>{% trans "Mailbox" %} {{ mbox.name }}</h1></div>
|
||||
{% if error %}<div class="error">{{ error }}</div>{% endif %}
|
||||
{% url admin.views.editmailbox mbox.domain_id mbox.id as box_url %}
|
||||
{% url admin.views.editmailbox mbox.id as box_url %}
|
||||
<form action="{{ box_url }}" method="POST" id="mboxform" name="mboxform">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="spacer"></div>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% load i18n %}
|
||||
<div class="title"><h1>Alias {{ alias.address }}</h1></div>
|
||||
<div class="title"><h1>Mailbox alias {{ alias.address }}</h1></div>
|
||||
{% if error %}<div class="error">{{ error }}</div>{% endif %}
|
||||
{% url admin.views.editalias domain alias.id as edit_url %}
|
||||
{% url admin.views.editmbalias alias.id as edit_url %}
|
||||
<form action="{{ edit_url }}" method="POST" id="aliasform" name="aliasform">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="spacer"></div>
|
||||
@@ -1,13 +1,9 @@
|
||||
{% extends "admin/domain_header.html" %}
|
||||
{% load i18n %}
|
||||
{% block menu %}
|
||||
{% load admin_extras %}
|
||||
{% domain_menu domain.id "mailboxes" user %}
|
||||
{% endblock %}
|
||||
{% block domcontent %}
|
||||
{% load i18n %}
|
||||
{% extends "admin/domains_header.html" %}
|
||||
{% load i18n admin_extras %}
|
||||
{% block pagetitle %}{% trans "Available mailboxes" %}{% endblock %}
|
||||
{% block subcontent %}
|
||||
{% if not mailboxes %}
|
||||
<p>{% trans "No mailbox defined." %}</p>
|
||||
<div class="info">{% trans "No mailbox defined." %}</div>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
@@ -19,7 +15,7 @@
|
||||
</tr>
|
||||
{% for mb in mailboxes %}
|
||||
<tr class="{% cycle 'odd' 'even' %}">
|
||||
<td>{% mailbox_actions user domain.id mb.id %}</td>
|
||||
<td>{% mailbox_actions user mb %}</td>
|
||||
<td>{{ mb.name }}</td>
|
||||
<td>{{ mb.address }}@{{ mb.domain.name }}</td>
|
||||
<td>{{ mb.quota }} {% trans "MB" %}</td>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{% extends "admin/domains_header.html" %}
|
||||
{% load i18n admin_extras %}
|
||||
{% block pagetitle %}{% trans "Mailbox aliases" %}{% endblock %}
|
||||
{% block subcontent %}
|
||||
{% if not aliases %}
|
||||
<div class="info">{% trans "No mailbox alias defined." %}</div>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
<th width="50px">{% trans "Actions" %}</th>
|
||||
<th width="150px">{% trans "Address" %}</th>
|
||||
<th width="200px">{% trans "Mailbox" %}</th>
|
||||
<th width="75px">{% trans "Enabled" %}</th>
|
||||
</tr>
|
||||
{% for alias in aliases %}
|
||||
<tr>
|
||||
<td>{% mbalias_actions user alias %}
|
||||
<td>{{ alias.full_address }}</td>
|
||||
<td>
|
||||
{% for mb in alias.mboxes.all %}
|
||||
{{ mb.full_address }}<br/>
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>{{ alias.enabled|yesno }}</td
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="title"><h1>{% trans "New mailbox" %}</h1></div>
|
||||
|
||||
{% if error %}<div class="error">{{ error }}</div>{% endif %}
|
||||
{% url admin.views.newmailbox domain.id as box_url %}
|
||||
{% url admin.views.newmailbox as box_url %}
|
||||
<form action="{{ box_url }}" method="POST" id="mboxform" name="mboxform">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="spacer"></div>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<script src="{{ MEDIA_URL }}js/form.js" type="text/javascript"></script>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="title"><h1>{% trans "New alias" %}</h1></div>
|
||||
<div class="title"><h1>{% trans "New mailbox alias" %}</h1></div>
|
||||
{% if error %}<div class="error">{{ error }}</div>{% endif %}
|
||||
{% url admin.views.newalias domain as box_url %}
|
||||
{% url admin.views.newmbalias as box_url %}
|
||||
<form action="{{ box_url }}" method="POST" id="aliasform" name="aliasform">
|
||||
{% include "common/genericform.html" %}
|
||||
<div class="spacer"></div>
|
||||
@@ -1,9 +1,11 @@
|
||||
{% load i18n %}
|
||||
{% for entry in entries %}
|
||||
{% if entry.menu %}
|
||||
<li class="dropdown {{ entry.class }}">
|
||||
<li class="dropdown {{ entry.class }}{% if selection == entry.name %} selected{% endif %}">
|
||||
<img src="{{ entry.img }}" border="0" />
|
||||
{% if entry.url %}<a href="{{ entry.url }}">{% endif %}
|
||||
<label>{{ entry.label }}</label>
|
||||
{% if entry.url %}</a>{% endif %}
|
||||
<ul class="links"
|
||||
{% if entry.width %}style="width: {{ entry.width }}px"{% endif %}>
|
||||
{% for sentry in entry.menu %}
|
||||
@@ -20,7 +22,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li {% ifequal selection entry.name %}class="selected"{% endifequal %}>
|
||||
<li {% if selection == entry.name %}class="selected"{% endif %}>
|
||||
<a href="{{ entry.url }}" name="{{ entry.name }}"
|
||||
{% if entry.class %}class={{ entry.class }}{% endif %}
|
||||
{% if entry.rel %}rel={{ entry.rel }}{% endif %}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
from django import forms
|
||||
from modoboa.admin.models import Mailbox
|
||||
from modoboa.lib.authbackends import _check_password
|
||||
from modoboa.lib import _check_password
|
||||
from django.contrib.auth.models import check_password
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ from django.contrib.auth.decorators \
|
||||
from django.utils import simplejson
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib import _render, _ctx_ok, _ctx_ko, getctx, parameters
|
||||
from modoboa.lib.authbackends import crypt_password
|
||||
from modoboa.lib import crypt_password
|
||||
from forms import ChangePasswordForm
|
||||
from modoboa.admin.models import Mailbox
|
||||
|
||||
|
||||
Reference in New Issue
Block a user