def show(request, username=None, id_string=None, uuid=None): if uuid: return redirect_to_public_link(request, uuid) xform, is_owner, can_edit, can_view, can_delete_data = get_xform_and_perms( username, id_string, request) # no access if not (xform.shared or can_view or request.session.get('public_link')): return HttpResponseRedirect(reverse(home)) data = {} data['cloned'] = len( XForm.objects.filter( user__username__iexact=request.user.username, id_string__exact=id_string + XForm.CLONED_SUFFIX)) > 0 data['public_link'] = MetaData.public_link(xform) data['is_owner'] = is_owner data['can_edit'] = can_edit data['can_view'] = can_view or request.session.get('public_link') data['can_delete_data'] = can_delete_data data['xform'] = xform data['content_user'] = xform.user data['base_url'] = "https://%s" % request.get_host() data['supporting_docs'] = MetaData.supporting_docs(xform) data['media_upload'] = MetaData.media_upload(xform) if is_owner: data['media_form'] = MediaForm() if xform.kpi_asset_uid: data['kpi_url'] = ( f'{settings.KOBOFORM_URL}/#/forms/{xform.kpi_asset_uid}') return render(request, "show.html", data)
def test_user_add_crowdform_duplicate_entry(self): self._add_crowdform() self.assertEqual(self.response.status_code, 302) meta = MetaData.crowdform_users(self.xform) self.assertEqual(len(meta), 1) self._add_crowdform() meta = MetaData.crowdform_users(self.xform) self.assertEqual(len(meta), 1)
def test_upload_source_file_keep_name(self): desc = 'Snooky' response = self.client.post(self.edit_url, {'source': desc}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) self._add_metadata('source') self.assertNotEqual(MetaData.source(self.xform).data_file, None) self.assertEqual(MetaData.source(self.xform).data_value, desc)
def test_export_list_with_meta_perms(self): """ Test export list for forms with meta permissions. """ with HTTMock(enketo_mock): self._publish_transportation_form() for survey in self.surveys: self._make_submission(os.path.join( settings.PROJECT_ROOT, 'apps', 'main', 'tests', 'fixtures', 'transportation', 'instances', survey, survey + '.xml'), forced_submission_time=parse_datetime( '2013-02-18 15:54:01Z')) alice = self._create_user('alice', 'alice', True) MetaData.xform_meta_permission(self.xform, data_value="editor|dataentry-minor") DataEntryMinorRole.add(alice, self.xform) for i in self.xform.instances.all()[:2]: i.user = alice i.save() view = XFormViewSet.as_view({'get': 'retrieve'}) alices_extra = { 'HTTP_AUTHORIZATION': 'Token %s' % alice.auth_token.key } # Alice creates an export with her own submissions request = self.factory.get('/', **alices_extra) response = view(request, pk=self.xform.pk, format='csv') self.assertEqual(response.status_code, 200) exports = Export.objects.filter(xform=self.xform) view = ExportViewSet.as_view({'get': 'list'}) request = self.factory.get('/export', data={'xform': self.xform.id}) force_authenticate(request, user=alice) response = view(request) self.assertEqual(len(exports), len(response.data)) # Mary should not have access to the export with Alice's # submissions. self._create_user_and_login(username='******', password='******') self.assertEqual(self.user.username, 'mary') # Mary should only view their own submissions. DataEntryMinorRole.add(self.user, self.xform) request = self.factory.get('/export', data={'xform': self.xform.id}) force_authenticate(request, user=self.user) response = view(request) self.assertFalse(bool(response.data), response.data) self.assertEqual(status.HTTP_200_OK, response.status_code)
def test_metadata_file_hash(self): self._publish_transportation_form() src = os.path.join(self.this_directory, "fixtures", "transportation", "screenshot.png") uf = UploadedFile(file=open(src), content_type='image/png') count = MetaData.objects.count() MetaData.media_upload(self.xform, uf) # assert successful insert of new metadata record self.assertEqual(MetaData.objects.count(), count + 1) md = MetaData.objects.get(xform=self.xform, data_value='screenshot.png') # assert checksum string has been generated, hash length > 1 self.assertTrue(len(md.hash) > 16)
def test_windows_csv_file_upload(self): count = MetaData.objects.filter(data_type='media').count() media_file = os.path.join(self.this_directory, 'fixtures', 'transportation', 'transportation.csv') f = InMemoryUploadedFile(open(media_file), 'media', 'transportation.csv', 'application/octet-stream', 2625, None) MetaData.media_upload(self.xform, f) media_list = MetaData.objects.filter(data_type='media') new_count = media_list.count() self.assertEqual(count + 1, new_count) media = media_list.get(data_value='transportation.csv') self.assertEqual(media.data_file_type, 'text/csv')
def handle(self, *args, **kwargs): cursor = connection.cursor() cursor.execute( 'SELECT uid FROM kpi_asset WHERE asset_type=%s', ['survey']) rs = cursor.cursor.fetchall() uids = [a[0] for a in rs] xforms = XForm.objects.filter(id_string__in=uids) for x in xforms: MetaData.published_by_formbuilder(x, 'True') self.stdout.write( "Done creating published_by_formbuilder metadata!!!" )
def test_retrieve_xform_manifest_linked_form(self): # for linked forms check if manifest media download url for csv # has a group_delimiter param data_type = 'media' data_value = 'xform {} transportation'.format(self.xform.pk) media = self._add_form_metadata(self.xform, data_type, data_value) self.view = XFormListViewSet.as_view( { "get": "manifest", "head": "manifest" } ) # sign in bob request = self.factory.head('/') auth_response = self.view(request, pk=self.xform.pk) auth = DigestAuth('bob', 'bobbob') # set up bob's request request = self.factory.get('/xformsManifest') request.META.update(auth(request.META, auth_response)) # make request response = self.view(request, pk=self.xform.pk, format='csv') # test manifest_media_url = '{}{}'.format( media.data['media_url'], '?group_delimiter=.&repeat_index_tags=_,_') download_url = response.data[0]['downloadUrl'] self.assertEqual(manifest_media_url, download_url) url = '/bob/xformsMedia/{}/{}.csv?group_delimiter=.'\ .format(self.xform.pk, self.metadata.pk) username = '******' password = '******' client = DigestClient() client.set_authorization(username, password, 'Digest') req = client.get(url) self.assertEqual(req.status_code, 200) # enable meta perms data_value = "editor-minor|dataentry" MetaData.xform_meta_permission(self.xform, data_value=data_value) req = client.get(url) self.assertEqual(req.status_code, 401)
def test_private_set_link_to_share_toggle_off(self): response = self.client.post(self.perm_url, {'for_user': '******', 'perm_type': 'link'}) self.assertEqual(MetaData.public_link(self.xform), True) response = self.anon.get(self.show_url) self.assertRedirects(response, self.show_normal_url) response = self.client.post(self.perm_url, {'for_user': '******', 'perm_type': 'link'}) self.assertEqual(MetaData.public_link(self.xform), False) response = self.anon.get(self.show_url) # follow redirect response = self.anon.get(response['Location']) self.assertEqual(response.status_code, 302) self.assertNotEqual(response['Location'], '%s%s' % (self.base_url, self.show_normal_url))
def send(self, url, parsed_instance): """ Sends the submission to the configured rest service :param url: :param parsed_instance: :return: """ extra_data = self.clean_keys_of_slashes(parsed_instance.instance.json) meta = MetaData.textit(parsed_instance.instance.xform) token, flow_uuid, contacts = meta.data_value.split(METADATA_SEPARATOR) post_data = { "extra": extra_data, "flow_uuid": flow_uuid, "contacts": contacts } headers = { "Content-Type": "application/json", "Authorization": "Token {}".format(token) } http = httplib2.Http() resp, content = http.request(uri=url, method='POST', headers=headers, body=json.dumps(post_data))
def test_public_with_link_to_share_toggle_on(self): # sharing behavior as of 09/13/2012: # it requires both data_share and form_share both turned on # in order to grant anon access to form uploading # TODO: findout 'for_user': '******' and what it means response = self.client.post(self.perm_url, { 'for_user': '******', 'perm_type': 'link' }) self.assertEqual(response.status_code, 302) self.assertEqual(MetaData.public_link(self.xform), True) # toggle shared on self.xform.shared = True self.xform.shared_data = True self.xform.save() response = self.anon.get(self.show_url) self.assertEqual(response.status_code, 302) if not self._running_enketo(): raise SkipTest with HTTMock(enketo_mock): factory = RequestFactory() request = factory.get('/') request.user = AnonymousUser() response = enter_data(request, self.user.username, self.xform.id_string) self.assertEqual(response.status_code, 302)
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
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
def test_public_with_link_to_share_toggle_on(self): # sharing behavior as of 09/13/2012: # it requires both data_share and form_share both turned on # in order to grant anon access to form uploading # TODO: findout 'for_user': '******' and what it means response = self.client.post( self.perm_url, {"for_user": "******", "perm_type": "link"} ) self.assertEqual(response.status_code, 302) self.assertEqual(MetaData.public_link(self.xform), True) # toggle shared on self.xform.shared = True self.xform.shared_data = True self.xform.save() response = self.anon.get(self.show_url) self.assertEqual(response.status_code, 302) if not self._running_enketo(): raise SkipTest with HTTMock(enketo_mock): factory = RequestFactory() request = factory.get("/") request.user = AnonymousUser() response = enter_data( request, self.user.username, self.xform.id_string ) self.assertEqual(response.status_code, 302)
def test_public_with_link_to_share(self): response = self.client.post(self.perm_url, { 'for_user': '******', 'perm_type': 'link'}) self.assertEqual(response.status_code, 302) self.assertEqual(MetaData.public_link(self.xform), True) response = self.anon.get(self.show_url) self.assertRedirects(response, self.show_normal_url)
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
def show(request, username=None, id_string=None, uuid=None): if uuid: xform = get_object_or_404(XForm, uuid=uuid) request.session["public_link"] = xform.uuid if MetaData.public_link(xform) else False return HttpResponseRedirect( reverse(show, kwargs={"username": xform.user.username, "id_string": xform.id_string}) ) xform, is_owner, can_edit, can_view = get_xform_and_perms(username, id_string, request) # no access if not (xform.shared or can_view or request.session.get("public_link")): return HttpResponseRedirect(reverse(home)) context = RequestContext(request) context.cloned = ( len(XForm.objects.filter(user__username=request.user.username, id_string=id_string + XForm.CLONED_SUFFIX)) > 0 ) context.public_link = MetaData.public_link(xform) context.is_owner = is_owner context.can_edit = can_edit context.can_view = can_view or request.session.get("public_link") context.xform = xform context.content_user = xform.user context.base_url = "https://%s" % request.get_host() context.source = MetaData.source(xform) context.form_license = MetaData.form_license(xform).data_value context.data_license = MetaData.data_license(xform).data_value context.supporting_docs = MetaData.supporting_docs(xform) context.media_upload = MetaData.media_upload(xform) context.mapbox_layer = MetaData.mapbox_layer_upload(xform) if is_owner: context.sms_support_form = ActivateSMSSupportFom( initial={"enable_sms_support": xform.allows_sms, "sms_id_string": xform.sms_id_string} ) if not xform.allows_sms: context.sms_compatible = check_form_sms_compatibility(None, json_survey=json.loads(xform.json)) else: url_root = request.build_absolute_uri("/")[:-1] context.sms_providers_doc = providers_doc(url_root=url_root, username=username, id_string=id_string) context.url_root = url_root context.form_license_form = FormLicenseForm(initial={"value": context.form_license}) context.data_license_form = DataLicenseForm(initial={"value": context.data_license}) context.doc_form = SupportDocForm() context.source_form = SourceForm() context.media_form = MediaForm() context.mapbox_layer_form = MapboxLayerForm() users_with_perms = [] for perm in get_users_with_perms(xform, attach_perms=True).items(): has_perm = [] if "change_xform" in perm[1]: has_perm.append(_(u"Can Edit")) if "view_xform" in perm[1]: has_perm.append(_(u"Can View")) users_with_perms.append((perm[0], u" | ".join(has_perm))) context.users_with_perms = users_with_perms context.permission_form = PermissionForm(username) if xform.allows_sms: context.sms_support_doc = get_autodoc_for(xform) return render_to_response("show.html", context_instance=context)
def create(self, validated_data): data_type = validated_data.get('data_type') data_file = validated_data.get('data_file') data_file_type = validated_data.get('data_file_type') content_object = self.get_content_object(validated_data) data_value = data_file.name \ if data_file else validated_data.get('data_value') # not exactly sure what changed in the requests.FILES for django 1.7 # csv files uploaded in windows do not have the text/csv content_type # this works around that if data_type == MEDIA_TYPE and data_file \ and data_file.name.lower().endswith('.csv') \ and data_file_type != CSV_CONTENT_TYPE: data_file_type = CSV_CONTENT_TYPE content_type = ContentType.objects.get_for_model(content_object) try: if data_type == XFORM_META_PERMS: metadata = \ MetaData.xform_meta_permission(content_object, data_value=data_value) update_role_by_meta_xform_perms(content_object) elif data_type == SUBMISSION_REVIEW: # ensure only one submission_review metadata exists per form if MetaData.submission_review(content_object): raise serializers.ValidationError(_(UNIQUE_TOGETHER_ERROR)) else: metadata = MetaData.submission_review( content_object, data_value=data_value) else: metadata = MetaData.objects.create( content_type=content_type, data_type=data_type, data_value=data_value, data_file=data_file, data_file_type=data_file_type, object_id=content_object.id) return metadata except IntegrityError: raise serializers.ValidationError(_(UNIQUE_TOGETHER_ERROR))
def test_windows_csv_file_upload(self): count = MetaData.objects.filter(data_type='media').count() media_file = os.path.join( self.this_directory, 'fixtures', 'transportation', 'transportation.csv') f = InMemoryUploadedFile(open(media_file), 'media', 'transportation.csv', 'application/octet-stream', 2625, None) MetaData.media_upload(self.xform, f) media_list = MetaData.objects.filter(data_type='media') new_count = media_list.count() self.assertEqual(count + 1, new_count) media = media_list.get(data_value='transportation.csv') self.assertEqual(media.data_file_type, 'text/csv')
def redirect_to_public_link(request, uuid): xform = get_object_or_404(XForm, uuid=uuid) request.session['public_link'] = \ xform.uuid if MetaData.public_link(xform) else False return HttpResponseRedirect(reverse(show, kwargs={ 'username': xform.user.username, 'id_string': xform.id_string }))
def create_export(request, username, id_string, export_type): owner = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, id_string__exact=id_string, user=owner) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) if export_type == Export.EXTERNAL_EXPORT: # check for template before trying to generate a report if not MetaData.external_export(xform=xform): return HttpResponseForbidden(_(u'No XLS Template set.')) query = request.POST.get("query") force_xlsx = request.POST.get('xls') != 'true' # export options group_delimiter = request.POST.get("options[group_delimiter]", '/') if group_delimiter not in ['.', '/']: return HttpResponseBadRequest( _("%s is not a valid delimiter" % group_delimiter)) # default is True, so when dont_.. is yes # split_select_multiples becomes False split_select_multiples = request.POST.get( "options[dont_split_select_multiples]", "no") == "no" binary_select_multiples = getattr(settings, 'BINARY_SELECT_MULTIPLES', False) # external export option meta = request.POST.get("meta") options = { 'group_delimiter': group_delimiter, 'split_select_multiples': split_select_multiples, 'binary_select_multiples': binary_select_multiples, 'meta': meta.replace(",", "") if meta else None } try: create_async_export(xform, export_type, query, force_xlsx, options) except Export.ExportTypeError: return HttpResponseBadRequest( _("%s is not a valid export type" % export_type)) else: audit = {"xform": xform.id_string, "export_type": export_type} audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created %(export_type)s export on '%(id_string)s'.") % { 'export_type': export_type.upper(), 'id_string': xform.id_string, }, audit, request) return HttpResponseRedirect( reverse(export_list, kwargs={ "username": username, "id_string": id_string, "export_type": export_type }))
def setUp(self): TestBase.setUp(self) self._publish_transportation_form() self._submit_transport_instance_w_attachment() src = os.path.join(self.this_directory, "fixtures", "transportation", "screenshot.png") uf = UploadedFile(file=open(src, 'rb'), content_type='image/png') count = MetaData.objects.count() MetaData.media_upload(self.xform, uf) self.assertEqual(MetaData.objects.count(), count + 1) url = urljoin( self.base_url, reverse(profile, kwargs={'username': self.user.username})) self._logout() self._create_user_and_login('deno', 'deno') self.bc = BriefcaseClient(username='******', password='******', url=url, user=self.user)
def edit(request, username, id_string): xform = XForm.objects.get(user__username__iexact=username, id_string__exact=id_string) owner = xform.user if username == request.user.username or\ request.user.has_perm('logger.change_xform', xform): if request.POST.get('media_url'): uri = request.POST.get('media_url') try: SSRFProtect.validate(uri) except SSRFProtectException: return HttpResponseForbidden( t('URL {uri} is forbidden.').format(uri=uri)) MetaData.media_add_uri(xform, uri) elif request.FILES.get('media'): audit = {'xform': xform.id_string} audit_log( Actions.FORM_UPDATED, request.user, owner, t("Media added to '%(id_string)s'.") % {'id_string': xform.id_string}, audit, request) for aFile in request.FILES.getlist("media"): MetaData.media_upload(xform, aFile) xform.update() if request.is_ajax(): return HttpResponse(t('Updated succeeded.')) else: if 'HTTP_REFERER' in request.META and request.META[ 'HTTP_REFERER'].strip(): return HttpResponseRedirect(request.META['HTTP_REFERER']) return HttpResponseRedirect( reverse(show, kwargs={ 'username': username, 'id_string': id_string })) return HttpResponseForbidden(t('Update failed.'))
def test_public_with_link_to_share_toggle_on(self): response = self.client.post(self.perm_url, {'for_user': '******', 'perm_type': 'link'}) self.assertEqual(response.status_code, 302) self.assertEqual(MetaData.public_link(self.xform), True) response = self.anon.get(self.show_url) self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], '%s%s' % (self.base_url, self.show_normal_url)) response = self.anon.get(self.show_normal_url) self.assertEqual(response.status_code, 200)
def auto_add_crowd_form_to_registered_user(sender, **kwargs): new_user = kwargs.get("user") if ( hasattr(settings, "AUTO_ADD_CROWDFORM") and settings.AUTO_ADD_CROWDFORM and hasattr(settings, "DEFAULT_CROWDFORM") ): try: default_crowdform = settings.DEFAULT_CROWDFORM if ( isinstance(default_crowdform, dict) and "xform_username" in default_crowdform and "xform_id_string" in default_crowdform ): xform = XForm.objects.get( id_string=default_crowdform["xform_id_string"], user__username=default_crowdform["xform_username"] ) MetaData.crowdform_users(xform, new_user.username) except XForm.DoesNotExist: pass
def export_list(request, username, id_string, export_type): if export_type == Export.GDOC_EXPORT: redirect_url = reverse( export_list, kwargs={ 'username': username, 'id_string': id_string, 'export_type': export_type}) token = _get_google_token(request, redirect_url) if isinstance(token, HttpResponse): return token owner = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, id_string__exact=id_string, user=owner) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) if export_type == Export.EXTERNAL_EXPORT: # check for template before trying to generate a report if not MetaData.external_export(xform=xform): return HttpResponseForbidden(_(u'No XLS Template set.')) # Get meta and token export_token = request.GET.get('token') export_meta = request.GET.get('meta') options = { 'meta': export_meta, 'token': export_token, } if should_create_new_export(xform, export_type): try: create_async_export( xform, export_type, query=None, force_xlsx=True, options=options) except Export.ExportTypeError: return HttpResponseBadRequest( _("%s is not a valid export type" % export_type)) metadata = MetaData.objects.filter(xform=xform, data_type="external_export")\ .values('id', 'data_value') for m in metadata: m['data_value'] = m.get('data_value').split('|')[0] data = { 'username': owner.username, 'xform': xform, 'export_type': export_type, 'export_type_name': Export.EXPORT_TYPE_DICT[export_type], 'exports': Export.objects.filter( xform=xform, export_type=export_type).order_by('-created_on'), 'metas': metadata } return render(request, 'export_list.html', data)
def setUp(self): TestBase.setUp(self) self._publish_transportation_form() self._submit_transport_instance_w_attachment() src = os.path.join(self.this_directory, "fixtures", "transportation", "screenshot.png") uf = UploadedFile(file=open(src), content_type='image/png') count = MetaData.objects.count() MetaData.media_upload(self.xform, uf) self.assertEqual(MetaData.objects.count(), count + 1) url = urljoin( self.base_url, reverse(profile, kwargs={'username': self.user.username}) ) self._logout() self._create_user_and_login('deno', 'deno') self.bc = BriefcaseClient( username='******', password='******', url=url, user=self.user )
def test_crowdform_for_new_user(self): # initial meta = MetaData.crowdform_users(self.xform) self.assertEqual(len(meta), 0) #save settings to be restored later old_auto_add_cf = settings.AUTO_ADD_CROWDFORM old_default_cf = settings.DEFAULT_CROWDFORM # enable auto add crowdform settings.AUTO_ADD_CROWDFORM = True settings.DEFAULT_CROWDFORM = { 'xform_username': self.user.username, 'xform_id_string': self.xform.id_string } # register new user post_data = { 'username': self.alice, 'email': '*****@*****.**', 'password1': 'bobbob', 'password2': 'bobbob', 'name': 'Alice', 'city': 'Ecila', 'country': 'US', 'organization': 'Alic Inc.', 'home_page': 'alice.com', 'twitter': 'alicerama' } url = '/accounts/register/' self.response = self.client.post(url, post_data) # check to ensure that crowd form was added meta = MetaData.crowdform_users(self.xform) self.assertEqual(len(meta), 1) self.assertEqual(meta[0].data_value, self.alice) # restore old settings settings.AUTO_ADD_CROWDFORM = old_auto_add_cf settings.DEFAULT_CROWDFORM = old_default_cf
def map_view(request, username, id_string, template='map.html'): """ Map view. """ owner = get_object_or_404(User, username__iexact=username) xform = get_form({'user': owner, 'id_string__iexact': id_string}) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) data = {'content_user': owner, 'xform': xform} data['profile'], __ = UserProfile.objects.get_or_create(user=owner) data['form_view'] = True data['jsonform_url'] = reverse(download_jsonform, kwargs={ "username": username, "id_string": id_string }) data['enketo_edit_url'] = reverse('edit_data', kwargs={ "username": username, "id_string": id_string, "data_id": 0 }) data['enketo_add_url'] = reverse('enter_data', kwargs={ "username": username, "id_string": id_string }) data['enketo_add_with_url'] = reverse('add_submission_with', kwargs={ "username": username, "id_string": id_string }) data['mongo_api_url'] = reverse('mongo_view_api', kwargs={ "username": username, "id_string": id_string }) data['delete_data_url'] = reverse('delete_data', kwargs={ "username": username, "id_string": id_string }) data['mapbox_layer'] = MetaData.mapbox_layer_upload(xform) audit = {"xform": xform.id_string} audit_log( Actions.FORM_MAP_VIEWED, request.user, owner, _("Requested map on '%(id_string)s'.") % {'id_string': xform.id_string}, audit, request) return render(request, template, data)
def test_public_with_link_to_share_toggle_on(self): response = self.client.post(self.perm_url, { 'for_user': '******', 'perm_type': 'link' }) self.assertEqual(response.status_code, 302) self.assertEqual(MetaData.public_link(self.xform), True) response = self.anon.get(self.show_url) self.assertEqual(response.status_code, 302) self.assertEqual(response['Location'], '%s%s' % (self.base_url, self.show_normal_url)) response = self.anon.get(self.show_normal_url) self.assertEqual(response.status_code, 200)
def test_textit_service(self, mock_http): service_url = "https://textit.io/api/v1/runs.json" service_name = "textit" self._add_rest_service(service_url, service_name) # add metadata api_token = "asdaasda" flow_uuid = "getvdgdfd" default_contact = "sadlsdfskjdfds" MetaData.textit(self.xform, data_value="{}|{}|{}".format(api_token, flow_uuid, default_contact)) xml_submission = os.path.join(self.this_directory, u'fixtures', u'dhisform_submission1.xml') self.assertFalse(mock_http.called) self._make_submission(xml_submission) self.assertTrue(mock_http.called) self.assertEquals(mock_http.call_count, 1)
def test_crowdform_for_new_user(self): # initial meta = MetaData.crowdform_users(self.xform) self.assertEqual(len(meta), 0) #save settings to be restored later old_auto_add_cf = settings.AUTO_ADD_CROWDFORM old_default_cf = settings.DEFAULT_CROWDFORM # enable auto add crowdform settings.AUTO_ADD_CROWDFORM = True settings.DEFAULT_CROWDFORM = { 'xform_username': self.user.username, 'xform_id_string': self.xform.id_string} # register new user post_data = { 'username': self.alice, 'email': '*****@*****.**', 'password1': 'bobbob', 'password2': 'bobbob', 'name': 'Alice', 'city': 'Ecila', 'country': 'US', 'organization': 'Alic Inc.', 'home_page': 'alice.com', 'twitter': 'alicerama' } url = '/accounts/register/' self.response = self.client.post(url, post_data) # check to ensure that crowd form was added meta = MetaData.crowdform_users(self.xform) self.assertEqual(len(meta), 1) self.assertEqual(meta[0].data_value, self.alice) # restore old settings settings.AUTO_ADD_CROWDFORM = old_auto_add_cf settings.DEFAULT_CROWDFORM = old_default_cf
def show_form_settings(request, username=None, id_string=None, uuid=None): if uuid: return redirect_to_public_link(request, uuid) xform, is_owner, can_edit, can_view, can_delete_data = get_xform_and_perms( username, id_string, request) # no access if not (xform.shared or can_view or request.session.get('public_link')): return HttpResponseRedirect(reverse(home)) data = {} data['cloned'] = len( XForm.objects.filter( user__username__iexact=request.user.username, id_string__exact=id_string + XForm.CLONED_SUFFIX)) > 0 data['public_link'] = MetaData.public_link(xform) data['is_owner'] = is_owner data['can_edit'] = can_edit data['can_view'] = can_view or request.session.get('public_link') data['can_delete_data'] = can_delete_data data['xform'] = xform data['content_user'] = xform.user data['base_url'] = "https://%s" % request.get_host() data['source'] = MetaData.source(xform) data['media_upload'] = MetaData.media_upload(xform) # https://html.spec.whatwg.org/multipage/input.html#attr-input-accept # e.g. .csv,.xml,text/csv,text/xml media_upload_types = [] for supported_type in settings.SUPPORTED_MEDIA_UPLOAD_TYPES: extension = '.{}'.format(supported_type.split('/')[-1]) media_upload_types.append(extension) media_upload_types.append(supported_type) data['media_upload_types'] = ','.join(media_upload_types) if is_owner: data['media_form'] = MediaForm() return render(request, "show_form_settings.html", data)
def test_only_access_shared_link_form(self): response = self.client.post(self.perm_url, {'for_user': '******', 'perm_type': 'link'}) self.assertEqual(MetaData.public_link(self.xform), True) # publish a second form to make sure the user cant access other forms self._publish_xls_file(os.path.join( self.this_directory, "fixtures", "csv_export", "tutorial.xls")) xform_2 = XForm.objects.order_by('pk').reverse()[0] url_2 = reverse(show, kwargs={ 'username': self.user.username, 'id_string': xform_2.id_string }) response = self.anon.get(url_2) self.assertRedirects(response, "/")
def map_view(request, username, id_string, template='map.html'): owner = get_object_or_404(User, username=username) xform = get_object_or_404(XForm, id_string=id_string, user=owner) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) context = RequestContext(request) context.content_user = owner context.xform = xform context.profile, created = UserProfile.objects.get_or_create(user=owner) context.form_view = True context.jsonform_url = reverse(download_jsonform, kwargs={ "username": username, "id_string": id_string }) context.enketo_edit_url = reverse('edit_data', kwargs={ "username": username, "id_string": id_string, "data_id": 0 }) context.enketo_add_url = reverse('enter_data', kwargs={ "username": username, "id_string": id_string }) context.enketo_add_with_url = reverse('add_submission_with', kwargs={ "username": username, "id_string": id_string }) context.mongo_api_url = reverse('mongo_view_api', kwargs={ "username": username, "id_string": id_string }) context.delete_data_url = reverse('delete_data', kwargs={ "username": username, "id_string": id_string }) context.mapbox_layer = MetaData.mapbox_layer_upload(xform) audit = {"xform": xform.id_string} audit_log( Actions.FORM_MAP_VIEWED, request.user, owner, _("Requested map on '%(id_string)s'.") % {'id_string': xform.id_string}, audit, request) return render_to_response(template, context_instance=context)
def test_textit_service(self, mock_http): service_url = "https://textit.io/api/v1/runs.json" service_name = "textit" self._add_rest_service(service_url, service_name) # add metadata api_token = "asdaasda" flow_uuid = "getvdgdfd" default_contact = "sadlsdfskjdfds" MetaData.textit( self.xform, data_value="{}|{}|{}".format(api_token, flow_uuid, default_contact)) xml_submission = os.path.join(self.this_directory, u'fixtures', u'dhisform_submission1.xml') self.assertFalse(mock_http.called) self._make_submission(xml_submission) self.assertTrue(mock_http.called) self.assertEquals(mock_http.call_count, 1)
def export_list(request, username, id_string, export_type, is_project=0, id=0, site_id=0, version="0"): site_id = int(site_id) if export_type == Export.GDOC_EXPORT: return HttpResponseForbidden(_(u'Not shared.')) token = _get_google_token(request, redirect_url) if isinstance(token, HttpResponse): return token owner = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, id_string__exact=id_string, user=owner) if export_type == Export.EXTERNAL_EXPORT: return HttpResponseForbidden(_(u'Not shared.')) # check for template before trying to generate a report if not MetaData.external_export(xform=xform): return HttpResponseForbidden(_(u'No XLS Template set.')) # Get meta and token export_token = request.GET.get('token') export_meta = request.GET.get('meta') options = { 'meta': export_meta, 'token': export_token, } metadata = MetaData.objects.filter(xform=xform, data_type="external_export")\ .values('id', 'data_value') for m in metadata: m['data_value'] = m.get('data_value').split('|')[0] data = { 'username': xform.user.username, 'xform': xform, 'export_type': export_type, 'export_type_name': Export.EXPORT_TYPE_DICT[export_type], 'exports': Export.objects.filter( xform=xform, export_type=export_type, fsxf=id, site=site_id, version=version).order_by('-created_on'), 'metas': metadata, 'is_project': is_project, 'id': id, 'version': version, } data['site_id'] = site_id return render(request, 'export_list.html', data)
def map_view(request, username, id_string, template='map.html'): """ Map view. """ owner = get_object_or_404(User, username__iexact=username) xform = get_form({'user': owner, 'id_string__iexact': id_string}) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) data = {'content_user': owner, 'xform': xform} data['profile'], __ = UserProfile.objects.get_or_create(user=owner) data['form_view'] = True data['jsonform_url'] = reverse( download_jsonform, kwargs={"username": username, "id_string": id_string}) data['enketo_edit_url'] = reverse( 'edit_data', kwargs={"username": username, "id_string": id_string, "data_id": 0}) data['enketo_add_url'] = reverse( 'enter_data', kwargs={"username": username, "id_string": id_string}) data['enketo_add_with_url'] = reverse( 'add_submission_with', kwargs={"username": username, "id_string": id_string}) data['mongo_api_url'] = reverse( 'mongo_view_api', kwargs={"username": username, "id_string": id_string}) data['delete_data_url'] = reverse( 'delete_data', kwargs={"username": username, "id_string": id_string}) data['mapbox_layer'] = MetaData.mapbox_layer_upload(xform) audit = {"xform": xform.id_string} audit_log(Actions.FORM_MAP_VIEWED, request.user, owner, _("Requested map on '%(id_string)s'.") % {'id_string': xform.id_string}, audit, request) return render(request, template, data)
def xformsManifest(request, username, id_string): xform = get_object_or_404( XForm, id_string=id_string, user__username=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_to_response("xformsManifest.xml", { 'host': request.build_absolute_uri().replace( request.get_full_path(), ''), 'media_files': MetaData.media_upload(xform, download=True) }, 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
def send(self, url, submission_instance): """ Sends the submission to the configured rest service :param url: :param submission_instance: :return: """ extra_data = self.clean_keys_of_slashes(submission_instance.json) data_value = MetaData.textit(submission_instance.xform) if data_value: token, flow, contacts = data_value.split(METADATA_SEPARATOR) post_data = { "extra": extra_data, "flow": flow, "contacts": contacts.split(',') } headers = {"Content-Type": "application/json", "Authorization": "Token {}".format(token)} requests.post(url, headers=headers, data=json.dumps(post_data))
def map_view(request, username, id_string, template='map.html'): owner = get_object_or_404(User, username=username) xform = get_object_or_404(XForm, id_string=id_string, user=owner) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) context = RequestContext(request) context.content_user = owner context.xform = xform context.profile, created = UserProfile.objects.get_or_create(user=owner) context.form_view = True context.jsonform_url = reverse(download_jsonform, kwargs={"username": username, "id_string": id_string}) context.enketo_edit_url = reverse('edit_data', kwargs={"username": username, "id_string": id_string, "data_id": 0}) context.enketo_add_url = reverse('enter_data', kwargs={"username": username, "id_string": id_string}) context.enketo_add_with_url = reverse('add_submission_with', kwargs={"username": username, "id_string": id_string}) context.mongo_api_url = reverse('mongo_view_api', kwargs={"username": username, "id_string": id_string}) context.delete_data_url = reverse('delete_data', kwargs={"username": username, "id_string": id_string}) context.mapbox_layer = MetaData.mapbox_layer_upload(xform) audit = { "xform": xform.id_string } audit_log(Actions.FORM_MAP_VIEWED, request.user, owner, _("Requested map on '%(id_string)s'.") % {'id_string': xform.id_string}, audit, request) return render_to_response(template, context_instance=context)
def send(self, url, parsed_instance): """ Sends the submission to the configured rest service :param url: :param parsed_instance: :return: """ extra_data = self.clean_keys_of_slashes(parsed_instance.instance.json) meta = MetaData.textit(parsed_instance.instance.xform) token, flow_uuid, contacts = meta.data_value.split(METADATA_SEPARATOR) post_data = { "extra": extra_data, "flow_uuid": flow_uuid, "contacts": contacts } headers = {"Content-Type": "application/json", "Authorization": "Token {}".format(token)} http = httplib2.Http() resp, content = http.request(uri=url, method='POST', headers=headers, body=json.dumps(post_data))
def show(request, username=None, id_string=None, uuid=None): if uuid: return redirect_to_public_link(request, uuid) xform, is_owner, can_edit, can_view = get_xform_and_perms( username, id_string, request) # no access if not (xform.shared or can_view or request.session.get('public_link')): return HttpResponseRedirect(reverse(home)) context = RequestContext(request) context.cloned = len( XForm.objects.filter(user__username=request.user.username, id_string=id_string + XForm.CLONED_SUFFIX) ) > 0 context.public_link = MetaData.public_link(xform) context.is_owner = is_owner context.can_edit = can_edit context.can_view = can_view or request.session.get('public_link') context.xform = xform context.content_user = xform.user context.base_url = "https://%s" % request.get_host() context.source = MetaData.source(xform) context.form_license = MetaData.form_license(xform).data_value context.data_license = MetaData.data_license(xform).data_value context.supporting_docs = MetaData.supporting_docs(xform) context.media_upload = MetaData.media_upload(xform) context.mapbox_layer = MetaData.mapbox_layer_upload(xform) if is_owner: set_xform_owner_context(context, xform, request, username, id_string) if xform.allows_sms: context.sms_support_doc = get_autodoc_for(xform) return render_to_response("show.html", context_instance=context)
def show(request, username=None, id_string=None, uuid=None): if uuid: return redirect_to_public_link(request, uuid) xform, is_owner, can_edit, can_view = get_xform_and_perms( username, id_string, request) # no access if not (xform.shared or can_view or request.session.get('public_link')): return HttpResponseRedirect(reverse(home)) data = {} data['cloned'] = len( XForm.objects.filter(user__username__iexact=request.user.username, id_string__iexact=id_string + XForm.CLONED_SUFFIX) ) > 0 data['public_link'] = MetaData.public_link(xform) data['is_owner'] = is_owner data['can_edit'] = can_edit data['can_view'] = can_view or request.session.get('public_link') data['xform'] = xform data['content_user'] = xform.user data['base_url'] = "https://%s" % request.get_host() data['source'] = MetaData.source(xform) data['form_license'] = MetaData.form_license(xform).data_value data['data_license'] = MetaData.data_license(xform).data_value data['supporting_docs'] = MetaData.supporting_docs(xform) data['media_upload'] = MetaData.media_upload(xform) data['mapbox_layer'] = MetaData.mapbox_layer_upload(xform) if is_owner: set_xform_owner_data(data, xform, request, username, id_string) if xform.allows_sms: data['sms_support_doc'] = get_autodoc_for(xform) return render(request, "show.html", data)
def test_upload_source_file_set_value_to_name(self): name = self._add_metadata('source') self.assertEqual(MetaData.source(self.xform).data_value, name)
def set_perm(request, username, id_string): xform = get_object_or_404(XForm, user__username=username, id_string=id_string) owner = xform.user if username != request.user.username\ and not has_permission(xform, username, request): return HttpResponseForbidden(_(u'Permission denied.')) try: perm_type = request.POST['perm_type'] for_user = request.POST['for_user'] except KeyError: return HttpResponseBadRequest() if perm_type in ['edit', 'view', 'report', 'remove']: try: user = User.objects.get(username=for_user) except User.DoesNotExist: messages.add_message( request, messages.INFO, _(u"Wrong username <b>%s</b>." % for_user), extra_tags='alert-error') else: if perm_type == 'edit' and\ not user.has_perm('change_xform', xform): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_PERMISSIONS_UPDATED, request.user, owner, _("Edit permissions on '%(id_string)s' assigned to " "'%(for_user)s'.") % { 'id_string': xform.id_string, 'for_user': for_user }, audit, request) assign_perm('change_xform', user, xform) elif perm_type == 'view' and\ not user.has_perm('view_xform', xform): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_PERMISSIONS_UPDATED, request.user, owner, _("View permissions on '%(id_string)s' " "assigned to '%(for_user)s'.") % { 'id_string': xform.id_string, 'for_user': for_user }, audit, request) assign_perm('view_xform', user, xform) elif perm_type == 'report' and\ not user.has_perm('report_xform', xform): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_PERMISSIONS_UPDATED, request.user, owner, _("Report permissions on '%(id_string)s' " "assigned to '%(for_user)s'.") % { 'id_string': xform.id_string, 'for_user': for_user }, audit, request) assign_perm('report_xform', user, xform) elif perm_type == 'remove': audit = { 'xform': xform.id_string } audit_log( Actions.FORM_PERMISSIONS_UPDATED, request.user, owner, _("All permissions on '%(id_string)s' " "removed from '%(for_user)s'.") % { 'id_string': xform.id_string, 'for_user': for_user }, audit, request) remove_perm('change_xform', user, xform) remove_perm('view_xform', user, xform) elif perm_type == 'link': current = MetaData.public_link(xform) if for_user == 'all': MetaData.public_link(xform, True) elif for_user == 'none': MetaData.public_link(xform, False) elif for_user == 'toggle': MetaData.public_link(xform, not current) audit = { 'xform': xform.id_string } audit_log( Actions.FORM_PERMISSIONS_UPDATED, request.user, owner, _("Public link on '%(id_string)s' %(action)s.") % { 'id_string': xform.id_string, 'action': "created" if for_user == "all" or (for_user == "toggle" and not current) else "removed" }, audit, request) if request.is_ajax(): return HttpResponse( json.dumps( {'status': 'success'}), mimetype='application/json') return HttpResponseRedirect(reverse(show, kwargs={ 'username': username, 'id_string': id_string }))
def edit(request, username, id_string): xform = XForm.objects.get(user__username=username, id_string=id_string) owner = xform.user if username == request.user.username or\ request.user.has_perm('logger.change_xform', xform): if request.POST.get('description'): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Description for '%(id_string)s' updated from " "'%(old_description)s' to '%(new_description)s'.") % { 'id_string': xform.id_string, 'old_description': xform.description, 'new_description': request.POST['description'] }, audit, request) xform.description = request.POST['description'] elif request.POST.get('title'): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Title for '%(id_string)s' updated from " "'%(old_title)s' to '%(new_title)s'.") % { 'id_string': xform.id_string, 'old_title': xform.title, 'new_title': request.POST.get('title') }, audit, request) xform.title = request.POST['title'] elif request.POST.get('toggle_shared'): if request.POST['toggle_shared'] == 'data': audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Data sharing updated for '%(id_string)s' from " "'%(old_shared)s' to '%(new_shared)s'.") % { 'id_string': xform.id_string, 'old_shared': _("shared") if xform.shared_data else _("not shared"), 'new_shared': _("shared") if not xform.shared_data else _("not shared") }, audit, request) xform.shared_data = not xform.shared_data elif request.POST['toggle_shared'] == 'form': audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Form sharing for '%(id_string)s' updated " "from '%(old_shared)s' to '%(new_shared)s'.") % { 'id_string': xform.id_string, 'old_shared': _("shared") if xform.shared else _("not shared"), 'new_shared': _("shared") if not xform.shared else _("not shared") }, audit, request) xform.shared = not xform.shared elif request.POST['toggle_shared'] == 'active': audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Active status for '%(id_string)s' updated from " "'%(old_shared)s' to '%(new_shared)s'.") % { 'id_string': xform.id_string, 'old_shared': _("shared") if xform.downloadable else _("not shared"), 'new_shared': _("shared") if not xform.downloadable else _("not shared") }, audit, request) xform.downloadable = not xform.downloadable elif request.POST.get('form-license'): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Form License for '%(id_string)s' updated to " "'%(form_license)s'.") % { 'id_string': xform.id_string, 'form_license': request.POST['form-license'], }, audit, request) MetaData.form_license(xform, request.POST['form-license']) elif request.POST.get('data-license'): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Data license for '%(id_string)s' updated to " "'%(data_license)s'.") % { 'id_string': xform.id_string, 'data_license': request.POST['data-license'], }, audit, request) MetaData.data_license(xform, request.POST['data-license']) elif request.POST.get('source') or request.FILES.get('source'): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Source for '%(id_string)s' updated to '%(source)s'.") % { 'id_string': xform.id_string, 'source': request.POST.get('source'), }, audit, request) MetaData.source(xform, request.POST.get('source'), request.FILES.get('source')) elif request.POST.get('enable_sms_support_trigger') is not None: sms_support_form = ActivateSMSSupportFom(request.POST) if sms_support_form.is_valid(): audit = { 'xform': xform.id_string } enabled = \ sms_support_form.cleaned_data.get('enable_sms_support') if enabled: audit_action = Actions.SMS_SUPPORT_ACTIVATED audit_message = _(u"SMS Support Activated on") else: audit_action = Actions.SMS_SUPPORT_DEACTIVATED audit_message = _(u"SMS Support Deactivated on") audit_log( audit_action, request.user, owner, audit_message % {'id_string': xform.id_string}, audit, request) # stored previous states to be able to rollback form status # in case we can't save. pe = xform.allows_sms pid = xform.sms_id_string xform.allows_sms = enabled xform.sms_id_string = \ sms_support_form.cleaned_data.get('sms_id_string') compat = check_form_sms_compatibility(None, json.loads(xform.json)) if compat['type'] == 'alert-error': xform.allows_sms = False xform.sms_id_string = pid try: xform.save() except IntegrityError: # unfortunately, there's no feedback mechanism here xform.allows_sms = pe xform.sms_id_string = pid elif request.POST.get('media_url'): uri = request.POST.get('media_url') MetaData.media_add_uri(xform, uri) elif request.FILES.get('media'): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Media added to '%(id_string)s'.") % { 'id_string': xform.id_string }, audit, request) for aFile in request.FILES.getlist("media"): MetaData.media_upload(xform, aFile) elif request.POST.get('map_name'): mapbox_layer = MapboxLayerForm(request.POST) if mapbox_layer.is_valid(): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Map layer added to '%(id_string)s'.") % { 'id_string': xform.id_string }, audit, request) MetaData.mapbox_layer_upload(xform, mapbox_layer.cleaned_data) elif request.FILES: audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Supporting document added to '%(id_string)s'.") % { 'id_string': xform.id_string }, audit, request) MetaData.supporting_docs(xform, request.FILES['doc']) xform.update() if request.is_ajax(): return HttpResponse(_(u'Updated succeeded.')) else: return HttpResponseRedirect(reverse(show, kwargs={ 'username': username, 'id_string': id_string })) return HttpResponseForbidden(_(u'Update failed.'))