Skip to content

Commit 6dd83e6

Browse files
committed
Add DraftRetrieveApi
To do this functions related to Prefixes and the associated permissions were created Changes to be committed: modified: biocompute/apis.py modified: biocompute/models.py modified: biocompute/selectors.py modified: biocompute/services.py modified: biocompute/urls.py modified: config/asgi.py modified: config/fixtures/local_data.json modified: config/services.py modified: config/urls.py modified: prefix/selectors.py modified: prefix/services.py deleted: test.json modified: tests/fixtures/example_bco.py modified: tests/fixtures/test_data.json deleted: token.json
1 parent f308a9c commit 6dd83e6

File tree

15 files changed

+5085
-1240
lines changed

15 files changed

+5085
-1240
lines changed

biocompute/apis.py

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from drf_yasg import openapi
88
from drf_yasg.utils import swagger_auto_schema
9+
from django.conf import settings
910
from django.db import utils
1011
from rest_framework.views import APIView
1112
from rest_framework import status
@@ -14,6 +15,11 @@
1415
from tests.fixtures.example_bco import BCO_000001
1516
from config.services import legacy_api_converter, response_constructor
1617
from biocompute.services import BcoDraftSerializer
18+
from biocompute.selectors import retrieve_bco
19+
from prefix.selectors import user_can_draft
20+
21+
22+
hostname = settings.PUBLIC_HOSTNAME
1723

1824
BCO_DRAFT_SCHEMA = openapi.Schema(
1925
type=openapi.TYPE_ARRAY,
@@ -25,22 +31,17 @@
2531
"object_id": openapi.Schema(
2632
type=openapi.TYPE_STRING,
2733
description="BCO Object ID.",
28-
example="https://biocomputeobject.org/TEST_000001"
34+
example=f"{hostname}/TEST_000001/DRAFT"
2935
),
3036
"prefix": openapi.Schema(
3137
type=openapi.TYPE_STRING,
3238
description="BCO Prefix to use",
33-
example="BCO"
39+
example="TEST"
3440
),
3541
"authorized_users": openapi.Schema(
3642
type=openapi.TYPE_ARRAY,
3743
description="Users which can access the BCO draft.",
38-
items=openapi.Schema(type=openapi.TYPE_STRING, example="None")
39-
),
40-
"authorized_groups": openapi.Schema(
41-
type=openapi.TYPE_ARRAY,
42-
description="Group which can access the BCO draft.",
43-
items=openapi.Schema(type=openapi.TYPE_STRING, example="None")
44+
items=openapi.Schema(type=openapi.TYPE_STRING, example="tester")
4445
),
4546
"contents": openapi.Schema(
4647
type=openapi.TYPE_OBJECT,
@@ -53,14 +54,19 @@
5354
)
5455

5556
class DraftsCreateApi(APIView):
56-
"""
57-
Create BCO Draft [Bulk Enabled]
57+
"""Create BCO Draft [Bulk Enabled]
5858
59-
--------------------
59+
API endpoint for creating new BioCompute Object (BCO) drafts, with support
60+
for bulk operations.
6061
61-
Creates a new BCO draft object.
62+
This endpoint allows authenticated users to create new BCO drafts
63+
individually or in bulk by submitting a list of BCO drafts. The operation
64+
can be performed for one or more drafts in a single request. Each draft is
65+
validated and processed independently, allowing for mixed response
66+
statuses (HTTP_207_MULTI_STATUS) in the case of bulk submissions.
6267
"""
63-
68+
69+
permission_classes = [IsAuthenticated,]
6470
request_body = BCO_DRAFT_SCHEMA
6571

6672
@swagger_auto_schema(
@@ -87,6 +93,30 @@ def post(self, request) -> Response:
8793

8894
for index, object in enumerate(data):
8995
response_id = object.get("object_id", index)
96+
bco_prefix = object.get("prefix", index)
97+
prefix_permitted = user_can_draft(owner, bco_prefix)
98+
99+
if prefix_permitted is None:
100+
response_data.append(response_constructor(
101+
identifier=response_id,
102+
status = "NOT FOUND",
103+
code= 404,
104+
message= f"Invalid prefix: {bco_prefix}.",
105+
))
106+
rejected_requests = True
107+
continue
108+
109+
if prefix_permitted is False:
110+
response_data.append(response_constructor(
111+
identifier=response_id,
112+
status = "FORBIDDEN",
113+
code= 400,
114+
message= f"User, {owner}, does not have draft permissions"\
115+
+ " for prefix {bco_prefix}.",
116+
))
117+
rejected_requests = True
118+
continue
119+
90120
bco = BcoDraftSerializer(data=object, context={'request': request})
91121

92122
if bco.is_valid():
@@ -135,3 +165,49 @@ def post(self, request) -> Response:
135165
status=status.HTTP_200_OK,
136166
data=response_data
137167
)
168+
169+
class DraftRetrieveApi(APIView):
170+
"""Get a draft object
171+
172+
API View to Retrieve a Draft Object
173+
174+
This view allows authenticated users to retrieve the contents of a specific draft object
175+
identified by its BioCompute Object (BCO) accession number. The operation ensures that
176+
only users with appropriate permissions can access the draft contents.
177+
178+
Parameters:
179+
- bco_accession (str): A string parameter passed in the URL path that uniquely identifies
180+
the draft object to be retrieved.
181+
"""
182+
183+
@swagger_auto_schema(
184+
manual_parameters=[
185+
openapi.Parameter(
186+
"bco_accession",
187+
openapi.IN_PATH,
188+
description="Object ID to be viewed.",
189+
type=openapi.TYPE_STRING,
190+
default="BCO_000000"
191+
)
192+
],
193+
responses={
194+
200: "Success. Object contents returned",
195+
401: "Authentication credentials were not provided, or"
196+
" the token was invalid.",
197+
403: "Forbidden. The requestor does not have appropriate permissions.",
198+
404: "Not found. That draft could not be found on the server."
199+
},
200+
tags=["BCO Management"],
201+
)
202+
203+
def get(self, request, bco_accession):
204+
requester = request.user
205+
print(requester)
206+
bco_instance = retrieve_bco(bco_accession, requester)
207+
if bco_instance is False:
208+
return Response(
209+
status=status.HTTP_403_FORBIDDEN,
210+
data={"message": f"User, {requester}, does not have draft permissions"\
211+
+ f" for {bco_accession}."})
212+
else:
213+
return Response(status=status.HTTP_200_OK, data=bco_instance.contents)

biocompute/models.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ class Bco(models.Model):
3131
String representing the django.contrib.auth.models.User that 'owns' the object
3232
authorized_users: ManyToManyField(User)
3333
String representing the User that has access to the object
34-
authorized_group: ManyToManyField(Group)
35-
String representing the Group that has access to the object
3634
prefix: str
3735
Prefix for the BCO
3836
state:str
@@ -58,7 +56,6 @@ class Bco(models.Model):
5856
related_name="authorized_bcos",
5957
blank=True
6058
)
61-
authorized_groups = models.ManyToManyField(Group,blank=True)
6259
state = models.CharField(max_length=20, choices=STATE_CHOICES, default="DRAFT")
6360
last_update = models.DateTimeField()
6461
access_count = models.IntegerField(default=0)

biocompute/selectors.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# biocompute/selectors.py
2+
3+
"""BioCompute Selectors
4+
5+
Functions to query the database related to BioCompute Objects
6+
"""
7+
8+
from django.conf import settings
9+
from django.contrib.auth. models import User
10+
from biocompute.models import Bco
11+
from prefix.selectors import user_can_view
12+
13+
def retrieve_bco(bco_accession: str, user: User) -> bool:
14+
"""Retrieve BCO
15+
16+
Determines if a user can view a specific BioCompute Object (BCO).
17+
18+
This function checks whether a given user has the permission to view a BCO
19+
identified by its accession number. It performs several checks:
20+
21+
1. Verifies if the BCO exists. If not, returns `None`.
22+
2. Checks if the user is explicitly authorized to view this specific BCO.
23+
3. If not directly authorized, it then checks if the user has general 'view' permissions
24+
for the prefix associated with the BCO.
25+
26+
"""
27+
28+
hostname = settings.PUBLIC_HOSTNAME
29+
object_id = f"{hostname}/{bco_accession}/DRAFT"
30+
prefix_name = bco_accession.split("_")[0]
31+
32+
try:
33+
bco_instance = Bco.objects.get(object_id=object_id)
34+
except Bco.DoesNotExist:
35+
return None
36+
37+
if user in bco_instance.authorized_users.all():
38+
return bco_instance
39+
40+
view_permission = user_can_view(prefix_name, user)
41+
if view_permission is False:
42+
return False
43+
44+
return bco_instance

0 commit comments

Comments
 (0)