Skip to content

Commit

Permalink
Merge pull request #4884 from kobotoolbox/add-enketo-edit-and-view-re…
Browse files Browse the repository at this point in the history
…direct-endpoints

Add endpoints that redirect to Enketo for editing or viewing a submission
  • Loading branch information
noliveleger authored Aug 1, 2024
2 parents 9449399 + a1ad360 commit 39303a4
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 5 deletions.
61 changes: 61 additions & 0 deletions kpi/tests/api/v2/test_api_submissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,10 @@ def setUp(self):
self.submission_url = self.submission_url_legacy.replace(
'edit', 'enketo/edit'
)
self.submission_redirect_url = self.submission_url_legacy.replace(
'edit', 'enketo/redirect/edit'
)
assert 'redirect' in self.submission_redirect_url

@responses.activate
def test_get_legacy_edit_link_submission_as_owner(self):
Expand Down Expand Up @@ -1127,6 +1131,31 @@ def test_get_edit_link_submission_as_owner(self):
}
self.assertEqual(response.data, expected_response)

@responses.activate
def test_get_edit_submission_redirect_as_owner(self):
"""
someuser is the owner of the project.
someuser can retrieve enketo edit link
"""
ee_url = (
f'{settings.ENKETO_URL}/{settings.ENKETO_EDIT_INSTANCE_ENDPOINT}'
)
# Mock Enketo response
responses.add_callback(
responses.POST, ee_url,
callback=enketo_edit_instance_response,
content_type='application/json',
)

response = self.client.get(
self.submission_redirect_url, {'format': 'json'}
)
assert response.status_code == status.HTTP_302_FOUND
assert (
response.url
== f"{settings.ENKETO_URL}/edit/{self.submission['_uuid']}"
)

def test_get_edit_link_submission_as_anonymous(self):
"""
someuser is the owner of the project.
Expand Down Expand Up @@ -1602,6 +1631,12 @@ def setUp(self):
'pk': self.submission['_id'],
},
)
self.submission_view_redirect_url = (
self.submission_view_link_url.replace(
'/enketo/view/', '/enketo/redirect/view/'
)
)
assert 'redirect' in self.submission_view_redirect_url

@responses.activate
def test_get_view_link_submission_as_owner(self):
Expand Down Expand Up @@ -1629,6 +1664,32 @@ def test_get_view_link_submission_as_owner(self):
}
assert response.data == expected_response

@responses.activate
def test_get_view_submission_redirect_as_owner(self):
"""
someuser is the owner of the project.
someuser can get enketo view link
"""
ee_url = (
f'{settings.ENKETO_URL}/{settings.ENKETO_VIEW_INSTANCE_ENDPOINT}'
)

# Mock Enketo response
responses.add_callback(
responses.POST, ee_url,
callback=enketo_view_instance_response,
content_type='application/json',
)

response = self.client.get(
self.submission_view_redirect_url, {'format': 'json'}
)
assert response.status_code == status.HTTP_302_FOUND
assert (
response.url
== f"{settings.ENKETO_URL}/view/{self.submission['_uuid']}"
)

def test_get_view_link_submission_as_anonymous(self):
"""
someuser is the owner of the project.
Expand Down
41 changes: 36 additions & 5 deletions kpi/views/v2/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import requests
from django.conf import settings
from django.http import Http404
from django.http import Http404, HttpResponseRedirect
from django.utils.translation import gettext_lazy as t
from pymongo.errors import OperationFailure
from rest_framework import (
Expand Down Expand Up @@ -188,6 +188,16 @@ class DataViewSet(AssetNestedObjectViewsetMixin, NestedViewSetMixin,
>
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/edit/?return_url=false
To redirect (HTTP 302) to the Enketo editing URL, use the `…/enketo/redirect/edit/` endpoint:
<pre class="prettyprint">
<b>GET</b> /api/v2/assets/<code>{uid}</code>/data/<code>{id}</code>/enketo/redirect/edit/?return_url=false
</pre>
> Example
>
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/redirect/edit/?return_url=false
View-only version of current submission
Return a URL to display the filled submission in view-only mode in the Enketo UI.
Expand All @@ -200,6 +210,16 @@ class DataViewSet(AssetNestedObjectViewsetMixin, NestedViewSetMixin,
>
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/view/
To redirect (HTTP 302) to the Enketo viewing URL, use the `…/enketo/redirect/view/` endpoint:
<pre class="prettyprint">
<b>GET</b> /api/v2/assets/<code>{uid}</code>/data/<code>{id}</code>/enketo/redirect/view/?return_url=false
</pre>
> Example
>
> curl -X GET https://[kpi]/api/v2/assets/aSAvYreNzVEkrWg5Gdcvg/data/234/enketo/redirect/view/?return_url=false
### Duplicate submission
Duplicates the data of a submission
Expand Down Expand Up @@ -435,7 +455,7 @@ def duplicate(self, request, pk, *args, **kwargs):
methods=['GET'],
renderer_classes=[renderers.JSONRenderer],
permission_classes=[EditLinkSubmissionPermission],
url_path='(enketo/)?edit',
url_path='((enketo/)|(enketo/redirect/))?edit',
)
def enketo_edit(self, request, pk, *args, **kwargs):
submission_id = positive_int(pk)
Expand All @@ -447,18 +467,19 @@ def enketo_edit(self, request, pk, *args, **kwargs):
EnketoSessionAuthentication.prepare_response_with_csrf_cookie(
request, enketo_response
)
return enketo_response
return self._handle_enketo_redirect(request, enketo_response, *args, **kwargs)

@action(
detail=True,
methods=['GET'],
renderer_classes=[renderers.JSONRenderer],
permission_classes=[ViewSubmissionPermission],
url_path='enketo/view',
url_path='enketo/(redirect/)?view',
)
def enketo_view(self, request, pk, *args, **kwargs):
submission_id = positive_int(pk)
return self._get_enketo_link(request, submission_id, 'view')
enketo_response = self._get_enketo_link(request, submission_id, 'view')
return self._handle_enketo_redirect(request, enketo_response, *args, **kwargs)

def get_queryset(self):
# This method is needed when pagination is activated and renderer is
Expand Down Expand Up @@ -796,3 +817,13 @@ def _get_enketo_link(
'version_uid': version_uid,
}
)

def _handle_enketo_redirect(self, request, enketo_response, *args, **kwargs):
if request.path.strip('/').split('/')[-2] == 'redirect':
try:
enketo_url = enketo_response.data['url']
except KeyError:
pass
else:
return HttpResponseRedirect(enketo_url)
return enketo_response

0 comments on commit 39303a4

Please sign in to comment.