You've already forked Mailu
mirror of
https://github.com/Mailu/Mailu.git
synced 2025-11-23 22:04:47 +02:00
Implement the decorator-based access control for all views
This commit is contained in:
@@ -53,7 +53,12 @@ def domain_admin(args, kwargs, model, key):
|
|||||||
|
|
||||||
@permissions_wrapper
|
@permissions_wrapper
|
||||||
def owner(args, kwargs, model, key):
|
def owner(args, kwargs, model, key):
|
||||||
obj = model.query.get(kwargs[key])
|
# if no key is provided but the model is User, then return the current
|
||||||
|
# user
|
||||||
|
if kwargs[key] is None and model == models.User:
|
||||||
|
obj = model.query.get(flask_login.current_user.email)
|
||||||
|
else:
|
||||||
|
obj = model.query.get(kwargs[key])
|
||||||
if not obj:
|
if not obj:
|
||||||
flask.abort(404)
|
flask.abort(404)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from freeposte import dockercli
|
from freeposte import dockercli
|
||||||
from freeposte.admin import app, db, models, forms, utils
|
from freeposte.admin import app, db, models, forms, utils, access
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import flask
|
import flask
|
||||||
@@ -7,7 +7,7 @@ import flask_login
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/', methods=["GET"])
|
@app.route('/', methods=["GET"])
|
||||||
@flask_login.login_required
|
@access.authenticated
|
||||||
def index():
|
def index():
|
||||||
return flask.redirect(flask.url_for('.user_settings'))
|
return flask.redirect(flask.url_for('.user_settings'))
|
||||||
|
|
||||||
@@ -26,14 +26,14 @@ def login():
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/logout', methods=['GET'])
|
@app.route('/logout', methods=['GET'])
|
||||||
@flask_login.login_required
|
@access.authenticated
|
||||||
def logout():
|
def logout():
|
||||||
flask_login.logout_user()
|
flask_login.logout_user()
|
||||||
return flask.redirect(flask.url_for('.index'))
|
return flask.redirect(flask.url_for('.index'))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/services', methods=['GET'])
|
@app.route('/services', methods=['GET'])
|
||||||
@flask_login.login_required
|
@access.global_admin
|
||||||
def services():
|
def services():
|
||||||
utils.require_global_admin()
|
utils.require_global_admin()
|
||||||
containers = {}
|
containers = {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from freeposte.admin import app, db, models, forms, utils
|
from freeposte.admin import app, db, models, forms, utils, access
|
||||||
from freeposte import app as flask_app
|
from freeposte import app as flask_app
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -8,15 +8,14 @@ import wtforms_components
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/domain', methods=['GET'])
|
@app.route('/domain', methods=['GET'])
|
||||||
@flask_login.login_required
|
@access.authenticated
|
||||||
def domain_list():
|
def domain_list():
|
||||||
return flask.render_template('domain/list.html')
|
return flask.render_template('domain/list.html')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/domain/create', methods=['GET', 'POST'])
|
@app.route('/domain/create', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.global_admin
|
||||||
def domain_create():
|
def domain_create():
|
||||||
utils.require_global_admin()
|
|
||||||
form = forms.DomainForm()
|
form = forms.DomainForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
if models.Domain.query.get(form.name.data):
|
if models.Domain.query.get(form.name.data):
|
||||||
@@ -32,10 +31,9 @@ def domain_create():
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/domain/edit/<domain_name>', methods=['GET', 'POST'])
|
@app.route('/domain/edit/<domain_name>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.domain_admin(models.Domain, 'domain_name')
|
||||||
def domain_edit(domain_name):
|
def domain_edit(domain_name):
|
||||||
utils.require_global_admin()
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
domain = utils.get_domain_admin(domain_name)
|
|
||||||
form = forms.DomainForm(obj=domain)
|
form = forms.DomainForm(obj=domain)
|
||||||
wtforms_components.read_only(form.name)
|
wtforms_components.read_only(form.name)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
@@ -48,11 +46,10 @@ def domain_edit(domain_name):
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/domain/delete/<domain_name>', methods=['GET', 'POST'])
|
@app.route('/domain/delete/<domain_name>', methods=['GET', 'POST'])
|
||||||
|
@access.global_admin
|
||||||
@utils.confirmation_required("delete {domain_name}")
|
@utils.confirmation_required("delete {domain_name}")
|
||||||
@flask_login.login_required
|
|
||||||
def domain_delete(domain_name):
|
def domain_delete(domain_name):
|
||||||
utils.require_global_admin()
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
domain = utils.get_domain_admin(domain_name)
|
|
||||||
db.session.delete(domain)
|
db.session.delete(domain)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flask.flash('Domain %s deleted' % domain)
|
flask.flash('Domain %s deleted' % domain)
|
||||||
@@ -60,18 +57,18 @@ def domain_delete(domain_name):
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/domain/details/<domain_name>', methods=['GET'])
|
@app.route('/domain/details/<domain_name>', methods=['GET'])
|
||||||
@flask_login.login_required
|
@access.domain_admin(models.Domain, 'domain_name')
|
||||||
def domain_details(domain_name):
|
def domain_details(domain_name):
|
||||||
domain = utils.get_domain_admin(domain_name)
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
return flask.render_template('domain/details.html', domain=domain,
|
return flask.render_template('domain/details.html', domain=domain,
|
||||||
config=flask_app.config)
|
config=flask_app.config)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/domain/genkeys/<domain_name>', methods=['GET', 'POST'])
|
@app.route('/domain/genkeys/<domain_name>', methods=['GET', 'POST'])
|
||||||
|
@access.domain_admin(models.Domain, 'domain_name')
|
||||||
@utils.confirmation_required("regenerate keys for {domain_name}")
|
@utils.confirmation_required("regenerate keys for {domain_name}")
|
||||||
@flask_login.login_required
|
|
||||||
def domain_genkeys(domain_name):
|
def domain_genkeys(domain_name):
|
||||||
domain = utils.get_domain_admin(domain_name)
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
domain.generate_dkim_key()
|
domain.generate_dkim_key()
|
||||||
return flask.redirect(
|
return flask.redirect(
|
||||||
flask.url_for(".domain_details", domain_name=domain_name))
|
flask.url_for(".domain_details", domain_name=domain_name))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from freeposte.admin import app, db, models, forms, utils
|
from freeposte.admin import app, db, models, forms, utils, access
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import flask
|
import flask
|
||||||
@@ -8,17 +8,19 @@ import wtforms_components
|
|||||||
|
|
||||||
@app.route('/fetch/list', methods=['GET', 'POST'], defaults={'user_email': None})
|
@app.route('/fetch/list', methods=['GET', 'POST'], defaults={'user_email': None})
|
||||||
@app.route('/fetch/list/<user_email>', methods=['GET'])
|
@app.route('/fetch/list/<user_email>', methods=['GET'])
|
||||||
@flask_login.login_required
|
@access.owner(models.User, 'user_email')
|
||||||
def fetch_list(user_email):
|
def fetch_list(user_email):
|
||||||
user = utils.get_user(user_email)
|
user_email = user_email or flask_login.current_user.email
|
||||||
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
return flask.render_template('fetch/list.html', user=user)
|
return flask.render_template('fetch/list.html', user=user)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/fetch/create', methods=['GET', 'POST'], defaults={'user_email': None})
|
@app.route('/fetch/create', methods=['GET', 'POST'], defaults={'user_email': None})
|
||||||
@app.route('/fetch/create/<user_email>', methods=['GET', 'POST'])
|
@app.route('/fetch/create/<user_email>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.owner(models.User, 'user_email')
|
||||||
def fetch_create(user_email):
|
def fetch_create(user_email):
|
||||||
user = utils.get_user(user_email)
|
user_email = user_email or flask_login.current_user.email
|
||||||
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
form = forms.FetchForm()
|
form = forms.FetchForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
fetch = models.Fetch(user=user)
|
fetch = models.Fetch(user=user)
|
||||||
@@ -32,9 +34,9 @@ def fetch_create(user_email):
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/fetch/edit/<fetch_id>', methods=['GET', 'POST'])
|
@app.route('/fetch/edit/<fetch_id>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.owner(models.Fetch, 'fetch_id')
|
||||||
def fetch_edit(fetch_id):
|
def fetch_edit(fetch_id):
|
||||||
fetch = utils.get_fetch(fetch_id)
|
fetch = models.Fetch.query.get(fetch_id) or flask.abort(404)
|
||||||
form = forms.FetchForm(obj=fetch)
|
form = forms.FetchForm(obj=fetch)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
form.populate_obj(fetch)
|
form.populate_obj(fetch)
|
||||||
@@ -48,9 +50,9 @@ def fetch_edit(fetch_id):
|
|||||||
|
|
||||||
@app.route('/fetch/delete/<fetch_id>', methods=['GET', 'POST'])
|
@app.route('/fetch/delete/<fetch_id>', methods=['GET', 'POST'])
|
||||||
@utils.confirmation_required("delete a fetched account")
|
@utils.confirmation_required("delete a fetched account")
|
||||||
@flask_login.login_required
|
@access.owner(models.Fetch, 'fetch_id')
|
||||||
def fetch_delete(fetch_id):
|
def fetch_delete(fetch_id):
|
||||||
fetch = utils.get_fetch(fetch_id)
|
fetch = models.Fetch.query.get(fetch_id) or flask.abort(404)
|
||||||
db.session.delete(fetch)
|
db.session.delete(fetch)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flask.flash('Fetch configuration delete')
|
flask.flash('Fetch configuration delete')
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from freeposte.admin import app, db, models, forms, utils
|
from freeposte.admin import app, db, models, forms, utils, access
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import flask
|
import flask
|
||||||
@@ -7,16 +7,16 @@ import wtforms_components
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/manager/list/<domain_name>', methods=['GET'])
|
@app.route('/manager/list/<domain_name>', methods=['GET'])
|
||||||
@flask_login.login_required
|
@access.domain_admin(models.Domain, 'domain_name')
|
||||||
def manager_list(domain_name):
|
def manager_list(domain_name):
|
||||||
domain = utils.get_domain_admin(domain_name)
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
return flask.render_template('manager/list.html', domain=domain)
|
return flask.render_template('manager/list.html', domain=domain)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/manager/create/<domain_name>', methods=['GET', 'POST'])
|
@app.route('/manager/create/<domain_name>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.domain_admin(models.Domain, 'domain_name')
|
||||||
def manager_create(domain_name):
|
def manager_create(domain_name):
|
||||||
domain = utils.get_domain_admin(domain_name)
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
form = forms.ManagerForm()
|
form = forms.ManagerForm()
|
||||||
form.manager.choices = [
|
form.manager.choices = [
|
||||||
(user.email, user.email) for user in
|
(user.email, user.email) for user in
|
||||||
@@ -40,6 +40,7 @@ def manager_create(domain_name):
|
|||||||
@utils.confirmation_required("remove manager {manager}")
|
@utils.confirmation_required("remove manager {manager}")
|
||||||
@flask_login.login_required
|
@flask_login.login_required
|
||||||
def manager_delete(manager):
|
def manager_delete(manager):
|
||||||
|
# TODO fix this behaviour
|
||||||
user = utils.get_user(manager, admin=True)
|
user = utils.get_user(manager, admin=True)
|
||||||
domain = utils.get_domain_admin(user.domain_name)
|
domain = utils.get_domain_admin(user.domain_name)
|
||||||
if user in domain.managers:
|
if user in domain.managers:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from freeposte.admin import app, db, models, forms, utils
|
from freeposte.admin import app, db, models, forms, utils, access
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import flask
|
import flask
|
||||||
@@ -7,16 +7,16 @@ import wtforms_components
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/user/list/<domain_name>', methods=['GET'])
|
@app.route('/user/list/<domain_name>', methods=['GET'])
|
||||||
@flask_login.login_required
|
@access.domain_admin(models.Domain, 'domain_name')
|
||||||
def user_list(domain_name):
|
def user_list(domain_name):
|
||||||
domain = utils.get_domain_admin(domain_name)
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
return flask.render_template('user/list.html', domain=domain)
|
return flask.render_template('user/list.html', domain=domain)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/user/create/<domain_name>', methods=['GET', 'POST'])
|
@app.route('/user/create/<domain_name>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.domain_admin(models.Domain, 'domain_name')
|
||||||
def user_create(domain_name):
|
def user_create(domain_name):
|
||||||
domain = utils.get_domain_admin(domain_name)
|
domain = models.Domain.query.get(domain_name) or flask.abort(404)
|
||||||
if domain.max_users and len(domain.users) >= domain.max_users:
|
if domain.max_users and len(domain.users) >= domain.max_users:
|
||||||
flask.flash('Too many users for domain %s' % domain, 'error')
|
flask.flash('Too many users for domain %s' % domain, 'error')
|
||||||
return flask.redirect(
|
return flask.redirect(
|
||||||
@@ -39,9 +39,9 @@ def user_create(domain_name):
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/user/edit/<user_email>', methods=['GET', 'POST'])
|
@app.route('/user/edit/<user_email>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.domain_admin(models.User, 'user_email')
|
||||||
def user_edit(user_email):
|
def user_edit(user_email):
|
||||||
user = utils.get_user(user_email, True)
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
form = forms.UserForm(obj=user)
|
form = forms.UserForm(obj=user)
|
||||||
wtforms_components.read_only(form.localpart)
|
wtforms_components.read_only(form.localpart)
|
||||||
form.pw.validators = []
|
form.pw.validators = []
|
||||||
@@ -57,10 +57,10 @@ def user_edit(user_email):
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/user/delete/<user_email>', methods=['GET', 'POST'])
|
@app.route('/user/delete/<user_email>', methods=['GET', 'POST'])
|
||||||
|
@access.domain_admin(models.User, 'user_email')
|
||||||
@utils.confirmation_required("delete {user_email}")
|
@utils.confirmation_required("delete {user_email}")
|
||||||
@flask_login.login_required
|
|
||||||
def user_delete(user_email):
|
def user_delete(user_email):
|
||||||
user = utils.get_user(user_email, True)
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
db.session.delete(user)
|
db.session.delete(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flask.flash('User %s deleted' % user)
|
flask.flash('User %s deleted' % user)
|
||||||
@@ -70,9 +70,10 @@ def user_delete(user_email):
|
|||||||
|
|
||||||
@app.route('/user/settings', methods=['GET', 'POST'], defaults={'user_email': None})
|
@app.route('/user/settings', methods=['GET', 'POST'], defaults={'user_email': None})
|
||||||
@app.route('/user/usersettings/<user_email>', methods=['GET', 'POST'])
|
@app.route('/user/usersettings/<user_email>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.owner(models.User, 'user_email')
|
||||||
def user_settings(user_email):
|
def user_settings(user_email):
|
||||||
user = utils.get_user(user_email)
|
user_email = user_email or flask_login.current_user.email
|
||||||
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
form = forms.UserSettingsForm(obj=user)
|
form = forms.UserSettingsForm(obj=user)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
form.populate_obj(user)
|
form.populate_obj(user)
|
||||||
@@ -86,9 +87,10 @@ def user_settings(user_email):
|
|||||||
|
|
||||||
@app.route('/user/password', methods=['GET', 'POST'], defaults={'user_email': None})
|
@app.route('/user/password', methods=['GET', 'POST'], defaults={'user_email': None})
|
||||||
@app.route('/user/password/<user_email>', methods=['GET', 'POST'])
|
@app.route('/user/password/<user_email>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.owner(models.User, 'user_email')
|
||||||
def user_password(user_email):
|
def user_password(user_email):
|
||||||
user = utils.get_user(user_email)
|
user_email = user_email or flask_login.current_user.email
|
||||||
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
form = forms.UserPasswordForm()
|
form = forms.UserPasswordForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
if form.pw.data != form.pw2.data:
|
if form.pw.data != form.pw2.data:
|
||||||
@@ -105,9 +107,10 @@ def user_password(user_email):
|
|||||||
|
|
||||||
@app.route('/user/forward', methods=['GET', 'POST'], defaults={'user_email': None})
|
@app.route('/user/forward', methods=['GET', 'POST'], defaults={'user_email': None})
|
||||||
@app.route('/user/forward/<user_email>', methods=['GET', 'POST'])
|
@app.route('/user/forward/<user_email>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.owner(models.User, 'user_email')
|
||||||
def user_forward(user_email):
|
def user_forward(user_email):
|
||||||
user = utils.get_user(user_email)
|
user_email = user_email or flask_login.current_user.email
|
||||||
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
form = forms.UserForwardForm(obj=user)
|
form = forms.UserForwardForm(obj=user)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
form.populate_obj(user)
|
form.populate_obj(user)
|
||||||
@@ -121,9 +124,10 @@ def user_forward(user_email):
|
|||||||
|
|
||||||
@app.route('/user/reply', methods=['GET', 'POST'], defaults={'user_email': None})
|
@app.route('/user/reply', methods=['GET', 'POST'], defaults={'user_email': None})
|
||||||
@app.route('/user/reply/<user_email>', methods=['GET', 'POST'])
|
@app.route('/user/reply/<user_email>', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@access.owner(models.User, 'user_email')
|
||||||
def user_reply(user_email):
|
def user_reply(user_email):
|
||||||
user = utils.get_user(user_email)
|
user_email = user_email or flask_login.current_user.email
|
||||||
|
user = models.User.query.get(user_email) or flask.abort(404)
|
||||||
form = forms.UserReplyForm(obj=user)
|
form = forms.UserReplyForm(obj=user)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
form.populate_obj(user)
|
form.populate_obj(user)
|
||||||
|
|||||||
Reference in New Issue
Block a user