Files
modoboa/admin/lib.py
T
Antoine Nguyen 3681bb4198 wip: resellers and limits
I've finally started to rethink the database structure. The goal I'm trying to reach: only use User objects to manage permissions and accesses to the webui and associate other objects to them if needed (like mailboxes).

see #105
2012-01-20 17:33:05 +01:00

218 lines
7.1 KiB
Python

# coding: utf-8
from functools import wraps
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.models import User, Group
from django.utils.translation import ugettext as _
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from models import *
from modoboa.lib.exceptions import ModoboaException
from modoboa.lib.webutils import _render_error, _render
from modoboa.admin.tables import *
class AdminError(ModoboaException):
"""
Just a Custom exception to identify errors coming from the admin
application.
"""
pass
def is_not_localadmin(errortpl="error"):
def dec(f):
def wrapped_f(request, *args, **kwargs):
if request.user.id == 1:
return _render_error(request, errortpl, {
"error" : _("Invalid action, %(user)s is a local user" \
% {"user" : request.user.username})
})
return f(request, *args, **kwargs)
wrapped_f.__name__ = f.__name__
wrapped_f.__dict__ = f.__dict__
wrapped_f.__doc__ = f.__doc__
wrapped_f.__module__ = f.__module__
return wrapped_f
return dec
def is_domain_admin(user):
"""Tell if a user is administrator for a domain of not
Whatever the domain, we just want to know if the given user is
declared as a domain administrator.
:param user: a User object
:return: True if the user is a domain administrator, False otherwise.
"""
grp = Group.objects.get(name="DomainAdmins")
return grp in user.groups.all()
def good_domain(f):
"""Custom permission decorator
Check if a domain administrator is accessing the good domain.
:param f: the original called function
"""
def dec(request, **kwargs):
if request.user.is_superuser:
return f(request, **kwargs)
if is_domain_admin(request.user):
mb = Mailbox.objects.get(user=request.user.id)
access = True
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
from django.utils.http import urlquote
path = urlquote(request.get_full_path())
login_url = settings.LOGIN_URL
return HttpResponseRedirect("%s?next=%s" % (login_url, path))
return dec
# def has_access_to_domain(user, domain):
# """
# """
# access = events.raiseQueryEvent("CanViewDomain", user, domain)
# if True in access:
# return True
# if is_domain_admin(user):
# mb = Mailbox.objects.get(user=request.user.id)
# if mb.domain == domain:
# return True
# return False
def render_listing(request, objtype, tplname="admin/listing.html",
**kwargs):
"""Common function to render a listing
All listing pages available into the admin application use the
same layout, rendered by this function.
:param request: a ``Request`` object
:param objtype: the object type's name (lowercase)
:param tplname: the template used to render the HTML
"""
tblclass = "%sTable" % objtype.capitalize()
if not globals().has_key(tblclass):
raise AdminError(_("Unknown object type"))
tblclass = globals()[tblclass]
if request.GET.has_key("domid"):
kwargs["domid"] = request.GET["domid"]
else:
kwargs["domid"] = ""
kwargs["selection"] = objtype
paginator = Paginator(kwargs["objects"],
int(parameters.get_admin("ITEMS_PER_PAGE")))
try:
page = request.GET.get("page", "1")
except ValueError:
page = 1
try:
kwargs["objects"] = paginator.page(page)
except (EmptyPage, PageNotAnInteger):
kwargs["objects"] = paginator.page(paginator.num_pages)
kwargs["last_page"] = paginator.num_pages
kwargs["total"] = paginator.count
kwargs["table"] = tblclass(request, kwargs["objects"].object_list)
return _render(request, tplname, kwargs)
def set_object_ownership(user, obj):
"""Simple shorcut to associate an object to a user
:param user: a ``User`` object
:param obj: an admin. object (Domain, Mailbox, ...)
"""
obj_owner = ObjectOwner(user=user, content_object=obj)
obj_owner.save()
def is_object_owner(user, obj):
"""Check if a user is the object's owner
An object can have multiple owners but this function only
concerns one given user.
:param user: a ``User`` object
:param obj: a admin object
:return: a boolean
"""
if user.is_superuser:
return True
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model=obj._meta.module_name)
for entry in qs.all():
if entry.content_object == obj:
return True
return False
def check_domain_ownership(f):
@wraps(f)
def dec(request, **kwargs):
if not request.user.is_superuser:
domain = None
domid = request.GET.get("domid", None)
if domid:
domain = Domain.objects.get(pk=domid)
else:
mbid = request.GET.get("mbid", None)
if mbid:
domain = Mailbox.objects.get(pk=mbid).domain
if domain and not is_object_owner(request.user, domain):
raise PermDeniedError(_("You can't access this domain"))
return f(request, **kwargs)
return dec
def get_user_domains(user):
if user.is_superuser:
return Domain.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
domains = []
for entry in qs.all():
domains += [entry.content_object]
return domains
def get_user_domaliases(user):
if user.is_superuser:
return DomainAlias.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
domaliases = []
for entry in qs.all():
domaliases += entry.content_object.domainalias_set.all()
return domaliases
def get_user_mailboxes(user):
if user.is_superuser:
return Mailbox.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
mboxes = []
for ro in qs.all():
mboxes += Mailbox.objects.filter(domain=ro.content_object)
return mboxes
def get_user_mbaliases(user):
if user.is_superuser:
return Alias.objects.all()
qs = user.objectowner_set.filter(content_type__app_label="admin",
content_type__model="domain")
mbaliases = []
for ro in qs.all():
mbaliases += Alias.objects.filter(domain=ro.content_object)
return mbaliases