diff --git a/crc/api/approval.py b/crc/api/approval.py index 51dd406e..5a4299e2 100644 --- a/crc/api/approval.py +++ b/crc/api/approval.py @@ -34,6 +34,9 @@ def update_approval(approval_id, body): raise ApiError('unknown_approval', 'The approval "' + str(approval_id) + '" is not recognized.') approval: Approval = ApprovalSchema().load(body) + if approval_model.approver_uid != g.user.uid: + raise ApiError("not_your_approval", "You may not modify this approval. It belongs to another user.") + approval.update_model(approval_model) session.commit() diff --git a/crc/models/approval.py b/crc/models/approval.py index 198b5ef9..3a95c680 100644 --- a/crc/models/approval.py +++ b/crc/models/approval.py @@ -128,8 +128,8 @@ class ApprovalSchema(ma.Schema): class Meta: model = Approval fields = ["id", "study_id", "workflow_id", "version", "title", - "version", "status", "message", "approver", "primary_investigator", - "associated_files", "date_created"] + "status", "message", "approver", "primary_investigator", + "associated_files", "date_created"] unknown = INCLUDE @marshmallow.post_load diff --git a/tests/test_approvals_api.py b/tests/test_approvals_api.py index 7cf3d4a0..89eb4ab2 100644 --- a/tests/test_approvals_api.py +++ b/tests/test_approvals_api.py @@ -5,35 +5,6 @@ from crc import app, db, session from crc.models.approval import ApprovalModel, ApprovalSchema, ApprovalStatus -APPROVAL_PAYLOAD = { - 'id': None, - 'approver': { - 'uid': 'bgb22', - 'display_name': 'Billy Bob (bgb22)', - 'title': 'E42:He\'s a hoopy frood', - 'department': 'E0:EN-Eng Study of Parallel Universes' - }, - 'title': 'El Study', - 'status': 'DECLINED', - 'version': 1, - 'message': 'Incorrect documents', - 'associated_files': [ - { - 'id': 42, - 'name': 'File 1', - 'content_type': 'document' - }, - { - 'id': 43, - 'name': 'File 2', - 'content_type': 'document' - } - ], - 'workflow_id': 1, - 'study_id': 1 -} - - class TestApprovals(BaseTest): def setUp(self): """Initial setup shared by all TestApprovals tests""" @@ -98,25 +69,59 @@ class TestApprovals(BaseTest): response_count = len(response) self.assertEqual(1, response_count) + def test_update_approval_fails_if_not_the_approver(self): + approval = session.query(ApprovalModel).filter_by(approver_uid='arc93').first() + data = {'id': approval.id, + "approver_uid": "dhf8r", + 'message': "Approved. I like the cut of your jib.", + 'status': ApprovalStatus.APPROVED.value} + self.assertEqual(approval.status, ApprovalStatus.PENDING.value) - - def test_update_approval(self): - """Approval status will be updated""" - approval_id = self.approval.id - data = dict(APPROVAL_PAYLOAD) - data['id'] = approval_id - - self.assertEqual(self.approval.status, ApprovalStatus.PENDING.value) - - rv = self.app.put(f'/v1.0/approval/{approval_id}', + rv = self.app.put(f'/v1.0/approval/{approval.id}', content_type="application/json", - headers=self.logged_in_headers(), + headers=self.logged_in_headers(), # As dhf8r + data=json.dumps(data)) + self.assert_failure(rv) + + def test_accept_approval(self): + approval = session.query(ApprovalModel).filter_by(approver_uid='dhf8r').first() + data = {'id': approval.id, + "approver_uid": "dhf8r", + 'message': "Approved. I like the cut of your jib.", + 'status': ApprovalStatus.APPROVED.value} + + self.assertEqual(approval.status, ApprovalStatus.PENDING.value) + + rv = self.app.put(f'/v1.0/approval/{approval.id}', + content_type="application/json", + headers=self.logged_in_headers(), # As dhf8r data=json.dumps(data)) self.assert_success(rv) - session.refresh(self.approval) + session.refresh(approval) # Updated record should now have the data sent to the endpoint - self.assertEqual(self.approval.message, data['message']) - self.assertEqual(self.approval.status, ApprovalStatus.DECLINED.value) + self.assertEqual(approval.message, data['message']) + self.assertEqual(approval.status, ApprovalStatus.APPROVED.value) + + def test_decline_approval(self): + approval = session.query(ApprovalModel).filter_by(approver_uid='dhf8r').first() + data = {'id': approval.id, + "approver_uid": "dhf8r", + 'message': "Approved. I find the cut of your jib lacking.", + 'status': ApprovalStatus.DECLINED.value} + + self.assertEqual(approval.status, ApprovalStatus.PENDING.value) + + rv = self.app.put(f'/v1.0/approval/{approval.id}', + content_type="application/json", + headers=self.logged_in_headers(), # As dhf8r + data=json.dumps(data)) + self.assert_success(rv) + + session.refresh(approval) + + # Updated record should now have the data sent to the endpoint + self.assertEqual(approval.message, data['message']) + self.assertEqual(approval.status, ApprovalStatus.DECLINED.value)