Skip to content

Commit 39303a4

Browse files
authored
Merge pull request #4884 from kobotoolbox/add-enketo-edit-and-view-redirect-endpoints
Add endpoints that redirect to Enketo for editing or viewing a submission
2 parents 9449399 + a1ad360 commit 39303a4

File tree

2 files changed

+97
-5
lines changed

2 files changed

+97
-5
lines changed

kpi/tests/api/v2/test_api_submissions.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,10 @@ def setUp(self):
10771077
self.submission_url = self.submission_url_legacy.replace(
10781078
'edit', 'enketo/edit'
10791079
)
1080+
self.submission_redirect_url = self.submission_url_legacy.replace(
1081+
'edit', 'enketo/redirect/edit'
1082+
)
1083+
assert 'redirect' in self.submission_redirect_url
10801084

10811085
@responses.activate
10821086
def test_get_legacy_edit_link_submission_as_owner(self):
@@ -1127,6 +1131,31 @@ def test_get_edit_link_submission_as_owner(self):
11271131
}
11281132
self.assertEqual(response.data, expected_response)
11291133

1134+
@responses.activate
1135+
def test_get_edit_submission_redirect_as_owner(self):
1136+
"""
1137+
someuser is the owner of the project.
1138+
someuser can retrieve enketo edit link
1139+
"""
1140+
ee_url = (
1141+
f'{settings.ENKETO_URL}/{settings.ENKETO_EDIT_INSTANCE_ENDPOINT}'
1142+
)
1143+
# Mock Enketo response
1144+
responses.add_callback(
1145+
responses.POST, ee_url,
1146+
callback=enketo_edit_instance_response,
1147+
content_type='application/json',
1148+
)
1149+
1150+
response = self.client.get(
1151+
self.submission_redirect_url, {'format': 'json'}
1152+
)
1153+
assert response.status_code == status.HTTP_302_FOUND
1154+
assert (
1155+
response.url
1156+
== f"{settings.ENKETO_URL}/edit/{self.submission['_uuid']}"
1157+
)
1158+
11301159
def test_get_edit_link_submission_as_anonymous(self):
11311160
"""
11321161
someuser is the owner of the project.
@@ -1602,6 +1631,12 @@ def setUp(self):
16021631
'pk': self.submission['_id'],
16031632
},
16041633
)
1634+
self.submission_view_redirect_url = (
1635+
self.submission_view_link_url.replace(
1636+
'/enketo/view/', '/enketo/redirect/view/'
1637+
)
1638+
)
1639+
assert 'redirect' in self.submission_view_redirect_url
16051640

16061641
@responses.activate
16071642
def test_get_view_link_submission_as_owner(self):
@@ -1629,6 +1664,32 @@ def test_get_view_link_submission_as_owner(self):
16291664
}
16301665
assert response.data == expected_response
16311666

1667+
@responses.activate
1668+
def test_get_view_submission_redirect_as_owner(self):
1669+
"""
1670+
someuser is the owner of the project.
1671+
someuser can get enketo view link
1672+
"""
1673+
ee_url = (
1674+
f'{settings.ENKETO_URL}/{settings.ENKETO_VIEW_INSTANCE_ENDPOINT}'
1675+
)
1676+
1677+
# Mock Enketo response
1678+
responses.add_callback(
1679+
responses.POST, ee_url,
1680+
callback=enketo_view_instance_response,
1681+
content_type='application/json',
1682+
)
1683+
1684+
response = self.client.get(
1685+
self.submission_view_redirect_url, {'format': 'json'}
1686+
)
1687+
assert response.status_code == status.HTTP_302_FOUND
1688+
assert (
1689+
response.url
1690+
== f"{settings.ENKETO_URL}/view/{self.submission['_uuid']}"
1691+
)
1692+
16321693
def test_get_view_link_submission_as_anonymous(self):
16331694
"""
16341695
someuser is the owner of the project.

kpi/views/v2/data.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import requests
77
from django.conf import settings
8-
from django.http import Http404
8+
from django.http import Http404, HttpResponseRedirect
99
from django.utils.translation import gettext_lazy as t
1010
from pymongo.errors import OperationFailure
1111
from rest_framework import (
@@ -188,6 +188,16 @@ class DataViewSet(AssetNestedObjectViewsetMixin, NestedViewSetMixin,
188188
>
189189
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/edit/?return_url=false
190190
191+
To redirect (HTTP 302) to the Enketo editing URL, use the `…/enketo/redirect/edit/` endpoint:
192+
193+
<pre class="prettyprint">
194+
<b>GET</b> /api/v2/assets/<code>{uid}</code>/data/<code>{id}</code>/enketo/redirect/edit/?return_url=false
195+
</pre>
196+
197+
> Example
198+
>
199+
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/redirect/edit/?return_url=false
200+
191201
View-only version of current submission
192202
193203
Return a URL to display the filled submission in view-only mode in the Enketo UI.
@@ -200,6 +210,16 @@ class DataViewSet(AssetNestedObjectViewsetMixin, NestedViewSetMixin,
200210
>
201211
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/view/
202212
213+
To redirect (HTTP 302) to the Enketo viewing URL, use the `…/enketo/redirect/view/` endpoint:
214+
215+
<pre class="prettyprint">
216+
<b>GET</b> /api/v2/assets/<code>{uid}</code>/data/<code>{id}</code>/enketo/redirect/view/?return_url=false
217+
</pre>
218+
219+
> Example
220+
>
221+
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/redirect/view/?return_url=false
222+
203223
### Duplicate submission
204224
205225
Duplicates the data of a submission
@@ -435,7 +455,7 @@ def duplicate(self, request, pk, *args, **kwargs):
435455
methods=['GET'],
436456
renderer_classes=[renderers.JSONRenderer],
437457
permission_classes=[EditLinkSubmissionPermission],
438-
url_path='(enketo/)?edit',
458+
url_path='((enketo/)|(enketo/redirect/))?edit',
439459
)
440460
def enketo_edit(self, request, pk, *args, **kwargs):
441461
submission_id = positive_int(pk)
@@ -447,18 +467,19 @@ def enketo_edit(self, request, pk, *args, **kwargs):
447467
EnketoSessionAuthentication.prepare_response_with_csrf_cookie(
448468
request, enketo_response
449469
)
450-
return enketo_response
470+
return self._handle_enketo_redirect(request, enketo_response, *args, **kwargs)
451471

452472
@action(
453473
detail=True,
454474
methods=['GET'],
455475
renderer_classes=[renderers.JSONRenderer],
456476
permission_classes=[ViewSubmissionPermission],
457-
url_path='enketo/view',
477+
url_path='enketo/(redirect/)?view',
458478
)
459479
def enketo_view(self, request, pk, *args, **kwargs):
460480
submission_id = positive_int(pk)
461-
return self._get_enketo_link(request, submission_id, 'view')
481+
enketo_response = self._get_enketo_link(request, submission_id, 'view')
482+
return self._handle_enketo_redirect(request, enketo_response, *args, **kwargs)
462483

463484
def get_queryset(self):
464485
# This method is needed when pagination is activated and renderer is
@@ -796,3 +817,13 @@ def _get_enketo_link(
796817
'version_uid': version_uid,
797818
}
798819
)
820+
821+
def _handle_enketo_redirect(self, request, enketo_response, *args, **kwargs):
822+
if request.path.strip('/').split('/')[-2] == 'redirect':
823+
try:
824+
enketo_url = enketo_response.data['url']
825+
except KeyError:
826+
pass
827+
else:
828+
return HttpResponseRedirect(enketo_url)
829+
return enketo_response

0 commit comments

Comments
 (0)