From ec6d0a6477763c5bec3c1c5d82a14cc51816ecdf Mon Sep 17 00:00:00 2001 From: Inga Kirschnick Date: Tue, 28 Feb 2023 10:27:10 +0100 Subject: [PATCH] corpus permission decorator + sidenav update --- app/corpora/decorators.py | 37 ++++++++++++++++++++++++++++++++++ app/corpora/routes.py | 14 +++++++++---- app/templates/_sidenav.html.j2 | 17 ++++++++++------ 3 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 app/corpora/decorators.py diff --git a/app/corpora/decorators.py b/app/corpora/decorators.py new file mode 100644 index 00000000..3d841e9b --- /dev/null +++ b/app/corpora/decorators.py @@ -0,0 +1,37 @@ +from flask import abort, current_app +from flask_login import current_user +from functools import wraps +from app.models import Corpus, CorpusFollowerAssociation + +def corpus_follower_permission_required(permissions): + def decorator(f): + @wraps(f) + def decorated_function(*args, **kwargs): + corpus_id = kwargs.get('corpus_id') + corpus = Corpus.query.get_or_404(corpus_id) + if current_user == corpus.user or current_user.is_administrator(): + print('user or admin') + return f(*args, **kwargs) + if not current_user.is_following_corpus(corpus): + print('not following corpus') + abort(403) + corpus_follower_association = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first_or_404() + for permission in permissions: + if not corpus_follower_association.role.has_permission(permission): + abort(403) + return f(*args, **kwargs) + return decorated_function + return decorator + +def owner_or_admin_required(): + def decorator(f): + @wraps(f) + def decorated_function(*args, **kwargs): + corpus_id = kwargs.get('corpus_id') + corpus = Corpus.query.get_or_404(corpus_id) + if current_user == corpus.user or current_user.is_administrator(): + return f(*args, **kwargs) + abort(403) + return decorated_function + return decorator + diff --git a/app/corpora/routes.py b/app/corpora/routes.py index ecb74cae..9a69ebd8 100644 --- a/app/corpora/routes.py +++ b/app/corpora/routes.py @@ -15,6 +15,7 @@ from flask_login import current_user, login_required from threading import Thread import jwt import os +from .decorators import corpus_follower_permission_required, owner_or_admin_required from app import db, hashids from app.models import ( Corpus, @@ -32,6 +33,11 @@ from .forms import ( UpdateCorpusFileForm ) +@bp.route('//test') +@login_required +@corpus_follower_permission_required(['VIEW', 'ADD_CORPUS_FILE']) +def test(corpus_id): + return 'ok' @bp.route('/fake-add') @login_required @@ -45,10 +51,9 @@ def fake_add(): @bp.route('//is_public/enable', methods=['POST']) @login_required +@owner_or_admin_required() def enable_corpus_is_public(corpus_id): corpus = Corpus.query.get_or_404(corpus_id) - if not (corpus.user == current_user or current_user.is_administrator()): - abort(403) corpus.is_public = True db.session.commit() return '', 204 @@ -56,10 +61,9 @@ def enable_corpus_is_public(corpus_id): @bp.route('//is_public/disable', methods=['POST']) @login_required +@owner_or_admin_required() def disable_corpus_is_public(corpus_id): corpus = Corpus.query.get_or_404(corpus_id) - if not (corpus.user == current_user or current_user.is_administrator()): - abort(403) corpus.is_public = False db.session.commit() return '', 204 @@ -107,6 +111,7 @@ def current_user_unfollow_corpus(corpus_id): @bp.route('//followers//role', methods=['POST']) +@corpus_follower_permission_required(['REMOVE_FOLLOWER', 'UPDATE_FOLLOWER']) def add_permission(corpus_id, follower_id): corpus_follower_association = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404() if not (corpus_follower_association.corpus.user == current_user or current_user.is_administrator()): @@ -188,6 +193,7 @@ def corpus(corpus_id): @bp.route('//generate-corpus-share-link', methods=['GET', 'POST']) @login_required +@corpus_follower_permission_required('GENERATE_SHARE_LINK') def generate_corpus_share_link(corpus_id): data = request.get_json('data') role = data['role'] diff --git a/app/templates/_sidenav.html.j2 b/app/templates/_sidenav.html.j2 index 7fa34623..18b902af 100644 --- a/app/templates/_sidenav.html.j2 +++ b/app/templates/_sidenav.html.j2 @@ -3,11 +3,17 @@