Skip to content

Commit

Permalink
Create approve_file methods
Browse files Browse the repository at this point in the history
  • Loading branch information
madwort committed Mar 15, 2024
1 parent 52c5484 commit b98ae03
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 3 deletions.
38 changes: 38 additions & 0 deletions airlock/business_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ class InvalidStateTransition(APIException):
class RequestPermissionDenied(APIException):
pass

class ApprovalPermissionDenied(APIException):
pass

def get_workspace(self, name: str, metadata: dict = {}) -> Workspace:
"""Get a workspace object."""
# this almost trivial currently, but may involve more in future
Expand Down Expand Up @@ -503,6 +506,41 @@ def release_files(self, request: ReleaseRequest, user: User):

self.set_status(request, RequestStatus.RELEASED, user)

def get_file_approvals(self, release_request: ReleaseRequest):
# TODO: return BusinessLogicLayer.FileReview not LocalDB.FileReview
return bll._dal.get_file_approvals(release_request.id)


def approve_file(self, release_request: ReleaseRequest, user: User, path: Path):
""""Approve a file"""

if release_request.status != RequestStatus.SUBMITTED:
raise self.ApprovalPermissionDenied(
f"cannot approve file from request in state {release_request.status.name}"
)

if not user.output_checker:
raise self.ApprovalPermissionDenied(
f"only an output checker can approve a file"
)

if user.username == release_request.author:
raise self.ApprovalPermissionDenied(
f"cannot approve files in your own request"
)

if path not in release_request.file_set():
raise self.ApprovalPermissionDenied(
f"file is not part of the request"
)

bll._dal.approve_file(release_request.id, user, path)

def reject_file(self):
"""Reject a file"""

pass


def _get_configured_bll():
DataAccessLayer = import_string(settings.AIRLOCK_DATA_ACCESS_LAYER)
Expand Down
27 changes: 26 additions & 1 deletion local_db/data_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
DataAccessLayerProtocol,
RequestStatus,
)
from local_db.models import FileGroupMetadata, RequestFileMetadata, RequestMetadata
from local_db.models import FileGroupMetadata, RequestFileMetadata, RequestMetadata, FileReview, FileApprovalStatus


class LocalDBDataAccessLayer(DataAccessLayerProtocol):
Expand Down Expand Up @@ -118,3 +118,28 @@ def add_file_to_request(self, request_id, relpath: Path, group_name: str):
# Return updated FileGroups data
metadata = self._find_metadata(request_id)
return self._get_filegroups(metadata)


def get_file_approvals(self, request_id):
return FileReview.objects.filter(file__filegroup__request_id=request_id).all()


def approve_file(self, request_id, user, relpath):
with transaction.atomic():
try:
request_file = RequestFileMetadata.objects.get(
filegroup__request_id=request_id, relpath=relpath
)
except RequestFileMetadata.DoesNotExist:
raise BusinessLogicLayer.FileNotFound(
f"file {relpath} not part of a request {request_id}"
)
review, _ = FileReview.objects.get_or_create(
file=request_file, reviewer=user
)
review.status = FileApprovalStatus.APPROVED
review.save()


def reject_file(self, request_id, user, relpath):
pass
2 changes: 1 addition & 1 deletion local_db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class FileReview(models.Model):
"""An output checker's review of a file"""

file = models.ForeignKey(
RequestFileMetadata, related_name="file", on_delete=models.CASCADE
RequestFileMetadata, related_name="reviews", on_delete=models.CASCADE
)
reviewer = models.TextField()
status = StatusField(status_enum=FileApprovalStatus)
Expand Down
65 changes: 64 additions & 1 deletion tests/unit/test_business_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.conf import settings

import old_api
from airlock.business_logic import BusinessLogicLayer, RequestStatus, UrlPath, Workspace
from airlock.business_logic import BusinessLogicLayer, RequestStatus, UrlPath, Workspace, FileApprovalStatus
from airlock.users import User
from tests import factories

Expand Down Expand Up @@ -437,3 +437,66 @@ def test_release_request_add_same_file(bll):
# No additional files or groups have been created
assert len(release_request.filegroups) == 1
assert len(release_request.filegroups["default"].files) == 1


def test_approve_file_not_submitted(bll):
release_request, path, author = setup_empty_release_request()
checker = User(2, "checker", [], True)

bll.add_file_to_request(release_request, path, author)

with pytest.raises(bll.ApprovalPermissionDenied):
bll.approve_file(release_request, checker, path)


def test_approve_file_not_checker(bll):
release_request, path, author = setup_empty_release_request()
author2 = User(2, "author", [], True)

bll.add_file_to_request(release_request, path, author)

with pytest.raises(bll.ApprovalPermissionDenied):
bll.approve_file(release_request, author2, path)


def test_approve_file_not_your_own(bll):
release_request, path, author = setup_empty_release_request()

bll.add_file_to_request(release_request, path, author)

with pytest.raises(bll.ApprovalPermissionDenied):
bll.approve_file(release_request, author, path)


def test_approve_file_not_part_of_request(bll):
release_request, path, author = setup_empty_release_request()
checker = User(2, "checker", [], True)

bll.add_file_to_request(release_request, path, author)
bll.set_status(
release_request=release_request,
to_status=RequestStatus.SUBMITTED,
user=author
)

bad_path = Path("path/file2.txt")
with pytest.raises(bll.ApprovalPermissionDenied):
bll.approve_file(release_request, checker, bad_path)


def test_approve_file(bll):
release_request, path, author = setup_empty_release_request()
checker = User(2, "checker", [], True)

bll.add_file_to_request(release_request, path, author)
bll.set_status(
release_request=release_request,
to_status=RequestStatus.SUBMITTED,
user=author
)

assert len(bll.get_file_approvals(release_request)) == 0
bll.approve_file(release_request, checker, path)
assert len(bll.get_file_approvals(release_request)) == 1
assert bll.get_file_approvals(release_request)[0].status == FileApprovalStatus.APPROVED

0 comments on commit b98ae03

Please sign in to comment.