Example #1
0
 def test_build_challenge_response(self):
     response = HttpDigestAuthenticator().build_challenge_response()
     self.assertEqual(401, response.status_code)
     self.assertEqual('digest ', response["WWW-Authenticate"][:7].lower())
     parts = parse_parts(response["WWW-Authenticate"][7:])
     self.assertEqual(DEFAULT_REALM, parts['realm'])
     with patch(settings, DIGEST_REALM='CUSTOM'):
         response = HttpDigestAuthenticator().build_challenge_response()
         parts = parse_parts(response["WWW-Authenticate"][7:])
         self.assertEqual('CUSTOM', parts['realm'])
Example #2
0
    def test_authenticate_nonce(self):
        testuser = User.objects.create_user(
            username='******', email='*****@*****.**', password='******')
        User.objects.create_user(
            username='******', email='*****@*****.**', password='******')

        nonce=python_digest.calculate_nonce(time.time(), secret=settings.SECRET_KEY)

        first_request = self.create_mock_request(username=testuser.username,
                                                 password='******', nonce=nonce)
        first_request.user = testuser

        # same nonce, same nonce count, will fail
        second_request = self.create_mock_request(username=testuser.username,
                                                  password='******', nonce=nonce)

        # same nonce, new nonce count, it works
        third_request = self.create_mock_request(username=testuser.username,
                                                 password='******', nonce=nonce,
                                                 nonce_count=2)
        third_request.user = testuser

        authenticator = HttpDigestAuthenticator()
        with self.mocker:
            self.assertTrue(HttpDigestAuthenticator.contains_digest_credentials(
                first_request
            ))
            with transaction.commit_on_success():
                self.assertTrue(authenticator.authenticate(first_request))
                self.assertFalse(authenticator.authenticate(second_request))
                transaction.rollback()
                self.assertTrue(authenticator.authenticate(third_request))
Example #3
0
def xformsManifest(request, username, id_string):  # pylint: disable=C0103
    """
    XFormManifest view, part of OpenRosa Form Discovery API 1.0.
    """
    xform_kwargs = {
        'id_string__iexact': id_string,
        'user__username__iexact': username
    }

    xform = get_form(xform_kwargs)
    formlist_user = xform.user
    profile, __ = UserProfile.objects.get_or_create(user=formlist_user)

    if profile.require_auth:
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(request):
            return authenticator.build_challenge_response()

    response = render(
        request,
        "xformsManifest.xml", {
            'host':
            request.build_absolute_uri().replace(request.get_full_path(), ''),
            'media_files':
            MetaData.media_upload(xform, download=True)
        },
        content_type="text/xml; charset=utf-8")
    response['X-OpenRosa-Version'] = '1.0'
    response['Date'] = datetime.now(pytz.timezone(settings.TIME_ZONE))\
        .strftime('%a, %d %b %Y %H:%M:%S %Z')

    return response
Example #4
0
def xformsManifest(request, username, id_string):
    xform = get_object_or_404(XForm,
                              id_string__exact=id_string,
                              user__username__iexact=username)
    formlist_user = xform.user
    profile, created = \
        UserProfile.objects.get_or_create(user=formlist_user)

    if profile.require_auth:
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(request):
            return authenticator.build_challenge_response()

    response = render(
        request,
        "xformsManifest.xml", {
            'host':
            request.build_absolute_uri().replace(request.get_full_path(), ''),
            'media_files':
            MetaData.media_upload(xform, download=True)
        },
        content_type="text/xml; charset=utf-8")
    response['X-OpenRosa-Version'] = '1.0'
    tz = pytz.timezone(settings.TIME_ZONE)
    dt = datetime.now(tz).strftime('%a, %d %b %Y %H:%M:%S %Z')
    response['Date'] = dt

    return response
Example #5
0
        def wrapper(request, *args, **kwargs):
            authenticator = HttpDigestAuthenticator()
            if not authenticator.authenticate(request):
                return authenticator.build_challenge_response()

            response = f(request, *args, **kwargs)
            if hasattr(response,
                       'status_code') and response.status_code in [401, 403]:
                return authenticator.build_challenge_response()
            if 200 <= response.status_code < 300:
                digest = python_digest.parse_digest_credentials(
                    request.META['HTTP_AUTHORIZATION'])
                nc = "%08d" % digest.nc
                partial_digest = authenticator._account_storage.get_partial_digest(
                    digest.username)
                parameters = {
                    "username": request.user.username,
                    "ha1": partial_digest,
                    "nonce": digest.nonce,
                    "cnonce": digest.cnonce,
                    "method": digest.algorithm,
                    "uri": digest.uri,
                    "nc": nc,
                }
                rspauth = calc_rspauth(parameters)
                info = 'rspauth="%s",cnonce="%s",nc=%s,qop=%s' % (
                    rspauth, digest.cnonce, nc, digest.qop)
                response["Authentication-Info"] = info
            return response
Example #6
0
    def test_authenticate_basic(self):
        # a request for Basic auth
        thirteenth_request = self.create_mock_request_for_header(
            'Basic YmxhaDpibGFo')

        authenticator = HttpDigestAuthenticator()
        self.assertFalse(authenticator.authenticate(thirteenth_request))
Example #7
0
def form_upload(request, username):
    form_user = get_object_or_404(User, username__iexact=username)
    profile, created = \
        UserProfile.objects.get_or_create(user=form_user)
    authenticator = HttpDigestAuthenticator()
    if not authenticator.authenticate(request):
        return authenticator.build_challenge_response()
    if form_user != request.user:
        return HttpResponseForbidden(
            _(u"Not allowed to upload form[s] to %(user)s account." %
              {'user': form_user}))
    if request.method == 'HEAD':
        response = OpenRosaResponse(status=204)
        response['Location'] = request.build_absolute_uri().replace(
            request.get_full_path(), '/%s/formUpload' % form_user.username)
        return response
    xform_def = request.FILES.get('form_def_file', None)
    content = u""
    if isinstance(xform_def, File):
        do_form_upload = PublishXForm(xform_def, form_user)
        dd = publish_form(do_form_upload.publish_xform)
        status = 201
        if isinstance(dd, XForm):
            content = _(u"%s successfully published." % dd.id_string)
        else:
            content = dd['text']
            if isinstance(content, Exception):
                content = content.message
                status = 500
            else:
                status = 400
    return OpenRosaResponse(content, status=status)
Example #8
0
    def test_authenticate_invalid(self):
        testuser = User.objects.create_user(username='******',
                                            email='*****@*****.**',
                                            password='******')
        otheruser = User.objects.create_user(username='******',
                                             email='*****@*****.**',
                                             password='******')

        nonce=python_digest.calculate_nonce(time.time(),
                                            secret=settings.SECRET_KEY)
        # an invalid request
        fourth_request = self.create_mock_request_for_header(
            'Digest blah blah blah')

        # an invalid request
        fifth_request = self.create_mock_request_for_header(None)

        # an invalid nonce
        sixth_request = self.create_mock_request(
            username=testuser.username, password='******', nonce_count=1,
            nonce=python_digest.calculate_nonce(time.time(), secret='bad secret'))

        # an invalid request digest (wrong password)
        seventh_request = self.create_mock_request(
            username=testuser.username, password='******', nonce=nonce,
            nonce_count=3)

        # attack attempts / failures don't invalidate the session or increment nonce_cont
        eighth_request = self.create_mock_request(
            username=testuser.username, password='******', nonce=nonce,
            nonce_count=3)
        eighth_request.user = testuser

        # mismatched URI
        ninth_request = self.create_mock_request(
            username=testuser.username, nonce=nonce, password='******',
            nonce_count=4, request_path='/different/path')

        # stale nonce
        tenth_request = self.create_mock_request(
            username=testuser.username, password='******', nonce_count=4,
            nonce=python_digest.calculate_nonce(
                time.time()-60000, secret=settings.SECRET_KEY))

        # once the nonce is used by one user, can't be reused by another
        eleventh_request = self.create_mock_request(
            username=otheruser.username, password='******', nonce=nonce,
            nonce_count=4)

        authenticator = HttpDigestAuthenticator()
        with self.mocker:
            self.assertFalse(authenticator.authenticate(fourth_request))
            self.assertFalse(authenticator.authenticate(fifth_request))
            self.assertFalse(authenticator.authenticate(sixth_request))
            self.assertFalse(authenticator.authenticate(seventh_request))
            self.assertTrue(authenticator.authenticate(eighth_request))
            self.assertFalse(authenticator.authenticate(ninth_request))
            self.assertFalse(authenticator.authenticate(tenth_request))
            self.assertFalse(authenticator.authenticate(eleventh_request))
Example #9
0
def formList(request, username):

    formlist_user = get_object_or_404(User, username=username)
    content_user = get_object_or_404(User, username=username)
    profile, created = UserProfile.objects.get_or_create(user=formlist_user)

    if profile.require_auth:
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(request):
            return authenticator.build_challenge_response()

        # unauthorized if user in auth request does not match user in path
        # unauthorized if user not active
        if not request.user.is_active:
            return HttpResponseNotAuthorized()

    #xforms = XForm.objects.filter(downloadable=True, user__username=username)
    # forms shared with user
    print str(formlist_user.id)
    frm_qry = "select xform_id from vwrolewiseformpermission where can_submit=1 and user_id=" + str(
        formlist_user.id)

    cursor = connection.cursor()
    cursor.execute(frm_qry)
    tmp_db_value = cursor.fetchall()
    frm_list = []

    if tmp_db_value is not None:
        for every in tmp_db_value:
            frm_list.append(every[0])

    cursor.close()
    xforms = XForm.objects.filter(
        reduce(operator.or_, [Q(id=c) for c in frm_list]))

    #xfct = ContentType.objects.get(app_label='logger', model='xform')
    #xfs = content_user.userobjectpermission_set.filter(content_type=xfct)
    #shared_forms_pks = list(set([xf.object_pk for xf in xfs]))
    #xforms =  XForm.objects.filter(
    #        pk__in=shared_forms_pks).select_related('user')

    audit = {}
    audit_log(Actions.USER_FORMLIST_REQUESTED, request.user, formlist_user,
              _("Requested forms list."), audit, request)

    response = render_to_response("xformsList.xml", {
        'host':
        request.build_absolute_uri().replace(request.get_full_path(), ''),
        'xforms':
        xforms
    },
                                  mimetype="text/xml; charset=utf-8")
    response['X-OpenRosa-Version'] = '1.0'
    tz = pytz.timezone(settings.TIME_ZONE)
    dt = datetime.now(tz).strftime('%a, %d %b %Y %H:%M:%S %Z')
    response['Date'] = dt
    return response
Example #10
0
 def __call__(self, request):
     authenticator = HttpDigestAuthenticator()
     if (not authenticator.authenticate(request) and
         (get_setting("DIGEST_REQUIRE_AUTHENTICATION", False) or
          authenticator.contains_digest_credentials(request))):
         return authenticator.build_challenge_response()
     response = self.get_response(request)
     if response.status_code == 401:
         return authenticator.build_challenge_response()
     return response
def httpdigest(*args, **kwargs):
    '''
    May be used in one of three ways:
    * as a decorator factory (with the arguments being parameters to an instance of
    HttpDigestAuthenticator used to protect the decorated view)
    * as a decorator (protecting the decorated view with a default-constructed instance of
    HttpDigestAuthenticator)
    * as a decorator factory (with the argument being a pre-constructed HttpDigestAuthenticator
    instance used to protect the decorated view)
    '''
    if len(args) == 1 and not kwargs and isCallable(args[0]):
        authenticator = HttpDigestAuthenticator()
        return decorator(partial(_httpdigest, authenticator), args[0])

    if len(args) == 1 and not kwargs and isinstance(args[0],
                                                    HttpDigestAuthenticator):
        authenticator = args[0]
    else:
        authenticator = HttpDigestAuthenticator(*args, **kwargs)

    return lambda (f): decorator(partial(_httpdigest, authenticator), f)
Example #12
0
def formList(request, username):  # pylint: disable=C0103
    """
    formList view, /formList OpenRosa Form Discovery API 1.0.
    """
    formlist_user = get_object_or_404(User, username__iexact=username)
    profile = cache.get(f'{USER_PROFILE_PREFIX}{formlist_user.username}')
    if not profile:
        profile, __ = UserProfile.objects.get_or_create(
            user__username=formlist_user.username)

    if profile.require_auth:
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(request):
            return authenticator.build_challenge_response()

        # unauthorized if user in auth request does not match user in path
        # unauthorized if user not active
        if not request.user.is_active:
            return HttpResponseNotAuthorized()

    # filter private forms (where require_auth=False)
    # for users who are non-owner
    if request.user.username == profile.user.username:
        xforms = XForm.objects.filter(downloadable=True,
                                      deleted_at__isnull=True,
                                      user__username__iexact=username)
    else:
        xforms = XForm.objects.filter(downloadable=True,
                                      deleted_at__isnull=True,
                                      user__username__iexact=username,
                                      require_auth=False)

    audit = {}
    audit_log(Actions.USER_FORMLIST_REQUESTED, request.user, formlist_user,
              _("Requested forms list."), audit, request)

    data = {
        'host': request.build_absolute_uri().replace(request.get_full_path(),
                                                     ''),
        'xforms': xforms
    }
    response = render(request,
                      "xformsList.xml",
                      data,
                      content_type="text/xml; charset=utf-8")
    response['X-OpenRosa-Version'] = '1.0'
    response['Date'] = datetime.now(pytz.timezone(settings.TIME_ZONE))\
        .strftime('%a, %d %b %Y %H:%M:%S %Z')

    return response
Example #13
0
def formList(request, username):
    """
    This is where ODK Collect gets its download list.
    """
    if username.lower() == 'crowdforms':
        xforms = XForm.objects.filter(is_crowd_form=True)\
            .exclude(user__username=username)
    else:
        formlist_user = get_object_or_404(User, username=username)
        profile, created = \
            UserProfile.objects.get_or_create(user=formlist_user)

        if profile.require_auth:
            authenticator = HttpDigestAuthenticator()
            if not authenticator.authenticate(request):
                return authenticator.build_challenge_response()

            # unauthorized if user in auth request does not match user in path
            # unauthorized if user not active
            if formlist_user.username != request.user.username or\
                    not request.user.is_active:
                return HttpResponseNotAuthorized()

        xforms = \
            XForm.objects.filter(downloadable=True, user__username=username)
        # retrieve crowd_forms for this user
        crowdforms = XForm.objects.filter(
            metadata__data_type=MetaData.CROWDFORM_USERS,
            metadata__data_value=username)
        xforms = chain(xforms, crowdforms)
        audit = {}
        audit_log(Actions.USER_FORMLIST_REQUESTED, request.user, formlist_user,
                  _("Requested forms list."), audit, request)
    response = render_to_response(
        "xformsList.xml",
        {
            #'urls': urls,
            'host':
            request.build_absolute_uri().replace(request.get_full_path(), ''),
            'xforms':
            xforms
        },
        mimetype="text/xml; charset=utf-8")
    response['X-OpenRosa-Version'] = '1.0'
    tz = pytz.timezone(settings.TIME_ZONE)
    dt = datetime.now(tz).strftime('%a, %d %b %Y %H:%M:%S %Z')
    response['Date'] = dt
    return response
Example #14
0
def view_submission_list(request, username):
    """
    Submission list view.

    Briefcase Aggregate API view/submissionList.
    """
    form_user = get_object_or_404(User, username__iexact=username)
    __, ___ = UserProfile.objects.get_or_create(user=form_user)
    authenticator = HttpDigestAuthenticator()
    if not authenticator.authenticate(request):
        return authenticator.build_challenge_response()
    id_string = request.GET.get('formId', None)
    xform_kwargs = {
        'id_string__iexact': id_string,
        'user__username__iexact': username
    }

    xform = get_form(xform_kwargs)
    if not has_permission(xform, form_user, request, xform.shared_data):
        return HttpResponseForbidden('Not shared.')
    num_entries = request.GET.get('numEntries', None)
    cursor = request.GET.get('cursor', None)
    instances = xform.instances.filter(deleted_at=None).order_by('pk')

    cursor = _parse_int(cursor)
    if cursor:
        instances = instances.filter(pk__gt=cursor)

    num_entries = _parse_int(num_entries)
    if num_entries:
        instances = instances[:num_entries]

    data = {'instances': instances}

    resumption_cursor = 0
    if instances.count():
        last_instance = instances[instances.count() - 1]
        resumption_cursor = last_instance.pk
    elif instances.count() == 0 and cursor:
        resumption_cursor = cursor

    data['resumptionCursor'] = resumption_cursor

    return render(
        request,
        'submissionList.xml',
        data,
        content_type="text/xml; charset=utf-8")
Example #15
0
def view_submission_list(request, username):
    form_user = get_object_or_404(User, username=username)
    profile, created = \
        UserProfile.objects.get_or_create(user=form_user)
    authenticator = HttpDigestAuthenticator()
    if not authenticator.authenticate(request):
        return authenticator.build_challenge_response()
    context = RequestContext(request)
    id_string = request.GET.get('formId', None)
    xform = get_object_or_404(XForm,
                              id_string=id_string,
                              user__username=username)
    if not has_permission(xform, form_user, request, xform.shared_data):
        return HttpResponseForbidden('Not shared.')
    num_entries = request.GET.get('numEntries', None)
    cursor = request.GET.get('cursor', None)
    instances = xform.surveys.filter(deleted_at=None).order_by('pk')

    if cursor:
        try:
            cursor = int(cursor)
        except ValueError:
            pass
        else:
            instances = instances.filter(pk__gt=cursor)

    if num_entries:
        try:
            num_entries = int(num_entries)
        except ValueError:
            pass
        else:
            instances = instances[:num_entries]
    context.instances = instances

    if instances.count():
        last_instance = instances[instances.count() - 1]
        context.resumptionCursor = last_instance.pk
    elif instances.count() == 0 and cursor:
        context.resumptionCursor = cursor
    else:
        context.resumptionCursor = 0

    return render_to_response('submissionList.xml',
                              context_instance=context,
                              mimetype="text/xml; charset=utf-8")
Example #16
0
def formList(request, username):
    """
    This is where ODK Collect gets its download list.
    """
    formlist_user = get_object_or_404(User, username__iexact=username)
    profile, created = UserProfile.objects.get_or_create(user=formlist_user)

    if profile.require_auth:
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(request):
            return authenticator.build_challenge_response()

        # unauthorized if user in auth request does not match user in path
        # unauthorized if user not active
        if not request.user.is_active:
            return HttpResponseNotAuthorized()

    # filter private forms (where require_auth=False)
    # for users who are non-owner
    if request.user.username == profile.user.username:
        xforms = XForm.objects.filter(downloadable=True,
                                      user__username__iexact=username)
    else:
        xforms = XForm.objects.filter(downloadable=True,
                                      user__username__iexact=username,
                                      require_auth=False)

    audit = {}
    audit_log(Actions.USER_FORMLIST_REQUESTED, request.user, formlist_user,
              _("Requested forms list."), audit, request)

    data = {
        'host': request.build_absolute_uri().replace(request.get_full_path(),
                                                     ''),
        'xforms': xforms
    }
    response = render(request,
                      "xformsList.xml",
                      data,
                      content_type="text/xml; charset=utf-8")
    response['X-OpenRosa-Version'] = '1.0'
    tz = pytz.timezone(settings.TIME_ZONE)
    dt = datetime.now(tz).strftime('%a, %d %b %Y %H:%M:%S %Z')
    response['Date'] = dt

    return response
Example #17
0
def view_download_submission(request, username):
    """
    Submission download view.

    Briefcase Aggregate API view/downloadSubmissionList.
    """
    form_user = get_object_or_404(User, username__iexact=username)
    __, ___ = UserProfile.objects.get_or_create(user=form_user)
    authenticator = HttpDigestAuthenticator()
    if not authenticator.authenticate(request):
        return authenticator.build_challenge_response()
    data = {}
    form_id = request.GET.get('formId', None)
    if not isinstance(form_id, six.string_types):
        return HttpResponseBadRequest()

    id_string = form_id[0:form_id.find('[')]
    form_id_parts = form_id.split('/')
    if form_id_parts.__len__() < 2:
        return HttpResponseBadRequest()

    uuid = _extract_uuid(form_id_parts[1])
    instance = get_object_or_404(
        Instance,
        xform__id_string__iexact=id_string,
        uuid=uuid,
        xform__user__username=username,
        deleted_at__isnull=True)
    xform = instance.xform
    if not has_permission(xform, form_user, request, xform.shared_data):
        return HttpResponseForbidden('Not shared.')
    submission_xml_root_node = instance.get_root_node()
    submission_xml_root_node.setAttribute('instanceID',
                                          u'uuid:%s' % instance.uuid)
    submission_xml_root_node.setAttribute('submissionDate',
                                          instance.date_created.isoformat())
    data['submission_data'] = submission_xml_root_node.toxml()
    data['media_files'] = Attachment.objects.filter(instance=instance)
    data['host'] = request.build_absolute_uri().replace(
        request.get_full_path(), '')

    return render(
        request,
        'downloadSubmission.xml',
        data,
        content_type="text/xml; charset=utf-8")
Example #18
0
    def test_authenticate_missing(self):
        testuser = User.objects.create_user(username='******',
                                            email='*****@*****.**',
                                            password='******')
        User.objects.create_user(username='******',
                                 email='*****@*****.**',
                                 password='******')

        python_digest.calculate_nonce(time.time(), secret=settings.SECRET_KEY)
        # if the partial digest is not in the DB, authentication fails
        twelfth_request = self.create_mock_request(username=testuser.username,
                                                   password='******',
                                                   nonce_count=3)

        authenticator = HttpDigestAuthenticator()
        PartialDigest.objects.all().delete()
        self.assertFalse(authenticator.authenticate(twelfth_request))
Example #19
0
def view_download_submission(request, username):
    def extract_uuid(text):
        text = text[text.find("@key="):-1].replace("@key=", "")
        if text.startswith("uuid:"):
            text = text.replace("uuid:", "")
        return text

    form_user = get_object_or_404(User, username=username)
    profile, created = \
        UserProfile.objects.get_or_create(user=form_user)
    authenticator = HttpDigestAuthenticator()
    if not authenticator.authenticate(request):
        return authenticator.build_challenge_response()
    context = RequestContext(request)
    formId = request.GET.get('formId', None)
    if not isinstance(formId, basestring):
        return HttpResponseBadRequest()

    id_string = formId[0:formId.find('[')]
    form_id_parts = formId.split('/')
    if form_id_parts.__len__() < 2:
        return HttpResponseBadRequest()

    uuid = extract_uuid(form_id_parts[1])
    try:
        instance = Instance.objects.filter(xform__id_string=id_string,
                                           uuid=uuid,
                                           user__username=username,
                                           deleted_at=None)[0]
        xform = instance.xform
        if not has_permission(xform, form_user, request, xform.shared_data):
            return HttpResponseForbidden('Not shared.')
        submission_xml_root_node = instance.get_root_node()
        submission_xml_root_node.setAttribute('instanceID',
                                              u'uuid:%s' % instance.uuid)
        submission_xml_root_node.setAttribute(
            'submissionDate', instance.date_created.isoformat())
        context.submission_data = submission_xml_root_node.toxml()
        context.media_files = Attachment.objects.filter(instance=instance)
        context.host = request.build_absolute_uri().replace(
            request.get_full_path(), '')
        return render_to_response('downloadSubmission.xml',
                                  context_instance=context,
                                  mimetype="text/xml; charset=utf-8")
    except IndexError:
        raise Http404
Example #20
0
    def test_decorator_with_pre_constructed_authenticator(self):
        response = self.mocker.mock(count=False)
        expect(response.status_code).result(200)

        @httpdigest(HttpDigestAuthenticator(realm='MY_TEST_REALM'))
        def test_view(request):
            return response

        testuser = User.objects.create_user('testuser', '*****@*****.**', 'pass')
        request = self.create_mock_request_for_header(None)
        request.user = testuser

        with self.mocker:
            final_response = test_view(request)
            self.assertEqual(401, final_response.status_code)
            self.assertTrue('WWW-Authenticate' in final_response)
            self.assertTrue('MY_TEST_REALM' in final_response['WWW-Authenticate'])
Example #21
0
def odk_get_form(req, pk):
    # if forms are restricted, force digest authentication
    if getattr(settings, 'AUTHENTICATE_XFORMS', False):
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(req):
            return authenticator.build_challenge_response()

    xform = get_object_or_404(XForm, pk=pk)
    if not xform.does_user_have_permission(req.user):
        return HttpResponse("You do not have permission to view this form",
                            status=403)

    resp = render_to_response("xforms/odk_get_form.xml", {'xform': xform},
                              mimetype="text/xml",
                              context_instance=RequestContext(req))
    resp[
        'Content-Disposition'] = 'attachment;filename="%s.xml"' % xform.keyword
    return resp
Example #22
0
def odk_list_forms(req):
    # if forms are restricted, force digest authentication
    if getattr(settings, 'AUTHENTICATE_XFORMS', False):
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(req):
            return authenticator.build_challenge_response()

    xforms = []
    for form in XForm.on_site.filter(active=True):
        if form.does_user_have_permission(req.user):
            xforms.append(form)

    return render_to_response("xforms/odk_list_forms.xml", {
        'xforms': xforms,
        'host': settings.XFORMS_HOST
    },
                              mimetype="text/xml",
                              context_instance=RequestContext(req))
Example #23
0
    def test_authenticate_nonce(self):
        testuser = User.objects.create_user(username='******',
                                            email='*****@*****.**',
                                            password='******')
        User.objects.create_user(username='******',
                                 email='*****@*****.**',
                                 password='******')

        nonce = python_digest.calculate_nonce(time.time(),
                                              secret=settings.SECRET_KEY)

        first_request = self.create_mock_request(username=testuser.username,
                                                 password='******',
                                                 nonce=nonce)
        first_request.user = testuser

        # same nonce, same nonce count, will fail
        second_request = self.create_mock_request(username=testuser.username,
                                                  password='******',
                                                  nonce=nonce)

        # same nonce, new nonce count, it works
        third_request = self.create_mock_request(username=testuser.username,
                                                 password='******',
                                                 nonce=nonce,
                                                 nonce_count=2)
        third_request.user = testuser

        authenticator = HttpDigestAuthenticator()
        assert 'HTTP_AUTHORIZATION' in first_request.META
        assert python_digest.is_digest_credential(
            first_request.META['HTTP_AUTHORIZATION'])

        self.assertTrue(
            HttpDigestAuthenticator.contains_digest_credentials(first_request))
        transaction.set_autocommit(False)
        self.assertTrue(authenticator.authenticate(first_request))
        self.assertFalse(authenticator.authenticate(second_request))
        transaction.rollback()
        self.assertTrue(authenticator.authenticate(third_request))
        transaction.commit()
        transaction.set_autocommit(True)
Example #24
0
def download_xform(request, username, id_string):
    user = get_object_or_404(User, username__iexact=username)
    xform = get_object_or_404(XForm, user=user, id_string__exact=id_string)
    profile, created =\
        UserProfile.objects.get_or_create(user=user)

    if profile.require_auth:
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(request):
            return authenticator.build_challenge_response()
    audit = {"xform": xform.id_string}
    audit_log(
        Actions.FORM_XML_DOWNLOADED, request.user, xform.user,
        _("Downloaded XML for form '%(id_string)s'.") %
        {"id_string": xform.id_string}, audit, request)
    response = response_with_mimetype_and_name('xml',
                                               id_string,
                                               show_date=False)
    response.content = xform.xml
    return response
Example #25
0
def formList(request, username):
    """
    This is where ODK Collect gets its download list.
    """
    print '####'
    formlist_user = get_object_or_404(User, username=username)
    content_user = get_object_or_404(User, username=username)
    profile, created = UserProfile.objects.get_or_create(user=formlist_user)

    if profile.require_auth:
        authenticator = HttpDigestAuthenticator()
        if not authenticator.authenticate(request):
            return authenticator.build_challenge_response()

        # unauthorized if user in auth request does not match user in path
        # unauthorized if user not active
        if not request.user.is_active:
            return HttpResponseNotAuthorized()

    #xforms = XForm.objects.filter(downloadable=True, user__username=username)
    # forms shared with user
    xfct = ContentType.objects.get(app_label='logger', model='xform')
    xfs = content_user.userobjectpermission_set.filter(content_type=xfct)
    shared_forms_pks = list(set([xf.object_pk for xf in xfs]))
    xforms =  XForm.objects.filter(
            pk__in=shared_forms_pks).select_related('user')

    audit = {}
    audit_log(Actions.USER_FORMLIST_REQUESTED, request.user, formlist_user,
              _("Requested forms list."), audit, request)

    response = render_to_response("xformsList.xml", {
        'host': request.build_absolute_uri().replace(
            request.get_full_path(), ''),
        'xforms': xforms
    }, mimetype="text/xml; charset=utf-8")
    response['X-OpenRosa-Version'] = '1.0'
    tz = pytz.timezone(settings.TIME_ZONE)
    dt = datetime.now(tz).strftime('%a, %d %b %Y %H:%M:%S %Z')
    response['Date'] = dt
    return response
Example #26
0
    def test_disable_nonce_count_enforcement(self):
        with patch(settings, DIGEST_ENFORCE_NONCE_COUNT=False):
            testuser = User.objects.create_user(username='******',
                                                email='*****@*****.**',
                                                password='******')

            nonce = python_digest.calculate_nonce(time.time(),
                                                  secret=settings.SECRET_KEY)

            first_request = self.create_mock_request(
                username=testuser.username, password='******', nonce=nonce)

            first_request.user = testuser

            # same nonce, same nonce count, will succeed
            second_request = self.create_mock_request(
                username=testuser.username, password='******', nonce=nonce)
            second_request.user = testuser

            authenticator = HttpDigestAuthenticator()
            self.assertTrue(authenticator.authenticate(first_request))
            self.assertTrue(authenticator.authenticate(second_request))
Example #27
0
def form_upload(request, username):
    class DoXmlFormUpload():
        def __init__(self, xml_file, user):
            self.xml_file = xml_file
            self.user = user

        def publish(self):
            return publish_xml_form(self.xml_file, self.user)

    form_user = get_object_or_404(User, username=username)
    profile, created = \
        UserProfile.objects.get_or_create(user=form_user)
    authenticator = HttpDigestAuthenticator()
    if not authenticator.authenticate(request):
        return authenticator.build_challenge_response()
    if request.method == 'HEAD':
        response = OpenRosaResponse(status=204)
        response['Location'] = request.build_absolute_uri().replace(
            request.get_full_path(), '/%s/formUpload' % form_user.username)
        return response
    xform_def = request.FILES.get('form_def_file', None)
    content = u""
    if isinstance(xform_def, File):
        do_form_upload = DoXmlFormUpload(xform_def, form_user)
        dd = publish_form(do_form_upload.publish)
        status = 201
        if isinstance(dd, XForm):
            content = _(u"%s successfully published." % dd.id_string)
        else:
            content = dd['text']
            if isinstance(content, Exception):
                content = content.message
                status = 500
            else:
                status = 400
    return OpenRosaResponse(content, status=status)
 def __init__(self):
     self.authenticator = HttpDigestAuthenticator()
Example #29
0
def submission(request, username=None):
    if username:
        formlist_user = get_object_or_404(User, username__iexact=username)
        profile, created = UserProfile.objects.get_or_create(
            user=formlist_user)

        if profile.require_auth:
            authenticator = HttpDigestAuthenticator()
            if not authenticator.authenticate(request):
                return authenticator.build_challenge_response()

    if request.method == 'HEAD':
        response = OpenRosaResponse(status=204)
        if username:
            response['Location'] = request.build_absolute_uri().replace(
                request.get_full_path(), '/%s/submission' % username)
        else:
            response['Location'] = request.build_absolute_uri().replace(
                request.get_full_path(), '/submission')
        return response

    xml_file_list = []
    media_files = []

    # request.FILES is a django.utils.datastructures.MultiValueDict
    # for each key we have a list of values
    try:
        xml_file_list = request.FILES.pop("xml_submission_file", [])
        if len(xml_file_list) != 1:
            return OpenRosaResponseBadRequest(
                _(u"There should be a single XML submission file."))
        # save this XML file and media files as attachments
        media_files = request.FILES.values()

        # get uuid from post request
        uuid = request.POST.get('uuid')

        error, instance = safe_create_instance(username, xml_file_list[0],
                                               media_files, uuid, request)

        if error:
            return error
        elif instance is None:
            return OpenRosaResponseBadRequest(
                _(u"Unable to create submission."))

        audit = {"xform": instance.xform.id_string}
        audit_log(
            Actions.SUBMISSION_CREATED, request.user, instance.xform.user,
            _("Created submission on form %(id_string)s.") %
            {"id_string": instance.xform.id_string}, audit, request)

        # response as html if posting with a UUID
        if not username and uuid:
            response = _html_submission_response(request, instance)
        else:
            response = _submission_response(request, instance)

        # ODK needs two things for a form to be considered successful
        # 1) the status code needs to be 201 (created)
        # 2) The location header needs to be set to the host it posted to
        response.status_code = 201
        response['Location'] = request.build_absolute_uri(request.path)
        return response
    except IOError as e:
        if _bad_request(e):
            return OpenRosaResponseBadRequest(
                _(u"File transfer interruption."))
        else:
            raise
    finally:
        if len(xml_file_list):
            [_file.close() for _file in xml_file_list]
        if len(media_files):
            [_file.close() for _file in media_files]
Example #30
0
def submission(request, username=None):
    if username and username.lower() != 'crowdforms':
        formlist_user = get_object_or_404(User, username=username.lower())
        profile, created = \
            UserProfile.objects.get_or_create(user=formlist_user)

        if profile.require_auth:
            authenticator = HttpDigestAuthenticator()
            if not authenticator.authenticate(request):
                return authenticator.build_challenge_response()
    if request.method == 'HEAD':
        response = OpenRosaResponse(status=204)
        if username:
            response['Location'] = request.build_absolute_uri().replace(
                request.get_full_path(), '/%s/submission' % username)
        else:
            response['Location'] = request.build_absolute_uri().replace(
                request.get_full_path(), '/submission')
        return response
    context = RequestContext(request)
    xml_file_list = []
    media_files = []
    html_response = False
    # request.FILES is a django.utils.datastructures.MultiValueDict
    # for each key we have a list of values
    try:
        xml_file_list = request.FILES.pop("xml_submission_file", [])
        if len(xml_file_list) != 1:
            return OpenRosaResponseBadRequest(
                _(u"There should be a single XML submission file."))
        # save this XML file and media files as attachments
        media_files = request.FILES.values()

        # get uuid from post request
        uuid = request.POST.get('uuid')
        # response as html if posting with a UUID
        if not username and uuid:
            html_response = True
        try:
            instance = create_instance(username,
                                       xml_file_list[0],
                                       media_files,
                                       uuid=uuid,
                                       request=request)
        except InstanceInvalidUserError:
            return OpenRosaResponseBadRequest(_(u"Username or ID required."))
        except IsNotCrowdformError:
            return OpenRosaResponseNotAllowed(
                _(u"Sorry but the crowd form you submitted to is closed."))
        except InstanceEmptyError:
            return OpenRosaResponseBadRequest(
                _(u"Received empty submission. No instance was created"))
        except FormInactiveError:
            return OpenRosaResponseNotAllowed(_(u"Form is not active"))
        except XForm.DoesNotExist:
            return OpenRosaResponseNotFound(
                _(u"Form does not exist on this account"))
        except ExpatError:
            return OpenRosaResponseBadRequest(_(u"Improperly formatted XML."))
        except DuplicateInstance:
            response = OpenRosaResponse(_(u"Duplicate submission"))
            response.status_code = 202
            response['Location'] = request.build_absolute_uri(request.path)
            return response
        except PermissionDenied, e:
            return OpenRosaResponseNotAllowed(e.message)
        except Exception, e:
            raise