diff --git a/admin/freeposte/admin/access.py b/admin/freeposte/admin/access.py index 4c9e2764..8a8f2447 100644 --- a/admin/freeposte/admin/access.py +++ b/admin/freeposte/admin/access.py @@ -53,7 +53,12 @@ def domain_admin(args, kwargs, model, key): @permissions_wrapper 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: flask.abort(404) else: diff --git a/admin/freeposte/admin/views/base.py b/admin/freeposte/admin/views/base.py index 33e5d48d..2c32a832 100644 --- a/admin/freeposte/admin/views/base.py +++ b/admin/freeposte/admin/views/base.py @@ -1,5 +1,5 @@ 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 flask @@ -7,7 +7,7 @@ import flask_login @app.route('/', methods=["GET"]) -@flask_login.login_required +@access.authenticated def index(): return flask.redirect(flask.url_for('.user_settings')) @@ -26,14 +26,14 @@ def login(): @app.route('/logout', methods=['GET']) -@flask_login.login_required +@access.authenticated def logout(): flask_login.logout_user() return flask.redirect(flask.url_for('.index')) @app.route('/services', methods=['GET']) -@flask_login.login_required +@access.global_admin def services(): utils.require_global_admin() containers = {} diff --git a/admin/freeposte/admin/views/domains.py b/admin/freeposte/admin/views/domains.py index 93b0449e..b6c05c6d 100644 --- a/admin/freeposte/admin/views/domains.py +++ b/admin/freeposte/admin/views/domains.py @@ -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 import os @@ -8,15 +8,14 @@ import wtforms_components @app.route('/domain', methods=['GET']) -@flask_login.login_required +@access.authenticated def domain_list(): return flask.render_template('domain/list.html') @app.route('/domain/create', methods=['GET', 'POST']) -@flask_login.login_required +@access.global_admin def domain_create(): - utils.require_global_admin() form = forms.DomainForm() if form.validate_on_submit(): if models.Domain.query.get(form.name.data): @@ -32,10 +31,9 @@ def domain_create(): @app.route('/domain/edit/', methods=['GET', 'POST']) -@flask_login.login_required +@access.domain_admin(models.Domain, 'domain_name') def domain_edit(domain_name): - utils.require_global_admin() - domain = utils.get_domain_admin(domain_name) + domain = models.Domain.query.get(domain_name) or flask.abort(404) form = forms.DomainForm(obj=domain) wtforms_components.read_only(form.name) if form.validate_on_submit(): @@ -48,11 +46,10 @@ def domain_edit(domain_name): @app.route('/domain/delete/', methods=['GET', 'POST']) +@access.global_admin @utils.confirmation_required("delete {domain_name}") -@flask_login.login_required def domain_delete(domain_name): - utils.require_global_admin() - domain = utils.get_domain_admin(domain_name) + domain = models.Domain.query.get(domain_name) or flask.abort(404) db.session.delete(domain) db.session.commit() flask.flash('Domain %s deleted' % domain) @@ -60,18 +57,18 @@ def domain_delete(domain_name): @app.route('/domain/details/', methods=['GET']) -@flask_login.login_required +@access.domain_admin(models.Domain, '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, config=flask_app.config) @app.route('/domain/genkeys/', methods=['GET', 'POST']) +@access.domain_admin(models.Domain, 'domain_name') @utils.confirmation_required("regenerate keys for {domain_name}") -@flask_login.login_required 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() return flask.redirect( flask.url_for(".domain_details", domain_name=domain_name)) diff --git a/admin/freeposte/admin/views/fetches.py b/admin/freeposte/admin/views/fetches.py index 5870ef2a..649d8576 100644 --- a/admin/freeposte/admin/views/fetches.py +++ b/admin/freeposte/admin/views/fetches.py @@ -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 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']) -@flask_login.login_required +@access.owner(models.User, '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) @app.route('/fetch/create', methods=['GET', 'POST'], defaults={'user_email': None}) @app.route('/fetch/create/', methods=['GET', 'POST']) -@flask_login.login_required +@access.owner(models.User, '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() if form.validate_on_submit(): fetch = models.Fetch(user=user) @@ -32,9 +34,9 @@ def fetch_create(user_email): @app.route('/fetch/edit/', methods=['GET', 'POST']) -@flask_login.login_required +@access.owner(models.Fetch, '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) if form.validate_on_submit(): form.populate_obj(fetch) @@ -48,9 +50,9 @@ def fetch_edit(fetch_id): @app.route('/fetch/delete/', methods=['GET', 'POST']) @utils.confirmation_required("delete a fetched account") -@flask_login.login_required +@access.owner(models.Fetch, '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.commit() flask.flash('Fetch configuration delete') diff --git a/admin/freeposte/admin/views/managers.py b/admin/freeposte/admin/views/managers.py index b19789df..ec6e19e3 100644 --- a/admin/freeposte/admin/views/managers.py +++ b/admin/freeposte/admin/views/managers.py @@ -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 flask @@ -7,16 +7,16 @@ import wtforms_components @app.route('/manager/list/', methods=['GET']) -@flask_login.login_required +@access.domain_admin(models.Domain, '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) @app.route('/manager/create/', methods=['GET', 'POST']) -@flask_login.login_required +@access.domain_admin(models.Domain, '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.manager.choices = [ (user.email, user.email) for user in @@ -40,6 +40,7 @@ def manager_create(domain_name): @utils.confirmation_required("remove manager {manager}") @flask_login.login_required def manager_delete(manager): + # TODO fix this behaviour user = utils.get_user(manager, admin=True) domain = utils.get_domain_admin(user.domain_name) if user in domain.managers: diff --git a/admin/freeposte/admin/views/users.py b/admin/freeposte/admin/views/users.py index 0c6c6374..37cab07e 100644 --- a/admin/freeposte/admin/views/users.py +++ b/admin/freeposte/admin/views/users.py @@ -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 flask @@ -7,16 +7,16 @@ import wtforms_components @app.route('/user/list/', methods=['GET']) -@flask_login.login_required +@access.domain_admin(models.Domain, '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) @app.route('/user/create/', methods=['GET', 'POST']) -@flask_login.login_required +@access.domain_admin(models.Domain, '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: flask.flash('Too many users for domain %s' % domain, 'error') return flask.redirect( @@ -39,9 +39,9 @@ def user_create(domain_name): @app.route('/user/edit/', methods=['GET', 'POST']) -@flask_login.login_required +@access.domain_admin(models.User, '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) wtforms_components.read_only(form.localpart) form.pw.validators = [] @@ -57,10 +57,10 @@ def user_edit(user_email): @app.route('/user/delete/', methods=['GET', 'POST']) +@access.domain_admin(models.User, 'user_email') @utils.confirmation_required("delete {user_email}") -@flask_login.login_required 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.commit() 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/usersettings/', methods=['GET', 'POST']) -@flask_login.login_required +@access.owner(models.User, '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) if form.validate_on_submit(): 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']) -@flask_login.login_required +@access.owner(models.User, '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() if form.validate_on_submit(): 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']) -@flask_login.login_required +@access.owner(models.User, '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) if form.validate_on_submit(): 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']) -@flask_login.login_required +@access.owner(models.User, '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) if form.validate_on_submit(): form.populate_obj(user)