Skip to content

Commit b5b630d

Browse files
authored
Merge pull request #85 from opensafely-core/split-requests
Split API for authored requests vs requests to review
2 parents e31e1f6 + 18b907c commit b5b630d

File tree

6 files changed

+82
-32
lines changed

6 files changed

+82
-32
lines changed

airlock/api.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,12 @@ def get_current_request(
224224
"""
225225
raise NotImplementedError()
226226

227-
def get_requests_for_user(self, user: User) -> list[ReleaseRequest]:
228-
"""Get all current requests authored by user"""
227+
def get_requests_authored_by_user(self, user: User) -> list[ReleaseRequest]:
228+
"""Get all current requests authored by user."""
229+
raise NotImplementedError()
230+
231+
def get_outstanding_requests_for_review(self, user: User):
232+
"""Get all request that need review."""
229233
raise NotImplementedError()
230234

231235
VALID_STATE_TRANSITIONS = {

airlock/templates/requests.html

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
{% extends "base.html" %}
22

33
{% block content %}
4-
{% #card title="Requests for "|add:request.user.username %}
4+
5+
{% #card title="Requests by "|add:request.user.username %}
56
{% #list_group %}
6-
{% for request in requests %}
7-
{% #list_group_item href=request.get_absolute_url %}{{ request.id }}{% /list_group_item %}
7+
{% for request in authored_requests %}
8+
{% #list_group_item href=request.get_absolute_url %}{{ request.workspace }}: {{ request.status.name }}{% /list_group_item %}
89
{% endfor %}
910
{% /list_group %}
1011
{% /card %}
12+
13+
{% if request.user.output_checker %}
14+
{% #card title="Outstanding requests awaiting review" %}
15+
{% #list_group %}
16+
{% for request in outstanding_requests %}
17+
{% #list_group_item href=request.get_absolute_url %}{{ request.workspace }} by {{ request.author }}{% /list_group_item %}
18+
{% endfor %}
19+
{% /list_group %}
20+
{% /card %}
21+
{% endif %}
22+
1123
{% endblock content %}

airlock/views.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,20 @@ def workspace_add_file_to_request(request, workspace_name):
161161

162162

163163
def request_index(request):
164-
requests = api.get_requests_for_user(request.user)
165-
return TemplateResponse(request, "requests.html", {"requests": requests})
164+
authored_requests = api.get_requests_authored_by_user(request.user)
165+
166+
outstanding_requests = []
167+
if request.user.output_checker:
168+
outstanding_requests = api.get_outstanding_requests_for_review(request.user)
169+
170+
return TemplateResponse(
171+
request,
172+
"requests.html",
173+
{
174+
"authored_requests": authored_requests,
175+
"outstanding_requests": outstanding_requests,
176+
},
177+
)
166178

167179

168180
def request_view(request, request_id: str, path: str = ""):

local_db/api.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,30 @@ def get_current_request(self, workspace: str, user: User, create=False):
6060
author=user.username,
6161
)
6262

63-
def get_requests_for_user(self, user: User):
63+
def get_requests_authored_by_user(self, user: User):
64+
requests = []
65+
66+
for metadata in RequestMetadata.objects.filter(author=user.username).order_by(
67+
"status"
68+
):
69+
# to create a request, user *must* have explicit workspace
70+
# permissions - being an output checker is not enough
71+
if metadata.workspace in user.workspaces:
72+
requests.append(self._request(metadata))
73+
74+
return requests
75+
76+
def get_outstanding_requests_for_review(self, user: User):
6477
requests = []
65-
filter_args = {}
6678

67-
# if not output checker, can only see your own requests
6879
if not user.output_checker:
69-
filter_args = {"author": user.username}
80+
return []
7081

71-
for metadata in RequestMetadata.objects.filter(**filter_args):
72-
if user.output_checker or metadata.workspace in user.workspaces:
82+
for metadata in RequestMetadata.objects.filter(status=Status.SUBMITTED):
83+
# do not show output_checker their own requests
84+
if metadata.author != user.username:
7385
requests.append(self._request(metadata))
86+
7487
return requests
7588

7689
def set_status(self, request: ReleaseRequest, status: Status, user: User):

tests/integration/test_views.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,17 +248,30 @@ def test_request_index_user_permitted_requests(client_with_user):
248248
user = User.from_session(permitted_client.session)
249249
release_request = factories.create_release_request("test1", user)
250250
response = permitted_client.get("/requests/")
251-
request_ids = {r.id for r in response.context["requests"]}
252-
assert request_ids == {release_request.id}
251+
authored_ids = {r.id for r in response.context["authored_requests"]}
252+
outstanding_ids = {r.id for r in response.context["outstanding_requests"]}
253+
assert authored_ids == {release_request.id}
254+
assert outstanding_ids == set()
253255

254256

255257
def test_request_index_user_output_checker(client_with_user):
256-
r1 = factories.create_release_request("test1")
257-
r2 = factories.create_release_request("test2")
258-
permitted_client = client_with_user({"workspaces": [], "output_checker": True})
258+
permitted_client = client_with_user(
259+
{"workspaces": ["test_workspace"], "output_checker": True}
260+
)
261+
user = User.from_session(permitted_client.session)
262+
other = User(1, "other")
263+
r1 = factories.create_release_request(
264+
"test_workspace", user=user, status=Status.SUBMITTED
265+
)
266+
r2 = factories.create_release_request(
267+
"other_workspace", user=other, status=Status.SUBMITTED
268+
)
259269
response = permitted_client.get("/requests/")
260-
request_ids = {r.id for r in response.context["requests"]}
261-
assert request_ids == {r1.id, r2.id}
270+
271+
authored_ids = {r.id for r in response.context["authored_requests"]}
272+
outstanding_ids = {r.id for r in response.context["outstanding_requests"]}
273+
assert authored_ids == {r1.id}
274+
assert outstanding_ids == {r2.id}
262275

263276

264277
def test_request_submit_author(client_with_user):

tests/unit/test_api.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,29 +101,25 @@ def test_provider_request_release_files(mock_old_api):
101101
[
102102
([], False, []),
103103
(["allowed"], False, ["r1"]),
104-
(
105-
[],
106-
True,
107-
[
108-
"r1",
109-
"r2",
110-
"r3",
111-
],
112-
),
104+
# output checkers can't create requests unless explit permission for workspace
105+
([], True, []),
106+
(["allowed"], True, ["r1"]),
113107
(["allowed", "notexist"], False, ["r1"]),
114-
(["notexist", "notexist"], False, []),
108+
(["notexist"], False, []),
115109
(["no-request-dir", "notexist"], False, []),
116110
],
117111
)
118-
def test_provider_get_requests_for_user(workspaces, output_checker, expected, api):
112+
def test_provider_get_requests_authored_by_user(
113+
workspaces, output_checker, expected, api
114+
):
119115
user = User(1, "test", workspaces, output_checker)
120116
other_user = User(1, "other", [], False)
121117
factories.create_release_request("allowed", user, id="r1")
122118
factories.create_release_request("allowed", other_user, id="r2")
123119
factories.create_release_request("not-allowed", user, id="r3")
124120
factories.create_workspace("no-request-dir")
125121

126-
assert set(r.id for r in api.get_requests_for_user(user)) == set(expected)
122+
assert set(r.id for r in api.get_requests_authored_by_user(user)) == set(expected)
127123

128124

129125
def test_provider_get_current_request_for_user(api):

0 commit comments

Comments
 (0)