Ejemplo n.º 1
0
def _submit_data(user):

    answer_store = get_answer_store(user)

    if answer_store.answers:
        metadata = get_metadata(user)
        schema = load_schema_from_metadata(metadata)
        routing_path = PathFinder(schema, answer_store,
                                  metadata).get_routing_path()

        message = convert_answers(metadata,
                                  schema,
                                  answer_store,
                                  routing_path,
                                  flushed=True)
        message = current_app.eq['encrypter'].encrypt(message)

        sent = current_app.eq['submitter'].send_message(
            message, current_app.config['EQ_RABBITMQ_QUEUE_NAME'],
            metadata["tx_id"])

        if not sent:
            raise SubmissionFailedException()

        get_questionnaire_store(user.user_id, user.user_ik).delete()
        return True
    else:
        return False
def get_referenced_offset_value(answer_min_or_max, answer_store, metadata, group_instance=0):
    """
    Gets value of the referenced date type, whether it is a value,
    id of an answer or a meta date. Then adds/subtracts offset from that value and returns
    the new offset value

    :param answer_min_or_max: The minimum or maximum object which contains
    the referenced value.
    :param answer_store: The current answer store
    :param metadata: metadata for reference meta dates
    :return: date value
    """
    value = None

    if 'value' in answer_min_or_max:
        if answer_min_or_max['value'] == 'now':
            value = datetime.utcnow().strftime('%Y-%m-%d')
        else:
            value = answer_min_or_max['value']
    elif 'meta' in answer_min_or_max:
        value = get_metadata_value(metadata, answer_min_or_max['meta'])
    elif 'answer_id' in answer_min_or_max:
        schema = load_schema_from_metadata(metadata)
        value = get_answer_store_value(answer_min_or_max['answer_id'], answer_store, schema, group_instance=group_instance)

    value = convert_to_datetime(value)

    if 'offset_by' in answer_min_or_max:
        offset = answer_min_or_max['offset_by']
        value += relativedelta(years=offset.get('years', 0),
                               months=offset.get('months', 0),
                               days=offset.get('days', 0))

    return value
Ejemplo n.º 3
0
def _submit_data(user):

    answer_store = get_answer_store(user)

    if answer_store.answers:
        metadata = get_metadata(user)
        collection_metadata = get_collection_metadata(user)
        schema = load_schema_from_metadata(metadata)
        completed_blocks = get_completed_blocks(user)
        routing_path = PathFinder(schema, answer_store, metadata,
                                  completed_blocks).get_full_routing_path()

        message = convert_answers(metadata,
                                  collection_metadata,
                                  schema,
                                  answer_store,
                                  routing_path,
                                  flushed=True)
        encrypted_message = encrypt(message, current_app.eq['key_store'],
                                    KEY_PURPOSE_SUBMISSION)

        sent = current_app.eq['submitter'].send_message(
            encrypted_message, current_app.config['EQ_RABBITMQ_QUEUE_NAME'],
            metadata['tx_id'])

        if not sent:
            raise SubmissionFailedException()

        get_questionnaire_store(user.user_id, user.user_ik).delete()
        return True

    return False
Ejemplo n.º 4
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)

    try:
        runner_claims = validate_runner_claims(decrypted_token)
    except ValidationError as e:
        raise InvalidTokenException("Invalid runner claims") from e

    g.schema = load_schema_from_metadata(runner_claims)
    schema_metadata = g.schema.json["metadata"]

    try:
        questionnaire_claims = validate_questionnaire_claims(
            decrypted_token, schema_metadata)
    except ValidationError as e:
        raise InvalidTokenException("Invalid questionnaire claims") from e

    claims = {**runner_claims, **questionnaire_claims}

    schema_name = claims["schema_name"]
    tx_id = claims["tx_id"]
    ru_ref = claims["ru_ref"]
    case_id = claims["case_id"]

    logger.bind(
        schema_name=schema_name,
        tx_id=tx_id,
        ru_ref=ru_ref,
        case_id=case_id,
    )
    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")

    return redirect(url_for("questionnaire.get_questionnaire"))
Ejemplo n.º 5
0
def test_load_schema_from_metadata_with_survey_url():
    load_schema_from_url.cache_clear()

    metadata = {"survey_url": TEST_SCHEMA_URL, "language_code": "cy"}
    mock_schema = QuestionnaireSchema({}, language_code="cy")
    responses.add(responses.GET, TEST_SCHEMA_URL, json=mock_schema.json, status=200)
    loaded_schema = load_schema_from_metadata(metadata=metadata)

    assert loaded_schema.json == mock_schema.json
    assert loaded_schema.language_code == mock_schema.language_code
    def setUp(self):
        super().setUp()

        # Schema is loaded through metadata
        self.metadata = {
            'eq_id': 'census',
            'form_type': 'household',
        }
        self.schema = load_schema_from_metadata(self.metadata)
        self.block_json = self.schema.get_block('household-composition')
Ejemplo n.º 7
0
def dump_submission():
    answer_store = get_answer_store(current_user)
    metadata = get_metadata(current_user)
    schema = load_schema_from_metadata(metadata)
    routing_path = PathFinder(schema, answer_store,
                              metadata).get_routing_path()
    response = {
        'submission': convert_answers(metadata, schema, answer_store,
                                      routing_path)
    }
    return jsonify(response), 200
Ejemplo n.º 8
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
Ejemplo n.º 9
0
    def get_schema_value(self, schema_element):
        if isinstance(schema_element["value"], dict):
            if schema_element["value"]["source"] == "metadata":
                identifier = schema_element["value"].get("identifier")
                return self.metadata.get(identifier)
            if schema_element["value"]["source"] == "answers":
                schema = load_schema_from_metadata(self.metadata)
                answer_id = schema_element["value"].get("identifier")
                list_item_id = self.location.list_item_id if self.location else None

                return get_answer_value(
                    answer_id, self.answer_store, schema, list_item_id=list_item_id
                )
        return schema_element["value"]
Ejemplo n.º 10
0
def before_request():
    values = request.view_args
    logger.info('questionnaire request',
                eq_id=values['eq_id'],
                form_type=values['form_type'],
                ce_id=values['collection_id'],
                method=request.method,
                url_path=request.full_path)

    metadata = get_metadata(current_user)
    if metadata:
        logger.bind(tx_id=metadata['tx_id'])
        g.schema_json = load_schema_from_metadata(metadata)
        _check_same_survey(values['eq_id'], values['form_type'],
                           values['collection_id'])
Ejemplo n.º 11
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))
Ejemplo n.º 12
0
def get_questionnaire_store(user_id, user_ik):
    from app.storage.encrypted_questionnaire_storage import EncryptedQuestionnaireStorage
    from app.utilities.schema import load_schema_from_metadata

    # Sets up a single QuestionnaireStore instance per request.
    store = g.get('_questionnaire_store')
    if store is None:
        pepper = current_app.eq['secret_store'].get_secret_by_name(
            'EQ_SERVER_SIDE_STORAGE_ENCRYPTION_USER_PEPPER')
        storage = EncryptedQuestionnaireStorage(user_id, user_ik, pepper)
        store = g._questionnaire_store = QuestionnaireStore(storage)

    if store.metadata:  # When creating the questionnaire storage, there is no metadata for upgrading
        schema = load_schema_from_metadata(store.metadata)
        store.ensure_latest_version(schema)

    return store
def build_metadata_context(metadata):
    """
    Builds the metadata context using eq claims and schema defined metadata
    :param metadata: token metadata
    :return: metadata context
    """
    eq_context = {
        'eq_id': json_and_html_safe(metadata['eq_id']),
        'collection_id':
        json_and_html_safe(metadata['collection_exercise_sid']),
        'form_type': json_and_html_safe(metadata['form_type']),
        'ru_ref': json_and_html_safe(metadata['ru_ref']),
        'tx_id': json_and_html_safe(metadata['tx_id']),
    }

    schema = load_schema_from_metadata(metadata)

    eq_context.update(build_schema_metadata(metadata, schema))

    return eq_context
Ejemplo 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
    """
    decrypted_token = decrypt_token(request.args.get('token'))
    metadata = parse_metadata(decrypted_token)
    eq_id = metadata["eq_id"]
    form_type = metadata["form_type"]
    tx_id = metadata["tx_id"]
    ru_ref = metadata["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")

    if not eq_id or not form_type:
        logger.error("missing eq id or form type in jwt")
        raise NotFound

    # logging in again clears any session state
    if session:
        session.clear()

    jti_claim = metadata.get('jti')
    if jti_claim is None:
        logger.debug('jti claim not provided')
    else:
        try:
            jti_claim_storage = JtiClaimStorage(current_app.eq['database'])
            jti_claim_storage.use_jti_claim(jti_claim)
        except JtiTokenUsed as e:
            raise Unauthorized from e

    store_session(metadata)

    json = load_schema_from_metadata(metadata)

    navigator = PathFinder(json, get_answer_store(current_user), metadata)
    current_location = navigator.get_latest_location(get_completed_blocks(current_user))

    return redirect(current_location.url(metadata))
Ejemplo n.º 15
0
    def test_load_schema_from_metadata_raises_exception_when_no_schema_found(
            self):
        metadata = {"eq_id": "123", "form_type": "456"}

        with self.assertRaises(FileNotFoundError):
            load_schema_from_metadata(metadata)