Skip to content

Commit

Permalink
Send Digest Challenge response to anonymous user when fetching attach…
Browse files Browse the repository at this point in the history
…ments
  • Loading branch information
noliveleger committed Oct 20, 2021
1 parent acf884f commit 918eb6e
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 14 deletions.
19 changes: 16 additions & 3 deletions onadata/apps/api/viewsets/briefcase_api.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# coding: utf-8
from xml.dom import NotFoundErr

from django.conf import settings
from django.core.files import File
from django.core.validators import ValidationError
from django.contrib.auth.models import User
from django.http import Http404
from django.utils.translation import ugettext as _
from django.utils import six

from rest_framework import exceptions
from rest_framework import mixins
from rest_framework import status
Expand Down Expand Up @@ -96,8 +98,9 @@ def __init__(self, *args, **kwargs):
DigestAuthentication,
]
self.authentication_classes = authentication_classes + [
auth_class for auth_class in self.authentication_classes
if not auth_class in authentication_classes
auth_class
for auth_class in self.authentication_classes
if auth_class not in authentication_classes
]

def get_object(self):
Expand Down Expand Up @@ -222,6 +225,16 @@ def retrieve(self, request, *args, **kwargs):
submission_xml_root_node.setAttribute(
'submissionDate', self.object.date_created.isoformat()
)

# Added this because of https://github.com/onaio/onadata/pull/2139
# Should bring support to ODK v1.17+
if getattr(settings, 'SUPPORT_BRIEFCASE_SUBMISSION_DATE', True):
# Remove namespace attribute if any
try:
submission_xml_root_node.removeAttribute('xmlns')
except NotFoundErr:
pass

data = {
'submission_data': submission_xml_root_node.toxml(),
'media_files': Attachment.objects.filter(instance=self.object),
Expand Down
16 changes: 15 additions & 1 deletion onadata/apps/viewer/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from django.utils.http import urlquote
from django.utils.translation import ugettext as _
from django.views.decorators.http import require_POST
from django_digest import HttpDigestAuthenticator
from rest_framework.settings import api_settings

from onadata.apps.logger.models import XForm, Attachment
Expand Down Expand Up @@ -416,6 +417,17 @@ def attachment_url(request, size='medium'):
break

if not has_permission(xform, xform.user, request):
# New versions of ODK Briefcase (1.16+) do not sent Digest
# authentication headers anymore directly. So, if user does not
# pass `has_permission` and user is anonymous, we need to notify them
# that access is unauthorized (i.e.: send a HTTP 401) and give them
# a chance to authenticate.
if request.user.is_anonymous:
authenticator = HttpDigestAuthenticator()
if not authenticator.authenticate(request):
return authenticator.build_challenge_response()

# Otherwise, return a HTTP 403 (access forbidden)
return HttpResponseForbidden(_('Not shared.'))

media_url = None
Expand All @@ -426,7 +438,9 @@ def attachment_url(request, size='medium'):
try:
media_url = image_url(attachment, size)
except:
media_file_logger.error('could not get thumbnail for image', exc_info=True)
media_file_logger.error(
'could not get thumbnail for image', exc_info=True
)

if media_url:
# We want nginx to serve the media (instead of redirecting the media itself)
Expand Down
29 changes: 19 additions & 10 deletions onadata/libs/utils/user_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,33 @@ def set_profile_data(data, content_user):

def has_permission(xform, owner, request, shared=False):
user = request.user
return shared or xform.shared_data or \
(hasattr(request, 'session') and
request.session.get('public_link') == xform.uuid) or \
owner == user or \
user.has_perm('logger.' + CAN_VIEW_XFORM, xform) or \
user.has_perm('logger.' + CAN_CHANGE_XFORM, xform)
return (
shared
or xform.shared_data
or (
hasattr(request, 'session')
and request.session.get('public_link') == xform.uuid
)
or owner == user
or user.has_perm('logger.' + CAN_VIEW_XFORM, xform)
or user.has_perm('logger.' + CAN_CHANGE_XFORM, xform)
)


def has_delete_data_permission(xform, owner, request):
user = request.user
return owner == user or \
user.has_perm('logger.' + CAN_DELETE_DATA_XFORM, xform)
return (
owner == user
or user.has_perm('logger.' + CAN_DELETE_DATA_XFORM, xform)
)


def has_edit_permission(xform, owner, request):
user = request.user
return owner == user or \
user.has_perm('logger.' + CAN_CHANGE_XFORM, xform)
return (
owner == user
or user.has_perm('logger.' + CAN_CHANGE_XFORM, xform)
)


def check_and_set_user_and_form(username, id_string, request):
Expand Down

0 comments on commit 918eb6e

Please sign in to comment.