Ejemplo n.º 1
0
def choose_media(request, domain, app_id):
    # TODO: Add error handling
    app = get_app(domain, app_id)
    media_type = request.POST["media_type"]
    media_id = request.POST["id"]
    if media_type == "Image":
        file = CommCareImage.get(media_id)
    elif media_type == "Audio":
        file = CommCareImage.get(media_id)
    else:
        raise Http404()

    if file is None or not file.is_shared:
        return HttpResponse(json.dumps({"match_found": False}))

    file.add_domain(domain)
    app.create_mapping(file, request.POST["path"])
    if media_type == "Image":
        return HttpResponse(
            json.dumps({"match_found": True, "image": {"m_id": file._id, "url": file.url()}, "file": True})
        )
    elif media_type == "Audio":
        return HttpResponse(json.dumps({"match_found": True, "audio": {"m_id": file._id, "url": file.url()}}))
    else:
        raise Http404()
Ejemplo n.º 2
0
def choose_media(request, domain, app_id):
    # TODO: Add error handling
    app = get_app(domain, app_id)
    media_type = request.POST['media_type']
    media_id = request.POST['id']
    if media_type == 'Image':
        file = CommCareImage.get(media_id)
    elif media_type == 'Audio':
        file = CommCareImage.get(media_id)
    else:
        raise Http404()

    if file is None or not file.is_shared:
        return HttpResponse(simplejson.dumps({
            'match_found': False
        }))

    file.add_domain(domain)
    app.create_mapping(file, request.POST['path'])
    if media_type == 'Image':
        return HttpResponse(simplejson.dumps({
            'match_found': True,
            'image': {'m_id': file._id, 'url': file.url()},
            'file': True
        }))
    elif media_type == 'Audio':
        return HttpResponse(simplejson.dumps({'match_found': True, 'audio': {'m_id': file._id, 'url': file.url()}}))
    else:
        raise Http404()
Ejemplo n.º 3
0
def get_questions(domain, app_id, xmlns):
    if not app_id:
        raise QuestionListNotFound(
            _("This form is not associated with an app")
        )
    try:
        app = get_app(domain, app_id)
    except Http404:
        raise QuestionListNotFound(
            _("No app could be found")
        )
    if not isinstance(app, Application):
        raise QuestionListNotFound(
            _("Remote apps are not supported")
        )

    form = app.get_form_by_xmlns(xmlns)
    if not form:
        if xmlns == 'http://code.javarosa.org/devicereport':
            raise QuestionListNotFound(
                _("This is a Device Report")
            )
        else:
            raise QuestionListNotFound(
                _("We could not find the question list "
                  "associated with this form")
            )
    return get_questions_from_xform_node(form.wrapped_xform(), app.langs)
Ejemplo n.º 4
0
def task_creation(request, domain, app_id, module_id, form_id):
    '''
    This view is meant to be a run as a one-off script to support a specific
    app that Jeremy is writing. Running this script subsequent times on the
    same form will not have adverse affects.
    :param request:
    :param domain:
    :param app_id:
    :param module_id:
    :param form_id:
    :return:
    '''
    if request.method == 'POST':

        html_form = TaskCreationForm(request.POST)
        if html_form.is_valid():

            questions = html_form.cleaned_data['question_ids'].split()
            form = get_app(domain, app_id).modules[int(module_id)].forms[int(form_id)]
            # Make changes to the form
            message = _ucla_form_modifier(form, questions)
            return HttpResponse(message, content_type="text/plain")

        return HttpResponse("Soemthing was wrong with the form you submitted. Your CommCare form is unchanged.", content_type="text/plain")

    elif request.method == 'GET':
        html_form = TaskCreationForm()
        response = HttpResponse()
        response.write('<form action="'+reverse('ucla_task_creation', args=(domain, app_id, module_id, form_id))+'" method="post">')
        response.write(html_form.as_p())
        response.write('<p><input type="submit" value="Process Form"></p>')
        response.write("</form>")
        return response
    else:
        return HttpResponse("GET or POST only.", content_type="text/plain")
Ejemplo n.º 5
0
def choose_media(request, domain, app_id):
    # TODO: Add error handling
    app = get_app(domain, app_id)
    media_type = request.POST['media_type']
    media_id = request.POST['id']
    if media_type == 'Image':
        file = CommCareImage.get(media_id)
    elif media_type == 'Audio':
        file = CommCareImage.get(media_id)
    else:
        raise Http404()

    if file is None or not file.is_shared:
        return HttpResponse(json.dumps({
            'match_found': False
        }))

    file.add_domain(domain)
    app.create_mapping(file, request.POST['path'])
    if media_type == 'Image':
        return HttpResponse(json.dumps({
            'match_found': True,
            'image': {'m_id': file._id, 'url': file.url()},
            'file': True
        }))
    elif media_type == 'Audio':
        return HttpResponse(json.dumps({'match_found': True, 'audio': {'m_id': file._id, 'url': file.url()}}))
    else:
        raise Http404()
Ejemplo n.º 6
0
def get_custom_response_message(sender, xform, **kwargs):
    """
    This signal sends a custom response to xform submissions. 
    If the domain has one.
    """
    if xform.metadata and xform.metadata.userID:
        userID = xform.metadata.userID
        xmlns = xform.form.get("@xmlns")
        domain = xform.domain

        try:
            app = get_app(domain, xform.app_id)
        except Exception:
            app = Application.get_by_xmlns(domain, xmlns)

        if app and hasattr(app, "langs"):
            try:
                lang = xform.openrosa_headers[OPENROSA_ACCEPT_LANGUAGE]
            except (AttributeError, KeyError):
                lang = "default"
            if lang == "default":
                lang = app.build_langs[0] if app.build_langs else None
            message = app.success_message.get(lang)
            if message:
                success_message = SuccessMessage(message, userID, domain=domain, tz=timedelta(hours=0)).render()
                return ReceiverResult(
                    xml.get_simple_response_xml(success_message, nature=ResponseNature.SUBMIT_SUCCESS), Certainty.STRONG
                )
Ejemplo n.º 7
0
def get_form_list(domain):
    form_list = []
    for app in ApplicationBase.view("app_manager/applications_brief",
                                    startkey=[domain],
                                    endkey=[domain, {}]):
        latest_app = get_app(domain, app._id, latest=True)
        if latest_app.doc_type == "Application":
            lang = latest_app.langs[0]
            for m in latest_app.get_modules():
                for f in m.get_forms():
                    try:
                        module_name = m.name[lang]
                    except Exception:
                        module_name = m.name.items()[0][1]
                    try:
                        form_name = f.name[lang]
                    except Exception:
                        form_name = f.name.items()[0][1]
                    form_list.append({
                        "code":
                        f.unique_id,
                        "name":
                        app.name + "/" + module_name + "/" + form_name
                    })
    return form_list
Ejemplo n.º 8
0
def get_readable_form_data(xform):
    app_id = xform.build_id or xform.app_id
    domain = xform.domain
    xmlns = xform.xmlns
    try:
        app = get_app(domain, app_id)
    except Http404:
        raise QuestionListNotFound(
            "No app with id {} could be found".format(app_id)
        )
    if not isinstance(app, Application):
        raise QuestionListNotFound(
            "The app we found for id {} is not a {}, which are not supported."
            .format(app_id, app.__class__.__name__)
        )
    form = app.get_form_by_xmlns(xmlns)
    questions = form.wrapped_xform().get_questions(
        app.langs, include_triggers=True, include_groups=True)
    questions = [FormQuestionResponse(q) for q in questions]

    return zip_form_data_and_questions(
        strip_form_data(xform.form),
        questions_in_hierarchy(questions),
        path_context='/%s/' % xform.form.get('#type', 'data'),
        process_label=_html_interpolate_output_refs,
    )
Ejemplo n.º 9
0
 def __getitem__(self, item):
     if not self.has_key(item):
         try:
             self[item] = get_app(app_id=item, domain=self.domain)
         except Http404:
             pass
     return super(AppCache, self).__getitem__(item)
Ejemplo n.º 10
0
def get_questions(domain, app_id, xmlns):
    if not app_id:
        raise QuestionListNotFound(
            _("This form is not associated with an app")
        )
    try:
        app = get_app(domain, app_id)
    except Http404:
        raise QuestionListNotFound(
            _("No app could be found")
        )
    if not isinstance(app, Application):
        raise QuestionListNotFound(
            _("Remote apps are not supported")
        )

    form = app.get_form_by_xmlns(xmlns)
    if not form:
        if xmlns == 'http://code.javarosa.org/devicereport':
            raise QuestionListNotFound(
                _("This is a Device Report")
            )
        else:
            raise QuestionListNotFound(
                _("We could not find the question list "
                  "associated with this form")
            )
    # Search for 'READABLE FORMS TEST' for more info
    # to bootstrap a test and have it print out your form xml
    # uncomment this line. Ghetto but it works.
    # print form.wrapped_xform().render()
    return get_questions_from_xform_node(form.wrapped_xform(), app.langs)
Ejemplo n.º 11
0
def upload(request, domain, app_id):
    app = get_app(domain, app_id)
    DNS_name = "http://"+Site.objects.get(id = settings.SITE_ID).domain
    return render(request, "hqmedia/bulk_upload.html",
            {"domain": domain,
             "app": app,
             "DNS_name": DNS_name})
Ejemplo n.º 12
0
def get_custom_response_message(sender, xform, **kwargs):
    """
    This signal sends a custom response to xform submissions. 
    If the domain has one.
    """
    if xform.metadata and xform.metadata.userID:
        userID = xform.metadata.userID
        xmlns = xform.form.get('@xmlns')
        domain = xform.domain

        try:
            app = get_app(domain, xform.app_id)
        except Exception:
            app = Application.get_by_xmlns(domain, xmlns)

        if app and hasattr(app, 'langs'):
            try:
                lang = xform.openrosa_headers[OPENROSA_ACCEPT_LANGUAGE]
            except (AttributeError, KeyError):
                lang = "default"
            if lang == "default":
                lang = app.build_langs[0] if app.build_langs else None
            message = app.success_message.get(lang)
            if message:
                success_message = SuccessMessage(
                    message, userID, domain=domain,
                    tz=timedelta(hours=0)).render()
                return ReceiverResult(
                    xml.get_simple_response_xml(
                        success_message, nature=ResponseNature.SUBMIT_SUCCESS),
                    Certainty.STRONG)
Ejemplo n.º 13
0
def uploaded(request, domain, app_id):
    app = get_app(domain, app_id)
    response = {}
    errors = []
    if request.POST.get('media_type', ''):
        specific_params = dict(request.POST)
    else:
        specific_params = {}

    replace_existing = request.POST.get('replace_existing', True)
    try:
        uploaded_file = request.FILES.get('Filedata')
        data = uploaded_file.file.read()
        mime = magic.Magic(mime=True)
        content_type = mime.from_buffer(data)
        uploaded_file.file.seek(0)
        matcher = utils.HQMediaMatcher(app, domain, request.user.username, specific_params)

        license=request.POST.get('license', "")
        author=request.POST.get('author', "")
        att_notes = request.POST.get('attribution-notes', "")

        if content_type in utils.ZIP_MIMETYPES:
            zip = zipfile.ZipFile(uploaded_file)
            bad_file = zip.testzip()
            if bad_file:
                raise Exception("Bad ZIP file.")
            matched_images, matched_audio, unknown_files, errors = matcher.match_zipped(zip,
                                                                                        replace_existing_media=replace_existing,
                                                                                        license=license,
                                                                                        author=author,
                                                                                        attribution_notes=att_notes)
            response = {"unknown": unknown_files,
                        "images": matched_images,
                        "audio": matched_audio,
                        "zip": True}
        else:
            if content_type in utils.IMAGE_MIMETYPES:
                file_type = "image"
            elif content_type in utils.AUDIO_MIMETYPES:
                file_type = "audio"
            else:
                raise Exception("Unsupported content type.")
            tags = [t.strip() for t in request.POST.get('tags', '').split(' ')]
            match_found, match_map, errors = matcher.match_file(uploaded_file,
                                                                replace_existing_media=replace_existing,
                                                                shared=request.POST.get('shared', False),
                                                                tags=tags,
                                                                license=license,
                                                                author=author,
                                                                attribution_notes=att_notes)
            response = {"match_found": match_found,
                        file_type: match_map,
                        "file": True}
    except Exception as e:
        errors.append(e.message)

    response['errors'] = errors
    return HttpResponse(simplejson.dumps(response))
Ejemplo n.º 14
0
 def app(self):
     try:
         # if get_app is mainly used for views,
         # maybe it should be a classmethod of this mixin? todo
         return get_app(self.domain, self.app_id)
     except Exception:
         pass
     return None
Ejemplo n.º 15
0
def media_urls(request, domain, app_id):
    app = get_app(domain, app_id)
    refs, missing_refs = app.get_template_map(request.GET.getlist('path[]'))
    pathUrls = {}
    for ref in refs:
        pathUrls[ref['path']] = ref

    return HttpResponse(simplejson.dumps(pathUrls))
Ejemplo n.º 16
0
 def app(self):
     try:
         # if get_app is mainly used for views,
         # maybe it should be a classmethod of this mixin? todo
         return get_app(self.domain, self.app_id)
     except Exception:
         pass
     return None
Ejemplo n.º 17
0
    def save_copy(self, new_domain_name=None, user=None):
        from corehq.apps.app_manager.models import get_app
        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None  # TODO: use current user's organization (?)

        # reset the cda
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        for res in db.view('domain/related_to_domain', key=[self.name, True]):
            if not self.is_snapshot and res['value']['doc_type'] in (
                    'Application', 'RemoteApp'):
                app = get_app(self.name,
                              res['value']['_id']).get_latest_saved()
                if app:
                    self.copy_component(app.doc_type,
                                        app._id,
                                        new_domain_name,
                                        user=user)
                else:
                    self.copy_component(res['value']['doc_type'],
                                        res['value']['_id'],
                                        new_domain_name,
                                        user=user)
            else:
                self.copy_component(res['value']['doc_type'],
                                    res['value']['_id'],
                                    new_domain_name,
                                    user=user)

        new_domain.save()

        if user:

            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)

            apply_update(user, add_dom_to_user)

        return new_domain
Ejemplo n.º 18
0
def media_map(request, domain, app_id):
    app = get_app(domain, app_id)
    multimedia = app.get_media_references()

    return render(request, "hqmedia/map.html", {
        "domain": domain,
        "app": app,
        "multimedia": multimedia,
    })
Ejemplo n.º 19
0
 def app(self):
     if self.app_id:
         try:
             return get_app(self.domain, self.app_id, latest=True)
         except Http404:
             logging.error("App %s in domain %s not found for export %s" % (self.app_id, self.domain, self.get_id))
             raise AppNotFound()
     else:
         return None
Ejemplo n.º 20
0
 def app(self):
     if self.app_id:
         try:
             return get_app(self.domain, self.app_id, latest=True)
         except Http404:
             logging.error('App %s in domain %s not found for export %s' %
                           (self.app_id, self.domain, self.get_id))
             raise AppNotFound()
     else:
         return None
Ejemplo n.º 21
0
    def obj_get_list(self, bundle, domain, **kwargs):
        # There should be few enough apps per domain that doing an explicit refresh for each is OK.
        # This is the easiest way to filter remote apps
        # Later we could serialize them to their URL or whatevs but it is not that useful yet
        application_bases = ApplicationBase.by_domain(domain)

        # This wraps in the appropriate class so that is_remote_app() returns the correct answer
        applications = [get_app(domain, application_base.id) for application_base in application_bases]

        return [app for app in applications if not app.is_remote_app()]
Ejemplo n.º 22
0
    def obj_get_list(self, bundle, domain, **kwargs):
        # There should be few enough apps per domain that doing an explicit refresh for each is OK.
        # This is the easiest way to filter remote apps
        # Later we could serialize them to their URL or whatevs but it is not that useful yet
        application_bases = ApplicationBase.by_domain(domain)

        # This wraps in the appropriate class so that is_remote_app() returns the correct answer
        applications = [get_app(domain, application_base.id) for application_base in application_bases]

        return [app for app in applications if not app.is_remote_app()]
Ejemplo n.º 23
0
 def _safe_download(req, *args, **kwargs):
     domain = args[0] if len(args) > 0 else kwargs["domain"]
     app_id = args[1] if len(args) > 1 else kwargs["app_id"]
     latest = True if req.GET.get('latest') == 'true' else False
     
     try:
         req.app = get_app(domain, app_id, latest=latest)
         return f(req, *args, **kwargs)
     except (AppError, CaseError), e:
         logging.exception(e)
         messages.error(req, "Problem downloading file: %s" % e)
         return HttpResponseRedirect(reverse("corehq.apps.app_manager.views.view_app", args=[domain,app_id]))
Ejemplo n.º 24
0
def media_urls(request, domain, app_id):
    # IS THIS USED?????
    # I rewrote it so it actually produces _something_, but is it useful???
    app = get_app(domain, app_id)
    multimedia = app.get_media_references()
    pathUrls = {}
    for section, types in multimedia['references'].items():
        for media_type, info in types.items():
            for m in info['maps']:
                if m.get('path'):
                    pathUrls[m['path']] = m

    return HttpResponse(simplejson.dumps(pathUrls))
Ejemplo n.º 25
0
    def save_copy(self, new_domain_name=None, user=None):
        from corehq.apps.app_manager.models import get_app

        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)["id"]
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None  # TODO: use current user's organization (?)

        # reset stuff
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None
        new_domain.is_test = True
        new_domain.internal = InternalProperties()
        new_domain.creating_user = user.username if user else None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        for res in db.view("domain/related_to_domain", key=[self.name, True]):
            if not self.is_snapshot and res["value"]["doc_type"] in ("Application", "RemoteApp"):
                app = get_app(self.name, res["value"]["_id"]).get_latest_saved()
                if app:
                    self.copy_component(app.doc_type, app._id, new_domain_name, user=user)
                else:
                    self.copy_component(res["value"]["doc_type"], res["value"]["_id"], new_domain_name, user=user)
            else:
                self.copy_component(res["value"]["doc_type"], res["value"]["_id"], new_domain_name, user=user)

        new_domain.save()

        if user:

            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)

            apply_update(user, add_dom_to_user)

        return new_domain
Ejemplo n.º 26
0
def media_urls(request, domain, app_id):
    # IS THIS USED?????
    # I rewrote it so it actually produces _something_, but is it useful???
    app = get_app(domain, app_id)
    # todo remove get_media_references
    multimedia = app.get_media_references()
    pathUrls = {}
    for section, types in multimedia['references'].items():
        for media_type, info in types.items():
            for m in info['maps']:
                if m.get('path'):
                    pathUrls[m['path']] = m

    return HttpResponse(json.dumps(pathUrls))
Ejemplo n.º 27
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug, '')

        for user in self.users:
            last_seen = last_sync = app_name = None

            key = make_form_couch_key(self.domain, user_id=user.user_id,
                                      app_id=selected_app or None)
            xform = XFormInstance.view(
                "reports_forms/all_forms",
                startkey=key+[{}],
                endkey=key,
                include_docs=True,
                descending=True,
                reduce=False,
                limit=1,
            ).first()

            if xform:
                last_seen = xform.received_on
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}', app_name, mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append(
                [user.username_in_report, _fmt_date(last_seen), _fmt_date(last_sync), app_name or "---"]
            )
        return rows
Ejemplo n.º 28
0
def media_urls(request, domain, app_id):
    # IS THIS USED?????
    # I rewrote it so it actually produces _something_, but is it useful???
    app = get_app(domain, app_id)
    # todo remove get_media_references
    multimedia = app.get_media_references()
    pathUrls = {}
    for section, types in multimedia["references"].items():
        for media_type, info in types.items():
            for m in info["maps"]:
                if m.get("path"):
                    pathUrls[m["path"]] = m

    return HttpResponse(json.dumps(pathUrls))
Ejemplo n.º 29
0
    def _safe_download(req, *args, **kwargs):
        domain = args[0] if len(args) > 0 else kwargs["domain"]
        app_id = args[1] if len(args) > 1 else kwargs["app_id"]
        latest = True if req.GET.get('latest') == 'true' else False

        try:
            req.app = get_app(domain, app_id, latest=latest)
            return f(req, *args, **kwargs)
        except AppError, e:
            logging.exception(e)
            messages.error(req, "Problem downloading file: %s" % e)
            return HttpResponseRedirect(
                reverse("corehq.apps.app_manager.views.view_app",
                        args=[domain, app_id]))
Ejemplo n.º 30
0
def media_from_path(request, domain, app_id, file_path):
    # Not sure what the intentions were for this. I didn't see it getting used anywhere.
    # Rewrote it to use new media refs.
    # Yedi, care to comment?
    app = get_app(domain, app_id)
    multimedia = app.get_media_references()

    for section, types in multimedia['references'].items():
        for media_type, info in types.items():
            for media_map in info['maps']:
                # [10:] is to remove the 'jr://file/'
                if media_map['path'][10:] == file_path and media_map.get('url'):
                    return HttpResponseRedirect(media_map['url'])

    raise Http404('No Media Found')
Ejemplo n.º 31
0
def uploaded(request, domain, app_id):
    # todo move this over to something similar to what bulk upload does
    app = get_app(domain, app_id)
    response = {}
    errors = []

    if request.POST.get('media_type', ''):
        specific_params = dict(request.POST)
    else:
        specific_params = {}

    replace_existing = request.POST.get('replace_existing', True)
    try:
        uploaded_file = request.FILES.get('Filedata')
        data = uploaded_file.file.read()
        mime = magic.Magic(mime=True)
        content_type = mime.from_buffer(data)
        uploaded_file.file.seek(0)
        matcher = utils.HQMediaMatcher(app, domain, request.user.username, specific_params)

        license = request.POST.get('license', "")
        author = request.POST.get('author', "")
        att_notes = request.POST.get('attribution-notes', "")

        if not content_type in utils.ZIP_MIMETYPES:
            # zip files are no longer handled here todo clean this up too
            if content_type in utils.IMAGE_MIMETYPES:
                file_type = "image"
            elif content_type in utils.AUDIO_MIMETYPES:
                file_type = "audio"
            else:
                raise Exception("Unsupported content type.")
            tags = [t.strip() for t in request.POST.get('tags', '').split(' ')]
            match_found, match_map, errors = matcher.match_file(uploaded_file,
                                                                replace_existing_media=replace_existing,
                                                                shared=request.POST.get('shared', False),
                                                                tags=tags,
                                                                license=license,
                                                                author=author,
                                                                attribution_notes=att_notes)
            response = {"match_found": match_found,
                        file_type: match_map,
                        "file": True}
    except Exception as e:
        errors.append(e.message)

    response['errors'] = errors
    return HttpResponse(json.dumps(response))
Ejemplo n.º 32
0
def get_questions(domain, app_id, xmlns):
    if not app_id:
        raise QuestionListNotFound(
            _("This form is not associated with an app"))
    try:
        app = get_app(domain, app_id)
    except Http404:
        raise QuestionListNotFound(_("No app could be found"))
    if not isinstance(app, Application):
        raise QuestionListNotFound(_("Remote apps are not supported"))

    form = app.get_form_by_xmlns(xmlns)
    questions = form.wrapped_xform().get_questions(app.langs,
                                                   include_triggers=True,
                                                   include_groups=True)
    return [FormQuestionResponse(q) for q in questions]
Ejemplo n.º 33
0
def media_from_path(request, domain, app_id, file_path):
    # Not sure what the intentions were for this. I didn't see it getting used anywhere.
    # Rewrote it to use new media refs.
    # Yedi, care to comment?
    app = get_app(domain, app_id)
    # todo remove get_media_references
    multimedia = app.get_media_references()

    for section, types in multimedia['references'].items():
        for media_type, info in types.items():
            for media_map in info['maps']:
                # [10:] is to remove the 'jr://file/'
                if media_map['path'][10:] == file_path and media_map.get('url'):
                    return HttpResponseRedirect(media_map['url'])

    raise Http404('No Media Found')
Ejemplo n.º 34
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug, '')

        for user in self.users:
            last_seen = self.table_cell(-1, _("Never"))
            app_name = None

            key = make_form_couch_key(self.domain, user_id=user.user_id,
                                      app_id=selected_app or None)
            xform = XFormInstance.view(
                "reports_forms/all_forms",
                startkey=key+[{}],
                endkey=key,
                include_docs=True,
                descending=True,
                reduce=False,
                limit=1,
            ).first()

            if xform:
                last_seen = util.format_relative_date(xform.received_on)
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}', app_name, mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            rows.append(
                [user.username_in_report, last_seen, app_name or "---"]
            )
        return rows
Ejemplo n.º 35
0
def get_form_list(domain):
    form_list = []
    for app in ApplicationBase.view("app_manager/applications_brief", startkey=[domain], endkey=[domain, {}]):
        latest_app = get_app(domain, app._id, latest=True)
        if latest_app.doc_type == "Application":
            lang = latest_app.langs[0]
            for m in latest_app.get_modules():
                for f in m.get_forms():
                    try:
                        module_name = m.name[lang]
                    except Exception:
                        module_name = m.name.items()[0][1]
                    try:
                        form_name = f.name[lang]
                    except Exception:
                        form_name = f.name.items()[0][1]
                    form_list.append({"code" :  f.unique_id, "name" : app.name + "/" + module_name + "/" + form_name})
    return form_list
Ejemplo n.º 36
0
def media_map(request, domain, app_id):
    app = get_app(domain, app_id)
    sorted_images, sorted_audio, has_error = utils.get_sorted_multimedia_refs(app)

    images, missing_image_refs = app.get_template_map(sorted_images)
    audio, missing_audio_refs = app.get_template_map(sorted_audio)

    return render_to_response(request, "hqmedia/map.html", {
        "domain": domain,
        "app": app,
        "multimedia": {
         "images": images,
         "audio": audio,
         "has_error": has_error
        },
        "missing_image_refs": missing_image_refs,
        "missing_audio_refs": missing_audio_refs
    })
Ejemplo n.º 37
0
    def save_copy(self, new_domain_name=None, user=None):
        from corehq.apps.app_manager.models import get_app
        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None # TODO: use current user's organization (?)

        # reset the cda
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        for res in db.view('domain/related_to_domain', key=[self.name, True]):
            if not self.is_snapshot and res['value']['doc_type'] in ('Application', 'RemoteApp'):
                app = get_app(self.name, res['value']['_id']).get_latest_saved()
                if app:
                    self.copy_component(app.doc_type, app._id, new_domain_name, user=user)
                else:
                    self.copy_component(res['value']['doc_type'], res['value']['_id'], new_domain_name, user=user)
            else:
                self.copy_component(res['value']['doc_type'], res['value']['_id'], new_domain_name, user=user)

        new_domain.save()

        if user:
            user.add_domain_membership(new_domain_name, is_admin=True)
            user.save()

        return new_domain
Ejemplo n.º 38
0
def media_from_path(request, domain, app_id, file_path):
    # Not sure what the intentions were for this. I didn't see it getting used anywhere.
    # Rewrote it to use new media refs.
    # Yedi, care to comment?
    app = get_app(domain, app_id)
    if isinstance(app, RemoteApp):
        raise Http404("Media not yet available for remote apps")

    # todo remove get_media_references
    multimedia = app.get_media_references()

    for section, types in multimedia["references"].items():
        for media_type, info in types.items():
            for media_map in info["maps"]:
                # [10:] is to remove the 'jr://file/'
                if media_map["path"][10:] == file_path and media_map.get("url"):
                    return HttpResponseRedirect(media_map["url"])

    raise Http404("No Media Found")
Ejemplo n.º 39
0
def get_questions(domain, app_id, xmlns):
    if not app_id:
        raise QuestionListNotFound(
            _("This form is not associated with an app")
        )
    try:
        app = get_app(domain, app_id)
    except Http404:
        raise QuestionListNotFound(
            _("No app could be found")
        )
    if not isinstance(app, Application):
        raise QuestionListNotFound(
            _("Remote apps are not supported")
        )

    form = app.get_form_by_xmlns(xmlns)
    questions = form.wrapped_xform().get_questions(
        app.langs, include_triggers=True, include_groups=True)
    return [FormQuestionResponse(q) for q in questions]
Ejemplo n.º 40
0
    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 = None

            key = make_form_couch_key(self.domain, user_id=user.get('user_id'), app_id=selected_app if selected_app else None)
            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)
                build_version = get_build_version(data) or UNKNOWN

                if getattr(data, 'app_id', None):
                    try:
                        app = get_app(self.domain, data.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = "%s [%s]" % (app.name, build_version)
                else:
                    app_name = get_meta_appversion_text(data)
                    
                app_name = app_name or _("Unknown App")

            if app_name is None and selected_app:
                continue

            rows.append([user.get('username_in_report'), last_seen, app_name or "---"])
        return rows
Ejemplo n.º 41
0
def task_creation(request, domain, app_id, module_id, form_id):
    '''
    This view is meant to be a run as a one-off script to support a specific
    app that Jeremy is writing. Running this script subsequent times on the
    same form will not have adverse affects.
    :param request:
    :param domain:
    :param app_id:
    :param module_id:
    :param form_id:
    :return:
    '''
    if request.method == 'POST':

        html_form = TaskCreationForm(request.POST)
        if html_form.is_valid():

            questions = html_form.cleaned_data['question_ids'].split()
            form = get_app(domain,
                           app_id).modules[int(module_id)].forms[int(form_id)]
            # Make changes to the form
            message = _ucla_form_modifier(form, questions)
            return HttpResponse(message, content_type="text/plain")

        return HttpResponse(
            "Soemthing was wrong with the form you submitted. Your CommCare form is unchanged.",
            content_type="text/plain")

    elif request.method == 'GET':
        html_form = TaskCreationForm()
        response = HttpResponse()
        response.write('<form action="' + reverse(
            'ucla_task_creation', args=(domain, app_id, module_id, form_id)) +
                       '" method="post">')
        response.write(html_form.as_p())
        response.write('<p><input type="submit" value="Process Form"></p>')
        response.write("</form>")
        return response
    else:
        return HttpResponse("GET or POST only.", content_type="text/plain")
Ejemplo n.º 42
0
def get_questions(domain, app_id, xmlns):
    if not app_id:
        raise QuestionListNotFound(
            _("This form is not associated with an app"))
    try:
        app = get_app(domain, app_id)
    except Http404:
        raise QuestionListNotFound(_("No app could be found"))
    if not isinstance(app, Application):
        raise QuestionListNotFound(_("Remote apps are not supported"))

    form = app.get_form_by_xmlns(xmlns)
    if not form:
        if xmlns == 'http://code.javarosa.org/devicereport':
            raise QuestionListNotFound(_("This is a Device Report"))
        else:
            raise QuestionListNotFound(
                _("We could not find the question list "
                  "associated with this form"))
    # Search for 'READABLE FORMS TEST' for more info
    # to bootstrap a test and have it print out your form xml
    # uncomment this line. Ghetto but it works.
    # print form.wrapped_xform().render()
    return get_questions_from_xform_node(form.wrapped_xform(), app.langs)
Ejemplo n.º 43
0
def look_up_app_json(domain, app_id):
    app = get_app(domain, app_id)
    if app.is_remote_app():
        raise RemoteAppError()
    assert(app.domain == domain)
    return get_app_json(app)
Ejemplo n.º 44
0
def look_up_app_json(domain, app_id):
    app = get_app(domain, app_id)
    if app.is_remote_app():
        raise RemoteAppError()
    assert (app.domain == domain)
    return get_app_json(app)
Ejemplo n.º 45
0
def cloudcare_main(request, domain, urlPath):
    try:
        preview = string_to_boolean(request.REQUEST.get("preview", "false"))
    except ValueError:
        # this is typically only set at all if it's intended to be true so this
        # is a reasonable default for "something went wrong"
        preview = True

    app_access = ApplicationAccess.get_by_domain(domain)

    if not preview:
        apps = get_cloudcare_apps(domain)
        if request.project.use_cloudcare_releases:
            # replace the apps with the last starred build of each app, removing the ones that aren't starred
            apps = filter(lambda app: app.is_released, [get_app(domain, app['_id'], latest=True) for app in apps])
            # convert to json
            apps = [get_app_json(app) for app in apps]
        else:
            # legacy functionality - use the latest build regardless of stars
            apps = [get_app_json(ApplicationBase.get_latest_build(domain, app['_id'])) for app in apps]

    else:
        apps = ApplicationBase.view('app_manager/applications_brief', startkey=[domain], endkey=[domain, {}])
        apps = [get_app_json(app) for app in apps if app and app.application_version == V2]

    # trim out empty apps
    apps = filter(lambda app: app, apps)
    apps = filter(lambda app: app_access.user_can_access_app(request.couch_user, app), apps)
    
    def _default_lang():
        if apps:
            # unfortunately we have to go back to the DB to find this
            return Application.get(apps[0]["_id"]).build_langs[0]
        else:
            return "en"

    # default language to user's preference, followed by 
    # first app's default, followed by english
    language = request.couch_user.language or _default_lang()
    
    def _url_context():
        # given a url path, returns potentially the app and case, if they're
        # selected. the front end optimizes with these to avoid excess server
        # calls

        # there's an annoying dependency between this logic and backbone's
        # url routing that seems hard to solve well. this needs to be synced
        # with apps.js if anything changes

        # for apps anything with "view/app/" works

        # for cases it will be:
        # "view/:app/:module/:form/case/:case/"
        
        # could use regex here but this is actually simpler with the potential
        # absence of a trailing slash
        split = urlPath.split('/')
        app_id = split[1] if len(split) >= 2 else None
        case_id = split[5] if len(split) >= 6 else None
        
        app = None
        if app_id:
            if app_id in [a['_id'] for a in apps]:
                app = look_up_app_json(domain, app_id)
            else:
                messages.info(request, _("That app is no longer valid. Try using the "
                                         "navigation links to select an app."))
        if app is None and len(apps) == 1:
            app = look_up_app_json(domain, apps[0]['_id'])

        def _get_case(domain, case_id):
            case = CommCareCase.get(case_id)
            assert case.domain == domain, "case %s not in %s" % (case_id, domain)
            return case.get_json()
        
        case = _get_case(domain, case_id) if case_id else None
        return {
            "app": app,
            "case": case
        }

    context = {
       "domain": domain,
       "language": language,
       "apps": apps,
       "apps_raw": apps,
       "preview": preview,
       "maps_api_key": settings.GMAPS_API_KEY,
       'offline_enabled': toggles.OFFLINE_CLOUDCARE.enabled(request.user.username),
       'sessions_enabled': request.couch_user.is_commcare_user()
    }
    context.update(_url_context())
    return render(request, "cloudcare/cloudcare_home.html", context)
Ejemplo n.º 46
0
def process_bulk_upload_zip(processing_id,
                            domain,
                            app_id,
                            username=None,
                            share_media=False,
                            license_name=None,
                            author=None,
                            attribution_notes=None,
                            replace_existing=False):
    """
        Responsible for processing the uploaded zip from Bulk Upload.
    """
    status = BulkMultimediaStatusCache.get(processing_id)

    if not status:
        # no download data available, abort
        return

    app = get_app(domain, app_id)

    status.in_celery = True
    status.save()

    try:
        saved_file = StringIO.StringIO()
        saved_ref = DownloadBase.get(processing_id)
        data = saved_ref.get_content()
        saved_file.write(data)
    except Exception as e:
        status.mark_with_error(
            _("Could not fetch cached bulk upload file. Error: %s." % e))
        return

    try:
        saved_file.seek(0)
        uploaded_zip = zipfile.ZipFile(saved_file)
    except Exception as e:
        status.mark_with_error(_("Error opening file as zip file: %s" % e))
        return

    if uploaded_zip.testzip():
        status.mark_with_error(
            _("Error encountered processing Zip File. File doesn't look valid."
              ))
        return

    zipped_files = uploaded_zip.namelist()
    status.total_files = len(zipped_files)
    checked_paths = []

    try:
        for index, path in enumerate(zipped_files):
            status.update_progress(len(checked_paths))
            checked_paths.append(path)
            file_name = os.path.basename(path)
            try:
                data = uploaded_zip.read(path)
            except Exception as e:
                status.add_unmatched_path(path,
                                          _("Error reading file: %s" % e))
                continue

            media_class = CommCareMultimedia.get_class_by_data(data,
                                                               filename=path)
            if not media_class:
                status.add_skipped_path(path,
                                        CommCareMultimedia.get_mime_type(data))
                continue

            app_paths = list(app.get_all_paths_of_type(media_class.__name__))
            app_paths_lower = [p.lower() for p in app_paths]
            form_path = media_class.get_form_path(path, lowercase=True)

            if not form_path in app_paths_lower:
                status.add_unmatched_path(
                    path,
                    _("Did not match any %s paths in application." %
                      media_class.get_nice_name()))
                continue

            index_of_path = app_paths_lower.index(form_path)
            form_path = app_paths[
                index_of_path]  # this is the correct capitalization as specified in the form

            multimedia = media_class.get_by_data(data)
            if not multimedia:
                status.add_unmatched_path(
                    path,
                    _("Matching path found, but could not save the data to couch."
                      ))
                continue

            is_new = not form_path in app.multimedia_map.keys()
            is_updated = multimedia.attach_data(
                data,
                original_filename=file_name,
                username=username,
                replace_attachment=replace_existing)

            if not is_updated and not getattr(multimedia, '_id'):
                status.add_unmatched_path(
                    form_path,
                    _("Matching path found, but didn't save new multimedia correctly."
                      ))
                continue

            if is_updated or is_new:
                multimedia.add_domain(domain, owner=True)
                if share_media:
                    multimedia.update_or_add_license(
                        domain,
                        type=license_name,
                        author=author,
                        attribution_notes=attribution_notes)
                app.create_mapping(multimedia, form_path)

            media_info = multimedia.get_media_info(form_path,
                                                   is_updated=is_updated,
                                                   original_path=path)
            status.add_matched_path(media_class, media_info)

        status.update_progress(len(checked_paths))
    except Exception as e:
        status.mark_with_error(_("Error while processing zip: %s" % e))
    uploaded_zip.close()

    status.complete = True
    status.save()
Ejemplo n.º 47
0
    def save_copy(self, new_domain_name=None, user=None, ignore=None):
        from corehq.apps.app_manager.models import get_app
        from corehq.apps.reminders.models import CaseReminderHandler

        ignore = ignore if ignore is not None else []
        if new_domain_name is not None and Domain.get_by_name(new_domain_name):
            return None
        db = get_db()

        new_id = db.copy_doc(self.get_id)['id']
        if new_domain_name is None:
            new_domain_name = new_id
        new_domain = Domain.get(new_id)
        new_domain.name = new_domain_name
        new_domain.copy_history = self.get_updated_history()
        new_domain.is_snapshot = False
        new_domain.snapshot_time = None
        new_domain.organization = None  # TODO: use current user's organization (?)

        # reset stuff
        new_domain.cda.signed = False
        new_domain.cda.date = None
        new_domain.cda.type = None
        new_domain.cda.user_id = None
        new_domain.cda.user_ip = None
        new_domain.is_test = "none"
        new_domain.internal = InternalProperties()
        new_domain.creating_user = user.username if user else None

        for field in self._dirty_fields:
            if hasattr(new_domain, field):
                delattr(new_domain, field)

        new_comps = {}  # a mapping of component's id to it's copy
        for res in db.view('domain/related_to_domain', key=[self.name, True]):
            if not self.is_snapshot and res['value']['doc_type'] in (
                    'Application', 'RemoteApp'):
                app = get_app(self.name,
                              res['value']['_id']).get_latest_saved()
                if app:
                    comp = self.copy_component(app.doc_type,
                                               app._id,
                                               new_domain_name,
                                               user=user)
                else:
                    comp = self.copy_component(res['value']['doc_type'],
                                               res['value']['_id'],
                                               new_domain_name,
                                               user=user)
            elif res['value']['doc_type'] not in ignore:
                comp = self.copy_component(res['value']['doc_type'],
                                           res['value']['_id'],
                                           new_domain_name,
                                           user=user)
            else:
                comp = None
            if comp:
                new_comps[res['value']['_id']] = comp

        new_domain.save()

        if user:

            def add_dom_to_user(user):
                user.add_domain_membership(new_domain_name, is_admin=True)

            apply_update(user, add_dom_to_user)

        def update_events(handler):
            """
            Change the form_unique_id to the proper form for each event in a newly copied CaseReminderHandler
            """
            from corehq.apps.app_manager.models import FormBase
            for event in handler.events:
                if not event.form_unique_id:
                    continue
                form = FormBase.get_form(event.form_unique_id)
                form_app = form.get_app()
                m_index, f_index = form_app.get_form_location(form.unique_id)
                form_copy = new_comps[form_app._id].get_module(
                    m_index).get_form(f_index)
                event.form_unique_id = form_copy.unique_id

        def update_for_copy(handler):
            handler.active = False
            update_events(handler)

        if 'CaseReminderHandler' not in ignore:
            for handler in CaseReminderHandler.get_handlers(new_domain_name):
                apply_update(handler, update_for_copy)

        return new_domain
Ejemplo n.º 48
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug,
                                               '')

        def _fmt_date(date):
            def _timedelta_class(delta):
                if delta > timedelta(days=7):
                    return "label label-important"
                elif delta > timedelta(days=3):
                    return "label label-warning"
                else:
                    return "label label-success"

            if not date:
                return self.table_cell(
                    -1, '<span class="label">{0}</span>'.format(_("Never")))
            else:
                return self.table_cell(
                    date.toordinal(),
                    '<span class="{cls}">{text}</span>'.format(
                        cls=_timedelta_class(datetime.utcnow() - date),
                        text=naturaltime(date),
                    ))

        for user in self.users:
            last_seen = last_sync = app_name = None

            key = make_form_couch_key(self.domain,
                                      user_id=user.user_id,
                                      app_id=selected_app or None)
            xform = XFormInstance.view(
                "reports_forms/all_forms",
                startkey=key + [{}],
                endkey=key,
                include_docs=True,
                descending=True,
                reduce=False,
                limit=1,
            ).first()

            if xform:
                last_seen = xform.received_on
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}',
                    app_name,
                    mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append([
                user.username_in_report,
                _fmt_date(last_seen),
                _fmt_date(last_sync), app_name or "---"
            ])
        return rows
Ejemplo n.º 49
0
def cloudcare_main(request, domain, urlPath):
    try:
        preview = string_to_boolean(request.REQUEST.get("preview", "false"))
    except ValueError:
        # this is typically only set at all if it's intended to be true so this
        # is a reasonable default for "something went wrong"
        preview = True

    app_access = ApplicationAccess.get_by_domain(domain)

    if not preview:
        apps = get_cloudcare_apps(domain)
        if request.project.use_cloudcare_releases:
            # replace the apps with the last starred build of each app, removing the ones that aren't starred
            apps = filter(
                lambda app: app.is_released,
                [get_app(domain, app['_id'], latest=True) for app in apps])
            # convert to json
            apps = [get_app_json(app) for app in apps]
        else:
            # legacy functionality - use the latest build regardless of stars
            apps = [
                get_app_json(
                    ApplicationBase.get_latest_build(domain, app['_id']))
                for app in apps
            ]

    else:
        apps = ApplicationBase.view('app_manager/applications_brief',
                                    startkey=[domain],
                                    endkey=[domain, {}])
        apps = [
            get_app_json(app) for app in apps
            if app and app.application_version == V2
        ]

    # trim out empty apps
    apps = filter(lambda app: app, apps)
    apps = filter(
        lambda app: app_access.user_can_access_app(request.couch_user, app),
        apps)

    def _default_lang():
        if apps:
            # unfortunately we have to go back to the DB to find this
            return Application.get(apps[0]["_id"]).build_langs[0]
        else:
            return "en"

    # default language to user's preference, followed by
    # first app's default, followed by english
    language = request.couch_user.language or _default_lang()

    def _url_context():
        # given a url path, returns potentially the app, parent, and case, if
        # they're selected. the front end optimizes with these to avoid excess
        # server calls

        # there's an annoying dependency between this logic and backbone's
        # url routing that seems hard to solve well. this needs to be synced
        # with apps.js if anything changes

        # for apps anything with "view/app/" works

        # for cases it will be:
        # "view/:app/:module/:form/case/:case/"

        # if there are parent cases, it will be:
        # "view/:app/:module/:form/parent/:parent/case/:case/

        # could use regex here but this is actually simpler with the potential
        # absence of a trailing slash
        split = urlPath.split('/')
        app_id = split[1] if len(split) >= 2 else None

        if len(split) >= 5 and split[4] == "parent":
            parent_id = split[5]
            case_id = split[7] if len(split) >= 7 else None
        else:
            parent_id = None
            case_id = split[5] if len(split) >= 6 else None

        app = None
        if app_id:
            if app_id in [a['_id'] for a in apps]:
                app = look_up_app_json(domain, app_id)
            else:
                messages.info(
                    request,
                    _("That app is no longer valid. Try using the "
                      "navigation links to select an app."))
        if app is None and len(apps) == 1:
            app = look_up_app_json(domain, apps[0]['_id'])

        def _get_case(domain, case_id):
            case = CommCareCase.get(case_id)
            assert case.domain == domain, "case %s not in %s" % (case_id,
                                                                 domain)
            return case.get_json()

        case = _get_case(domain, case_id) if case_id else None
        if parent_id is None and case is not None:
            parent_id = case.get('indices', {}).get('parent',
                                                    {}).get('case_id', None)