def get_last_used_datetime_for_template(service_id, template_id): # Check the template and service exist dao_get_template_by_id_and_service_id(template_id, service_id) last_date_used = dao_get_last_date_template_was_used(template_id=template_id, service_id=service_id) return jsonify(last_date_used=last_date_used.strftime(DATETIME_FORMAT) if last_date_used else last_date_used)
def test_get_template_version_returns_none_for_hidden_templates( sample_service): sample_template = create_template(template_name='Test Template', hidden=True, service=sample_service) with pytest.raises(NoResultFound): dao_get_template_by_id_and_service_id(sample_template.id, sample_service.id, '1')
def test_get_template_by_id_and_service_returns_none_for_hidden_templates( notify_db, notify_db_session, sample_service): sample_template = create_sample_template(notify_db, notify_db_session, template_name='Test Template', hidden=True, service=sample_service) with pytest.raises(NoResultFound): dao_get_template_by_id_and_service_id(template_id=sample_template.id, service_id=sample_service.id)
def create_broadcast_message(service_id): data = request.get_json() validate(data, create_broadcast_message_schema) service = dao_fetch_service_by_id(data['service_id']) user = get_user_by_id(data['created_by']) template = dao_get_template_by_id_and_service_id(data['template_id'], data['service_id']) personalisation = data.get('personalisation', {}) broadcast_message = BroadcastMessage( service_id=service.id, template_id=template.id, template_version=template.version, personalisation=personalisation, areas={"areas": data.get("areas", []), "simple_polygons": data.get("simple_polygons", [])}, status=BroadcastStatusType.DRAFT, starts_at=_parse_nullable_datetime(data.get('starts_at')), finishes_at=_parse_nullable_datetime(data.get('finishes_at')), created_by_id=user.id, content=template._as_utils_template_with_personalisation( personalisation ).content_with_placeholders_filled_in, ) dao_save_object(broadcast_message) return jsonify(broadcast_message.serialize()), 201
def check_template_exists_by_id_and_service(template_id, service): try: return templates_dao.dao_get_template_by_id_and_service_id( template_id=template_id, service_id=service.id) except NoResultFound: message = "Template not found" raise BadRequestError(message=message, fields=[{"template": message}])
def post_template_preview(template_id): # The payload is empty when there are no place holders in the template. _data = request.get_data(as_text=True) if not _data: _data = {} else: _data = get_valid_json() _data['id'] = template_id data = validate(_data, post_template_preview_request) template = templates_dao.dao_get_template_by_id_and_service_id( template_id, authenticated_service.id) template_object = template._as_utils_template_with_personalisation( data.get('personalisation') ) check_placeholders(template_object) resp = create_post_template_preview_response(template=template, template_object=template_object) return jsonify(resp), 200
def send_one_off_notification(service_id, post_data): service = dao_fetch_service_by_id(service_id) template = dao_get_template_by_id_and_service_id( template_id=post_data['template_id'], service_id=service_id ) personalisation = post_data.get('personalisation', None) validate_template(template.id, personalisation, service, template.template_type) check_service_over_daily_message_limit(KEY_TYPE_NORMAL, service) validate_and_format_recipient( send_to=post_data['to'], key_type=KEY_TYPE_NORMAL, service=service, notification_type=template.template_type, allow_whitelisted_recipients=False, ) validate_created_by(service, post_data['created_by']) sender_id = post_data.get('sender_id', None) reply_to = get_reply_to_text( notification_type=template.template_type, sender_id=sender_id, service=service, template=template ) notification = persist_notification( template_id=template.id, template_version=template.version, template_postage=template.postage, recipient=post_data['to'], service=service, personalisation=personalisation, notification_type=template.template_type, api_key_id=None, key_type=KEY_TYPE_NORMAL, created_by_id=post_data['created_by'], reply_to_text=reply_to, reference=create_one_off_reference(template.template_type), ) queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None if template.template_type == LETTER_TYPE and service.research_mode: _update_notification_status( notification, NOTIFICATION_DELIVERED, ) else: send_notification_to_queue( notification=notification, research_mode=service.research_mode, queue=queue_name, ) return {'id': str(notification.id)}
def test_can_get_template_then_redacted_returns_right_values(sample_template): template = dao_get_template_by_id_and_service_id( template_id=sample_template.id, service_id=sample_template.service_id) assert not template.redact_personalisation dao_redact_template(template=template, user_id=sample_template.created_by_id) assert template.redact_personalisation
def test_get_template_history_version(sample_user, sample_service, sample_template): old_content = sample_template.content sample_template.content = "New content" dao_update_template(sample_template) old_template = dao_get_template_by_id_and_service_id( sample_template.id, sample_service.id, '1') assert old_template.content == old_content
def get_template_statistics_for_template_id(service_id, template_id): template = dao_get_template_by_id_and_service_id(template_id, service_id) data = None notification = dao_get_last_template_usage(template_id, template.template_type, template.service_id) if notification: data = notification_with_template_schema.dump(notification).data return jsonify(data=data)
def test_get_template_by_id_and_service(sample_service): sample_template = create_template(template_name='Test Template', service=sample_service) template = dao_get_template_by_id_and_service_id( template_id=sample_template.id, service_id=sample_service.id) assert template.id == sample_template.id assert template.name == 'Test Template' assert template.version == sample_template.version assert not template.redact_personalisation
def test_check_notification_content_is_not_empty_passes( notify_api, mocker, sample_service): template_id = create_template(sample_service, content="Content is not empty").id template = templates_dao.dao_get_template_by_id_and_service_id( template_id=template_id, service_id=sample_service.id) template_with_content = create_content_for_notification(template, {}) assert check_notification_content_is_not_empty( template_with_content) is None
def get_template_version(service_id, template_id, version): data = template_history_schema.dump( dao_get_template_by_id_and_service_id( template_id=template_id, service_id=service_id, version=version ) ).data return jsonify(data=data)
def test_get_template_by_id_and_service(notify_db, notify_db_session, sample_service): sample_template = create_sample_template( notify_db, notify_db_session, template_name='Test Template', service=sample_service) assert dao_get_template_by_id_and_service_id( template_id=sample_template.id, service_id=sample_service.id).name == 'Test Template' assert Template.query.count() == 1
def test_check_content_char_count_passes_for_long_email_or_letter( sample_service, template_type): t = create_template(service=sample_service, content='a' * 1000, template_type=template_type) template = templates_dao.dao_get_template_by_id_and_service_id( template_id=t.id, service_id=t.service_id) template_with_content = get_template_instance(template=template.__dict__, values={}) assert check_content_char_count(template_with_content) is None
def test_get_template_history_version(sample_user, sample_service, sample_template): old_content = sample_template.content sample_template.content = "New content" dao_update_template(sample_template) old_template = dao_get_template_by_id_and_service_id( sample_template.id, sample_service.id, '1' ) assert old_template.content == old_content
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 send_one_off_notification(service_id, post_data): service = dao_fetch_service_by_id(service_id) template = dao_get_template_by_id_and_service_id(template_id=post_data["template_id"], service_id=service_id) personalisation = post_data.get("personalisation", None) validate_template(template.id, personalisation, service, template.template_type) check_service_over_daily_message_limit(KEY_TYPE_NORMAL, service) validate_and_format_recipient( send_to=post_data["to"], key_type=KEY_TYPE_NORMAL, service=service, notification_type=template.template_type, allow_safelisted_recipients=False, ) validate_created_by(service, post_data["created_by"]) sender_id = post_data.get("sender_id", None) reply_to = get_reply_to_text( notification_type=template.template_type, sender_id=sender_id, service=service, template=template, ) notification = persist_notification( template_id=template.id, template_version=template.version, template_postage=template.postage, recipient=post_data["to"], service=service, personalisation=personalisation, notification_type=template.template_type, api_key_id=None, key_type=KEY_TYPE_NORMAL, created_by_id=post_data["created_by"], reply_to_text=reply_to, reference=create_one_off_reference(template.template_type), ) if template.template_type == LETTER_TYPE and service.research_mode: _update_notification_status( notification, NOTIFICATION_DELIVERED, ) else: send_notification_to_queue( notification=notification, research_mode=service.research_mode, queue=template.queue_to_use(), ) return {"id": str(notification.id)}
def test_check_content_char_count_fails(notify_db_session, show_prefix, char_count): with pytest.raises(BadRequestError) as e: service = create_service(prefix_sms=show_prefix) t = create_template(service=service, content='a' * char_count, template_type='sms') template = templates_dao.dao_get_template_by_id_and_service_id(template_id=t.id, service_id=service.id) template_with_content = get_template_instance(template=template.__dict__, values={}) check_content_char_count(template_with_content) assert e.value.status_code == 400 assert e.value.message == f'Text messages cannot be longer than {SMS_CHAR_COUNT_LIMIT} characters. ' \ f'Your message is {char_count} characters' assert e.value.fields == []
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 test_check_content_char_count_passes(notify_db_session, show_prefix, char_count, template_type): service = create_service(prefix_sms=show_prefix) t = create_template(service=service, content='a' * char_count, template_type=template_type) template = templates_dao.dao_get_template_by_id_and_service_id( template_id=t.id, service_id=service.id) template_with_content = get_template_instance(template=template.__dict__, values={}) assert check_content_char_count(template_with_content) is None
def get_template_statistics_for_template_id(service_id, template_id): template = dao_get_template_by_id_and_service_id(template_id, service_id) if not template: message = 'No template found for id {}'.format(template_id) errors = {'template_id': [message]} raise InvalidRequest(errors, status_code=404) data = None notification = dao_get_last_template_usage(template_id, template.template_type) if notification: data = notification_with_template_schema.dump(notification).data return jsonify(data=data)
def test_check_notification_content_is_not_empty_fails(notify_api, mocker, sample_service, template_content, notification_values): template_id = create_template(sample_service, content=template_content).id template = templates_dao.dao_get_template_by_id_and_service_id( template_id=template_id, service_id=sample_service.id) template_with_content = create_content_for_notification( template, notification_values) with pytest.raises(BadRequestError) as e: check_notification_content_is_not_empty(template_with_content) assert e.value.status_code == 400 assert e.value.message == 'Your message is empty.' assert e.value.fields == []
def __validate_template(form, service, notification_type): try: template = templates_dao.dao_get_template_by_id_and_service_id( template_id=form["template_id"], service_id=service.id ) except NoResultFound: message = "Template not found" raise BadRequestError(message=message, fields=[{"template": message}]) check_template_is_for_notification_type(notification_type, template.template_type) check_template_is_active(template) template_with_content = create_content_for_notification(template, form.get("personalisation", {})) if template.template_type == SMS_TYPE: check_sms_content_char_count(template_with_content.content_count) return template, template_with_content
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 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 validate_template(template_id, personalisation, service, notification_type): try: template = templates_dao.dao_get_template_by_id_and_service_id( template_id=template_id, service_id=service.id) except NoResultFound: message = 'Template not found' raise BadRequestError(message=message, fields=[{'template': message}]) check_template_is_for_notification_type(notification_type, template.template_type) check_template_is_active(template) template_with_content = create_content_for_notification( template, personalisation) if template.template_type == SMS_TYPE: check_sms_content_char_count(template_with_content.content_count) return template, template_with_content
def test_check_is_message_too_long_passes_for_long_email(sample_service): email_character_count = 2_000_001 t = create_template(service=sample_service, content='a' * email_character_count, template_type='email') template = templates_dao.dao_get_template_by_id_and_service_id(template_id=t.id, service_id=t.service_id) template_with_content = get_template_instance(template=template.__dict__, values={}) template_with_content.values with pytest.raises(BadRequestError) as e: check_is_message_too_long(template_with_content) assert e.value.status_code == 400 expected_message = ( 'Your message is too long. ' + 'Emails cannot be longer than 2000000 bytes. ' + 'Your message is 2000001 bytes.' ) assert e.value.message == expected_message assert e.value.fields == []
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
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 post_template_preview(template_id): _data = request.get_json() if _data is None: _data = {} _data['id'] = template_id data = validate(_data, post_template_preview_request) template = templates_dao.dao_get_template_by_id_and_service_id( template_id, authenticated_service.id) template_object = get_template_instance(template.__dict__, values=data.get('personalisation')) check_placeholders(template_object) resp = create_post_template_preview_response( template=template, template_object=template_object) return jsonify(resp), 200
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 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 create_broadcast_message(service_id): data = request.get_json() validate(data, create_broadcast_message_schema) service = dao_fetch_service_by_id(data['service_id']) user = get_user_by_id(data['created_by']) template = dao_get_template_by_id_and_service_id(data['template_id'], data['service_id']) broadcast_message = BroadcastMessage( service_id=service.id, template_id=template.id, template_version=template.version, personalisation=data.get('personalisation', {}), areas=data.get('areas', []), status=BroadcastStatusType.DRAFT, starts_at=_parse_nullable_datetime(data.get('starts_at')), finishes_at=_parse_nullable_datetime(data.get('finishes_at')), created_by_id=user.id, ) dao_save_object(broadcast_message) return jsonify(broadcast_message.serialize()), 201
def test_get_template_by_id_and_service_returns_none_if_no_template(sample_service, fake_uuid): with pytest.raises(NoResultFound) as e: dao_get_template_by_id_and_service_id(template_id=fake_uuid, service_id=sample_service.id) assert 'No row was found for one' in str(e.value)
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)