Exemplo n.º 1
0
def get_block(
        routing_path,
        schema,
        metadata,
        answer_store,
        eq_id,
        form_type,
        collection_id,
        group_id,  # pylint: disable=too-many-locals
        group_instance,
        block_id):
    current_location = Location(group_id, group_instance, block_id)
    completeness = get_completeness(current_user)
    router = Router(schema, routing_path, completeness, current_location)

    if not router.can_access_location():
        next_location = router.get_next_location()
        return _redirect_to_location(collection_id, eq_id, form_type,
                                     next_location)

    block = _get_block_json(current_location, schema, answer_store, metadata)
    context = _get_context(routing_path, block, current_location, schema)

    return _render_page(block['type'], context, current_location, schema,
                        answer_store, metadata, routing_path)
    def test_get_section_return_location_when_section_complete_section_summary(
            self):
        schema = load_schema_from_name("test_hub_and_spoke")

        router = Router(
            schema,
            self.answer_store,
            self.list_store,
            self.progress_store,
            self.metadata,
        )

        routing_path = RoutingPath(
            ["proxy", "accommodation-details-summary"],
            section_id="accommodation-section",
        )
        location_when_section_complete = router.get_section_return_location_when_section_complete(
            routing_path=routing_path)
        self.assertEqual(
            location_when_section_complete,
            Location(
                section_id="accommodation-section",
                block_id="accommodation-details-summary",
            ),
        )
    def test_get_first_incomplete_location_in_section(self):
        schema = load_schema_from_name("test_section_summary")

        progress_store = ProgressStore([{
            "section_id": "property-details-section",
            "list_item_id": None,
            "status": CompletionStatus.COMPLETED,
            "block_ids": ["insurance-type"],
        }])

        router = Router(schema, self.answer_store, self.list_store,
                        progress_store, self.metadata)

        section_routing_path = RoutingPath(
            ["insurance-type", "insurance-address"],
            section_id="property-details-section",
        )

        incomplete = router.get_first_incomplete_location_for_section(
            routing_path=section_routing_path)

        self.assertEqual(
            incomplete,
            Location(section_id="property-details-section",
                     block_id="insurance-address"),
        )
Exemplo n.º 4
0
    def test_section_summary_accessible_when_section_complete(self):
        schema = load_schema_from_params('test', 'is_skipping_to_end')

        current_location = Location('test-skipping-section-summary-group-2', 0,
                                    'test-skipping-section-summary-2')

        routing_path = [
            Location('test-skipping-group', 0, 'test-skipping-forced'),
            Location('test-skipping-group', 0, 'test-skipping-optional'),
            Location('test-skipping-section-summary-group', 0,
                     'test-skipping-section-summary'),
            Location('test-skipping-group-2', 0, 'test-skipping-forced-2'),
            Location('test-skipping-group-2', 0, 'test-skipping-optional-2'),
            Location('test-skipping-section-summary-group-2', 0,
                     'test-skipping-section-summary-2'),
            Location('summary-group', 0, 'summary')
        ]

        completed_blocks = [
            Location('test-skipping-group', 0, 'test-skipping-forced'),
            Location('test-skipping-group-2', 0, 'test-skipping-forced-2'),
            Location('test-skipping-group-2', 0, 'test-skipping-optional-2'),
            Location('test-skipping-section-summary-group-2', 0,
                     'test-skipping-section-summary-2')
        ]

        completeness = Completeness(schema,
                                    answer_store=MagicMock(),
                                    completed_blocks=completed_blocks,
                                    routing_path=routing_path,
                                    metadata={})
        router = Router(schema, routing_path, completeness, current_location)

        self.assertTrue(router.can_access_location())
        self.assertEqual(routing_path[1], router.get_next_location())
Exemplo n.º 5
0
def get_questionnaire(schema, questionnaire_store):
    router = Router(
        schema,
        questionnaire_store.answer_store,
        questionnaire_store.list_store,
        questionnaire_store.progress_store,
        questionnaire_store.metadata,
    )

    if not router.can_access_hub():
        redirect_location = router.get_first_incomplete_location_in_survey()
        return redirect(redirect_location.url())

    language_code = get_session_store().session_data.language_code

    hub = HubContext(
        language=language_code,
        schema=schema,
        answer_store=questionnaire_store.answer_store,
        list_store=questionnaire_store.list_store,
        progress_store=questionnaire_store.progress_store,
        metadata=questionnaire_store.metadata,
    )

    hub_context = hub.get_context(
        router.is_survey_complete(), router.enabled_section_ids
    )

    return render_template("hub", content=hub_context)
    def test_cant_access_location_not_on_allowable_path(self):
        schema = load_schema_from_name("test_unit_patterns")

        router = Router(
            schema,
            self.answer_store,
            self.list_store,
            self.progress_store,
            self.metadata,
        )

        current_location = Location(section_id="default-section",
                                    block_id="set-duration-units-block")
        routing_path = RoutingPath(
            [
                "set-length-units-block",
                "set-duration-units-block",
                "set-area-units-block",
                "set-volume-units-block",
                "summary",
            ],
            section_id="default-section",
        )

        can_access_location = router.can_access_location(
            current_location, routing_path)
        self.assertFalse(can_access_location)
Exemplo n.º 7
0
    def __init__(self, schema, questionnaire_store, section_id, list_item_id, language):
        self._schema = schema
        self._questionnaire_store = questionnaire_store
        self._section_id = section_id
        self._list_item_id = list_item_id
        self._language = language
        self._router = Router(
            schema,
            questionnaire_store.answer_store,
            questionnaire_store.list_store,
            questionnaire_store.progress_store,
            questionnaire_store.metadata,
            questionnaire_store.response_metadata,
        )
        if not self._is_valid_location():
            raise InvalidLocationException(f"location {self._section_id} is not valid")

        self.current_location = Location(
            section_id=self._section_id,
            list_name=self._schema.get_repeating_list_for_section(self._section_id),
            list_item_id=self._list_item_id,
        )

        self._routing_path = self._router.routing_path(
            section_id=self._section_id, list_item_id=self._list_item_id
        )
Exemplo n.º 8
0
class SectionHandler:
    def __init__(self, schema, questionnaire_store, section_id, list_item_id, language):
        self._schema = schema
        self._questionnaire_store = questionnaire_store
        self._section_id = section_id
        self._list_item_id = list_item_id
        self._language = language
        self._router = Router(
            schema,
            questionnaire_store.answer_store,
            questionnaire_store.list_store,
            questionnaire_store.progress_store,
            questionnaire_store.metadata,
            questionnaire_store.response_metadata,
        )
        if not self._is_valid_location():
            raise InvalidLocationException(f"location {self._section_id} is not valid")

        self.current_location = Location(
            section_id=self._section_id,
            list_name=self._schema.get_repeating_list_for_section(self._section_id),
            list_item_id=self._list_item_id,
        )

        self._routing_path = self._router.routing_path(
            section_id=self._section_id, list_item_id=self._list_item_id
        )

    def get_context(self):
        section_summary_context = SectionSummaryContext(
            self._language,
            self._schema,
            self._questionnaire_store.answer_store,
            self._questionnaire_store.list_store,
            self._questionnaire_store.progress_store,
            self._questionnaire_store.metadata,
            self._questionnaire_store.response_metadata,
            self._routing_path,
            self.current_location,
        )
        return section_summary_context()

    def get_next_location_url(self):
        return self._router.get_next_location_url_for_end_of_section()

    def get_previous_location_url(self):
        return self._router.get_last_location_in_section(self._routing_path).url()

    def get_resume_url(self):
        return self._router.get_section_resume_url(self._routing_path)

    def can_display_summary(self):
        return self._router.can_display_section_summary(
            self._section_id, self._list_item_id
        )

    def _is_valid_location(self):
        return self._section_id in self._router.enabled_section_ids
Exemplo n.º 9
0
def post_block(
        routing_path,
        schema,
        metadata,
        collection_metadata,
        answer_store,
        eq_id,
        form_type,
        collection_id,
        group_id,  # pylint: disable=too-many-locals
        group_instance,
        block_id):
    current_location = Location(group_id, group_instance, block_id)
    completeness = get_completeness(current_user)
    router = Router(schema, routing_path, completeness, current_location)

    if not router.can_access_location():
        next_location = router.get_next_location()
        return _redirect_to_location(collection_id, eq_id, form_type,
                                     next_location)

    block = _get_block_json(current_location, schema, answer_store, metadata)

    schema_context = _get_schema_context(routing_path, current_location,
                                         metadata, collection_metadata,
                                         answer_store, schema)

    rendered_block = renderer.render(block, **schema_context)

    form = _generate_wtf_form(request.form, rendered_block, current_location,
                              schema)

    if 'action[save_sign_out]' in request.form:
        return _save_sign_out(routing_path, current_location, form, schema,
                              answer_store, metadata)

    if form.validate():
        _set_started_at_metadata_if_required(form, collection_metadata)
        _update_questionnaire_store(current_location, form, schema)
        next_location = path_finder.get_next_location(
            current_location=current_location)

        if _is_end_of_questionnaire(block, next_location):
            return submit_answers(routing_path, eq_id, form_type, schema)

        return redirect(_next_location_url(next_location))

    context = build_view_context(block['type'], metadata, schema, answer_store,
                                 schema_context, rendered_block,
                                 current_location, form)

    return _render_page(block['type'], context, current_location, schema,
                        answer_store, metadata, routing_path)
Exemplo n.º 10
0
def _submit_data(user):
    answer_store = get_answer_store(user)

    if answer_store:
        questionnaire_store = get_questionnaire_store(user.user_id,
                                                      user.user_ik)
        answer_store = questionnaire_store.answer_store
        metadata = questionnaire_store.metadata
        response_metadata = questionnaire_store.response_metadata
        progress_store = questionnaire_store.progress_store
        list_store = questionnaire_store.list_store
        submitted_at = datetime.now(timezone.utc)
        schema = load_schema_from_metadata(metadata)

        router = Router(
            schema,
            answer_store,
            list_store,
            progress_store,
            metadata,
            response_metadata,
        )
        full_routing_path = router.full_routing_path()

        message = json_dumps(
            convert_answers(
                schema,
                questionnaire_store,
                full_routing_path,
                submitted_at,
                flushed=True,
            ))

        encrypted_message = encrypt(message, current_app.eq["key_store"],
                                    KEY_PURPOSE_SUBMISSION)

        sent = current_app.eq["submitter"].send_message(
            encrypted_message,
            tx_id=metadata.get("tx_id"),
            case_id=metadata["case_id"],
        )

        if not sent:
            raise SubmissionFailedException()

        get_questionnaire_store(user.user_id, user.user_ik).delete()
        logger.info("successfully flushed answers")
        return True

    logger.info("no answers found to flush")
    return False
    def test_is_survey_not_complete(self):
        schema = load_schema_from_name("test_textfield")

        router = Router(
            schema,
            self.answer_store,
            self.list_store,
            self.progress_store,
            self.metadata,
        )

        is_survey_complete = router.is_survey_complete()

        self.assertFalse(is_survey_complete)
    def test_full_routing_path_with_repeating_sections(self):
        schema = load_schema_from_name(
            "test_repeating_sections_with_hub_and_spoke")

        list_store = ListStore([{
            "items": ["abc123", "123abc"],
            "name": "people",
            "primary_person": "abc123",
        }])

        router = Router(schema, self.answer_store, list_store,
                        self.progress_store, self.metadata)

        routing_path = router.full_routing_path()

        expected_path = [
            RoutingPath(
                [
                    "primary-person-list-collector",
                    "list-collector",
                    "next-interstitial",
                    "another-list-collector-block",
                    "visitors-block",
                ],
                section_id="section",
                list_name=None,
                list_item_id=None,
            ),
            RoutingPath(
                [
                    "proxy", "date-of-birth", "confirm-dob", "sex",
                    "personal-summary"
                ],
                section_id="personal-details-section",
                list_name="people",
                list_item_id="abc123",
            ),
            RoutingPath(
                [
                    "proxy", "date-of-birth", "confirm-dob", "sex",
                    "personal-summary"
                ],
                section_id="personal-details-section",
                list_name="people",
                list_item_id="123abc",
            ),
        ]

        self.assertEqual(routing_path, expected_path)
    def test_is_survey_complete(self):
        schema = load_schema_from_name("test_textfield")
        progress_store = ProgressStore([{
            "section_id": "default-section",
            "list_item_id": None,
            "status": CompletionStatus.COMPLETED,
            "block_ids": ["name-block"],
        }])

        router = Router(schema, self.answer_store, self.list_store,
                        progress_store, self.metadata)

        is_survey_complete = router.is_survey_complete()

        self.assertTrue(is_survey_complete)
Exemplo n.º 14
0
def login():
    """
    Initial url processing - expects a token parameter and then will authenticate this token. Once authenticated
    it will be placed in the users session
    :return: a 302 redirect to the next location for the user
    """
    # logging in again clears any session state
    if cookie_session:
        cookie_session.clear()

    decrypted_token = decrypt_token(request.args.get('token'))
    validate_jti(decrypted_token)

    claims = parse_runner_claims(decrypted_token)

    g.schema = load_schema_from_metadata(claims)
    schema_metadata = g.schema.json['metadata']
    validate_metadata(claims, schema_metadata)

    eq_id = claims['eq_id']
    form_type = claims['form_type']
    tx_id = claims['tx_id']
    ru_ref = claims['ru_ref']

    logger.bind(eq_id=eq_id, form_type=form_type, tx_id=tx_id, ru_ref=ru_ref)
    logger.info('decrypted token and parsed metadata')

    store_session(claims)

    cookie_session['theme'] = g.schema.json['theme']
    cookie_session['survey_title'] = g.schema.json['title']
    cookie_session['expires_in'] = get_session_timeout_in_seconds(g.schema)

    if claims.get('account_service_url'):
        cookie_session['account_service_url'] = claims.get(
            'account_service_url')

    if claims.get('account_service_log_out_url'):
        cookie_session['account_service_log_out_url'] = claims.get(
            'account_service_log_out_url')

    routing_path = path_finder.get_full_routing_path()
    completeness = get_completeness(current_user)
    router = Router(g.schema, routing_path, completeness)

    next_location = router.get_next_location()

    return redirect(next_location.url(claims))
Exemplo n.º 15
0
    def __init__(
        self,
        language: str,
        schema: QuestionnaireSchema,
        answer_store: AnswerStore,
        list_store: ListStore,
        progress_store: ProgressStore,
        metadata: Mapping[str, Any],
        response_metadata: Mapping,
    ):
        self._language = language
        self._schema = schema
        self._answer_store = answer_store
        self._list_store = list_store
        self._progress_store = progress_store
        self._metadata = metadata
        self._response_metadata = response_metadata

        self._router = Router(
            self._schema,
            self._answer_store,
            self._list_store,
            self._progress_store,
            self._metadata,
            self._response_metadata,
        )

        self._placeholder_renderer = PlaceholderRenderer(
            language=self._language,
            answer_store=self._answer_store,
            list_store=self._list_store,
            metadata=self._metadata,
            response_metadata=self._response_metadata,
            schema=self._schema,
        )
    def test_is_path_not_complete(self):
        schema = load_schema_from_name("test_textfield")

        router = Router(
            schema,
            self.answer_store,
            self.list_store,
            self.progress_store,
            self.metadata,
        )

        routing_path = router.routing_path(section_id="default-section")

        is_path_complete = router.is_path_complete(routing_path)

        self.assertFalse(is_path_complete)
Exemplo n.º 17
0
def dump_routing(schema, questionnaire_store):
    router = Router(
        schema,
        questionnaire_store.answer_store,
        questionnaire_store.list_store,
        questionnaire_store.progress_store,
        questionnaire_store.metadata,
    )

    response = [{
        "section_id": routing_path.section_id,
        "list_item_id": routing_path.list_item_id,
        "routing_path": routing_path.block_ids,
    } for routing_path in router.full_routing_path()]

    return json_dumps(response), 200
Exemplo n.º 18
0
def get_thank_you(schema, metadata, eq_id, form_type):
    session_data = get_session_store().session_data
    completeness = get_completeness(current_user)

    if session_data.submitted_time:
        metadata_context = build_metadata_context_for_survey_completed(
            session_data)

        view_submission_url = None
        view_submission_duration = 0
        if _is_submission_viewable(schema.json, session_data.submitted_time):
            view_submission_url = url_for('.get_view_submission',
                                          eq_id=eq_id,
                                          form_type=form_type)
            view_submission_duration = humanize.naturaldelta(
                timedelta(seconds=schema.json['view_submitted_response']
                          ['duration']))

        cookie_message = request.cookies.get('ons_cookie_message_displayed')
        allow_analytics = analytics_allowed(request)

        return render_theme_template(
            schema.json['theme'],
            template_name='thank-you.html',
            metadata=metadata_context,
            analytics_gtm_id=current_app.config['EQ_GTM_ID'],
            analytics_gtm_env_id=current_app.config['EQ_GTM_ENV_ID'],
            survey_id=schema.json['survey_id'],
            survey_title=TemplateRenderer.safe_content(schema.json['title']),
            is_view_submitted_response_enabled=
            is_view_submitted_response_enabled(schema.json),
            view_submission_url=view_submission_url,
            account_service_url=cookie_session.get('account_service_url'),
            account_service_log_out_url=cookie_session.get(
                'account_service_log_out_url'),
            view_submission_duration=view_submission_duration,
            cookie_message=cookie_message,
            allow_analytics=allow_analytics)

    routing_path = path_finder.get_full_routing_path()

    router = Router(schema, routing_path, completeness)
    next_location = router.get_next_location()

    return _redirect_to_location(metadata['collection_exercise_sid'],
                                 metadata.get('eq_id'),
                                 metadata.get('form_type'), next_location)
    def test_is_path_complete(self):
        schema = load_schema_from_name("test_textfield")
        progress_store = ProgressStore([{
            "section_id": "default-section",
            "list_item_id": None,
            "status": CompletionStatus.IN_PROGRESS,
            "block_ids": ["name-block"],
        }])

        router = Router(schema, self.answer_store, self.list_store,
                        progress_store, self.metadata)

        routing_path = router.routing_path(section_id="default-section")

        is_path_complete = router.is_path_complete(routing_path)

        self.assertTrue(is_path_complete)
    def test_cant_access_location_invalid_list_item_id(self):
        schema = load_schema_from_name("test_textfield")
        router = Router(
            schema,
            self.answer_store,
            self.list_store,
            self.progress_store,
            self.metadata,
        )

        current_location = Location(section_id="default-section",
                                    block_id="name-block")
        routing_path = []
        can_access_location = router.can_access_location(
            current_location, routing_path)

        self.assertFalse(can_access_location)
 def router(self):
     return Router(
         schema=self._schema,
         answer_store=self._questionnaire_store.answer_store,
         list_store=self._questionnaire_store.list_store,
         progress_store=self._questionnaire_store.progress_store,
         metadata=self._questionnaire_store.metadata,
     )
 def router(self):
     return Router(
         self.schema,
         self.answer_store,
         self.list_store,
         self.progress_store,
         self.metadata,
     )
Exemplo n.º 23
0
def dump_submission(schema, questionnaire_store):
    router = Router(
        schema,
        questionnaire_store.answer_store,
        questionnaire_store.list_store,
        questionnaire_store.progress_store,
        questionnaire_store.metadata,
    )

    routing_path = router.full_routing_path()
    questionnaire_store = get_questionnaire_store(
        current_user.user_id, current_user.user_ik
    )
    response = {
        "submission": convert_answers(schema, questionnaire_store, routing_path)
    }
    return json.dumps(response, for_json=True), 200
Exemplo n.º 24
0
    def test_is_not_valid_location(self):
        schema = load_schema_from_params('test', 'is_skipping_to_end')

        current_location = Location('not-in-path', 0, 'not-in-path')

        routing_path = [
            Location('test-skipping-group', 0, 'test-skipping-forced'),
            Location('test-skipping-section-summary-group', 0,
                     'test-skipping-section-summary'),
            Location('summary-group', 0, 'summary')
        ]

        completed_blocks = [
            Location('test-skipping-group', 0, 'test-skipping-forced')
        ]

        completeness = Completeness(schema,
                                    answer_store=MagicMock(),
                                    completed_blocks=completed_blocks,
                                    routing_path=routing_path,
                                    metadata={})
        router = Router(schema, routing_path, completeness, current_location)

        self.assertFalse(router.can_access_location())

        router = Router(schema, routing_path, completeness)

        self.assertFalse(router.can_access_location())
        # Currently, section summary is not added to completed_blocks without POST, ie when using nav bar.
        self.assertEqual(routing_path[2], router.get_next_location())
Exemplo n.º 25
0
def get_section(schema, questionnaire_store, section_id, list_item_id=None):
    router = Router(
        schema,
        questionnaire_store.answer_store,
        questionnaire_store.list_store,
        questionnaire_store.progress_store,
        questionnaire_store.metadata,
    )

    if not schema.is_hub_enabled():
        redirect_location = router.get_first_incomplete_location_in_survey()
        return redirect(redirect_location.url())

    if section_id not in router.enabled_section_ids:
        return redirect(url_for(".get_questionnaire"))

    routing_path = router.routing_path(section_id=section_id,
                                       list_item_id=list_item_id)
    section_status = questionnaire_store.progress_store.get_section_status(
        section_id=section_id, list_item_id=list_item_id)

    if section_status == CompletionStatus.COMPLETED:
        return redirect(
            router.get_section_return_location_when_section_complete(
                routing_path).url())

    if section_status == CompletionStatus.NOT_STARTED:
        return redirect(
            router.get_first_incomplete_location_for_section(
                routing_path).url())

    return redirect(
        router.get_first_incomplete_location_for_section(
            routing_path=routing_path).url())
    def test_cant_access_location_section_disabled(self):
        schema = load_schema_from_name("test_section_enabled_checkbox")

        router = Router(
            schema,
            self.answer_store,
            self.list_store,
            self.progress_store,
            self.metadata,
        )

        current_location = Location(section_id="section-2",
                                    block_id="section-2-block",
                                    list_item_id=None)
        can_access_location = router.can_access_location(current_location,
                                                         routing_path=[])

        self.assertFalse(can_access_location)
def router(schema, answer_store, list_store, progress_store):
    return Router(
        schema,
        answer_store,
        list_store,
        progress_store,
        metadata={},
        response_metadata={},
    )
Exemplo n.º 28
0
def post_questionnaire(schema, questionnaire_store):
    if any(action in request.form
           for action in ("action[save_sign_out]", "action[sign_out]")):
        return redirect(url_for("session.get_sign_out"))

    router = Router(
        schema,
        questionnaire_store.answer_store,
        questionnaire_store.list_store,
        questionnaire_store.progress_store,
        questionnaire_store.metadata,
    )

    if schema.is_hub_enabled() and router.is_survey_complete():
        return submit_answers(schema, questionnaire_store,
                              router.full_routing_path())

    return redirect(router.get_first_incomplete_location_in_survey().url())
Exemplo n.º 29
0
def dump_submission(schema, questionnaire_store):
    router = Router(
        schema,
        questionnaire_store.answer_store,
        questionnaire_store.list_store,
        questionnaire_store.progress_store,
        questionnaire_store.metadata,
    )

    routing_path = router.full_routing_path()
    questionnaire_store = get_questionnaire_store(current_user.user_id,
                                                  current_user.user_ik)

    submission_handler = SubmissionHandler(schema, questionnaire_store,
                                           routing_path)

    response = {"submission": submission_handler.get_payload()}
    return json_dumps(response), 200
Exemplo n.º 30
0
    def test_get_next_location_no_completed_blocks(self):
        schema = load_schema_from_params('test', 'is_skipping_to_end')

        current_location = Location('test-skipping-group', 0,
                                    'test-skipping-forced')

        routing_path = [
            Location('test-skipping-group', 0, 'test-skipping-forced')
        ]

        completeness = Completeness(schema,
                                    answer_store=MagicMock(),
                                    completed_blocks=[],
                                    routing_path=routing_path,
                                    metadata={})
        router = Router(schema, routing_path, completeness, current_location)

        self.assertEqual(routing_path[0], router.get_next_location())