def publish_xlsform(request, user, existing_xform=None): ''' If `existing_xform` is specified, that form will be overwritten with the new XLSForm ''' if not request.user.has_perm( 'can_add_xform', UserProfile.objects.get_or_create(user=user)[0] ): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % {'user': request.user.username, 'account': user.username})) if existing_xform and not request.user.has_perm( 'change_xform', existing_xform): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to change this " "form." % {'user': request.user.username, }) ) def set_form(): form = QuickConverter(request.POST, request.FILES) if existing_xform: return form.publish(user, existing_xform.id_string) else: return form.publish(user) return publish_form(set_form)
def update_xform(request, username, id_string): xform = get_object_or_404(XForm, user__username=username, id_string=id_string) owner = xform.user def set_form(): form = QuickConverter(request.POST, request.FILES) survey = form.publish(request.user, id_string).survey enketo_webform_url = reverse(enter_data, kwargs={"username": username, "id_string": survey.id_string}) audit = {"xform": xform.id_string} audit_log( Actions.FORM_XLS_UPDATED, request.user, owner, _("XLS for '%(id_string)s' updated.") % {"id_string": xform.id_string}, audit, request, ) return { "type": "alert-success", "text": _( u"Successfully published %(form_id)s." u' <a href="%(form_url)s">Enter Web Form</a>' u' or <a href="#preview-modal" data-toggle="modal">' u"Preview Web Form</a>" ) % {"form_id": survey.id_string, "form_url": enketo_webform_url}, } message = publish_form(set_form) messages.add_message(request, messages.INFO, message["text"], extra_tags=message["type"]) return HttpResponseRedirect(reverse(show, kwargs={"username": username, "id_string": id_string}))
def do_publish_xlsform(user, post, files, owner, id_string=None, project=None): if id_string and project: xform = get_object_or_404(XForm, user=owner, id_string=id_string, project=project) if not ManagerRole.user_has_role(user, xform): raise exceptions.PermissionDenied(_( "{} has no manager/owner role to the form {}". format( user, xform))) elif not user.has_perm('can_add_xform', owner.profile): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % {'user': user.username, 'account': owner.username})) def set_form(): if project: args = dict({'project': project.pk}.items() + post.items()) else: args = post form = QuickConverter(args, files) return form.publish(owner, id_string=id_string, created_by=user) return publish_form(set_form)
def publish_project_xform(request, project): def set_form(): props = { 'project': project.pk, 'dropbox_xls_url': request.DATA.get('dropbox_xls_url'), 'xls_url': request.DATA.get('xls_url'), 'csv_url': request.DATA.get('csv_url') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None if 'formid' in request.DATA: xform = get_object_or_404(XForm, pk=request.DATA.get('formid')) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied(_( "{} has no manager/owner role to the form {}". format( request.user, xform))) xform.project = project xform.save() set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
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)
def publish_project_xform(request, project): def set_form(): props = { 'project': project.pk, 'dropbox_xls_url': request.DATA.get('dropbox_xls_url'), 'xls_url': request.DATA.get('xls_url'), 'csv_url': request.DATA.get('csv_url') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None if 'formid' in request.DATA: xform = get_object_or_404(XForm, pk=request.DATA.get('formid')) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied( _("{} has no manager/owner role to the form {}".format( request.user, xform))) xform.project = project xform.save() set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
def publish_project_xform(request, project): def set_form(): form = QuickConverter(request.POST, request.FILES) return form.publish(project.organization) xform = publish_form(set_form) if isinstance(xform, XForm): add_xform_to_project(xform, project, request.user) return xform
def publish_xlsform(request, user=None): user = request.user if user is None else user def set_form(): form = QuickConverter(request.POST, request.FILES) return form.publish(user) return publish_form(set_form)
def survey_preview(self, request, **kwargs): username = request.user.username if request.method.upper() == 'POST': if not username: raise ParseError("User has to be authenticated") csv_data = request.data.get('body') if csv_data: rand_name = "survey_draft_%s.csv" % ''.join( random.sample("abcdefghijklmnopqrstuvwxyz0123456789", 6)) csv_file = ContentFile(csv_data) csv_name = default_storage.save( upload_to_survey_draft(rand_name, username), csv_file) result = publish_form(lambda: get_survey_xml(csv_name)) if result_has_error(result): raise ParseError(result.get('text')) return Response( {'unique_string': rand_name, 'username': username}, status=200) else: raise ParseError('Missing body') if request.method.upper() == 'GET': filename = request.query_params.get('filename') username = request.query_params.get('username') if not username: raise ParseError('Username not provided') if not filename: raise ParseError("Filename MUST be provided") csv_name = upload_to_survey_draft(filename, username) result = publish_form(lambda: get_survey_xml(csv_name)) if result_has_error(result): raise ParseError(result.get('text')) self.etag_data = result return Response(result, status=200)
def publish_project_xform(request, project): def set_form(): props = { 'project': project.pk, 'dropbox_xls_url': request.data.get('dropbox_xls_url'), 'xls_url': request.data.get('xls_url'), 'csv_url': request.data.get('csv_url'), 'text_xls_form': request.data.get('text_xls_form') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None def id_string_exists_in_account(): try: XForm.objects.get(user=project.organization, id_string=xform.id_string) except XForm.DoesNotExist: return False return True if 'formid' in request.data: xform = get_object_or_404(XForm, pk=request.data.get('formid')) safe_delete('{}{}'.format(PROJ_FORMS_CACHE, xform.project.pk)) safe_delete('{}{}'.format(PROJ_BASE_FORMS_CACHE, xform.project.pk)) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied( _("{} has no manager/owner role to the form {}".format( request.user, xform))) msg = 'Form with the same id_string already exists in this account' # Without this check, a user can't transfer a form to projects that # he/she owns because `id_string_exists_in_account` will always # return true if project.organization != xform.user and \ id_string_exists_in_account(): raise exceptions.ParseError(_(msg)) xform.user = project.organization xform.project = project try: with transaction.atomic(): xform.save() except IntegrityError: raise exceptions.ParseError(_(msg)) set_project_perms_to_xform_async.delay(xform.pk, project.pk) else: xform = publish_form(set_form) return xform
def publish_xlsform(request, user): if not request.user.has_perm('can_add_xform', user.profile): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % {'user': request.user.username, 'account': user.username})) def set_form(): form = QuickConverter(request.POST, request.FILES) return form.publish(user) return publish_form(set_form)
def _upload_xform(self, path, file_name): class PublishXForm: def __init__(self, xml_file, user): self.xml_file = xml_file self.user = user def publish_xform(self): return publish_xml_form(self.xml_file, self.user) xml_file = default_storage.open(path) xml_file.name = file_name k = PublishXForm(xml_file, self.user) return publish_form(k.publish_xform)
def _upload_xform(self, path, file_name): class PublishXForm(object): def __init__(self, xml_file, user): self.xml_file = xml_file self.user = user def publish_xform(self): return publish_xml_form(self.xml_file, self.user) xml_file = default_storage.open(path) xml_file.name = file_name k = PublishXForm(xml_file, self.user) return publish_form(k.publish_xform)
def publish_xlsform(request, user, id_string=None): if not request.user.has_perm('can_add_xform', user.profile): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % {'user': request.user.username, 'account': user.username})) def set_form(): form = QuickConverter(request.POST, request.FILES) return form.publish(user, id_string=id_string, created_by=request.user) return publish_form(set_form)
def publish_xlsform(request, user): if not request.user.has_perm( 'can_add_xform', UserProfile.objects.get_or_create(user=user)[0]): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % { 'user': request.user.username, 'account': user.username })) def set_form(): form = QuickConverter(request.POST, request.FILES) return form.publish(user) return publish_form(set_form)
def publish_project_xform(request, project): def set_form(): form = QuickConverter({'project': project.pk}, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None if 'formid' in request.DATA: xform = get_object_or_404(XForm, pk=request.DATA.get('formid')) xform.project = project xform.save() set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
def publish_project_xform(request, project): def set_form(): form = QuickConverter(request.POST, request.FILES) return form.publish(project.organization) xform = None if 'formid' in request.DATA: xform = get_object_or_404(XForm, pk=request.DATA.get('formid')) else: xform = publish_form(set_form) if isinstance(xform, XForm): add_xform_to_project(xform, project, request.user) return xform
def create(self, request, *args, **kwargs): if request.method.upper() == 'HEAD': return Response(status=status.HTTP_204_NO_CONTENT, headers=self.get_openrosa_headers(request), template_name=self.template_name) xform_def = request.FILES.get('form_def_file', None) response_status = status.HTTP_201_CREATED username = kwargs.get('username') form_user = (username and get_object_or_404(User, username=username)) \ or request.user if not request.user.has_perm( 'can_add_xform', UserProfile.objects.get_or_create(user=form_user)[0]): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % { 'user': request.user.username, 'account': form_user.username })) data = {} if isinstance(xform_def, File): do_form_upload = DoXmlFormUpload(xform_def, form_user) dd = publish_form(do_form_upload.publish) if isinstance(dd, XForm): data['message'] = _(u"%s successfully published." % dd.id_string) else: data['message'] = dd['text'] response_status = status.HTTP_400_BAD_REQUEST else: data['message'] = _(u"Missing xml file.") response_status = status.HTTP_400_BAD_REQUEST return Response(data, status=response_status, headers=self.get_openrosa_headers(request, location=False), template_name=self.template_name)
def create(self, request, *args, **kwargs): if request.method.upper() == 'HEAD': return Response(status=status.HTTP_204_NO_CONTENT, headers=self.get_openrosa_headers(request), template_name=self.template_name) xform_def = request.FILES.get('form_def_file', None) response_status = status.HTTP_201_CREATED username = kwargs.get('username') form_user = (username and get_object_or_404(User, username=username)) \ or request.user if not request.user.has_perm( 'can_add_xform', UserProfile.objects.get_or_create(user=form_user)[0] ): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % {'user': request.user.username, 'account': form_user.username})) data = {} if isinstance(xform_def, File): do_form_upload = DoXmlFormUpload(xform_def, form_user) dd = publish_form(do_form_upload.publish) if isinstance(dd, XForm): data['message'] = _( u"%s successfully published." % dd.id_string) else: data['message'] = dd['text'] response_status = status.HTTP_400_BAD_REQUEST else: data['message'] = _(u"Missing xml file.") response_status = status.HTTP_400_BAD_REQUEST return Response(data, status=response_status, headers=self.get_openrosa_headers(request, location=False), template_name=self.template_name)
def update_xform(request, username, id_string): xform = get_object_or_404( XForm, user__username__iexact=username, id_string__iexact=id_string) owner = xform.user def set_form(): form = QuickConverter(request.POST, request.FILES) survey = form.publish(request.user, id_string).survey enketo_webform_url = reverse( enter_data, kwargs={'username': username, 'id_string': survey.id_string} ) audit = { 'xform': xform.id_string } audit_log( Actions.FORM_XLS_UPDATED, request.user, owner, _("XLS for '%(id_string)s' updated.") % { 'id_string': xform.id_string, }, audit, request) return { 'type': 'alert-success', 'text': _(u'Successfully published %(form_id)s.' u' <a href="%(form_url)s">Enter Web Form</a>' u' or <a href="#preview-modal" data-toggle="modal">' u'Preview Web Form</a>') % {'form_id': survey.id_string, 'form_url': enketo_webform_url} } message = publish_form(set_form) messages.add_message( request, messages.INFO, message['text'], extra_tags=message['type']) return HttpResponseRedirect(reverse(show, kwargs={ 'username': username, 'id_string': id_string }))
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__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 = 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 clone_xlsform(request, username): """ Copy a public/Shared form to a users list of forms. Eliminates the need to download Excel File and upload again. """ to_username = request.user.username context = RequestContext(request) context.message = {'type': None, 'text': '....'} def set_form(): form_owner = request.POST.get('username') id_string = request.POST.get('id_string') xform = XForm.objects.get(user__username=form_owner, id_string=id_string) if len(id_string) > 0 and id_string[0].isdigit(): id_string = '_' + id_string path = xform.xls.name if default_storage.exists(path): xls_file = upload_to(None, '%s%s.xls' % ( id_string, XForm.CLONED_SUFFIX), to_username) xls_data = default_storage.open(path) xls_file = default_storage.save(xls_file, xls_data) context.message = u'%s-%s' % (form_owner, xls_file) survey = DataDictionary.objects.create( user=request.user, xls=xls_file ).survey # log to cloner's account audit = {} audit_log( Actions.FORM_CLONED, request.user, request.user, _("Cloned form '%(id_string)s'.") % { 'id_string': survey.id_string, }, audit, request) clone_form_url = reverse( show, kwargs={ 'username': to_username, 'id_string': xform.id_string + XForm.CLONED_SUFFIX}) return { 'type': 'alert-success', 'text': _(u'Successfully cloned to %(form_url)s into your ' u'%(profile_url)s') % {'form_url': u'<a href="%(url)s">%(id_string)s</a> ' % { 'id_string': survey.id_string, 'url': clone_form_url }, 'profile_url': u'<a href="%s">profile</a>.' % reverse(profile, kwargs={'username': to_username})} } form_result = publish_form(set_form) if form_result['type'] == 'alert-success': # comment the following condition (and else) # when we want to enable sms check for all. # until then, it checks if form barely related to sms if is_sms_related(form_result.get('form_o')): form_result_sms = check_form_sms_compatibility(form_result) context.message_list = [form_result, form_result_sms] else: context.message = form_result else: context.message = form_result if request.is_ajax(): res = loader.render_to_string( 'message.html', context_instance=context).replace("'", r"\'").replace('\n', '') return HttpResponse( "$('#mfeedback').html('%s').show();" % res) else: return HttpResponse(context.message['text'])
def profile(request, username): context = RequestContext(request) content_user = get_object_or_404(User, username=username) context.form = QuickConverter() # xlsform submission... if request.method == 'POST' and request.user.is_authenticated(): def set_form(): form = QuickConverter(request.POST, request.FILES) survey = form.publish(request.user).survey audit = {} audit_log( Actions.FORM_PUBLISHED, request.user, content_user, _("Published form '%(id_string)s'.") % { 'id_string': survey.id_string, }, audit, request) enketo_webform_url = reverse( enter_data, kwargs={'username': username, 'id_string': survey.id_string} ) return { 'type': 'alert-success', 'preview_url': reverse(enketo_preview, kwargs={ 'username': username, 'id_string': survey.id_string }), 'text': _(u'Successfully published %(form_id)s.' u' <a href="%(form_url)s">Enter Web Form</a>' u' or <a href="#preview-modal" data-toggle="modal">' u'Preview Web Form</a>') % {'form_id': survey.id_string, 'form_url': enketo_webform_url}, 'form_o': survey } form_result = publish_form(set_form) if form_result['type'] == 'alert-success': # comment the following condition (and else) # when we want to enable sms check for all. # until then, it checks if form barely related to sms if is_sms_related(form_result.get('form_o')): form_result_sms = check_form_sms_compatibility(form_result) context.message_list = [form_result, form_result_sms] else: context.message = form_result else: context.message = form_result # profile view... # for the same user -> dashboard if content_user == request.user: context.show_dashboard = True context.all_forms = content_user.xforms.count() context.form = QuickConverterFile() context.form_url = QuickConverterURL() request_url = request.build_absolute_uri( "/%s" % request.user.username) context.url = request_url.replace('http://', 'https://') xforms = XForm.objects.filter(user=content_user)\ .select_related('user', 'instances') context.user_xforms = xforms # 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])) context.forms_shared_with = XForm.objects.filter( pk__in=shared_forms_pks).exclude(user=content_user)\ .select_related('user') context.xforms_list = [ { 'id': 'published', 'xforms': context.user_xforms, 'title': _(u"Published Forms"), 'small': _("Export, map, and view submissions.") }, { 'id': 'shared', 'xforms': context.forms_shared_with, 'title': _(u"Shared Forms"), 'small': _("List of forms shared with you.") } ] # for any other user -> profile set_profile_data(context, content_user) return render_to_response("profile.html", context_instance=context)
def _upload_xform(self, path, file_name): xml_file = default_storage.open(path) xml_file.name = file_name k = PublishXForm(xml_file, self.user) return publish_form(k.publish_xform)
def publish_project_xform(request, project): """ Publish XLSForm to a project given a request. """ def set_form(): """ Instantiates QuickConverter form to publish a form. """ props = { 'project': project.pk, 'dropbox_xls_url': request.data.get('dropbox_xls_url'), 'xls_url': request.data.get('xls_url'), 'csv_url': request.data.get('csv_url'), 'text_xls_form': request.data.get('text_xls_form') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None def id_string_exists_in_account(): """ Checks if an id_string exists in an account, returns True if it exists otherwise returns False. """ try: XForm.objects.get( user=project.organization, id_string=xform.id_string) except XForm.DoesNotExist: return False return True if 'formid' in request.data: xform = get_object_or_404(XForm, pk=request.data.get('formid')) safe_delete('{}{}'.format(PROJ_FORMS_CACHE, xform.project.pk)) safe_delete('{}{}'.format(PROJ_BASE_FORMS_CACHE, xform.project.pk)) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied( _("{} has no manager/owner role to the form {}".format( request.user, xform))) msg = 'Form with the same id_string already exists in this account' # Without this check, a user can't transfer a form to projects that # he/she owns because `id_string_exists_in_account` will always # return true if project.organization != xform.user and \ id_string_exists_in_account(): raise exceptions.ParseError(_(msg)) xform.user = project.organization xform.project = project try: with transaction.atomic(): xform.save() except IntegrityError: raise exceptions.ParseError(_(msg)) else: # First assign permissions to the person who uploaded the form OwnerRole.add(request.user, xform) try: # Next run async task to apply all other perms set_project_perms_to_xform_async.delay(xform.pk, project.pk) except OperationalError: # Apply permissions synchrounously set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
def profile(request, username): context = RequestContext(request) content_user = get_object_or_404(User, username=username) context.form = QuickConverter() # xlsform submission... if request.method == "POST" and request.user.is_authenticated(): def set_form(): form = QuickConverter(request.POST, request.FILES) survey = form.publish(request.user).survey audit = {} audit_log( Actions.FORM_PUBLISHED, request.user, content_user, _("Published form '%(id_string)s'.") % {"id_string": survey.id_string}, audit, request, ) enketo_webform_url = reverse(enter_data, kwargs={"username": username, "id_string": survey.id_string}) return { "type": "alert-success", "preview_url": reverse(enketo_preview, kwargs={"username": username, "id_string": survey.id_string}), "text": _( u"Successfully published %(form_id)s." u' <a href="%(form_url)s">Enter Web Form</a>' u' or <a href="#preview-modal" data-toggle="modal">' u"Preview Web Form</a>" ) % {"form_id": survey.id_string, "form_url": enketo_webform_url}, "form_o": survey, } form_result = publish_form(set_form) if form_result["type"] == "alert-success": # comment the following condition (and else) # when we want to enable sms check for all. # until then, it checks if form barely related to sms if is_sms_related(form_result.get("form_o")): form_result_sms = check_form_sms_compatibility(form_result) context.message_list = [form_result, form_result_sms] else: context.message = form_result else: context.message = form_result # profile view... # for the same user -> dashboard if content_user == request.user: context.show_dashboard = True context.all_forms = content_user.xforms.count() context.form = QuickConverterFile() context.form_url = QuickConverterURL() context.url = request.build_absolute_uri("/%s" % request.user.username) xforms = XForm.objects.filter(user=content_user).select_related("user", "instances") context.user_xforms = xforms # 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])) context.forms_shared_with = ( XForm.objects.filter(pk__in=shared_forms_pks).exclude(user=content_user).select_related("user") ) context.xforms_list = [ { "id": "published", "xforms": context.user_xforms, "title": _(u"Published Forms"), "small": _("Export, map, and view submissions."), }, { "id": "shared", "xforms": context.forms_shared_with, "title": _(u"Shared Forms"), "small": _("List of forms shared with you."), }, ] # for any other user -> profile set_profile_data(context, content_user) return render_to_response("profile.html", context_instance=context)