Skip to content

Commit

Permalink
Merge pull request #775 from Lunatic-Labs/SKIL-518
Browse files Browse the repository at this point in the history
SKIL-518
  • Loading branch information
aparriaran authored Nov 20, 2024
2 parents eadc20e + b36a96e commit 92a47d0
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 14 deletions.
9 changes: 8 additions & 1 deletion BackEndFlask/controller/Routes/Assessment_task_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
from models.role import get_role
from controller.Route_response import *
from models.user_course import get_user_courses_by_user_id

from flask_jwt_extended import jwt_required
from controller.security.CustomDecorators import AuthCheck, bad_token_check
from controller.security.CustomDecorators import (
AuthCheck, bad_token_check,
admin_check
)

from models.assessment_task import (
get_assessment_tasks_by_course_id,
Expand Down Expand Up @@ -173,6 +177,7 @@ def get_one_assessment_task():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def add_assessment_task():
try:
new_assessment_task = create_assessment_task(request.json)
Expand All @@ -192,6 +197,7 @@ def add_assessment_task():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def update_assessment_task():
try:
if request.args and request.args.get("notification"):
Expand Down Expand Up @@ -256,6 +262,7 @@ def update_assessment_task():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def copy_course_assessments():
try:
source_course_id = request.args.get('source_course_id')
Expand Down
7 changes: 6 additions & 1 deletion BackEndFlask/controller/Routes/Bulk_upload_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@
import shutil
from controller.Route_response import create_bad_response, create_good_response
from flask_jwt_extended import jwt_required
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import (
AuthCheck, bad_token_check,
admin_check
)

@bp.route('/bulk_upload', methods = ['POST'])
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def upload_CSV():
try:
file = request.files['csv_file']
Expand Down
2 changes: 1 addition & 1 deletion BackEndFlask/controller/Routes/Checkin_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def get_checked_in():
except Exception as e:
return create_bad_response(f"An error occurred getting checked in user {e}", "checkin", 400)

@bp.route('/checkin_events', methods = ['GET'])
@bp.route('/checkin_events', methods = ['GET'])
@jwt_required()
@bad_token_check()
@AuthCheck()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
from controller.Route_response import *
from flask_jwt_extended import jwt_required
from models.assessment_task import get_assessment_task
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import (
AuthCheck, bad_token_check,
admin_check
)

from models.completed_assessment import (
get_completed_assessments,
Expand Down Expand Up @@ -173,6 +177,7 @@ def add_completed_assessment():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def update_completed_assessment():
try:
completed_assessment_id = request.args.get("completed_assessment_id")
Expand Down
8 changes: 7 additions & 1 deletion BackEndFlask/controller/Routes/Course_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
from controller import bp
from controller.Route_response import *
from flask_jwt_extended import jwt_required
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import(
AuthCheck, bad_token_check,
admin_check
)

from models.course import(
get_course,
Expand Down Expand Up @@ -76,6 +80,7 @@ def get_one_course():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def add_course():
try:
new_course = create_course(request.json)
Expand All @@ -98,6 +103,7 @@ def add_course():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def update_course():
try:
course_id = request.args.get("course_id")
Expand Down
6 changes: 5 additions & 1 deletion BackEndFlask/controller/Routes/Csv_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@
from controller import bp
from controller.Route_response import *
from flask_jwt_extended import jwt_required
from controller.security.CustomDecorators import AuthCheck, bad_token_check
from Functions.exportCsv import create_csv_strings
from models.assessment_task import get_assessment_task
from models.user import get_user

from controller.security.CustomDecorators import (
AuthCheck, bad_token_check,
admin_check
)

@bp.route('/csv_assessment_export', methods = ['GET'])
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def get_completed_assessment_csv() -> dict:
"""
Description:
Expand Down
8 changes: 7 additions & 1 deletion BackEndFlask/controller/Routes/Rating_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
from models.completed_assessment import *
from models.queries import get_individual_ratings
from flask_jwt_extended import jwt_required
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import (
AuthCheck, bad_token_check,
admin_check
)

@bp.route("/rating", methods=["GET"])
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def get_student_individual_ratings():
"""
Description:
Expand Down Expand Up @@ -53,6 +58,7 @@ def get_student_individual_ratings():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def student_view_feedback():
"""
Description:
Expand Down
9 changes: 8 additions & 1 deletion BackEndFlask/controller/Routes/Rubric_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
from models.rubric import get_rubric, get_rubrics, create_rubric, delete_rubric_by_id
from models.category import get_categories_per_rubric, get_categories, get_ratings_by_category
from models.suggestions import get_suggestions_per_category
from controller.security.CustomDecorators import AuthCheck, bad_token_check
from models.observable_characteristics import get_observable_characteristic_per_category
from models.queries import get_rubrics_and_total_categories, get_rubrics_and_total_categories_for_user_id, get_categories_for_user_id
from models.user import get_user

from controller.security.CustomDecorators import(
AuthCheck, bad_token_check,
admin_check
)

@bp.route('/rubric', methods = ['GET'])
@jwt_required()
@bad_token_check()
Expand Down Expand Up @@ -103,6 +107,7 @@ def get_all_rubrics():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def add_rubric():
# expects to recieve a json object with all two fields.
# one named 'rubric' holds all the fields for a rubric (except rubric_id)
Expand Down Expand Up @@ -161,6 +166,7 @@ def get_all_categories():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def edit_rubric():
try:
if request.args and request.args.get("rubric_id"):
Expand Down Expand Up @@ -197,6 +203,7 @@ def edit_rubric():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def delete_rubric():
try:
if request.args and request.args.get("rubric_id"):
Expand Down
7 changes: 6 additions & 1 deletion BackEndFlask/controller/Routes/Team_bulk_upload_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@
from Functions import customExceptions
from controller.Route_response import *
from flask_jwt_extended import jwt_required
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import (
AuthCheck, bad_token_check,
admin_check
)

@bp.route('/team_bulk_upload', methods=['POST'])
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def upload_team_csv():
try:
file = request.files['csv_file']
Expand Down
10 changes: 9 additions & 1 deletion BackEndFlask/controller/Routes/Team_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
from models.assessment_task import get_assessment_tasks_by_team_id
from models.completed_assessment import completed_assessment_team_or_user_exists
from models.team_user import *
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import(
AuthCheck, bad_token_check,
admin_check
)

from models.queries import (
get_team_by_course_id_and_user_id,
get_all_nonfull_adhoc_teams
Expand Down Expand Up @@ -110,6 +115,7 @@ def get_nonfull_adhoc_teams():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def add_team():
try:
new_team = create_team(request.json)
Expand All @@ -124,6 +130,7 @@ def add_team():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def update_team():
try:
team_id = request.args.get("team_id")
Expand All @@ -139,6 +146,7 @@ def update_team():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def update_team_user_by_edit():
try:
data = request.get_json()
Expand Down
7 changes: 6 additions & 1 deletion BackEndFlask/controller/Routes/Upload_csv_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@
from controller.Route_response import *
from flask_jwt_extended import jwt_required
import Functions.studentImport as studentImport
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import (
AuthCheck, bad_token_check,
admin_check
)

@bp.route('/studentbulkuploadcsv', methods = ['POST'])
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def student_bulk_upload_csv():
try:
file = request.files['csv_file']
Expand Down
9 changes: 8 additions & 1 deletion BackEndFlask/controller/Routes/User_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
from controller import bp
from controller.Route_response import *
from flask_jwt_extended import jwt_required
from controller.security.CustomDecorators import AuthCheck, bad_token_check

from controller.security.CustomDecorators import(
AuthCheck, bad_token_check,
admin_check
)

from models.role import (
get_role
Expand Down Expand Up @@ -186,6 +190,7 @@ def get_all_team_members():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def add_user():
try:
if(request.args and request.args.get("team_id")):
Expand Down Expand Up @@ -247,6 +252,7 @@ def add_user():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def update_user():
try:
if(request.args and request.args.get("uid") and request.args.get("course_id")):
Expand Down Expand Up @@ -305,6 +311,7 @@ def update_user():
@jwt_required()
@bad_token_check()
@AuthCheck()
@admin_check()
def delete_user():
try:
if request.args and request.args.get("uid"):
Expand Down
37 changes: 36 additions & 1 deletion BackEndFlask/controller/security/CustomDecorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from functools import wraps
from .utility import to_int
from .blacklist import is_token_blacklisted
from typing import Callable
from models.queries import is_admin_by_user_id
from flask_jwt_extended import decode_token
from flask_jwt_extended.exceptions import (
NoAuthorizationError,
Expand Down Expand Up @@ -58,4 +60,37 @@ def verify_token(refresh: bool):
raise NoAuthorizationError("No Authorization")
id = to_int(id, "user_id")
if id == decoded_id : return
raise NoAuthorizationError("No Authorization")
raise NoAuthorizationError("No Authorization")

def admin_check(refresh: bool = False) -> Callable:
"""
Description:
This is a decorator that checks to make sure that the route was called by an admin permisions.
I think it is best to use the decorator as the last decorator since it hits the db.
"""
def wrapper(fn):
@wraps(fn)
def decorator(*args):
verify_admin(refresh)
return current_app.ensure_sync(fn)(*args)
return decorator
return wrapper

def verify_admin(refresh: bool) -> None:
"""
Description:
Uses token user_id to check user permisions.
Exceptions:
Raises NoAuthorizationError if at any instance it can not be reliably determined if
the individual that called the route has admin level permissions.
"""
try:
# Figuring out the user_id from token.
# Assumes authcheck() has already concluded token_user_id == user_id from parameters.
token = request.headers.get('Authorization').split()[1]
decoded_id = decode_token(token)['sub'] if refresh else decode_token(token)['sub'][0]
if is_admin_by_user_id(decoded_id) == False:
raise NoAuthorizationError("No Authorization")
except:
raise NoAuthorizationError("No Authorization")
Loading

0 comments on commit 92a47d0

Please sign in to comment.