Skip to content
Snippets Groups Projects
Commit 9972a62b authored by Bjarke Madsen's avatar Bjarke Madsen
Browse files

Add observer checks

parent 4ccfa0f7
No related branches found
No related tags found
1 merge request!76Comp 282 add observer role
...@@ -75,6 +75,10 @@ class User(UserMixin, db.Model): ...@@ -75,6 +75,10 @@ class User(UserMixin, db.Model):
def is_admin(self): def is_admin(self):
return self.roles == ROLES.admin return self.roles == ROLES.admin
@property
def is_observer(self):
return self.roles == ROLES.observer
@property @property
def nren(self): def nren(self):
if len(self.nrens) == 0: if len(self.nrens) == 0:
......
...@@ -77,16 +77,29 @@ class SurveyMode(str, Enum): ...@@ -77,16 +77,29 @@ class SurveyMode(str, Enum):
Edit = "edit" Edit = "edit"
def check_access_nren(user: User, nren: str) -> bool: def check_access_nren_read(user: User, nren: str) -> bool:
if user.is_anonymous: if user.is_anonymous:
return False return False
if user.is_admin: if user.is_admin:
return True return True
if user.is_observer:
return True
if nren == user.nren: if nren == user.nren:
return True return True
return False return False
def check_access_nren_write(user: User, nren: str) -> bool:
if not check_access_nren_read(current_user, nren):
return False
if user.is_observer:
# observers can't edit their own nrens either!
return False
# admins can edit all nrens
# users can edit their own nrens
return True
@routes.route('/try/<int:year>', methods=['GET']) @routes.route('/try/<int:year>', methods=['GET'])
@common.require_accepts_json @common.require_accepts_json
@admin_required @admin_required
...@@ -206,7 +219,7 @@ def load_survey(year, nren_name) -> Any: ...@@ -206,7 +219,7 @@ def load_survey(year, nren_name) -> Any:
if not survey: if not survey:
return {'message': 'Survey not found'}, 404 return {'message': 'Survey not found'}, 404
if not check_access_nren(current_user, nren): if not check_access_nren_read(current_user, nren):
return {'message': 'You do not have permissions to access this survey.'}, 403 return {'message': 'You do not have permissions to access this survey.'}, 403
response = db.session.scalar( response = db.session.scalar(
...@@ -215,6 +228,8 @@ def load_survey(year, nren_name) -> Any: ...@@ -215,6 +228,8 @@ def load_survey(year, nren_name) -> Any:
data, page, verification_status, locked_by = get_response_data(response, year, nren.id) data, page, verification_status, locked_by = get_response_data(response, year, nren.id)
edit_allowed = current_user.is_admin or (
survey.status == SurveyStatus.open and check_access_nren_write(current_user, nren))
return { return {
"model": survey.survey, "model": survey.survey,
"locked_by": locked_by, "locked_by": locked_by,
...@@ -223,7 +238,7 @@ def load_survey(year, nren_name) -> Any: ...@@ -223,7 +238,7 @@ def load_survey(year, nren_name) -> Any:
"verification_status": verification_status, "verification_status": verification_status,
"mode": SurveyMode.Display, "mode": SurveyMode.Display,
"status": response.status.value if response else RESPONSE_NOT_STARTED, "status": response.status.value if response else RESPONSE_NOT_STARTED,
"edit_allowed": current_user.is_admin or survey.status == SurveyStatus.open "edit_allowed": edit_allowed
} }
...@@ -249,7 +264,7 @@ def lock_survey(year, nren_name) -> Any: ...@@ -249,7 +264,7 @@ def lock_survey(year, nren_name) -> Any:
if not survey: if not survey:
return {'message': 'Survey not found'}, 404 return {'message': 'Survey not found'}, 404
if not check_access_nren(current_user, nren): if not check_access_nren_write(current_user, nren):
return {'message': 'You do not have permissions to access this survey.'}, 403 return {'message': 'You do not have permissions to access this survey.'}, 403
if survey.status != SurveyStatus.open and not current_user.is_admin: if survey.status != SurveyStatus.open and not current_user.is_admin:
...@@ -321,7 +336,7 @@ def save_survey(year, nren_name) -> Any: ...@@ -321,7 +336,7 @@ def save_survey(year, nren_name) -> Any:
if survey is None: if survey is None:
return {'message': 'Survey not found'}, 404 return {'message': 'Survey not found'}, 404
if not check_access_nren(current_user, nren): if not check_access_nren_write(current_user, nren):
return {'message': 'You do not have permission to edit this survey.'}, 403 return {'message': 'You do not have permission to edit this survey.'}, 403
if survey.status != SurveyStatus.open and not current_user.is_admin: if survey.status != SurveyStatus.open and not current_user.is_admin:
...@@ -384,7 +399,7 @@ def unlock_survey(year, nren_name) -> Any: ...@@ -384,7 +399,7 @@ def unlock_survey(year, nren_name) -> Any:
if survey is None: if survey is None:
return {'message': 'Survey not found'}, 404 return {'message': 'Survey not found'}, 404
if not check_access_nren(current_user, nren): if not check_access_nren_write(current_user, nren):
return {'message': 'You do not have permission to edit this survey.'}, 403 return {'message': 'You do not have permission to edit this survey.'}, 403
response = db.session.scalar( response = db.session.scalar(
......
...@@ -2,6 +2,7 @@ import logging ...@@ -2,6 +2,7 @@ import logging
from typing import Any, TypedDict, List, Dict from typing import Any, TypedDict, List, Dict
from flask import Blueprint from flask import Blueprint
from flask_login import login_required, current_user
from sqlalchemy import delete, select from sqlalchemy import delete, select
from sqlalchemy.orm import joinedload, load_only from sqlalchemy.orm import joinedload, load_only
...@@ -47,7 +48,7 @@ LIST_SURVEYS_RESPONSE_SCHEMA = { ...@@ -47,7 +48,7 @@ LIST_SURVEYS_RESPONSE_SCHEMA = {
@routes.route('/list', methods=['GET']) @routes.route('/list', methods=['GET'])
@common.require_accepts_json @common.require_accepts_json
@admin_required @login_required
def list_surveys() -> Any: def list_surveys() -> Any:
""" """
retrieve a list of surveys and responses, including their status retrieve a list of surveys and responses, including their status
...@@ -58,6 +59,10 @@ def list_surveys() -> Any: ...@@ -58,6 +59,10 @@ def list_surveys() -> Any:
compendium_v2.routes.survey.LIST_SURVEYS_RESPONSE_SCHEMA compendium_v2.routes.survey.LIST_SURVEYS_RESPONSE_SCHEMA
""" """
if not (current_user.is_admin or current_user.is_observer):
return {'message': 'Insufficient privileges to access this resource'}, 403
surveys = db.session.scalars( surveys = db.session.scalars(
select(Survey).options( select(Survey).options(
load_only(Survey.year, Survey.status), load_only(Survey.year, Survey.status),
...@@ -74,21 +79,26 @@ def list_surveys() -> Any: ...@@ -74,21 +79,26 @@ def list_surveys() -> Any:
status: str status: str
responses: List[Dict[str, str]] responses: List[Dict[str, str]]
entries: List[SurveyDict] = [ entries: List[SurveyDict] = []
{
"year": entry.year, def _get_response(response: SurveyResponse) -> Dict[str, str]:
"status": entry.status.value, res = {
"responses": [ "nren": response.nren.name,
{ "status": response.status.value,
"nren": r.nren.name, "lock_description": response.lock_description
"status": r.status.value,
"lock_description": r.lock_description
}
for r in sorted(entry.responses, key=response_key)
]
} }
for entry in surveys if current_user.is_observer:
] res["lock_description"] = response.lock_description
return res
for entry in surveys:
# only include lock description if the user is an admin
entries.append(
{
"year": entry.year,
"status": entry.status.value,
"responses": [_get_response(r) for r in sorted(entry.responses, key=response_key)]
})
# add in nrens without a response if the survey is open # add in nrens without a response if the survey is open
nren_names = set([name for name in db.session.scalars(select(NREN.name))]) nren_names = set([name for name in db.session.scalars(select(NREN.name))])
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment