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
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)
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
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)
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}' )
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
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
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
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}
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
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)
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)
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
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)
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
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
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)
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)
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)
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)
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)
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