Esempio n. 1
0
def test_create_service_callback_api_schema_validate_fails_with_misspelled_keys(
        key, wrong_key, value):
    under_test = {
        "url": "https://some_url.for_service",
        "bearer_token": "something_ten_chars",
        "notification_statuses": ["failed"],
        "updated_by_id": str(uuid.uuid4())
    }
    del under_test[key]
    under_test[wrong_key] = value

    with pytest.raises(ValidationError) as e:
        validate(under_test, create_service_callback_api_request_schema)

    errors = json.loads(str(e.value)).get('errors')
    assert len(errors) == 1
    assert errors[0]['error'] == 'ValidationError'
    assert errors[0]['message'] == f"{key} is a required property"
Esempio n. 2
0
def update_service_letter_contact(service_id, letter_contact_id):
    # validate the service exists, throws ResultNotFound exception.
    dao_fetch_service_by_id(service_id)
    form = validate(request.get_json(), add_service_letter_contact_block_request)
    new_reply_to = update_letter_contact(service_id=service_id,
                                         letter_contact_id=letter_contact_id,
                                         contact_block=form['contact_block'],
                                         is_default=form.get('is_default', True))
    return jsonify(data=new_reply_to.serialize()), 200
Esempio n. 3
0
def send_user_2fa_code(user_id, code_type):
    user_to_send_to = get_user_by_id(user_id=user_id)

    if count_user_verify_codes(user_to_send_to) >= current_app.config.get(
            'MAX_VERIFY_CODE_COUNT'):
        set_verify_codes_to_used(user_id)

    data = request.get_json()
    if code_type == SMS_TYPE:
        validate(data, post_send_user_sms_code_schema)
        send_user_sms_code(user_to_send_to, data)
    elif code_type == EMAIL_TYPE:
        validate(data, post_send_user_email_code_schema)
        send_user_email_code(user_to_send_to, data)
    else:
        abort(404)

    return '{}', 204
Esempio n. 4
0
def test_post_email_schema_invalid_scheduled_for(invalid_datetime, schema):
    j = {"template_id": str(uuid.uuid4()), "scheduled_for": invalid_datetime}
    if schema == post_email_request_schema:
        j.update({"email_address": "*****@*****.**"})
    else:
        j.update({"phone_number": "07515111111"})
    with pytest.raises(ValidationError) as e:
        validate(j, schema)
    error = json.loads(str(e.value))
    assert error['status_code'] == 400
    assert error['errors'] == [{
        'error':
        'ValidationError',
        'message':
        "scheduled_for datetime format is invalid. "
        "It must be a valid ISO8601 date time format, "
        "https://en.wikipedia.org/wiki/ISO_8601"
    }]
def test_get_notifications_request_invalid_statuses(invalid_statuses,
                                                    valid_statuses):
    partial_error_status = (
        "is not one of "
        "[cancelled, created, sending, sent, delivered, pending, failed, "
        "technical-failure, temporary-failure, permanent-failure, pending-virus-check, "
        "validation-failed, virus-scan-failed, returned-letter, pii-check-failed, accepted, received]"
    )

    with pytest.raises(ValidationError) as e:
        validate({"status": invalid_statuses + valid_statuses},
                 get_notifications_request)

    errors = json.loads(str(e.value)).get("errors")
    assert len(errors) == len(invalid_statuses)
    for index, value in enumerate(invalid_statuses):
        assert errors[index]["message"] == "status {} {}".format(
            value, partial_error_status)
Esempio n. 6
0
def test_service_inbound_api_schema_validates():
    under_test = {
        "url": "https://some_url.for_service",
        "bearer_token": "something_ten_chars",
        "updated_by_id": str(uuid.uuid4())
    }

    validated = validate(under_test, update_service_inbound_api_schema)
    assert validated == under_test
Esempio n. 7
0
def add_service_reply_to_email_address(service_id):
    # validate the service exists, throws ResultNotFound exception.
    dao_fetch_service_by_id(service_id)
    form = validate(request.get_json(), add_service_email_reply_to_request)
    new_reply_to = add_reply_to_email_address_for_service(
        service_id=service_id,
        email_address=form['email_address'],
        is_default=form.get('is_default', True))
    return jsonify(data=new_reply_to.serialize()), 201
Esempio n. 8
0
def move_to_template_folder(service_id, target_template_folder_id=None):
    data = request.get_json()

    validate(data, post_move_template_folder_schema)

    if target_template_folder_id:
        target_template_folder = dao_get_template_folder_by_id_and_service_id(
            target_template_folder_id, service_id)
    else:
        target_template_folder = None

    for template_folder_id in data["folders"]:
        try:
            template_folder = dao_get_template_folder_by_id_and_service_id(
                template_folder_id, service_id)
        except NoResultFound:
            msg = "No folder found with id {} for service {}".format(
                template_folder_id, service_id)
            raise InvalidRequest(msg, status_code=400)
        _validate_folder_move(
            target_template_folder,
            target_template_folder_id,
            template_folder,
            template_folder_id,
        )

        template_folder.parent = target_template_folder

    for template_id in data["templates"]:
        try:
            template = dao_get_template_by_id_and_service_id(
                template_id, service_id)
        except NoResultFound:
            msg = "Could not move to folder: No template found with id {} for service {}".format(
                template_id, service_id)
            raise InvalidRequest(msg, status_code=400)

        if template.archived:
            current_app.logger.info(
                "Could not move to folder: Template {} is archived. (Skipping)"
                .format(template_id))
        else:
            template.folder = target_template_folder
    return "", 204
Esempio n. 9
0
def update_broadcast_message_status(service_id, broadcast_message_id):
    data = request.get_json()

    validate(data, update_broadcast_message_status_schema)
    broadcast_message = dao_get_broadcast_message_by_id_and_service_id(
        broadcast_message_id, service_id)

    new_status = data['status']
    updating_user = get_user_by_id(data['created_by'])

    _update_broadcast_message(broadcast_message, new_status, updating_user)
    dao_save_object(broadcast_message)

    if new_status in {
            BroadcastStatusType.BROADCASTING, BroadcastStatusType.CANCELLED
    }:
        _create_broadcast_event(broadcast_message)

    return jsonify(broadcast_message.serialize()), 200
def test_post_email_json_schema_missing_recipient_identifier_required_fields(
        recipient_identifier, missing_key_name):
    j = {
        "recipient_identifier": recipient_identifier,
        "template_id": str(uuid.uuid4())
    }
    with pytest.raises(ValidationError) as e:
        validate(j, post_email_request_schema)
    error = json.loads(str(e.value))
    assert len(error.keys()) == 2
    assert error.get('status_code') == 400
    assert len(error.get('errors')) == len(missing_key_name)
    for key_name in missing_key_name:
        assert {
            'error':
            'ValidationError',
            'message':
            "recipient_identifier " + key_name + " is a required property"
        } in error['errors']
Esempio n. 11
0
def get_template_by_id(template_id, version=None):
    _data = {'id': template_id}
    if version:
        _data['version'] = version

    data = validate(_data, get_template_by_id_request)

    template = templates_dao.dao_get_template_by_id_and_service_id(
        template_id, authenticated_service.id, data.get('version'))
    return jsonify(template.serialize()), 200
def test_post_sms_schema_with_personalisation_that_is_not_a_dict():
    j = {
        "phone_number": "6502532222",
        "template_id": str(uuid.uuid4()),
        "reference": "reference from caller",
        "personalisation": "not_a_dict"
    }
    with pytest.raises(ValidationError) as e:
        validate(j, post_sms_request_schema)
    error = json.loads(str(e.value))
    assert len(error.get('errors')) == 1
    assert error['errors'] == [{
        'error':
        'ValidationError',
        'message':
        "personalisation not_a_dict is not of type object"
    }]
    assert error.get('status_code') == 400
    assert len(error.keys()) == 2
Esempio n. 13
0
def create_contact_list(service_id):
    service_contact_list = validate(request.get_json(), create_service_contact_list_schema)
    service_contact_list['created_by_id'] = service_contact_list.pop('created_by')
    service_contact_list['created_at'] = datetime.utcnow()
    service_contact_list['service_id'] = str(service_id)
    list_to_save = ServiceContactList(**service_contact_list)

    save_service_contact_list(list_to_save)

    return jsonify(list_to_save.serialize()), 201
def test_post_email_schema_id_type_should_only_use_enum_values(id_type):
    id_type_as_parameter_json = {
        "recipient_identifier": {
            "id_type": id_type,
            "id_value": "bar"
        },
        "template_id": str(uuid.uuid4())
    }
    if id_type in RECIPIENT_IDENTIFIER_TYPES:
        assert validate(id_type_as_parameter_json, post_email_request_schema) == id_type_as_parameter_json
    else:
        with pytest.raises(ValidationError) as e:
            validate(id_type_as_parameter_json, post_email_request_schema)
        error = json.loads(str(e.value))
        assert len(error.keys()) == 2
        assert error.get('status_code') == 400
        assert len(error.get('errors')) == 1
        assert {'error': 'ValidationError',
                'message': "recipient_identifier INVALID is not one of [VAPROFILEID, PID, ICN]"} in error['errors']
Esempio n. 15
0
def import_speakers():
    data = request.get_json(force=True)

    validate(data, post_import_speakers_schema)

    errors = []
    speakers = []
    for item in data:
        err = ''
        if item.get('parent_name'):
            parent_speaker = Speaker.query.filter(Speaker.name == item['parent_name']).first()
            if parent_speaker:
                if parent_speaker.parent_id:
                    err = 'Parent speaker can`t have a parent'
                    current_app.logger.error(err)
                    errors.append(err)
                else:
                    item['parent_id'] = str(parent_speaker.id)
            else:
                err = 'Can`t find speaker: {}'.format(item['parent_name'])
                current_app.logger.error(err)
                errors.append(err)
            del item['parent_name']

        if not err:
            speaker = Speaker.query.filter(Speaker.name == item['name']).first()
            if not speaker:
                speaker = Speaker(**item)
                speakers.append(speaker)
                dao_create_speaker(speaker)
            else:
                err = u'speaker already exists: {}'.format(speaker.name)
                current_app.logger.error(err)
                errors.append(err)

    res = {
        "speakers": [s.serialize() for s in speakers]
    }

    if errors:
        res['errors'] = errors

    return jsonify(res), 201 if speakers else 400 if errors else 200
Esempio n. 16
0
def send_message():
    data = request.get_json(force=True)
    current_app.logger.info('send_message: %r', data)

    validate(data, post_send_message_schema)

    emails_to = [user.email for user in dao_get_admin_users()]

    status_code = send_smtp_email(emails_to,
                                  'Web message: {}'.format(data['reason']),
                                  data['message'],
                                  from_email=data['email'],
                                  from_name=data['name'])

    return jsonify({
        'message':
        'Your message was sent'
        if status_code == 200 else 'An error occurred sending your message'
    })
def test_post_sms_json_schema_bad_uuid_and_missing_phone_number_and_recipient_identifier(
):
    j = {"template_id": "notUUID"}
    with pytest.raises(ValidationError) as e:
        validate(j, post_sms_request_schema)
    error = json.loads(str(e.value))
    assert len(error.keys()) == 2
    assert error.get('status_code') == 400
    assert len(error.get('errors')) == 2
    assert {
        'error':
        'ValidationError',
        'message':
        "{template_id: notUUID} is not valid under any of the given schemas"
    } in error['errors']
    assert {
        'error': 'ValidationError',
        'message': "template_id is not a valid UUID"
    } in error['errors']
Esempio n. 18
0
def create_or_update_free_sms_fragment_limit(service_id):

    req_args = request.get_json()

    form = validate(req_args, create_or_update_free_sms_fragment_limit_schema)

    update_free_sms_fragment_limit_data(service_id,
                                        free_sms_fragment_limit=form.get('free_sms_fragment_limit'),
                                        financial_year_start=form.get('financial_year_start'))
    return jsonify(form), 201
Esempio n. 19
0
def create_magazine():
    data = request.get_json(force=True)

    validate(data, post_create_magazine_schema)

    new_filename = get_magazine_filename(data['filename'])

    if new_filename:
        magazine = Magazine(title=data['title'], filename=new_filename)

        dao_create_record(magazine)

        upload_tasks.upload_magazine.apply_async(
            (str(magazine.id), data['pdf_data']))

        return jsonify(magazine.serialize()), 201

    raise InvalidRequest(
        'Invalid filename for magazine: {}'.format(data['filename']), 400)
Esempio n. 20
0
def add_user_to_service(service_id, user_id):
    service = dao_fetch_service_by_id(service_id)
    user = get_user_by_id(user_id=user_id)

    if user in service.users:
        error = 'User id: {} already part of service id: {}'.format(user_id, service_id)
        raise InvalidRequest(error, status_code=400)

    data = request.get_json()
    validate(data, post_set_permissions_schema)

    permissions = [
        Permission(service_id=service_id, user_id=user_id, permission=p['permission'])
        for p in data['permissions']
    ]
    folder_permissions = data.get('folder_permissions', [])

    dao_add_user_to_service(service, user, permissions, folder_permissions)
    data = service_schema.dump(service).data
    return jsonify(data=data), 201
Esempio n. 21
0
def add_service_letter_contact(service_id):
    # validate the service exists, throws ResultNotFound exception.
    dao_fetch_service_by_id(service_id)
    form = validate(request.get_json(),
                    add_service_letter_contact_block_request)
    new_letter_contact = add_letter_contact_for_service(
        service_id=service_id,
        contact_block=form["contact_block"],
        is_default=form.get("is_default", True),
    )
    return jsonify(data=new_letter_contact.serialize()), 201
Esempio n. 22
0
def update_service_reply_to_email_address(service_id, reply_to_email_id):
    # validate the service exists, throws ResultNotFound exception.
    dao_fetch_service_by_id(service_id)
    form = validate(request.get_json(), add_service_email_reply_to_request)
    new_reply_to = update_reply_to_email_address(
        service_id=service_id,
        reply_to_id=reply_to_email_id,
        email_address=form["email_address"],
        is_default=form.get("is_default", True),
    )
    return jsonify(data=new_reply_to.serialize()), 200
Esempio n. 23
0
def add_service_reply_to_email_address(service_id):
    # validate the service exists, throws ResultNotFound exception.
    dao_fetch_service_by_id(service_id)
    form = validate(request.get_json(), add_service_email_reply_to_request)
    check_if_reply_to_address_already_in_use(service_id, form["email_address"])
    new_reply_to = add_reply_to_email_address_for_service(
        service_id=service_id,
        email_address=form["email_address"],
        is_default=form.get("is_default", True),
    )
    return jsonify(data=new_reply_to.serialize()), 201
def test_post_notification_with_document_upload(client, notify_db_session,
                                                mocker, csv_param):
    service = create_service(service_permissions=[EMAIL_TYPE])
    service.contact_link = '*****@*****.**'
    template = create_template(
        service=service,
        template_type='email',
        content="Document 1: ((first_link)). Document 2: ((second_link))")

    mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
    document_download_mock = mocker.patch(
        'app.v2.notifications.post_notifications.document_download_client')
    document_download_mock.upload_document.side_effect = lambda service_id, content, is_csv: f'{content}-link'

    data = {
        "email_address": service.users[0].email_address,
        "template_id": template.id,
        "personalisation": {
            "first_link": {
                "file": "abababab",
                **csv_param
            },
            "second_link": {
                "file": "cdcdcdcd",
                **csv_param
            }
        }
    }

    auth_header = create_authorization_header(service_id=service.id)
    response = client.post(path="v2/notifications/email",
                           data=json.dumps(data),
                           headers=[('Content-Type', 'application/json'),
                                    auth_header])

    assert response.status_code == 201, response.get_data(as_text=True)
    resp_json = json.loads(response.get_data(as_text=True))
    assert validate(resp_json, post_email_response) == resp_json

    assert document_download_mock.upload_document.call_args_list == [
        call(str(service.id), 'abababab', csv_param.get('is_csv')),
        call(str(service.id), 'cdcdcdcd', csv_param.get('is_csv'))
    ]

    notification = Notification.query.one()
    assert notification.status == NOTIFICATION_CREATED
    assert notification.personalisation == {
        'first_link': 'abababab-link',
        'second_link': 'cdcdcdcd-link'
    }
    assert notification.document_download_count == 2

    assert resp_json['content'][
        'body'] == 'Document 1: abababab-link. Document 2: cdcdcdcd-link'
Esempio n. 25
0
def get_inbound_sms():
    data = validate(request.args.to_dict(), get_inbound_sms_request)

    paginated_inbound_sms = inbound_sms_dao.dao_get_paginated_inbound_sms_for_service_for_public_api(
        authenticated_service.id,
        older_than=data.get('older_than', None),
        page_size=current_app.config.get('API_PAGE_SIZE'))

    return jsonify(
        received_text_messages=[i.serialize() for i in paginated_inbound_sms],
        links=_build_links(paginated_inbound_sms)), 200
Esempio n. 26
0
def test_create_service_callback_api_schema_validate_succeeds():
    under_test = {
        "url": "https://some_url.for_service",
        "bearer_token": "something_ten_chars",
        "notification_statuses": ["failed"],
        "updated_by_id": str(uuid.uuid4())
    }

    validated = validate(under_test,
                         create_service_callback_api_request_schema)
    assert validated == under_test
Esempio n. 27
0
def invite_user_to_org(organisation_id):
    data = request.get_json()
    validate(data, post_create_invited_org_user_status_schema)

    invited_org_user = InvitedOrganisationUser(
        email_address=data["email_address"],
        invited_by_id=data["invited_by"],
        organisation_id=organisation_id,
    )
    save_invited_org_user(invited_org_user)

    template = dao_get_template_by_id(
        current_app.config["ORGANISATION_INVITATION_EMAIL_TEMPLATE_ID"])

    saved_notification = persist_notification(
        template_id=template.id,
        template_version=template.version,
        recipient=invited_org_user.email_address,
        service=template.service,
        personalisation={
            "user_name":
            invited_org_user.invited_by.name,
            "organisation_name":
            invited_org_user.organisation.name,
            "url":
            invited_org_user_url(
                invited_org_user.id,
                data.get("invite_link_host"),
            ),
        },
        notification_type=EMAIL_TYPE,
        api_key_id=None,
        key_type=KEY_TYPE_NORMAL,
        reply_to_text=invited_org_user.invited_by.email_address,
    )

    send_notification_to_queue(saved_notification,
                               research_mode=False,
                               queue=QueueNames.NOTIFY)

    return jsonify(data=invited_org_user.serialize()), 201
def set_permissions(user_id, service_id):
    # TODO fix security hole, how do we verify that the user
    # who is making this request has permission to make the request.
    service_user = dao_get_service_user(user_id, service_id)
    user = service_user.user
    service = dao_fetch_service_by_id(service_id=service_id)

    data = request.get_json()
    validate(data, post_set_permissions_schema)

    permission_list = [
        Permission(service_id=service_id,
                   user_id=user_id,
                   permission=p['permission']) for p in data['permissions']
    ]

    service_key = "service_id_{}".format(service_id)
    change_dict = {service_key: service_id, "permissions": permission_list}

    try:
        _update_alert(user, update_dct_to_str(change_dict))
    except Exception as e:
        current_app.logger.error(e)

    permission_dao.set_user_service_permission(user,
                                               service,
                                               permission_list,
                                               _commit=True,
                                               replace=True)

    if 'folder_permissions' in data:
        folders = [
            dao_get_template_folder_by_id_and_service_id(
                folder_id, service_id)
            for folder_id in data['folder_permissions']
        ]

        service_user.folders = folders
        dao_update_service_user(service_user)

    return jsonify({}), 204
def test_post_email_schema_id_type_should_only_use_enum_values(id_type):
    id_type_as_parameter_json = {
        "recipient_identifier": {
            "id_type": id_type,
            "id_value": "bar"
        },
        "template_id": str(uuid.uuid4())
    }
    if id_type in IdentifierType.values():
        assert validate(id_type_as_parameter_json,
                        post_email_request_schema) == id_type_as_parameter_json
    else:
        with pytest.raises(ValidationError) as e:
            validate(id_type_as_parameter_json, post_email_request_schema)
        error = json.loads(str(e.value))
        assert len(error.keys()) == 2
        assert error.get('status_code') == 400
        assert len(error.get('errors')) == 1
        assert 'ValidationError' in error['errors'][0]['error']
        assert f"recipient_identifier {id_type} is not one of " in error[
            'errors'][0]['message']
Esempio n. 30
0
def send_user_2fa_code(user_id, code_type):
    user_to_send_to = get_user_by_id(user_id=user_id)

    if(verify_within_time(user_to_send_to, age=timedelta(seconds=10)) >= 1):
        raise InvalidRequest("Code already sent, wait 10 seconds", status_code=400)

    if count_user_verify_codes(user_to_send_to) >= current_app.config.get('MAX_VERIFY_CODE_COUNT'):
        # Prevent more than `MAX_VERIFY_CODE_COUNT` active verify codes at a time
        current_app.logger.warning('Too many verify codes created for user {}'.format(user_to_send_to.id))
    else:
        data = request.get_json()
        if code_type == SMS_TYPE:
            validate(data, post_send_user_sms_code_schema)
            send_user_sms_code(user_to_send_to, data)
        elif code_type == EMAIL_TYPE:
            validate(data, post_send_user_email_code_schema)
            send_user_email_code(user_to_send_to, data)
        else:
            abort(404)

    return '{}', 204