from functools import wraps from flask_login import current_user from flask import flash, redirect, request, abort from comport.department.models import Extractor, Department def authorized_access_only(dataset=None): ''' Decorates views that require authentication if the department is not public ''' def check_authorized(view_function): @wraps(view_function) def decorated_function(*args, **kwargs): try: department = Department.query.filter_by(short_name=kwargs["short_name"].upper()).first() except KeyError: department = Department.query.filter_by(id=kwargs["department_id"]).first() # check whether the current dataset is public dataset_is_public = True if dataset: try: dataset_is_public = getattr(department, "is_public_{}".format(dataset)) except ValueError: dataset_is_public = True # check whether the user has access to this department if current_user.is_authenticated(): user_has_dept_access = current_user.has_department(department.id) or current_user.is_admin() else: user_has_dept_access = False # abort with a 403 Forbidden if the department or dataset's not public and the user's not authorized to access it if (not department.is_public or not dataset_is_public) and (not current_user.is_authenticated() or not user_has_dept_access): abort(403) return view_function(*args, **kwargs) return decorated_function return check_authorized def requires_roles(required_roles): ''' Takes in a list of roles and checks whether the user has access to those role ''' def check_roles(view_function): @wraps(view_function) def decorated_function(*args, **kwargs): def names(role): return role.name if not all(r in map(names, current_user.roles) for r in required_roles): flash('You do not have sufficient permissions to do that', 'alert alert-danger') return redirect(request.args.get('next') or '/') return view_function(*args, **kwargs) return decorated_function return check_roles def admin_or_department_required(): ''' Reads department from current_user and checks whether the user has access to that department or is an admin ''' def check_department(view_function): @wraps(view_function) def decorated_function(*args, **kwargs): if current_user.has_department(kwargs["department_id"]) or current_user.is_admin(): return view_function(*args, **kwargs) flash('You do not have sufficient permissions to do that', 'alert alert-danger') return redirect(request.args.get('next') or '/') return decorated_function return check_department def extractor_auth_required(): ''' Ensures that current_user is an extractor with access to the correct department ''' def check_extractor(view_function): @wraps(view_function) def decorated_function(*args, **kwargs): username = request.authorization.username password = request.authorization.password found_extractor = Extractor.query.filter_by(username=username).first() if not found_extractor: return ("No extractor with that username!", 401) if not found_extractor.check_password(password): return ("Extractor authorization failed!", 401) return view_function(*args, **kwargs) return decorated_function return check_extractor