From 433c046ca82183ba005f68f61b8476c513c09db0 Mon Sep 17 00:00:00 2001 From: kirianguiller Date: Sat, 24 Oct 2020 12:59:42 +0200 Subject: [PATCH] require access service --- app/auth/auth_config.py | 8 ++--- app/projects/controller.py | 1 + app/projects/schema.py | 3 +- app/projects/service.py | 30 +++++++++++++++---- app/shared/decorator.py | 44 ++++++++++++++++++++++++++++ app/templates/auth/redirect_dev.html | 2 +- app/trees/controller.py | 11 ++++--- app/utils/conll3/__init__.py | 2 +- 8 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 app/shared/decorator.py diff --git a/app/auth/auth_config.py b/app/auth/auth_config.py index 026f14c..54c5c73 100644 --- a/app/auth/auth_config.py +++ b/app/auth/auth_config.py @@ -42,12 +42,12 @@ 'github': { # prod - 'consumer_key':'a10dffc2b29dbddacb9d', - 'consumer_secret': '59cf1a4ffda3d036bc8274131ad82e7fa6038c01', + #'consumer_key':'a10dffc2b29dbddacb9d', + #'consumer_secret': '59cf1a4ffda3d036bc8274131ad82e7fa6038c01', # dev - #'consumer_key':'924aedede12fde87b5f4', - #'consumer_secret':'4b4e6235887137665573659c7ebd2f3980dde718', + 'consumer_key':'924aedede12fde87b5f4', + 'consumer_secret':'4b4e6235887137665573659c7ebd2f3980dde718', # shared 'class_': oauth2.GitHub, diff --git a/app/projects/controller.py b/app/projects/controller.py index b5f10f4..cbd6d2d 100644 --- a/app/projects/controller.py +++ b/app/projects/controller.py @@ -41,6 +41,7 @@ def get(self) -> List[ProjectExtendedInterface]: # if len(grewnames ^ dbnames) > 0: # projects_info["difference"] = True for project in projects: + print("KK bla") dumped_project: ProjectExtendedInterface = ProjectSchema().dump(project) if dumped_project["project_name"] not in common: continue diff --git a/app/projects/schema.py b/app/projects/schema.py index 8500ddb..d529bba 100644 --- a/app/projects/schema.py +++ b/app/projects/schema.py @@ -16,7 +16,8 @@ class ProjectSchema(Schema): id = fields.Integer(attribute="id") project_name = fields.String(attribute="project_name") description = fields.String(attribute="description") - image = BytesField(attribute="image") + # TODO : Find how to serialize glob images + # image = BytesField(attribute="image") visibility = fields.Integer(attribute="visibility") show_all_trees = fields.Boolean(attribute="show_all_trees") exercise_mode = fields.Boolean(attribute="exercise_mode") diff --git a/app/projects/service.py b/app/projects/service.py index 4151e5f..e3416eb 100644 --- a/app/projects/service.py +++ b/app/projects/service.py @@ -1,6 +1,8 @@ from typing import Dict, List from app import db +from flask import abort +from flask_login import current_user from .interface import ProjectExtendedInterface, ProjectInterface from .model import Project, ProjectAccess, ProjectFeature, ProjectMetaFeature @@ -64,7 +66,7 @@ def delete(user_id: str, project_id: int): db.session.commit() return [(project_id, user_id)] - # TODO : Rename this as `get_by_username` because we are not fetching the user_id + # TODO : Rename this as `get_by_username` because we are not fetching the user_id # ... but the username @staticmethod def get_by_user_id(user_id: str, project_id: str) -> ProjectAccess: @@ -101,6 +103,23 @@ def get_users_role(project_id: str) -> Dict[str, List[str]]: "guests": guests, } + @staticmethod + def require_access_level(project_id, required_access_level) -> None: + access_level = 0 + if current_user.is_authenticated: + if current_user.super_admin: + pass + + else: + access_level = ProjectAccessService.get_by_user_id( + current_user.id, project_id + ).access_level.code + + if access_level >= required_access_level: + return + else: + abort(403) + class ProjectFeatureService: @staticmethod @@ -119,8 +138,8 @@ def get_by_project_id(project_id: str) -> List[str]: return [] @staticmethod - def delete_by_project_id(project_id: str) ->str: - """TODO : Delete all the project features at once. This is a weird way of doing, but it's because we have a table specificaly + def delete_by_project_id(project_id: str) -> str: + """TODO : Delete all the project features at once. This is a weird way of doing, but it's because we have a table specificaly ...dedicated for linking project shown features and project. Maybe a simple textfield in the project settings would do the job""" features = ProjectFeature.query.filter_by(project_id=project_id).all() for feature in features: @@ -146,10 +165,9 @@ def get_by_project_id(project_id: str) -> List[str]: else: return [] - @staticmethod - def delete_by_project_id(project_id: str) ->str: - """Delete all the project features at once. This is a weird way of doing, but it's because we have a table specificaly + def delete_by_project_id(project_id: str) -> str: + """Delete all the project features at once. This is a weird way of doing, but it's because we have a table specificaly ...dedicated for linking project shown features and project. Maybe a simple textfield in the project settings would do the job""" features = ProjectMetaFeature.query.filter_by(project_id=project_id).all() for feature in features: diff --git a/app/shared/decorator.py b/app/shared/decorator.py new file mode 100644 index 0000000..d1f9029 --- /dev/null +++ b/app/shared/decorator.py @@ -0,0 +1,44 @@ +# from flask import redirect, url_for, abort, +# from flask_login import current_user +# from functools import wraps +# # from flask_cors import cross_origin + +# from app.projects.service import ProjectAccessService, ProjectService + +# from ...services import project_service, user_service, robot_service, github_service, samples_service # type: ignore + + +# def requires_access_level(access_level): +# """ decorator for access control. except for superadmins """ +# def decorator(f): +# @wraps(f) +# def decorated_function(*args, **kwargs): +# # not authenticated -> login +# if not current_user.id: +# return redirect(url_for('auth.login')) + +# if kwargs.get("project_name"): +# project_id = project_service.get_by_name( +# kwargs["project_name"]).id +# elif kwargs.get("id"): +# project_id = kwargs["id"] +# else: +# abort(400) + +# project_access = project_service.get_project_access( +# project_id, current_user.id) + +# print("project_access for current user: {}".format(project_access)) + +# if not current_user.super_admin: # super_admin are always admin even if it's not in the table +# if project_access < access_level: +# abort(403, "User doesn't have the right privileges") +# # if isinstance(project_access, int): +# # abort(403, "ERROR isinstance(project_access, int)") +# # if project_access is None or project_access.access_level.code < access_level: +# # abort(403, "project_access is None or project_access.access_level.code < access_level") +# # # return redirect(url_for('home.home_page')) + +# return f(*args, **kwargs) +# return decorated_function +# return decorator \ No newline at end of file diff --git a/app/templates/auth/redirect_dev.html b/app/templates/auth/redirect_dev.html index 7da7026..75a6508 100644 --- a/app/templates/auth/redirect_dev.html +++ b/app/templates/auth/redirect_dev.html @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/trees/controller.py b/app/trees/controller.py index 3a41639..f3f0413 100644 --- a/app/trees/controller.py +++ b/app/trees/controller.py @@ -22,7 +22,6 @@ def get(self, projectName: str, sampleName: str): data={"project_id": projectName, "sample_id": sampleName}, ) data = reply.get("data") - print("KK data", reply.get("status")) if reply.get("status") != "OK": abort(409) @@ -31,17 +30,17 @@ def get(self, projectName: str, sampleName: str): abort(404) samples = reply.get("data", {}) - + ProjectAccessService.require_access_level(project.id, 2) ##### exercise mode block ##### exercise_mode = project.exercise_mode project_access: int = 0 exercise_level: int = 4 - project_access = ProjectAccessService.get_by_user_id( - current_user.id, project.id - ).access_level + if current_user.is_authenticated: + project_access = ProjectAccessService.get_by_user_id( + current_user.id, project.id + ).access_level.code - print("KK current_user.id", project_access) if exercise_mode: exercise_level_obj = SampleExerciseLevelService.get_by_sample_name( project.id, sampleName diff --git a/app/utils/conll3/__init__.py b/app/utils/conll3/__init__.py index 7c85571..a33bb50 100644 --- a/app/utils/conll3/__init__.py +++ b/app/utils/conll3/__init__.py @@ -8,7 +8,7 @@ #### # Copyright (C) 2009-2017 Kim Gerdes # kim AT gerdes. fr -# http://arborator.ilpga.fr/ +# http://arborator.elizia.net/ # # This program is free software; you can redistribute it and/or # modify it under the terms of version 3 of the GNU Affero General Public License (the "License")