def dispatch(self, request, *args, **kwargs): try: self.first_app_id = self.kwargs["first_app_id"] self.second_app_id = self.kwargs["second_app_id"] self.first_app = Application.get(self.first_app_id) self.second_app = Application.get(self.second_app_id) except (ResourceNotFound, KeyError): raise Http404() return super(AppDiffView, self).dispatch(request, *args, **kwargs)
def test_last_modified_bulk(self): lm = self.app.last_modified Application.save_docs([self.app]) app = Application.get(self.app._id) self.assertGreater(app.last_modified, lm) lm = self.app.last_modified Application.bulk_save([self.app]) app = Application.get(self.app._id) self.assertGreater(app.last_modified, lm)
def handle(self, *args, **options): app_ids = [] try: Application.get(args[0]) app_ids = [args[0]] except ResourceNotFound: app_ids = get_app_ids_in_domain(args[0]) logger.info('migrating {} apps in domain {}'.format(len(app_ids), args[0])) for app_id in app_ids: logger.info('migrating app {}'.format(app_id)) self.migrate_app(app_id) logger.info('done with migrate_app_to_cmitfb')
def test_app_icon_permissions(self): LOGO_HOME = u'hq_logo_android_home' LOGO_LOGIN = u'hq_logo_android_login' advanced_sub = Subscription.new_domain_subscription( self.account, self.domain.name, self.advanced_plan, web_user=self.admin_user.username ) with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-standard.json')) as f: standard_source = json.load(f) with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-build.json')) as f: build_source = json.load(f) app_standard = Application.wrap(standard_source) app_standard.save() self.assertEqual(self.domain.name, app_standard.domain) app_build = Application.wrap(build_source) app_build.save() self.assertEqual(self.domain.name, app_build.domain) self.assertTrue(LOGO_HOME in app_standard.logo_refs.keys()) self.assertTrue(LOGO_LOGIN in app_standard.logo_refs.keys()) self.assertTrue(LOGO_HOME in app_build.logo_refs.keys()) self.assertTrue(LOGO_LOGIN in app_build.logo_refs.keys()) advanced_sub.cancel_subscription(web_user=self.admin_user.username) app_standard = Application.get(app_standard._id) app_build = Application.get(app_build._id) self.assertFalse(LOGO_HOME in app_standard.logo_refs.keys()) self.assertFalse(LOGO_LOGIN in app_standard.logo_refs.keys()) self.assertFalse(LOGO_HOME in app_build.logo_refs.keys()) self.assertFalse(LOGO_LOGIN in app_build.logo_refs.keys()) Subscription.new_domain_subscription( self.account, self.domain.name, self.advanced_plan, web_user=self.admin_user.username ) app_standard = Application.get(app_standard._id) app_build = Application.get(app_build._id) self.assertTrue(LOGO_HOME in app_standard.logo_refs.keys()) self.assertTrue(LOGO_LOGIN in app_standard.logo_refs.keys()) self.assertTrue(LOGO_HOME in app_build.logo_refs.keys()) self.assertTrue(LOGO_LOGIN in app_build.logo_refs.keys())
def case_list(request, domain): apps = filter(lambda app: app.doc_type == "Application", ApplicationBase.view('app_manager/applications_brief', startkey=[domain], endkey=[domain, {}])) user_id = request.REQUEST.get("user_id", request.couch_user.get_id) app_id = request.REQUEST.get("app_id", "") module_id = int(request.REQUEST.get("module_id", "0")) language = request.REQUEST.get("language", "en") if not app_id and apps: app_id = apps[0].get_id if app_id: app = Application.get(app_id) case_short = app.modules[module_id].get_detail("case_short") case_long = app.modules[module_id].get_detail("case_long") else: case_short="" case_long="" return render_to_response(request, "cloudcare/list_cases.html", {"domain": domain, "language": language, "user_id": user_id, "apps": apps, "case_short": json.dumps(case_short._doc), "case_long": json.dumps(case_long._doc), "cases": json.dumps(get_owned_cases(domain, user_id), default=json_handler)})
def handle(self, path, app_id, **options): if options['deploy'] and not options['user']: raise CommandError('Deploy argument requires a user') elif options['deploy']: user = CouchUser.get_by_username(options['user']) if not user: raise CommandError("Couldn't find user with username {}".format(options['user'])) app = Application.get(app_id) for module_dir in os.listdir(path): module_index, name = module_dir.split(' - ') module = app.get_module(int(module_index)) for form_name in os.listdir(os.path.join(path, module_dir)): form_index, name = form_name.split(' - ') form = module.get_form(int(form_index)) with open(os.path.join(path, module_dir, form_name), 'rb') as f: save_xform(app, form, f.read()) app.save() print('successfully updated {}'.format(app.name)) if options['deploy']: # make build and star it comment = options.get('comment', 'form changes from {0}'.format(datetime.utcnow().strftime(SERVER_DATETIME_FORMAT_NO_SEC))) copy = app.make_build( comment=comment, user_id=user._id, ) copy.is_released = True copy.save(increment_version=False) print('successfully released new version')
def form_context(request, domain, app_id, module_id, form_id): app = Application.get(app_id) form_url = "%s%s" % (get_url_base(), reverse('download_xform', args=[domain, app_id, module_id, form_id])) case_id = request.GET.get('case_id') try: form = app.get_module(module_id).get_form(form_id).name.values()[0] except (FormNotFoundException, ModuleNotFoundException): raise Http404() # make the name for the session we will use with the case and form session_name = u'{app} > {form}'.format( app=app.name, form=form, ) if case_id: session_name = u'{0} - {1}'.format(session_name, CommCareCase.get(case_id).name) delegation = request.GET.get('task-list') == 'true' offline = request.GET.get('offline') == 'true' session_helper = SessionDataHelper(domain, request.couch_user, case_id, delegation=delegation, offline=offline) return json_response(session_helper.get_full_context( {'form_url': form_url,}, {'session_name': session_name, 'app_id': app._id} ))
def app(self): try: app = Application.get(self.app_id) assert app.doc_type is 'Application' return app except (ResourceNotFound, AssertionError): return None
def test_update_user_restore(self, mock): # updating user restore should result in version change in restore resource # so that CommCare mobile will refetch the resource turn_on_demo_mode(self.user, self.domain) app = self.factory.app app.practice_mobile_worker_id = self.user._id app.save() self.assertXmlPartialEqual( self._get_restore_resource(self.user.demo_restore_id), app.create_suite(), "./user-restore" ) version_before = self.user.demo_restore_id turn_off_demo_mode(self.user) turn_on_demo_mode(self.user, self.domain) version_after = self.user.demo_restore_id self.assertNotEqual(version_before, version_after) # refetch so that memoized app.get_practice_user gets busted` app = Application.get(app._id) app.build_spec.version = '2.30.0' # for some reason, this gets set to an old version, after refetch self.assertXmlPartialEqual( self._get_restore_resource(version_after), app.create_suite(), "./user-restore" )
def create_data_source_from_app(request, domain): if request.method == 'POST': form = ConfigurableDataSourceFromAppForm(domain, request.POST) if form.is_valid(): # save config app_source = form.app_source_helper.get_app_source(form.cleaned_data) app = Application.get(app_source.application) if app_source.source_type == 'case': data_source = get_case_data_source(app, app_source.source) data_source.save() messages.success(request, _(u"Data source created for '{}'".format(app_source.source))) else: assert app_source.source_type == 'form' xform = Form.get_form(app_source.source) data_source = get_form_data_source(app, xform) data_source.save() messages.success(request, _(u"Data source created for '{}'".format(xform.default_name()))) return HttpResponseRedirect(reverse('edit_configurable_data_source', args=[domain, data_source._id])) else: form = ConfigurableDataSourceFromAppForm(domain) context = _shared_context(domain) context['sources_map'] = form.app_source_helper.all_sources context['form'] = form return render(request, 'userreports/data_source_from_app.html', context)
def __init__(self, app_id, source_type, report_source_id, *args, **kwargs): super(ConfigureNewReportBase, self).__init__(*args, **kwargs) assert source_type in ['case', 'form'] self.source_type = source_type self.report_source_id = report_source_id self.app = Application.get(app_id) self.domain = self.app.domain self.ds_builder = DataSourceBuilder( self.domain, self.app, self.source_type, self.report_source_id ) self.data_source_properties = self.ds_builder.data_source_properties # NOTE: The corresponding knockout view model is defined in: # templates/userreports/partials/report_builder_configure_report.html self.helper = FormHelper() self.helper.form_class = "form-horizontal" self.helper.attrs['data_bind'] = "submit: submitHandler" self.helper.form_id = "report-config-form" self.helper.layout = crispy.Layout( self.top_fieldset, FormActions( crispy.ButtonHolder( crispy.Submit( 'submit', _(self.button_text) ) ), ), )
def post(self, request, domain, *args, **kwargs): data = json.loads(request.body) subscription = get_subscription_by_url(domain, data['target_url']) if subscription: # https://zapier.com/developer/documentation/v2/rest-hooks/ # Generally, subscription URLs should be unique. # Return a 409 status code if this criteria isn't met (IE: there is a uniqueness conflict). return HttpResponse(status=409) if data['event'] == EventTypes.NEW_FORM: application = Application.get(data['application']) if not application or not application.get_forms_by_xmlns(data['form']): return HttpResponse(status=400) subscription = ZapierSubscription.objects.create( domain=domain, user_id=str(request.couch_user.get_id), event_name=data['event'], url=data['target_url'], application_id=data['application'], form_xmlns=data['form'], ) elif data['event'] in CASE_TYPE_REPEATER_CLASS_MAP: subscription = ZapierSubscription.objects.create( domain=domain, user_id=str(request.couch_user.get_id), event_name=data['event'], url=data['target_url'], case_type=data['case_type'], ) else: return HttpResponseBadRequest() # respond with the ID so that zapier can use it to unsubscribe return json_response({'id': subscription.id})
def page_context(self): try: self.first_app = Application.get(self.first_app_id) self.second_app = Application.get(self.second_app_id) except (ResourceNotFound, KeyError): raise Http404() for app in (self.first_app, self.second_app): if not self.request.couch_user.is_member_of(app.domain): raise Http404() return { "app": self.first_app, "other_app": self.second_app, "files": {None: self.app_diffs}, }
def handle(self, linked_app_id, linked_domain, master_domain, **options): try: linked_app = Application.get(linked_app_id) except ResourceNotFound: print('No downstream app found for ID {} '.format(linked_app_id)) return if linked_app.domain != linked_domain: print("Project space in the app found from ID {} does not match the linked project space " "that was given.".format(linked_app_id)) return confirm = input( """ Found {} in project space {} linked to project space {}. Are you sure you want to un-link these apps? [y/n] """.format(linked_app.name, linked_domain, master_domain) ) if confirm.lower() != 'y': return print('Unlinking apps') linked_app.convert_to_application() linked_app.save() self.hide_domain_link_history(linked_domain, linked_app_id, master_domain) print('Operation completed')
def clean(self): cleaned_data = self.cleaned_data sm = cleaned_data["share_multimedia"] license = cleaned_data["license"] app_ids = self._get_apps_to_publish() if sm and license not in self.dom.most_restrictive_licenses(apps_to_check=app_ids): license_choices = [LICENSES[l] for l in self.dom.most_restrictive_licenses(apps_to_check=app_ids)] msg = render_to_string('domain/partials/restrictive_license.html', {'licenses': license_choices}) self._errors["license"] = self.error_class([msg]) del cleaned_data["license"] sr = cleaned_data["share_reminders"] if sr: # check that the forms referenced by the events in each reminders exist in the project referenced_forms = CaseReminderHandler.get_referenced_forms(domain=self.dom.name) if referenced_forms: apps = [Application.get(app_id) for app_id in app_ids] app_forms = [f.unique_id for forms in [app.get_forms() for app in apps] for f in forms] nonexistent_forms = filter(lambda f: f not in app_forms, referenced_forms) nonexistent_forms = [FormBase.get_form(f) for f in nonexistent_forms] if nonexistent_forms: msg = """ Your reminders reference forms that are not being published. Make sure the following forms are being published: %s """ % str([f.default_name() for f in nonexistent_forms]).strip('[]') self._errors["share_reminders"] = self.error_class([msg]) return cleaned_data
def clean(self): """ Raise a validation error if there are already 5 data sources and this report won't be able to use one of the existing ones. """ cleaned_data = super(DataSourceForm, self).clean() source_type = cleaned_data.get('source_type') report_source = cleaned_data.get('report_source') app_id = cleaned_data.get('application') if report_source and source_type and app_id: app = Application.get(app_id) ds_builder = DataSourceBuilder(self.domain, app, source_type, report_source) existing_sources = DataSourceConfiguration.by_domain(self.domain) if len(existing_sources) >= 5: if not ds_builder.get_existing_match(): raise forms.ValidationError(_( "Too many data sources!\n" "Creating this report would cause you to go over the maximum " "number of data sources allowed in this domain. The current " "limit is 5. " "To continue, delete all of the reports using a particular " "data source (or the data source itself) and try again. " )) return cleaned_data
def form_context(request, domain, app_id, module_id, form_id): app = Application.get(app_id) form_url = "%s%s" % (get_url_base(), reverse('download_xform', args=[domain, app_id, module_id, form_id])) case_id = request.GET.get('case_id') delegation = request.GET.get('task-list') == 'true' return json_response( touchforms_api.get_full_context(domain, request.couch_user, app, form_url, case_id, delegation=delegation))
def form_context(request, domain, app_id, module_id, form_id): app = Application.get(app_id) module = app.get_module(module_id) form = module.get_form(form_id) case_id = request.REQUEST.get("case_id") return json_response( touchforms_api.get_full_context(domain, request.couch_user, app, module, form, case_id))
def test_xform_pillow_couch(self): form = self._make_form() kafka_seq = self._get_kafka_seq() producer.send_change(topics.FORM, doc_to_change(form.to_json()).metadata) self.assertFalse(self.app.has_submissions) self.pillow.process_changes(since=kafka_seq, forever=False) self.assertTrue(Application.get(self.app._id).has_submissions)
def test_app_icon_permissions(self): LOGO_HOME = 'hq_logo_android_home' LOGO_LOGIN = '******' advanced_sub = self._subscribe_to_advanced() with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-standard.json')) as f: standard_source = json.load(f) with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-build.json')) as f: build_source = json.load(f) app_standard = Application.wrap(standard_source) app_standard.save() self.assertEqual(self.project.name, app_standard.domain) app_build = Application.wrap(build_source) app_build.save() self.assertEqual(self.project.name, app_build.domain) self.assertTrue(LOGO_HOME in app_standard.logo_refs) self.assertTrue(LOGO_LOGIN in app_standard.logo_refs) self.assertTrue(LOGO_HOME in app_build.logo_refs) self.assertTrue(LOGO_LOGIN in app_build.logo_refs) community_sub = advanced_sub.change_plan(DefaultProductPlan.get_default_plan_version()) app_standard = Application.get(app_standard._id) app_build = Application.get(app_build._id) self.assertFalse(LOGO_HOME in app_standard.logo_refs) self.assertFalse(LOGO_LOGIN in app_standard.logo_refs) self.assertFalse(LOGO_HOME in app_build.logo_refs) self.assertFalse(LOGO_LOGIN in app_build.logo_refs) community_sub.change_plan( DefaultProductPlan.get_default_plan_version(edition=SoftwarePlanEdition.ADVANCED) ) app_standard = Application.get(app_standard._id) app_build = Application.get(app_build._id) self.assertTrue(LOGO_HOME in app_standard.logo_refs) self.assertTrue(LOGO_LOGIN in app_standard.logo_refs) self.assertTrue(LOGO_HOME in app_build.logo_refs) self.assertTrue(LOGO_LOGIN in app_build.logo_refs)
def filter_cases(request, domain, app_id, module_id): app = Application.get(app_id) module = app.get_module(module_id) delegation = request.GET.get('task-list') == 'true' auth_cookie = request.COOKIES.get('sessionid') suite_gen = SuiteGenerator(app) xpath = suite_gen.get_filter_xpath(module, delegation=delegation) extra_instances = [{'id': inst.id, 'src': inst.src} for inst in suite_gen.get_instances_for_module(module, additional_xpaths=[xpath])] # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) if delegation: case_type = DELEGATION_STUB_CASE_TYPE else: case_type = module.case_type if xpath: # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = SessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances) if result.get('status', None) == 'error': return HttpResponseServerError( result.get("message", _("Something went wrong filtering your cases."))) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, ids_only=True )] cases = [CommCareCase.wrap(doc) for doc in iter_docs(CommCareCase.get_db(), case_ids)] # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.get_json(lite=True) for c in cases if c] parents = [] if delegation: for case in cases: parent_id = case['indices']['parent']['case_id'] parents.append(CommCareCase.get(parent_id)) return json_response({ 'cases': cases, 'parents': parents }) else: return json_response(cases)
def filename(self): file_ext = Format.from_format(self.format).extension filename = "%s.%s" % (self.export_id, file_ext) try: app = Application.get(self.export_id) if app: filename = "%s-%s.%s" %(app.name, app.get_id, file_ext) except Exception: pass return filename
def test_broken_build(self): client = Client() url = '/a/{domain}/apps/download/{build_id}/suite.xml'.format( domain=self.build.domain, build_id=self.build.get_id, ) self.build = Application.get(self.build.get_id) self.assertEqual(self.build.build_broken, False) # delete the file and do it again, and assert the build is broken self.assertIn('files/suite.xml', self.build._attachments) self.build.delete_attachment('files/suite.xml') self.assertNotIn('files/suite.xml', self.build._attachments) self.build = Application.get(self.build.get_id) response = client.get(url) self.assertEqual(response.status_code, 404) self.build = Application.get(self.build.get_id) self.assertEqual(self.build.build_broken, True)
def ensure_prerequisites(self, domain, app_id, version_number, test_run): self.domain = domain self.app_id = app_id self.version_number = version_number self.test_run = test_run == 'yes' _notify_parsed_args(domain, app_id, version_number, test_run) app = Application.get(self.app_id) if app.domain != self.domain: raise CommandError('Domain not same as from app id') self.setup()
def _get_app_by_name(domain, name): app = Application.view('app_manager/applications_brief', startkey=[domain, name, {}], endkey=[domain, name], descending=True, limit=1).one() if app: return Application.get(app['_id']) else: raise ResourceNotFound(_("Not found application by name: %s") % name)
def testCreateJadJar(self, mock): self.app.build_spec = BuildSpec(**self.build1) self.app.create_build_files(save=True) self.app.save(increment_version=False) # get a fresh one from the db to make sure attachments aren't cached # since that's closer to the real situation self.app = Application.get(self.app._id) self.app.create_jadjar_from_build_files(save=True) self.app.save(increment_version=False) self._check_has_build_files(self.app, self.jad_jar_paths)
def filter_cases(request, domain, app_id, module_id, parent_id=None): app = Application.get(app_id) module = app.get_module(module_id) auth_cookie = request.COOKIES.get('sessionid') suite_gen = SuiteGenerator(app) xpath = SuiteGenerator.get_filter_xpath(module) extra_instances = [{'id': inst.id, 'src': inst.src} for inst in suite_gen.get_instances_for_module(module, additional_xpaths=[xpath])] # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) case_type = module.case_type if xpath: # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = SessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances) if result.get('status', None) == 'error': code = result.get('code', 500) message = result.get('message', _("Something went wrong filtering your cases.")) if code == 500: notify_exception(None, message=message) return json_response(message, status_code=code) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, footprint=True, ids_only=True, )] cases = [CommCareCase.wrap(doc) for doc in iter_docs(CommCareCase.get_db(), case_ids)] if parent_id: cases = filter(lambda c: c.parent and c.parent.case_id == parent_id, cases) # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.get_json(lite=True) for c in cases if c] return json_response(cases)
def test_two_forms_with_same_app(self): """Ensures two forms submitted to the same app does not error""" kafka_seq = self._get_kafka_seq() self._make_form() # confirm change made it to kafka self.assertFalse(self.app.has_submissions) self.pillow.process_changes(since=kafka_seq, forever=False) newly_saved_app = Application.get(self.app._id) self.assertTrue(newly_saved_app.has_submissions) # Ensure that the app has been saved self.assertNotEqual(self.app._rev, newly_saved_app._rev) self._make_form() self.pillow.process_changes(since=kafka_seq, forever=False) self.assertTrue(Application.get(self.app._id).has_submissions) # Ensure that the app has not been saved twice self.assertEqual(Application.get(self.app._id)._rev, newly_saved_app._rev)
def clean(self): cleaned_data = super(ConfigurableDataSourceFromAppForm, self).clean() app = Application.get(cleaned_data['app_id']) if cleaned_data['case_type'] not in app.get_case_types(): raise ValidationError(_('Case type {} not found in application {}!'.format( cleaned_data['case_type'], app.name, ))) # set the app property on the form so we don't have to go back to the DB for it # there may be a better way to do this. self.app = app return cleaned_data
def clean(self): cleaned_data = super(ConfigurableFormDataSourceFromAppForm, self).clean() app = Application.get(cleaned_data['app_id']) form = Form.get_form(cleaned_data['form_id']) if form.get_app()._id != app._id: raise ValidationError(_('Form name {} not found in application {}').format( form.default_name(), app.name )) self.app = app self.form = form return cleaned_data
def __call__(self, item, context=None): xforms_ids = CommCareCase.objects.get_case_xform_ids(item['_id']) forms = XFormInstance.objects.get_forms(xforms_ids, item['domain']) f_forms = [f for f in forms if f.xmlns == self.xmlns] s_forms = sorted(f_forms, key=lambda x: x.received_on) if len(s_forms) > 0: latest_form = s_forms[-1] else: latest_form = None path_to_action_plan = 'form/action_plan/%s/action_plan' % self.section if latest_form: action_plans = latest_form.get_data(path_to_action_plan) if action_plans: action_plan_for_question = None for action_plan in action_plans: if action_plan.get('incorrect_questions', '') == self.question_id: action_plan_for_question = action_plan break if action_plan_for_question: incorrect_question = action_plan_for_question.get('incorrect_questions', '') responsible = ', '.join( [ item.get(x.strip(), '---') for x in action_plan_for_question.get('action_plan_input', {}).get('responsible', '').split(',') ] ) support = ', '.join( [ item.get(x.strip(), '---') for x in action_plan_for_question.get('action_plan_input', {}).get('support', '').split(',') ] ) application = Application.get(latest_form.app_id) form = application.get_forms_by_xmlns(self.xmlns)[0] question_list = application.get_questions(self.xmlns) questions = {x['value']: x for x in question_list} return { 'form_name': form.name['en'], 'section': self.section, 'timeEnd': latest_form.metadata.timeEnd, 'gap': questions.get('data/code_to_text/%s' % incorrect_question, {}).get('label', '---'), 'intervention_action': action_plan_for_question.get('intervention_action', '---'), 'responsible': responsible, 'support': support, 'deadline': action_plan_for_question.get('DEADLINE', '---'), 'notes': action_plan_for_question.get('notes', '---'), }
def obj_get_list(self, bundle, **kwargs): """ https://zapier.com/developer/documentation/v2/trigger-fields-custom/ Zapier custom fields allow to show default form properties, even if there are no forms submitted. It also allows to assign label to json property. Format of custom field: { "type": "unicode", "key": "json_key", "label": "Label", // optional "help_text": "Helps to explain things to users." // optional } """ application_id = bundle.request.GET.get('application_id') xmlns = bundle.request.GET.get('xmlns') if not application_id or not xmlns: return [] try: app = Application.get(application_id) except ResourceNotFound: raise NotFound form = app.get_form_by_xmlns(xmlns) custom_fields = [] for idx, question in enumerate(form.get_questions(app.langs)): if self._has_default_label(question): label = question['label'].split('/')[-1] else: label = question['label'] custom_fields.append( CustomField( dict(type='unicode', key=self._build_key(question['hashtagValue']), label=label))) for form_property in MAIN_FORM_TABLE_PROPERTIES: if form_property.is_advanced: continue custom_fields.append( CustomField( dict(type='unicode', key='__'.join( [node.name for node in form_property.item.path]), label=form_property.label, help_text=form_property.help_text))) return custom_fields
def test_deletes_module_child_removed(self): # Create new module handle_shadow_child_modules( self.app, self.app.get_module_by_unique_id(self.shadow_module.unique_id)) # Change child module's parent app = Application.get(self.app.get_id) app.modules[1].root_module_id = None app.save() # The new shadow module should be deleted, since it is no longer needed handle_shadow_child_modules( app, app.get_module_by_unique_id(self.shadow_module.unique_id)) self.assertEqual(len(app.modules), 3)
def export_gzip(req, domain, app_id): app_json = get_app(domain, app_id) fd, fpath = tempfile.mkstemp() with os.fdopen(fd, 'w') as tmp: with zipfile.ZipFile(tmp, "w", zipfile.ZIP_DEFLATED) as z: z.writestr('application.json', app_json.export_json()) wrapper = FileWrapper(open(fpath)) response = HttpResponse(wrapper, content_type='application/zip') response['Content-Length'] = os.path.getsize(fpath) app = Application.get(app_id) set_file_download(response, '{domain}-{app_name}-{app_version}.zip'.format( app_name=slugify(app.name), app_version=slugify(unicode(app.version)), domain=domain )) return response
def test_form_pillow_non_existant_build_id(self): consumer = get_test_kafka_consumer(topics.FORM, topics.FORM_SQL) kafka_seq = self._get_kafka_seq() form = self._make_form(build_id='not-here') # confirm change made it to kafka message = next(consumer) change_meta = change_meta_from_kafka_message(message.value) self.assertEqual(form.form_id, change_meta.document_id) self.assertEqual(self.domain, change_meta.domain) self.assertFalse(self.app.has_submissions) self.pillow.process_changes(since=kafka_seq, forever=False) self.assertFalse(Application.get(self.app._id).has_submissions)
def handle(self, master_id, linked_id, **options): print("Linking apps") master_app = Application.get(master_id) master_version = get_latest_released_app_version(master_app.domain, master_id) if not master_version: raise CommandError( "Creating linked app failed." " Unable to get latest released version of your app." " Make sure you have at least one released build." ) linked_app = LinkedApplication.get(linked_id) link_app(linked_app, master_app.domain, master_id) update_linked_app(linked_app, 'system')
def create_build_files_if_necessary_handling_conflicts(is_retry=False): try: try: # look for file guaranteed to exist if profile is created request.app.fetch_attachment( 'files/{id}/profile.xml'.format(id=build_profile), return_bytes=True) except ResourceNotFound: request.app.create_build_files(build_profile_id=build_profile) request.app.save() except ResourceConflict: if is_retry: raise request.app = Application.get(request.app.get_id) create_build_files_if_necessary_handling_conflicts(True)
def toggle_build_profile(request, domain, build_id, build_profile_id): build = Application.get(build_id) action = request.GET.get('action') if action and action == 'enable' and not build.is_released: messages.error(request, _("Release the build first. Can not enable profiles for unreleased versions")) return HttpResponseRedirect(reverse('download_index', args=[domain, build_id])) latest_enabled_build_profile = LatestEnabledBuildProfiles.objects.filter( app_id=build.copy_of, build_profile_id=build_profile_id ).order_by('-version').first() if action == 'enable' and latest_enabled_build_profile: if latest_enabled_build_profile.version > build.version: messages.error(request, _( "Latest version available for this profile is {}, which is " "higher than this version. Disable any higher versions first.".format( latest_enabled_build_profile.version ))) return HttpResponseRedirect(reverse('download_index', args=[domain, build_id])) if action == 'enable': build_profile = LatestEnabledBuildProfiles.objects.create( app_id=build.copy_of, version=build.version, build_profile_id=build_profile_id, build_id=build_id ) build_profile.expire_cache(domain) elif action == 'disable': build_profile = LatestEnabledBuildProfiles.objects.filter( app_id=build.copy_of, version=build.version, build_profile_id=build_profile_id, build_id=build_id ).first() build_profile.delete() build_profile.expire_cache(domain) latest_enabled_build_profile = LatestEnabledBuildProfiles.objects.filter( app_id=build.copy_of, build_profile_id=build_profile_id ).order_by('-version').first() if latest_enabled_build_profile: messages.success(request, _("Latest version for profile {} is now {}").format( build.build_profiles[build_profile_id].name, latest_enabled_build_profile.version )) else: messages.success(request, _("Latest release now available for profile {}").format( build.build_profiles[build_profile_id].name )) return HttpResponseRedirect(reverse('download_index', args=[domain, build_id]))
def obj_get_list(self, bundle, **kwargs): application_id = bundle.request.GET.get('application_id') if not application_id: raise NotFound('application_id parameter required') results = [] application = Application.get(docid=application_id) if not application: return [] forms_objects = application.get_forms(bare=False) for form_object in forms_objects: form = form_object['form'] module = form_object['module'] form_name = '{} > {} > {}'.format(application.name, module.default_name(), form.default_name()) results.append(Form(form_xmlns=form.xmlns, form_name=form_name)) return results
def handle(self, app_id, path, **options): # setup directory if not os.path.exists(path): os.mkdir(path) app = Application.get(app_id) for module_index, module in enumerate(app.get_modules()): module_dir_name = '{index} - {name}'.format(index=module_index, name=unicode_slug(module.default_name())) module_dir = os.path.join(path, module_dir_name) if not os.path.exists(module_dir): os.mkdir(module_dir) for form_index, form in enumerate(module.get_forms()): form_name = ('{index} - {name}.xml'.format(index=form_index, name=unicode_slug(form.default_name()))) form_path = os.path.join(module_dir, form_name) with open(form_path, 'w') as f: f.write(form.source.encode('utf-8')) print('wrote {}'.format(form_path))
def test_form_pillow_mismatch_domains(self): consumer = get_test_kafka_consumer(topics.FORM, topics.FORM_SQL) kafka_seq = self._get_kafka_seq() self.app.domain = 'not-this-domain' self.app.save() form = self._make_form() # confirm change made it to kafka message = consumer.next() change_meta = change_meta_from_kafka_message(message.value) self.assertEqual(form.form_id, change_meta.document_id) self.assertEqual(self.domain, change_meta.domain) self.assertFalse(self.app.has_submissions) self.pillow.process_changes(since=kafka_seq, forever=False) self.assertFalse(Application.get(self.app._id).has_submissions)
def form_context(request, domain, app_id, module_id, form_id): app = Application.get(app_id) form_url = "%s%s" % (get_url_base(), reverse('download_xform', args=[domain, app_id, module_id, form_id])) case_id = request.GET.get('case_id') instance_id = request.GET.get('instance_id') try: form = app.get_module(module_id).get_form(form_id) except (FormNotFoundException, ModuleNotFoundException): raise Http404() form_name = form.name.values()[0] # make the name for the session we will use with the case and form session_name = u'{app} > {form}'.format( app=app.name, form=form_name, ) if case_id: session_name = u'{0} - {1}'.format(session_name, CommCareCase.get(case_id).name) root_context = { 'form_url': form_url, } if instance_id: try: root_context['instance_xml'] = XFormInstance.get_db( ).fetch_attachment(instance_id, ATTACHMENT_NAME) except ResourceNotFound: raise Http404() session_extras = {'session_name': session_name, 'app_id': app._id} session_extras.update( get_cloudcare_session_data(domain, form, request.couch_user)) delegation = request.GET.get('task-list') == 'true' offline = request.GET.get('offline') == 'true' session_helper = SessionDataHelper(domain, request.couch_user, case_id, delegation=delegation, offline=offline) return json_response( session_helper.get_full_context(root_context, session_extras))
def post(self, request, *args, **kwargs): if self.create_export_form.is_valid(): app_id = self.create_export_form.cleaned_data['application'] form_unique_id = self.create_export_form.cleaned_data['form'] return HttpResponseRedirect( reverse( CreateCustomFormExportView.urlname, args=[self.domain], ) + ('?export_tag="%(export_tag)s"&app_id=%(app_id)s' % { 'app_id': app_id, 'export_tag': [ form for form in Application.get(app_id).get_forms() if form.get_unique_id() == form_unique_id ][0].xmlns, }) ) return self.get(self.request, *args, **kwargs)
def _create_linked_app(request, app_id, build_id, from_domain, to_domain, link_app_name): # Linked apps can only be created from released versions error = None if from_domain == to_domain: error = _( "You may not create a linked app in the same domain as its master app." ) elif build_id: from_app = Application.get(build_id) if not from_app.is_released: error = _( "Make sure the version you are copying from is released.") else: from_app = get_latest_released_app(from_domain, app_id) if not from_app: error = _("Unable to get latest released version of your app." " Make sure you have at least one released build.") if error: messages.error(request, _("Creating linked app failed. {}").format(error)) return HttpResponseRedirect( reverse_util('app_settings', params={}, args=[from_domain, app_id])) linked_app = create_linked_app(from_domain, from_app.master_id, to_domain, link_app_name) try: update_linked_app(linked_app, request.couch_user.get_id, master_build=from_app) except AppLinkError as e: linked_app.delete() messages.error(request, str(e)) return HttpResponseRedirect( reverse_util('app_settings', params={}, args=[from_domain, from_app.master_id])) messages.success(request, _('Application successfully copied and linked.')) return HttpResponseRedirect( reverse_util('app_settings', params={}, args=[to_domain, linked_app.get_id]))
def get_form_source_download_url(xform): """Returns the download url for the form source for a submitted XForm """ if not xform.build_id: return None from corehq.apps.app_manager.models import Application app = Application.get(xform.build_id) try: form = app.get_forms_by_xmlns(xform.xmlns)[0] except KeyError: return None return reverse("app_download_file", args=[ xform.domain, xform.build_id, app.get_form_filename(module=form.get_module(), form=form), ])
def test_deletes_module_source_changed(self): # Create new module handle_shadow_child_modules( self.app, self.app.get_module_by_unique_id(self.shadow_module.unique_id)) # Change parent shadow module's source app = Application.get(self.app.get_id) new_module = Module.new_module("name", "en") app.add_module(new_module) app.get_module_by_unique_id(self.shadow_module.unique_id ).source_module_id = new_module.unique_id app.save() self.assertEqual(len(app.modules), 5) # Child shadow module should be removed handle_shadow_child_modules( app, app.get_module_by_unique_id(self.shadow_module.unique_id)) self.assertEqual(len(app.modules), 4)
def rows(self): rows = [] selected_app = self.request_params.get(SelectApplicationField.slug, '') UNKNOWN = _("unknown") for user in self.users: last_seen = self.table_cell(-1, _("Never")) app_name = "---" is_unknown = True key = make_form_couch_key(self.domain, user_id=user.get('user_id')) data = XFormInstance.view("reports_forms/all_forms", startkey=key+[{}], endkey=key, include_docs=True, descending=True, reduce=False, limit=1, ).first() if data: last_seen = util.format_relative_date(data.received_on) if data.version != '1': build_id = data.version else: build_id = UNKNOWN form_data = data.get_form try: app_name = form_data['meta']['appVersion']['#text'] except KeyError: try: app = Application.get(data.app_id) is_unknown = False if selected_app and selected_app != data.app_id: continue app_name = "%s [%s]" % (app.name, build_id) except Exception: app_name = UNKNOWN if is_unknown and selected_app: continue row = [user.get('username_in_report'), last_seen, app_name] rows.append(row) return rows
def _bootstrap(self, existing_report): """ Use an existing report to initialize some of the instance variables of this form. This method is used when editing an existing report. """ self.report_name = existing_report.title self.source_type = { "CommCareCase": "case", "XFormInstance": "form" }[existing_report.config.referenced_doc_type] self.report_source_id = existing_report.config.meta.build.source_id app_id = existing_report.config.meta.build.app_id if app_id: self.app = Application.get(app_id) else: raise BadBuilderConfigError( _("Report builder data source doesn't reference an application. " "It is likely this report has been customized and it is no longer editable. " ))
def clean(self): cleaned_data = self.cleaned_data sm = cleaned_data["share_multimedia"] license = cleaned_data["license"] app_ids = self._get_apps_to_publish() if sm and license not in self.dom.most_restrictive_licenses( apps_to_check=app_ids): license_choices = [ LICENSES[l] for l in self.dom.most_restrictive_licenses( apps_to_check=app_ids) ] msg = render_to_string('domain/partials/restrictive_license.html', {'licenses': license_choices}) self._errors["license"] = self.error_class([msg]) del cleaned_data["license"] sr = cleaned_data["share_reminders"] if sr: # check that the forms referenced by the events in each reminders exist in the project referenced_forms = CaseReminderHandler.get_referenced_forms( domain=self.dom.name) if referenced_forms: apps = [Application.get(app_id) for app_id in app_ids] app_forms = [ f.unique_id for forms in [app.get_forms() for app in apps] for f in forms ] nonexistent_forms = filter(lambda f: f not in app_forms, referenced_forms) nonexistent_forms = [ FormBase.get_form(f) for f in nonexistent_forms ] if nonexistent_forms: msg = """ Your reminders reference forms that are not being published. Make sure the following forms are being published: %s """ % str([f.default_name() for f in nonexistent_forms]).strip('[]') self._errors["share_reminders"] = self.error_class([msg]) return cleaned_data
def testRevertToCopy(self, mock): old_name = 'old name' new_name = 'new name' app = Application.wrap(self._yesno_source) app.name = old_name app.save() copy = app.make_build() copy.save() self.assertEqual(copy.name, old_name) app.name = new_name app.save() app = Application.get(app.get_id) self.assertEqual(app.name, new_name) app = app.make_reversion_to_copy(copy) app.save() self.assertEqual(app.name, old_name)
def migrate_app(self, app_id): app = Application.get(app_id) if app.vellum_case_management: logger.info('already migrated app {}'.format(app_id)) return modules = [m for m in app.modules if m.module_type == 'basic'] for module in modules: forms = [f for f in module.forms if f.doc_type == 'Form'] for form in forms: preload = form.actions.case_preload.preload if preload: xform = XForm(form.source) xform.add_case_preloads(preload) save_xform(app, form, ET.tostring(xform.xml)) form.actions.load_from_form = form.actions.case_preload form.actions.case_preload = PreloadAction() app.vellum_case_management = True app.save()
def post(self, request, domain, *args, **kwargs): data = json.loads(request.body) application = Application.get(docid=data['application']) if not application or not application.get_form_by_xmlns(data['form']): return HttpResponse(status=400) subscription = get_subscription_by_url(domain, data['target_url']) if subscription: # https://zapier.com/developer/documentation/v2/rest-hooks/ # Generally, subscription URLs should be unique. # Return a 409 status code if this criteria isn't met (IE: there is a uniqueness conflict). return HttpResponse(status=409) ZapierSubscription.objects.create(domain=domain, user_id=str( request.couch_user.get_id), event_name=data['event'], url=data['target_url'], application_id=data['application'], form_xmlns=data['form']) return HttpResponse('OK')
def handle(self, *args, **options): if len(args) != 2: raise CommandError('Usage: %s\n%s' % (self.args, self.help)) if options['deploy'] and not options['user']: raise CommandError('Deploy argument requires a user') elif options['deploy']: user = CouchUser.get_by_username(options['user']) if not user: raise CommandError( "Couldn't find user with username {}".format( options['user'])) # todo: would be nice if this worked off remote servers too path, app_id = args app = Application.get(app_id) for module_dir in os.listdir(path): module_index, name = module_dir.split(' - ') module = app.get_module(int(module_index)) for form_name in os.listdir(os.path.join(path, module_dir)): form_index, name = form_name.split(' - ') form = module.get_form(int(form_index)) with open(os.path.join(path, module_dir, form_name)) as f: save_xform(app, form, f.read()) app.save() print 'successfully updated {}'.format(app.name) if options['deploy']: # make build and star it comment = options.get( 'comment', 'form changes from {0}'.format( datetime.utcnow().strftime(SERVER_DATETIME_FORMAT_NO_SEC))) copy = app.make_build( comment=comment, user_id=user._id, previous_version=app.get_latest_app(released_only=False), ) copy.is_released = True copy.save(increment_version=False) print 'successfully released new version'
def migrate_app(self, app_id): app = Application.get(app_id) if app.vellum_case_management: logger.info('already migrated app {}'.format(app_id)) return modules = [m for m in app.modules if m.module_type == 'basic'] for module in modules: forms = [f for f in module.forms if f.doc_type == 'Form'] for form in forms: preload = form.actions.case_preload.preload if preload: if form.requires == 'case': xform = XForm(form.source) xform.add_case_preloads(preload) save_xform(app, form, ET.tostring(xform.xml)) form.case_references = {"load": {path: [case_property] for path, case_property in preload.iteritems()}} form.actions.case_preload = PreloadAction() app.vellum_case_management = True app.save()
def handle(self, add_on_name, *args, **options): add_to_toggle = options.get('add_to_toggle') if add_to_toggle: add_to_toggle = find_static_toggle(add_to_toggle) if not add_to_toggle: raise CommandError('Toggle %s not found.' % add_to_toggle) with open("apps_with_feature_%s.csv" % add_on_name, "w", encoding='utf-8') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=[ 'domain', 'application_id', 'app_name', 'all_add_ons_enabled', 'status' ]) writer.writeheader() for domain_obj in self._iter_domains(options): application_ids = get_app_ids_in_domain(domain_obj.name) for application_id in application_ids: application = Application.get(application_id) if not application.is_remote_app(): all_add_ons_enabled = toggles.ENABLE_ALL_ADD_ONS.enabled(domain_obj.name) if add_on_name in application.add_ons or all_add_ons_enabled: try: writer.writerow({ 'domain': domain_obj.name.encode('utf-8'), 'application_id': application.get_id, 'app_name': application.name.encode('utf-8'), 'all_add_ons_enabled': all_add_ons_enabled, 'status': application.add_ons.get(add_on_name) }) if add_to_toggle: add_to_toggle.set(domain_obj.name, True, NAMESPACE_DOMAIN) except UnicodeEncodeError: print('encode error') print({ 'domain': domain_obj.name, 'application_id': application.get_id, 'app_name': application.name, 'all_add_ons_enabled': all_add_ons_enabled, 'status': application.add_ons.get(add_on_name) })
def test_fix_xforms_with_missing_xmlns_task_fixed(self): """Tests the ability to fix xforms with the periodic cron task """ good_form, bad_form, good_xform, bad_xforms = self.build_app_with_bad_form() # Fix bad builds for bad_xform in bad_xforms: app = Application.get(bad_xform.build_id) for form in app.get_forms(): if form.xmlns == 'undefined': form.xmlns = 'my-fixed-xmlns' app.save() self._refresh_pillow() with tempdir() as tmp: with patch('corehq.apps.cleanup.tasks.UNDEFINED_XMLNS_LOG_DIR', tmp): with patch('corehq.apps.cleanup.tasks.mail_admins_async') as mocked_mail: stats, log_file_path = fix_xforms_with_missing_xmlns() self.assertTrue(mocked_mail.delay.called) self.assertTrue(stats['fixed'][DOMAIN], len(bad_xforms))
def handle(self, **options): logger.setLevel('DEBUG') app_ids_by_domain = defaultdict(set) self.force = options["force"] self.dry = "DRY RUN " if options["dry_run"] else "" self.fail_hard = options["fail_hard"] self.fup_caseref = options["fix_user_props_caseref"] self.fix_user_props = options["fix_user_properties"] or self.fup_caseref self.migrate_usercase = options["usercase"] for ident in options["app_id_or_domain"]: if not (self.migrate_usercase or self.fix_user_props): try: app = Application.get(ident) app_ids_by_domain[app.domain].add(ident) continue except ResourceNotFound: pass app_ids_by_domain[ident].update(get_app_ids_in_domain(ident)) for domain, app_ids in sorted(app_ids_by_domain.items()): logger.info('migrating %s: %s apps', domain, len(app_ids)) for app_id in app_ids: try: app = get_app(domain, app_id) if app.doc_type == "Application": if self.fix_user_props: self.fix_user_properties(app) else: self.migrate_app(app) else: logger.info("Skipping %s/%s because it is a %s", domain, app_id, app.doc_type) except Exception as e: logger.exception("skipping app %s/%s", domain, app_id) if self.fail_hard: raise e logger.info('done with migrate_app_to_cmitfb %s', self.dry)
def form_context(request, domain, app_id, module_id, form_id): app = Application.get(app_id) form_url = '{}{}'.format( settings.CLOUDCARE_BASE_URL or get_url_base(), reverse('download_xform', args=[domain, app_id, module_id, form_id])) case_id = request.GET.get('case_id') instance_id = request.GET.get('instance_id') try: form = app.get_module(module_id).get_form(form_id) except (FormNotFoundException, ModuleNotFoundException): raise Http404() form_name = list(form.name.values())[0] # make the name for the session we will use with the case and form session_name = '{app} > {form}'.format( app=app.name, form=form_name, ) if case_id: case = CaseAccessors(domain).get_case(case_id) session_name = '{0} - {1}'.format(session_name, case.name)
def test_update_user_restore(self, mock): # updating user restore should result in version change in restore resource # so that CommCare mobile will refetch the resource turn_on_demo_mode(self.user, self.domain) app = self.factory.app app.practice_mobile_worker_id = self.user._id app.save() self.assertXmlPartialEqual( self._get_restore_resource(self.user.demo_restore_id), app.create_suite(), "./user-restore") version_before = self.user.demo_restore_id turn_off_demo_mode(self.user) turn_on_demo_mode(self.user, self.domain) version_after = self.user.demo_restore_id self.assertNotEqual(version_before, version_after) # refetch so that memoized app.get_practice_user gets busted` app = Application.get(app._id) app.build_spec.version = '2.30.0' # for some reason, this gets set to an old version, after refetch self.assertXmlPartialEqual(self._get_restore_resource(version_after), app.create_suite(), "./user-restore")
def obj_get_list(self, bundle, **kwargs): application_id = bundle.request.GET.get('application_id') if not application_id: raise NotFound('application_id parameter required') domain = kwargs['domain'] couch_user = CouchUser.from_django_user(bundle.request.user) if not domain_has_privilege(domain, privileges.ZAPIER_INTEGRATION) or not couch_user.is_member_of(domain): raise ImmediateHttpResponse( HttpForbidden('You are not allowed to get list of forms for this domain') ) results = [] application = Application.get(docid=application_id) if not application: return [] forms_objects = application.get_forms(bare=False) for form_object in forms_objects: form = form_object['form'] module = form_object['module'] form_name = '{} > {} > {}'.format(application.name, module.name['en'], form.name['en']) results.append(Form(form_xmlns=form.xmlns, form_name=form_name)) return results