예제 #1
0
def update_template(service_id, template_id):
    try:
        service = get_model_services(service_id=service_id)
    except DataError:
        return jsonify(result="error", message="Invalid service id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Service not found"), 404
    try:
        template = get_model_templates(template_id=template_id)
    except DataError:
        return jsonify(result="error", message="Invalid template id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Template not found"), 404
    if request.method == 'DELETE':
        status_code = 202
        delete_model_template(template)
    else:
        status_code = 200
        # TODO there has got to be a better way to do the next three lines
        upd_temp, errors = template_schema.load(request.get_json())
        if errors:
            return jsonify(result="error", message=errors), 400
        upd_temp.service = service
        update_dict, errors = template_schema.dump(upd_temp)
        # TODO FIX ME
        # Remove update_temp model which is added to db.session
        db.session.rollback()
        try:
            save_model_template(template, update_dict=update_dict)
        except DAOException as e:
            return jsonify(result="error", message=str(e)), 400
    return jsonify(data=template_schema.dump(template).data), status_code
예제 #2
0
def update_template(service_id, template_id):
    try:
        service = get_model_services(service_id=service_id)
    except DataError:
        return jsonify(result="error", message="Invalid service id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Service not found"), 404
    try:
        template = get_model_templates(template_id=template_id)
    except DataError:
        return jsonify(result="error", message="Invalid template id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Template not found"), 404
    if request.method == 'DELETE':
        status_code = 202
        delete_model_template(template)
    else:
        status_code = 200
        # TODO there has got to be a better way to do the next three lines
        upd_temp, errors = template_schema.load(request.get_json())
        if errors:
            return jsonify(result="error", message=errors), 400
        upd_temp.service = service
        update_dict, errors = template_schema.dump(upd_temp)
        # TODO FIX ME
        # Remove update_temp model which is added to db.session
        db.session.rollback()
        try:
            save_model_template(template, update_dict=update_dict)
        except DAOException as e:
            return jsonify(result="error", message=str(e)), 400
    return jsonify(data=template_schema.dump(template).data), status_code
예제 #3
0
def update_template(service_id, template_id):
    fetched_template = dao_get_template_by_id_and_service_id(
        template_id=template_id, service_id=service_id)

    if not service_has_permission(
            fetched_template.template_type,
        [p.permission for p in fetched_template.service.permissions]):
        message = "Updating {} templates is not allowed".format(
            get_public_notify_type_text(fetched_template.template_type))
        errors = {'template_type': [message]}

        raise InvalidRequest(errors, 403)

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

    # if redacting, don't update anything else
    if data.get('redact_personalisation') is True:
        return redact_template(fetched_template, data)

    if "reply_to" in data:
        check_reply_to(service_id, data.get("reply_to"),
                       fetched_template.template_type)
        updated = dao_update_template_reply_to(template_id=template_id,
                                               reply_to=data.get("reply_to"))
        return jsonify(data=template_schema.dump(updated).data), 200

    current_data = dict(template_schema.dump(fetched_template).data.items())
    updated_template = dict(
        template_schema.dump(fetched_template).data.items())
    updated_template.update(data)

    # Check if there is a change to make.
    if _template_has_not_changed(current_data, updated_template):
        return jsonify(data=updated_template), 200

    over_limit = _content_count_greater_than_limit(
        updated_template['content'], fetched_template.template_type)
    if over_limit:
        message = 'Content has a character count greater than the limit of {}'.format(
            SMS_CHAR_COUNT_LIMIT)
        errors = {'content': [message]}
        raise InvalidRequest(errors, status_code=400)

    update_dict = template_schema.load(updated_template).data

    dao_update_template(update_dict)
    return jsonify(data=template_schema.dump(update_dict).data), 200
def test_send_sms_to_provider_should_return_template_if_found_in_redis(
        mocker, client, sample_template):
    from app.schemas import service_schema, template_schema
    service_dict = service_schema.dump(sample_template.service).data
    template_dict = template_schema.dump(sample_template).data

    mocker.patch(
        'app.redis_store.get',
        side_effect=[
            json.dumps({
                'data': service_dict
            }).encode('utf-8'),
            json.dumps({
                'data': template_dict
            }).encode('utf-8'),
        ],
    )
    mock_get_template = mocker.patch(
        'app.dao.templates_dao.dao_get_template_by_id_and_service_id')
    mock_get_service = mocker.patch(
        'app.dao.services_dao.dao_fetch_service_by_id')

    send_mock = mocker.patch('app.mmg_client.send_sms')
    notification = create_notification(template=sample_template,
                                       to_field='+447700900855',
                                       normalised_to='447700900855')
    send_to_providers.send_sms_to_provider(notification)
    assert mock_get_template.called is False
    assert mock_get_service.called is False
    send_mock.assert_called_once_with(to=notification.normalised_to,
                                      content=ANY,
                                      reference=str(notification.id),
                                      sender=notification.reply_to_text)
예제 #5
0
def test_create_a_template_with_reply_to(admin_request, sample_user):
    service = create_service(service_permissions=['letter'])
    letter_contact = create_letter_contact(service, "Edinburgh, ED1 1AA")
    data = {
        'name': 'my template',
        'subject': 'subject',
        'template_type': 'letter',
        'content': 'template <b>content</b>',
        'service': str(service.id),
        'created_by': str(sample_user.id),
        'reply_to': str(letter_contact.id),
    }

    json_resp = admin_request.post('template.create_template',
                                   service_id=service.id,
                                   _data=data,
                                   _expected_status=201)

    assert json_resp['data']['template_type'] == 'letter'
    assert json_resp['data']['reply_to'] == str(letter_contact.id)
    assert json_resp['data']['reply_to_text'] == letter_contact.contact_block

    template = Template.query.get(json_resp['data']['id'])
    from app.schemas import template_schema
    assert sorted(json_resp['data']) == sorted(
        template_schema.dump(template).data)
    th = TemplateHistory.query.filter_by(id=template.id, version=1).one()
    assert th.service_letter_contact_id == letter_contact.id
예제 #6
0
def get_all_templates_for_service(service_id):
    templates = dao_get_all_templates_for_service(service_id=service_id)
    if str(request.args.get('detailed', True)) == 'True':
        data = template_schema.dump(templates, many=True).data
    else:
        data = template_schema_no_detail.dump(templates, many=True).data
    return jsonify(data=data)
예제 #7
0
def send_broadcast_message(broadcast_message_id, provider='stub-1'):
    # imports of schemas from tasks have to happen within functions to prevent
    # `AttributeError: 'DummySession' object has no attribute 'query'` errors in unrelated tests
    from app.schemas import template_schema

    broadcast_message = dao_get_broadcast_message_by_id(broadcast_message_id)

    current_app.logger.info(
        f'sending broadcast_message {broadcast_message_id} '
        f'status {broadcast_message.status} to {provider}'
    )

    payload = {
        "template": template_schema.dump(broadcast_message.template).data,
        "broadcast_message": broadcast_message.serialize(),
    }
    resp = requests.post(
        f'{current_app.config["CBC_PROXY_URL"]}/broadcasts/{provider}',
        json=payload
    )
    resp.raise_for_status()

    current_app.logger.info(
        f'broadcast_message {broadcast_message.id} '
        f'status {broadcast_message.status} sent to {provider}'
    )
예제 #8
0
def create_template(service_id):
    fetched_service = dao_fetch_service_by_id(service_id=service_id)
    # permissions needs to be placed here otherwise marshmallow will intefere with versioning
    permissions = fetched_service.permissions
    new_template = template_schema.load(request.get_json()).data

    if not service_has_permission(new_template.template_type, permissions):
        message = "Creating {} templates is not allowed".format(
            get_public_notify_type_text(new_template.template_type))
        errors = {'template_type': [message]}
        raise InvalidRequest(errors, 403)

    new_template.service = fetched_service
    over_limit = _content_count_greater_than_limit(new_template.content,
                                                   new_template.template_type)
    if over_limit:
        char_count_limit = SMS_CHAR_COUNT_LIMIT
        message = 'Content has a character count greater than the limit of {}'.format(
            char_count_limit)
        errors = {'content': [message]}
        raise InvalidRequest(errors, status_code=400)

    check_reply_to(service_id, new_template.reply_to,
                   new_template.template_type)

    dao_create_template(new_template)
    return jsonify(data=template_schema.dump(new_template).data), 201
예제 #9
0
def create_template(service_id):
    fetched_service = dao_fetch_service_by_id(service_id=service_id)
    # permissions needs to be placed here otherwise marshmallow will interfere with versioning
    permissions = [p.permission for p in fetched_service.permissions]
    template_json = validate(request.get_json(), post_create_template_schema)
    folder = validate_parent_folder(template_json=template_json)
    new_template = Template.from_json(template_json, folder)

    if not service_has_permission(new_template.template_type, permissions):
        message = "Creating {} templates is not allowed".format(
            get_public_notify_type_text(new_template.template_type))
        errors = {'template_type': [message]}
        raise InvalidRequest(errors, 403)

    if not new_template.postage and new_template.template_type == LETTER_TYPE:
        new_template.postage = SECOND_CLASS

    new_template.service = fetched_service

    over_limit = _content_count_greater_than_limit(new_template.content,
                                                   new_template.template_type)
    if over_limit:
        message = 'Content has a character count greater than the limit of {}'.format(
            SMS_CHAR_COUNT_LIMIT)
        errors = {'content': [message]}
        raise InvalidRequest(errors, status_code=400)

    check_reply_to(service_id, new_template.reply_to,
                   new_template.template_type)

    dao_create_template(new_template)

    return jsonify(data=template_schema.dump(new_template).data), 201
예제 #10
0
def update_template(service_id, template_id):
    fetched_template = dao_get_template_by_id_and_service_id(template_id=template_id, service_id=service_id)

    current_data = dict(template_schema.dump(fetched_template).data.items())
    updated_template = dict(template_schema.dump(fetched_template).data.items())
    updated_template.update(request.get_json())
    updated_template['content'] = _strip_html(updated_template['content'])
    # Check if there is a change to make.
    if _template_has_not_changed(current_data, updated_template):
        return jsonify(data=updated_template), 200

    update_dict = template_schema.load(updated_template).data
    over_limit = _content_count_greater_than_limit(updated_template['content'], fetched_template.template_type)
    if over_limit:
        char_count_limit = current_app.config.get('SMS_CHAR_COUNT_LIMIT')
        message = 'Content has a character count greater than the limit of {}'.format(char_count_limit)
        errors = {'content': [message]}
        raise InvalidRequest(errors, status_code=400)
    dao_update_template(update_dict)
    return jsonify(data=template_schema.dump(update_dict).data), 200
예제 #11
0
    def get_dict(template_id, service_id):
        from app.dao import templates_dao
        from app.schemas import template_schema

        fetched_template = templates_dao.dao_get_template_by_id_and_service_id(
            template_id=template_id, service_id=service_id)

        template_dict = template_schema.dump(fetched_template).data
        db.session.commit()

        return {'data': template_dict}
예제 #12
0
def create_template(service_id):
    fetched_service = dao_fetch_service_by_id(service_id=service_id)
    new_template = template_schema.load(request.get_json()).data
    new_template.service = fetched_service
    new_template.content = _strip_html(new_template.content)
    over_limit = _content_count_greater_than_limit(new_template.content, new_template.template_type)
    if over_limit:
        char_count_limit = current_app.config.get('SMS_CHAR_COUNT_LIMIT')
        message = 'Content has a character count greater than the limit of {}'.format(char_count_limit)
        errors = {'content': [message]}
        raise InvalidRequest(errors, status_code=400)

    dao_create_template(new_template)
    return jsonify(data=template_schema.dump(new_template).data), 201
예제 #13
0
def get_template(template_id=None):
    try:
        templates = get_model_templates(template_id=template_id)
    except DataError:
        return jsonify(result="error", message="Invalid template id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Template not found"), 404
    if isinstance(templates, list):
        data, errors = templates_schema.dump(templates)
    else:
        data, errors = template_schema.dump(templates)
    if errors:
        return jsonify(result="error", message=str(errors))
    return jsonify(data=data)
예제 #14
0
def preview_template_by_id_and_service_id(service_id, template_id):
    fetched_template = dao_get_template_by_id_and_service_id(template_id=template_id, service_id=service_id)
    data = template_schema.dump(fetched_template).data
    template_object = get_template_instance(data, values=request.args.to_dict())

    if template_object.missing_data:
        raise InvalidRequest(
            {'template': [
                'Missing personalisation: {}'.format(", ".join(template_object.missing_data))
            ]}, status_code=400
        )

    data['subject'], data['content'] = template_object.subject, str(template_object)

    return jsonify(data)
예제 #15
0
def create_template(service_id):
    try:
        service = get_model_services(service_id=service_id)
    except DataError:
        return jsonify(result="error", message="Invalid service id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Service not found"), 404
    template, errors = template_schema.load(request.get_json())
    if errors:
        return jsonify(result="error", message=errors), 400
    template.service = service
    # I believe service is already added to the session but just needs a
    # db.session.commit
    save_model_template(template)
    return jsonify(data=template_schema.dump(template).data), 201
예제 #16
0
def create_template(service_id):
    try:
        service = get_model_services(service_id=service_id)
    except DataError:
        return jsonify(result="error", message="Invalid service id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Service not found"), 404
    template, errors = template_schema.load(request.get_json())
    if errors:
        return jsonify(result="error", message=errors), 400
    template.service = service
    # I believe service is already added to the session but just needs a
    # db.session.commit
    save_model_template(template)
    return jsonify(data=template_schema.dump(template).data), 201
예제 #17
0
def get_service_template(service_id, template_id=None):
    try:
        templates = get_model_templates(service_id=service_id,
                                        template_id=template_id)
    except DataError:
        return jsonify(result="error", message="Invalid template id"), 400
    except NoResultFound:
        return jsonify(result="error", message="Template not found"), 404
    if isinstance(templates, list):
        data, errors = templates_schema.dump(templates)
    else:
        data, errors = template_schema.dump(templates)
    if errors:
        return jsonify(result="error", message=str(errors))
    return jsonify(data=data)
예제 #18
0
def test_should_cache_template_and_service_in_redis(mocker, client, sample_template):

    from app.schemas import service_schema, template_schema

    mock_redis_get = mocker.patch(
        'app.redis_store.get',
        return_value=None,
    )
    mock_redis_set = mocker.patch(
        'app.redis_store.set',
    )

    mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')

    data = {
        'phone_number': '+447700900855',
        'template_id': str(sample_template.id),
    }

    auth_header = create_authorization_header(service_id=sample_template.service_id)
    client.post(
        path='/v2/notifications/sms',
        data=json.dumps(data),
        headers=[('Content-Type', 'application/json'), auth_header]
    )

    expected_service_key = f'service-{sample_template.service_id}'
    expected_templates_key = f'service-{sample_template.service_id}-template-{sample_template.id}-version-None'

    assert mock_redis_get.call_args_list == [
        call(expected_service_key),
        call(expected_templates_key),
    ]

    service_dict = service_schema.dump(sample_template.service).data
    template_dict = template_schema.dump(sample_template).data

    assert len(mock_redis_set.call_args_list) == 2

    service_call, templates_call = mock_redis_set.call_args_list

    assert service_call[0][0] == expected_service_key
    assert json.loads(service_call[0][1]) == {'data': service_dict}
    assert service_call[1]['ex'] == 604_800

    assert templates_call[0][0] == expected_templates_key
    assert json.loads(templates_call[0][1]) == {'data': template_dict}
    assert templates_call[1]['ex'] == 604_800
예제 #19
0
def preview_template_by_id_and_service_id(service_id, template_id):
    fetched_template = dao_get_template_by_id_and_service_id(
        template_id=template_id, service_id=service_id)
    data = template_schema.dump(fetched_template).data
    template_object = fetched_template._as_utils_template_with_personalisation(
        request.args.to_dict())

    if template_object.missing_data:
        raise InvalidRequest(
            {
                'template': [
                    'Missing personalisation: {}'.format(", ".join(
                        template_object.missing_data))
                ]
            },
            status_code=400)

    data['subject'] = template_object.subject
    data['content'] = template_object.content_with_placeholders_filled_in

    return jsonify(data)
def test_should_return_template_if_found_in_redis(mocker, client,
                                                  sample_template):

    from app.schemas import service_schema, template_schema
    service_dict = service_schema.dump(sample_template.service).data
    template_dict = template_schema.dump(sample_template).data

    mocker.patch(
        'app.redis_store.get',
        side_effect=[
            json.dumps({
                'data': service_dict
            }).encode('utf-8'),
            json.dumps({
                'data': template_dict
            }).encode('utf-8'),
        ],
    )
    mock_get_template = mocker.patch(
        'app.dao.templates_dao.dao_get_template_by_id_and_service_id')
    mock_get_service = mocker.patch(
        'app.dao.services_dao.dao_fetch_service_by_id')

    mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')

    data = {
        'phone_number': '+447700900855',
        'template_id': str(sample_template.id),
    }

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

    assert response.status_code == 201
    assert mock_get_template.called is False
    assert mock_get_service.called is False
예제 #21
0
def test_should_create_a_new_template_for_a_service(
    client, sample_user, template_type, subject
):
    service = create_service(service_permissions=[template_type])
    data = {
        'name': 'my template',
        'template_type': template_type,
        'content': 'template <b>content</b>',
        'service': str(service.id),
        'created_by': str(sample_user.id)
    }
    if subject:
        data.update({'subject': subject})
    data = json.dumps(data)
    auth_header = create_authorization_header()

    response = client.post(
        '/service/{}/template'.format(service.id),
        headers=[('Content-Type', 'application/json'), auth_header],
        data=data
    )
    assert response.status_code == 201
    json_resp = json.loads(response.get_data(as_text=True))
    assert json_resp['data']['name'] == 'my template'
    assert json_resp['data']['template_type'] == template_type
    assert json_resp['data']['content'] == 'template <b>content</b>'
    assert json_resp['data']['service'] == str(service.id)
    assert json_resp['data']['id']
    assert json_resp['data']['version'] == 1
    assert json_resp['data']['process_type'] == 'normal'
    assert json_resp['data']['created_by'] == str(sample_user.id)
    if subject:
        assert json_resp['data']['subject'] == 'subject'
    else:
        assert not json_resp['data']['subject']

    template = Template.query.get(json_resp['data']['id'])
    from app.schemas import template_schema
    assert sorted(json_resp['data']) == sorted(template_schema.dump(template).data)
예제 #22
0
def preview_template_by_id_and_service_id(service_id, template_id):
    fetched_template = dao_get_template_by_id_and_service_id(template_id=template_id, service_id=service_id)
    data = template_schema.dump(fetched_template).data

    template_object = get_template_instance(data, values=request.args.to_dict())

    if template_object.missing_data:
        raise InvalidRequest(
            {'template': [
                'Missing personalisation: {}'.format(", ".join(template_object.missing_data))
            ]}, status_code=400
        )

    if template_object.additional_data:
        raise InvalidRequest(
            {'template': [
                'Personalisation not needed for template: {}'.format(", ".join(template_object.additional_data))
            ]}, status_code=400
        )

    data['subject'], data['content'] = template_object.subject, str(template_object)

    return jsonify(data)
def test_send_email_to_provider_should_return_template_if_found_in_redis(
        mocker, client, sample_email_template):
    from app.schemas import service_schema, template_schema
    service_dict = service_schema.dump(sample_email_template.service).data
    template_dict = template_schema.dump(sample_email_template).data

    mocker.patch(
        'app.redis_store.get',
        side_effect=[
            json.dumps({
                'data': service_dict
            }).encode('utf-8'),
            json.dumps({
                'data': template_dict
            }).encode('utf-8'),
        ],
    )
    mock_get_template = mocker.patch(
        'app.dao.templates_dao.dao_get_template_by_id_and_service_id')
    mock_get_service = mocker.patch(
        'app.dao.services_dao.dao_fetch_service_by_id')
    send_mock = mocker.patch('app.aws_ses_client.send_email',
                             return_value='reference')
    notification = create_notification(template=sample_email_template,
                                       to_field='*****@*****.**',
                                       normalised_to='*****@*****.**')

    send_to_providers.send_email_to_provider(notification)
    assert mock_get_template.called is False
    assert mock_get_service.called is False
    send_mock.assert_called_once_with(
        ANY,
        notification.normalised_to,
        ANY,
        body=ANY,
        html_body=ANY,
        reply_to_address=notification.reply_to_text)
예제 #24
0
def get_all_templates_for_service(service_id):
    templates = dao_get_all_templates_for_service(service_id=service_id)
    data = template_schema.dump(templates, many=True).data
    return jsonify(data=data)
예제 #25
0
def get_template_by_id_and_service_id(service_id, template_id):
    fetched_template = dao_get_template_by_id_and_service_id(template_id=template_id, service_id=service_id)
    data = template_schema.dump(fetched_template).data
    return jsonify(data=data)
예제 #26
0
def get_template_by_id_and_service_id(service_id, template_id):
    fetched_template = dao_get_template_by_id_and_service_id(
        template_id=template_id, service_id=service_id)
    data = template_schema.dump(fetched_template).data
    return jsonify(data=data)
예제 #27
0
def get_precompiled_template_for_service(service_id):
    template = get_precompiled_letter_template(service_id)
    template_dict = template_schema.dump(template).data

    return jsonify(template_dict), 200
예제 #28
0
def get_all_templates_for_service(service_id):
    templates = dao_get_all_templates_for_service(service_id=service_id)
    data = template_schema.dump(templates, many=True).data
    return jsonify(data=data)