From e1cfd394fa2e321dad9e73dc2aac7621b0d00cf5 Mon Sep 17 00:00:00 2001 From: Patrick Jentsch Date: Sat, 4 May 2024 14:55:05 +0200 Subject: [PATCH] move socketio decorators --- app/admin/events.py | 4 +- app/corpora/cqi_over_sio/__init__.py | 8 ++-- app/corpora/events.py | 6 +-- app/decorators.py | 39 +++++++++++-------- app/extensions/__init__.py | 1 - .../flask_socketio_extras/__init__.py | 3 -- .../flask_socketio_extras/decorators.py | 27 ------------- app/users/events.py | 8 ++-- app/users/nevents.py | 18 ++++----- 9 files changed, 44 insertions(+), 70 deletions(-) delete mode 100644 app/extensions/__init__.py delete mode 100644 app/extensions/flask_socketio_extras/__init__.py delete mode 100644 app/extensions/flask_socketio_extras/decorators.py diff --git a/app/admin/events.py b/app/admin/events.py index e5ed7b0b..01cefa55 100644 --- a/app/admin/events.py +++ b/app/admin/events.py @@ -1,7 +1,7 @@ from flask_login import current_user from flask_socketio import disconnect, Namespace from app import db, hashids -from app.extensions.flask_socketio_extras import admin_required +from app.decorators import socketio_admin_required from app.models import User @@ -12,7 +12,7 @@ class AdminNamespace(Namespace): disconnect() - @admin_required + @socketio_admin_required def on_set_user_confirmed(self, user_hashid: str, confirmed_value: bool): # Decode the user hashid user_id = hashids.decode(user_hashid) diff --git a/app/corpora/cqi_over_sio/__init__.py b/app/corpora/cqi_over_sio/__init__.py index 90d9719e..25102c94 100644 --- a/app/corpora/cqi_over_sio/__init__.py +++ b/app/corpora/cqi_over_sio/__init__.py @@ -9,7 +9,7 @@ from inspect import signature from threading import Lock from typing import Callable, Dict, List, Optional from app import db, docker_client, hashids, socketio -from app.extensions.flask_socketio_extras import login_required +from app.decorators import socketio_login_required from app.models import Corpus, CorpusStatus from . import extensions @@ -87,11 +87,11 @@ CQI_API_FUNCTION_NAMES: List[str] = [ class CQiNamespace(Namespace): - @login_required + @socketio_login_required def on_connect(self): pass - @login_required + @socketio_login_required def on_init(self, db_corpus_hashid: str): db_corpus_id: int = hashids.decode(db_corpus_hashid) db_corpus: Optional[Corpus] = Corpus.query.get(db_corpus_id) @@ -134,7 +134,7 @@ class CQiNamespace(Namespace): } return {'code': 200, 'msg': 'OK'} - @login_required + @socketio_login_required def on_exec(self, fn_name: str, fn_args: Dict = {}): try: cqi_client: CQiClient = session['cqi_over_sio']['cqi_client'] diff --git a/app/corpora/events.py b/app/corpora/events.py index cc0baad1..9a0e3a36 100644 --- a/app/corpora/events.py +++ b/app/corpora/events.py @@ -1,12 +1,12 @@ from flask_login import current_user from flask_socketio import join_room from app import hashids, socketio -from app.extensions.flask_socketio_extras import login_required +from app.decorators import socketio_login_required from app.models import Corpus @socketio.on('GET /corpora/') -@login_required +@socketio_login_required def get_corpus(corpus_hashid): corpus_id = hashids.decode(corpus_hashid) corpus = Corpus.query.get(corpus_id) @@ -29,7 +29,7 @@ def get_corpus(corpus_hashid): @socketio.on('SUBSCRIBE /corpora/') -@login_required +@socketio_login_required def subscribe_corpus(corpus_hashid): corpus_id = hashids.decode(corpus_hashid) corpus = Corpus.query.get(corpus_id) diff --git a/app/decorators.py b/app/decorators.py index 5fbd7671..051807ab 100644 --- a/app/decorators.py +++ b/app/decorators.py @@ -1,7 +1,6 @@ -from flask import abort, current_app, request +from flask import abort, request from flask_login import current_user from functools import wraps -from threading import Thread from typing import List, Union from werkzeug.exceptions import NotAcceptable from app.models import Permission @@ -22,22 +21,28 @@ def admin_required(f): return permission_required(Permission.ADMINISTRATE)(f) -def background(f): - ''' - ' This decorator executes a function in a Thread. - ' Decorated functions need to be executed within a code block where an - ' app context exists. - ' - ' NOTE: An app object is passed as a keyword argument to the decorated - ' function. - ''' +def socketio_login_required(f): @wraps(f) - def wrapped(*args, **kwargs): - kwargs['app'] = current_app._get_current_object() - thread = Thread(target=f, args=args, kwargs=kwargs) - thread.start() - return thread - return wrapped + def wrapper(*args, **kwargs): + if current_user.is_authenticated: + return f(*args, **kwargs) + return {'code': 401, 'body': 'Unauthorized'} + return wrapper + + +def socketio_permission_required(permission): + def decorator(f): + @wraps(f) + def wrapper(*args, **kwargs): + if not current_user.can(permission): + return {'code': 403, 'body': 'Forbidden'} + return f(*args, **kwargs) + return wrapper + return decorator + + +def socketio_admin_required(f): + return socketio_permission_required(Permission.ADMINISTRATE)(f) def content_negotiation( diff --git a/app/extensions/__init__.py b/app/extensions/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/app/extensions/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/extensions/flask_socketio_extras/__init__.py b/app/extensions/flask_socketio_extras/__init__.py deleted file mode 100644 index 866c0cc9..00000000 --- a/app/extensions/flask_socketio_extras/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .decorators import login_required -from .decorators import permission_required -from .decorators import admin_required diff --git a/app/extensions/flask_socketio_extras/decorators.py b/app/extensions/flask_socketio_extras/decorators.py deleted file mode 100644 index 8e8d0a05..00000000 --- a/app/extensions/flask_socketio_extras/decorators.py +++ /dev/null @@ -1,27 +0,0 @@ -from flask_login import current_user -from functools import wraps -from app.models import Permission as UserPermission - - -def login_required(f): - @wraps(f) - def wrapper(*args, **kwargs): - if current_user.is_authenticated: - return f(*args, **kwargs) - return {'code': 401, 'body': 'Unauthorized'} - return wrapper - - -def permission_required(permission): - def decorator(f): - @wraps(f) - def wrapper(*args, **kwargs): - if not current_user.can(permission): - return {'code': 403, 'body': 'Forbidden'} - return f(*args, **kwargs) - return wrapper - return decorator - - -def admin_required(f): - return permission_required(UserPermission.ADMINISTRATE)(f) diff --git a/app/users/events.py b/app/users/events.py index e010ce10..8132f818 100644 --- a/app/users/events.py +++ b/app/users/events.py @@ -1,12 +1,12 @@ from flask_login import current_user from flask_socketio import join_room, leave_room from app import hashids, socketio -from app.extensions.flask_socketio_extras import login_required +from app.decorators import socketio_login_required from app.models import User @socketio.on('GET /users/') -@login_required +@socketio_login_required def get_user(user_hashid): user_id = hashids.decode(user_hashid) user = User.query.get(user_id) @@ -22,7 +22,7 @@ def get_user(user_hashid): @socketio.on('SUBSCRIBE /users/') -@login_required +@socketio_login_required def subscribe_user(user_hashid): user_id = hashids.decode(user_hashid) user = User.query.get(user_id) @@ -35,7 +35,7 @@ def subscribe_user(user_hashid): @socketio.on('UNSUBSCRIBE /users/') -@login_required +@socketio_login_required def unsubscribe_user(user_hashid): user_id = hashids.decode(user_hashid) user = User.query.get(user_id) diff --git a/app/users/nevents.py b/app/users/nevents.py index de79161c..c67817b8 100644 --- a/app/users/nevents.py +++ b/app/users/nevents.py @@ -1,12 +1,12 @@ from flask_login import current_user from flask_socketio import join_room from app import hashids, socketio -from app.extensions.flask_socketio_extras import admin_required, login_required +from app.decorators import socketio_admin_required, socketio_login_required from app.models import User @socketio.on('GET /users') -@admin_required +@socketio_admin_required def get_users(): users = User.query.filter_by().all() return { @@ -20,14 +20,14 @@ def get_users(): @socketio.on('SUBSCRIBE /users') -@admin_required +@socketio_admin_required def subscribe_users(): join_room('/users') return {'options': {'status': 200, 'statusText': 'OK'}} @socketio.on('GET /users/') -@login_required +@socketio_login_required def get_user(user_hashid): user_id = hashids.decode(user_hashid) user = User.query.get(user_id) @@ -46,7 +46,7 @@ def get_user(user_hashid): @socketio.on('SUBSCRIBE /users/') -@login_required +@socketio_login_required def subscribe_user(user_hashid): user_id = hashids.decode(user_hashid) user = User.query.get(user_id) @@ -59,7 +59,7 @@ def subscribe_user(user_hashid): @socketio.on('GET /public_users') -@login_required +@socketio_login_required def get_public_users(): users = User.query.filter_by(is_public=True).all() return { @@ -76,14 +76,14 @@ def get_public_users(): @socketio.on('SUBSCRIBE /users') -@admin_required +@socketio_admin_required def subscribe_users(): join_room('/public_users') return {'options': {'status': 200, 'statusText': 'OK'}} @socketio.on('GET /public_users/') -@login_required +@socketio_login_required def get_user(user_hashid): user_id = hashids.decode(user_hashid) user = User.query.filter_by(id=user_id, is_public=True).first() @@ -102,7 +102,7 @@ def get_user(user_hashid): @socketio.on('SUBSCRIBE /public_users/') -@login_required +@socketio_login_required def subscribe_user(user_hashid): user_id = hashids.decode(user_hashid) user = User.query.filter_by(id=user_id, is_public=True).first()