コード例 #1
0
def respondent_add_survey():
    payload = request.get_json() or {}
    v = Validator(Exists('party_id', 'enrolment_code'))
    if not v.validate(payload):
        logger.debug(v.errors, url=request.url)
        raise BadRequest(v.errors)

    account_controller.add_new_survey_for_respondent(payload)
    return make_response(jsonify('OK'), 200)
コード例 #2
0
def change_respondent_enrolment_status():
    payload = request.get_json() or {}
    v = Validator(
        Exists('respondent_id', 'business_id', 'survey_id', 'change_flag'))
    if not v.validate(payload):
        logger.debug(v.errors, url=request.url)
        raise BadRequest(v.errors)
    account_controller.change_respondent_enrolment_status(payload)

    return make_response(jsonify('OK'), 200)
コード例 #3
0
def change_respondent(payload, session):
    """
    Modify an existing respondent's email address, identified by their current email address.
    """
    v = Validator(Exists('email_address', 'new_email_address'))
    if not v.validate(payload):
        logger.info("Payload for change respondent was invalid",
                    errors=v.errors)
        raise BadRequest(v.errors, 400)

    email_address = payload['email_address']
    new_email_address = payload['new_email_address']

    respondent = query_respondent_by_email(email_address, session)

    if not respondent:
        logger.info("Respondent does not exist")
        raise NotFound("Respondent does not exist")

    if new_email_address == email_address:
        return respondent.to_respondent_dict()

    respondent_with_new_email = query_respondent_by_email(
        new_email_address, session)
    if respondent_with_new_email:
        logger.info("Respondent with email already exists")
        raise Conflict("New email address already taken")

    respondent.pending_email_address = new_email_address

    # check if respondent has initiated this request
    if 'change_requested_by_respondent' in payload:
        verification_url = PublicWebsite().confirm_account_email_change_url(
            new_email_address)
        personalisation = {
            'CONFIRM_EMAIL_URL': verification_url,
            'FIRST_NAME': respondent.first_name
        }
        logger.info('Account change email URL for party_id',
                    party_id=str(respondent.party_uuid),
                    url=verification_url)
        _send_account_email_change_email(
            personalisation,
            template='verify_account_email_change',
            email=new_email_address,
            party_id=respondent.party_uuid)
    else:
        _send_email_verification(respondent.party_uuid, new_email_address)

    logger.info('Verification email sent for changing respondents email',
                respondent_id=str(respondent.party_uuid))

    return respondent.to_respondent_dict()
コード例 #4
0
def put_edit_account_status(party_id):
    # This is the party endpoint to lock and notify respondent when account is locked
    # This is also the end point for internal user to unlock a respondents account
    payload = request.get_json() or {}
    v = Validator(Exists('status_change'))
    if not v.validate(payload):
        logger.debug(v.errors, url=request.url)
        raise BadRequest(v.errors)

    response = account_controller.notify_change_account_status(
        payload=payload, party_id=party_id)
    return make_response(jsonify(response), 200)
コード例 #5
0
def businesses_sample_ce_link(sample, ce_data, session):
    """
    Update business versions to have the correct collection exercise and sample link.

    :param sample: the sample summary id to update.
    :param ce_data: dictionary containing the collectionExerciseId to link with sample.
    :param session: database session.
    """

    v = Validator(Exists('collectionExerciseId'))
    if not v.validate(ce_data):
        logger.debug(v.errors)
        raise BadRequest(v.errors)

    collection_exercise_id = ce_data['collectionExerciseId']

    session.query(BusinessAttributes).filter(BusinessAttributes.sample_summary_id == sample)\
        .update({'collection_exercise': collection_exercise_id})
コード例 #6
0
def post_pending_shares():
    """
     Creates new records for pending shares
     accepted payload example:
     {  pending_shares: [{
            "business_id": "business_id"
            "survey_id": "survey_id",
            "email_address": "email_address",
            "shared_by": "respondent_id"
        },
        {
            "business_id": "business_id":
            "survey_id": "survey_id",
            "email_address": "email_address",
            "shared_by": "respondent_id"
        }]
     }
    """
    payload = request.get_json() or {}
    try:
        pending_shares = payload['pending_shares']
        if len(pending_shares) == 0:
            raise BadRequest('Payload Invalid - pending_shares list is empty')
        for share in pending_shares:
            # Validation, curation and checks
            expected = ('email_address', 'survey_id', 'business_id', 'shared_by')
            v = Validator(Exists(*expected))
            if not v.validate(share):
                logger.debug(v.errors)
                raise BadRequest(v.errors)
        for pending_share in pending_shares:
            share_survey_controller.pending_share_create(business_id=pending_share['business_id'],
                                                         survey_id=pending_share['survey_id'],
                                                         email_address=pending_share['email_address'],
                                                         shared_by=pending_share['shared_by'])
            # TODO: Add logic to send email
        return make_response(jsonify({"created": "success"}), 201)
    except KeyError:
        raise BadRequest('Payload Invalid - Pending share key missing')

    except SQLAlchemyError:
        raise BadRequest('This share is already in progress')
コード例 #7
0
def post_respondent(party, session):
    """
    Register respondent and set up pending enrolment before account verification
    :param party: respondent to be created details
    :param session
    :return: created respondent
    """

    # Validation, curation and checks
    expected = ('emailAddress', 'firstName', 'lastName', 'password',
                'telephone', 'enrolmentCode')

    v = Validator(Exists(*expected))
    if 'id' in party:
        # Note: there's not strictly a requirement to be able to pass in a UUID, this is currently supported to
        # aid with testing.
        logger.info("'id' in respondent post message")
        try:
            uuid.UUID(party['id'])
        except ValueError:
            logger.info("Invalid respondent id type",
                        respondent_id=party['id'])
            raise BadRequest(
                f"'{party['id']}' is not a valid UUID format for property 'id'"
            )

    if not v.validate(party):
        logger.debug(v.errors)
        raise BadRequest(v.errors)

    iac = request_iac(party['enrolmentCode'])
    if not iac.get('active'):
        logger.info("Inactive enrolment code")
        raise BadRequest("Enrolment code is not active")

    existing = query_respondent_by_email(party['emailAddress'].lower(),
                                         session)
    if existing:
        logger.info("Email already exists",
                    party_uuid=str(existing.party_uuid))
        raise BadRequest("Email address already exists")

    case_context = request_case(party['enrolmentCode'])
    case_id = case_context['id']
    business_id = case_context['partyId']
    collection_exercise_id = case_context['caseGroup']['collectionExerciseId']
    collection_exercise = request_collection_exercise(collection_exercise_id)
    survey_id = collection_exercise['surveyId']

    business = query_business_by_party_uuid(business_id, session)
    if not business:
        logger.error(
            "Could not locate business when creating business association",
            business_id=business_id,
            case_id=case_id,
            collection_exercise_id=collection_exercise_id)
        raise InternalServerError(
            "Could not locate business when creating business association")

    # Chain of enrolment processes
    translated_party = {
        'party_uuid': party.get('id') or str(uuid.uuid4()),
        'email_address': party['emailAddress'].lower(),
        'first_name': party['firstName'],
        'last_name': party['lastName'],
        'telephone': party['telephone'],
        'status': RespondentStatus.CREATED
    }

    # This might look odd but it's done in the interest of keeping the code working in the same way.
    # If raise_for_status in the function raises an error, it would've been caught by @with_db_session,
    # rolled back the db and raised it.  Whether that's something we want is another question.
    try:
        respondent = _add_enrolment_and_auth(business, business_id, case_id,
                                             party, session, survey_id,
                                             translated_party)
    except HTTPError:
        logger.error("add_enrolment_and_auth raised an HTTPError",
                     exc_info=True)
        session.rollback()
        raise

    # If the disabling of the enrolment code fails we log an error and continue anyway.  In the interest of keeping
    # the code working in the same way (which may itself be wrong...) we'll handle the ValueError that can be raised
    # in the same way as before (rollback the session and raise) but it's not clear whether this is the desired
    # behaviour.
    try:
        disable_iac(party['enrolmentCode'], case_id)
    except ValueError:
        logger.error("disable_iac didn't return json in its response",
                     exc_info=True)
        session.rollback()
        raise

    _send_email_verification(respondent.party_uuid,
                             party['emailAddress'].lower())

    return respondent.to_respondent_dict()
コード例 #8
0
def _is_valid(payload, attribute):
    v = Validator(Exists(attribute))
    if v.validate(payload):
        return True
    logger.debug(v.errors)
    raise BadRequest(v.errors, 400)