You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mailu/admin/mailu/admin/access.py

111 lines
3.7 KiB
Python

from mailu.admin import db, models, forms
import flask
import flask_login
import functools
def permissions_wrapper(handler):
""" Decorator that produces a decorator for checking permissions.
"""
def callback(function, args, kwargs, dargs, dkwargs):
authorized = handler(args, kwargs, *dargs, **dkwargs)
if not authorized:
flask.abort(403)
elif type(authorized) is int:
flask.abort(authorized)
else:
return function(*args, **kwargs)
# If the handler has no argument, declare a
# simple decorator, otherwise declare a nested decorator
# There are at least two mandatory arguments
if handler.__code__.co_argcount > 2:
def decorator(*dargs, **dkwargs):
def inner(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
return callback(function, args, kwargs, dargs, dkwargs)
wrapper._audit_permissions = handler, dargs
return flask_login.login_required(wrapper)
return inner
else:
def decorator(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
return callback(function, args, kwargs, (), {})
wrapper._audit_permissions = handler, []
return flask_login.login_required(wrapper)
return decorator
@permissions_wrapper
def global_admin(args, kwargs):
""" The view is only available to global administrators.
"""
return flask_login.current_user.global_admin
@permissions_wrapper
def domain_admin(args, kwargs, model, key):
""" The view is only available to specific domain admins.
Global admins will still be able to access the resource.
A model and key must be provided. The model will be queries
based on the query parameter named after the key. The model may
either be Domain or an Email subclass (or any class with a
``domain`` attribute which stores a related Domain instance).
"""
obj = model.query.get(kwargs[key])
if obj:
domain = obj if type(obj) is models.Domain else obj.domain
return domain in flask_login.current_user.get_managed_domains()
@permissions_wrapper
def owner(args, kwargs, model, key):
""" The view is only available to the resource owner or manager.
A model and key must be provided. The model will be queries
based on the query parameter named after the key. The model may
either be User or any model with a ``user`` attribute storing
a user instance (like Fetch).
If the query parameter is empty and the model is User, then
the resource being accessed is supposed to be the current
logged in user and access is obviously authorized.
"""
if kwargs[key] is None and model == models.User:
return True
obj = model.query.get(kwargs[key])
if obj:
user = obj if type(obj) is models.User else obj.user
return (
user.email == flask_login.current_user.email
or user.domain in flask_login.current_user.get_managed_domains()
)
@permissions_wrapper
def authenticated(args, kwargs):
""" The view is only available to logged in users.
"""
return True
def confirmation_required(action):
""" View decorator that asks for a confirmation first.
"""
def inner(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
form = forms.ConfirmationForm()
if form.validate_on_submit():
return function(*args, **kwargs)
return flask.render_template(
"confirm.html", action=action.format(*args, **kwargs),
form=form
)
return wrapper
return inner