Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,39 @@ def test_digest_auth_allows_submission_on_username_endpoint(self):
response, 'Successful submission', status_code=status.HTTP_201_CREATED
)

def test_head_and_post_behavior_for_username_endpoint(self):
"""
Test that HEAD requests to `/<username>/submission` return 204 and that
anonymous POSTs work when the xform does not require auth.

KoboCollect performs an initial HEAD probe to confirm the endpoint is
reachable. This HEAD request must return 204. After that, an anonymous
POST containing the XML payload should succeed with a 201 response.
"""
username = self.user.username
self.xform.require_auth = False
self.xform.save(update_fields=['require_auth'])

# HEAD request to `/<username>/submission` must return 204
head_req = self.factory.head(f'/{username}/submission')
head_resp = self.view(head_req, username=username)
self.assertEqual(head_resp.status_code, status.HTTP_204_NO_CONTENT)

# Anonymous POST with actual xml payload must succeed
s = self.surveys[0]
submission_path = os.path.join(
self.main_directory, 'fixtures',
'transportation', 'instances', s, s + '.xml'
)
with open(submission_path, 'rb') as sf:
data = {'xml_submission_file': sf}
request = self.factory.post(f'/{username}/submission', data)
request.user = AnonymousUser()
response = self.view(request, username=username)
self.assertContains(
response, 'Successful submission', status_code=201
)


class ConcurrentSubmissionTestCase(RequestMixin, LiveServerTestCase):
"""
Expand Down
12 changes: 6 additions & 6 deletions kobo/apps/openrosa/apps/api/viewsets/xform_submission_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,19 +250,19 @@ def create(self, request, *args, **kwargs):
user = get_database_user(request.user)
username = user.username

# Return 401 if no authentication provided and there are no files,
# for digest authentication to work properly
has_auth = bool(get_authorization_header(request))
if not has_auth and not (bool(request.FILES) or bool(request.data)):
raise NotAuthenticated

if request.method.upper() == 'HEAD':
return Response(
status=status.HTTP_204_NO_CONTENT,
headers=self.get_openrosa_headers(request),
template_name=self.template_name,
)

# Return 401 if no authentication provided and there are no files,
# for digest authentication to work properly
has_auth = bool(get_authorization_header(request))
if not has_auth and not (bool(request.FILES) or bool(request.data)):
raise NotAuthenticated

is_json_request = is_json(request)

create_instance_func = (
Expand Down