Skip to content

Commit c7f9972

Browse files
committed
Split checks for tasks status and user permission in function so that correct error response can be returned
1 parent e8b18f1 commit c7f9972

File tree

5 files changed

+33
-21
lines changed

5 files changed

+33
-21
lines changed

backend/api/tasks/actions.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ def post(self, project_id, task_id):
328328
project_id, task_id, token_auth.current_user(), preferred_locale
329329
)
330330
return task.to_primitive(), 200
331-
except MappingServiceError as e: # FLAGGED FOR STATUS CODE
332-
return {"Error": str(e).split("-")[1], "SubCode": str(e).split("-")[0]}, 403
331+
except MappingServiceError as e:
332+
return {"Error": str(e).split("-")[1], "SubCode": str(e).split("-")[0]}, 409
333333

334334

335335
class TasksActionsValidationLockAPI(Resource):

backend/error_messages.json

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"USER_NOT_ADMIN": "This action is only allowed for system administrators.",
2828
"USER_NOT_ORG_MANAGER": "This action is only allowed for organisation managers or system administrators.",
2929
"USER_NOT_PROJECT_MANAGER": "This action is only allowed for users with project manage permissions.",
30+
"USER_NOT_VALIDATOR": "This action is only allowed for users with validation permissions in the project.",
3031
"USER_NOT_TEAM_MANAGER": "This action is only allowed for users with team manage permissions.",
3132
"INVALID_NEW_PROJECT_OWNER": "New project owner must be project's organisation manager or system admin",
3233
"USER_ACTION_NOT_PERMITTED": "This user does not have the required permissions to perform this action.",

backend/services/mapping_service.py

+20-11
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,31 @@ def get_task_as_dto(
5959
@staticmethod
6060
def _is_task_undoable(logged_in_user_id: int, task: Task) -> bool:
6161
"""Determines if the current task status can be undone by the logged in user"""
62-
# Test to see if user can undo status on this task
63-
if logged_in_user_id and TaskStatus(task.task_status) not in [
62+
# Check if task status is in a state that can be undone
63+
if TaskStatus(task.task_status) in [
6464
TaskStatus.LOCKED_FOR_MAPPING,
6565
TaskStatus.LOCKED_FOR_VALIDATION,
6666
TaskStatus.READY,
6767
]:
68-
last_action = TaskHistory.get_last_action(task.project_id, task.id)
69-
70-
# User requesting task made the last change, so they are allowed to undo it.
71-
is_user_permitted, _ = ProjectService.is_user_permitted_to_validate(
72-
task.project_id, logged_in_user_id
73-
) # FLAGGED: Make use of error_reason
74-
if last_action.user_id == int(logged_in_user_id) or is_user_permitted:
75-
return True
68+
raise MappingServiceError(
69+
"UndoNotAllowed- Task is in a state that cannot be undone"
70+
)
71+
# Test to see if user can undo status on this task
72+
last_action = TaskHistory.get_last_action(task.project_id, task.id)
7673

77-
return False # FLAGGED: Split out for permission and state
74+
# User requesting task made the last change, so they are allowed to undo it.
75+
is_user_permitted, _ = ProjectService.is_user_permitted_to_validate(
76+
task.project_id, logged_in_user_id
77+
)
78+
if last_action.user_id == int(logged_in_user_id) or is_user_permitted:
79+
return True
80+
else:
81+
raise Forbidden(
82+
sub_code="USER_NOT_VALIDATOR",
83+
user_id=logged_in_user_id,
84+
project_id=task.project_id,
85+
task_id=task.id,
86+
)
7887

7988
@staticmethod
8089
def lock_task_for_mapping(lock_task_dto: LockTaskDTO) -> TaskDTO:

tests/backend/integration/api/tasks/test_actions.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -1388,10 +1388,10 @@ def test_returns_404_if_task_not_found(self):
13881388
self.assertEqual(response.status_code, 404)
13891389
self.assertEqual(response.json["error"]["sub_code"], TASK_NOT_FOUND_SUB_CODE)
13901390

1391-
def test_returns_403_if_task_in_invalid_state_for_undo(self):
1392-
"""Test returns 403 if task in invalid state for undo."""
1391+
def test_returns_409_if_task_in_invalid_state_for_undo(self):
1392+
"""Test returns 409 if task in invalid state for undo."""
13931393
# Since task cannot be in READY, LOCKED_FOR_VALIDATION or LOCKED_FOR_MAPPING state for undo,
1394-
# we should get a 403
1394+
# we should get a 409
13951395
# Arrange
13961396
task = Task.get(1, self.test_project.id)
13971397
task.task_status = TaskStatus.READY.value
@@ -1402,8 +1402,8 @@ def test_returns_403_if_task_in_invalid_state_for_undo(self):
14021402
headers={"Authorization": self.user_session_token},
14031403
)
14041404
# Assert
1405-
self.assertEqual(response.status_code, 403)
1406-
self.assertEqual(response.json["SubCode"], "UndoPermissionError")
1405+
self.assertEqual(response.status_code, 409)
1406+
self.assertEqual(response.json["SubCode"], "UndoNotAllowed")
14071407

14081408
@staticmethod
14091409
def validate_task(task_id, project_id, user_id):
@@ -1428,7 +1428,7 @@ def test_returns_403_if_user_not_permitted_for_undo(self):
14281428
)
14291429
# Assert
14301430
self.assertEqual(response.status_code, 403)
1431-
self.assertEqual(response.json["SubCode"], "UndoPermissionError")
1431+
self.assertEqual(response.json["error"]["sub_code"], "USER_NOT_VALIDATOR")
14321432

14331433
@staticmethod
14341434
def assert_undo_response(response, project_id, last_status, username, new_status):

tests/backend/unit/services/test_mapping_service.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from unittest.mock import patch, MagicMock
2+
3+
from backend.exceptions import Forbidden
24
from backend.services.mapping_service import (
35
MappingService,
46
Task,
@@ -231,7 +233,7 @@ def test_task_is_not_undoable_if_last_change_not_made_by_you(
231233

232234
# Act
233235
mock_project.return_value = (False, None)
234-
is_undoable = MappingService._is_task_undoable(1, task)
235236

236237
# Assert
237-
self.assertFalse(is_undoable)
238+
with self.assertRaises(Forbidden):
239+
MappingService._is_task_undoable(1, task)

0 commit comments

Comments
 (0)