diff --git a/app/config.py b/app/config.py index 7ce5cfb0f..4c5270e40 100644 --- a/app/config.py +++ b/app/config.py @@ -145,6 +145,8 @@ class Config(object): CHANGE_EMAIL_CONFIRMATION_TEMPLATE_ID = 'eb4d9930-87ab-4aef-9bce-786762687884' SERVICE_NOW_LIVE_TEMPLATE_ID = '618185c6-3636-49cd-b7d2-6f6f5eb3bdde' ORGANISATION_INVITATION_EMAIL_TEMPLATE_ID = '203566f0-d835-47c5-aa06-932439c86573' + TEAM_MEMBER_EDIT_EMAIL_TEMPLATE_ID = 'c73f1d71-4049-46d5-a647-d013bdeca3f0' + TEAM_MEMBER_EDIT_MOBILE_TEMPLATE_ID = '8a31520f-4751-4789-8ea1-fe54496725eb' BROKER_URL = 'sqs://' BROKER_TRANSPORT_OPTIONS = { diff --git a/app/user/rest.py b/app/user/rest.py index 0a7822c9b..377bf3a46 100644 --- a/app/user/rest.py +++ b/app/user/rest.py @@ -84,10 +84,45 @@ def create_user(): def update_user_attribute(user_id): user_to_update = get_user_by_id(user_id=user_id) req_json = request.get_json() + if 'updated_by' in req_json: + updated_by = get_user_by_id(user_id=req_json.pop('updated_by')) + else: + updated_by = None + update_dct, errors = user_update_schema_load_json.load(req_json) if errors: raise InvalidRequest(errors, status_code=400) save_user_attribute(user_to_update, update_dict=update_dct) + if updated_by: + if 'email_address' in update_dct: + template = dao_get_template_by_id(current_app.config['TEAM_MEMBER_EDIT_EMAIL_TEMPLATE_ID']) + recipient = user_to_update.email_address + reply_to = template.service.get_default_reply_to_email_address() + elif 'mobile_number' in update_dct: + template = dao_get_template_by_id(current_app.config['TEAM_MEMBER_EDIT_MOBILE_TEMPLATE_ID']) + recipient = user_to_update.mobile_number + reply_to = template.service.get_default_sms_sender() + else: + return jsonify(data=user_to_update.serialize()), 200 + service = Service.query.get(current_app.config['NOTIFY_SERVICE_ID']) + + saved_notification = persist_notification( + template_id=template.id, + template_version=template.version, + recipient=recipient, + service=service, + personalisation={ + 'name': user_to_update.name, + 'servicemanagername': updated_by.name, + 'email address': user_to_update.email_address + }, + notification_type=template.template_type, + api_key_id=None, + key_type=KEY_TYPE_NORMAL, + reply_to_text=reply_to + ) + + send_notification_to_queue(saved_notification, False, queue=QueueNames.NOTIFY) return jsonify(data=user_to_update.serialize()), 200 diff --git a/migrations/versions/0265_add_confirm_edit_templates.py b/migrations/versions/0265_add_confirm_edit_templates.py new file mode 100644 index 000000000..190a7541e --- /dev/null +++ b/migrations/versions/0265_add_confirm_edit_templates.py @@ -0,0 +1,117 @@ +""" + +Revision ID: 0265_add_confirm_edit_templates +Revises: 0264_add_folder_permissions_perm +Create Date: 2019-02-26 15:16:53.268135 + +""" +from datetime import datetime + +from alembic import op +from flask import current_app + + +revision = '0265_add_confirm_edit_templates' +down_revision = '0264_add_folder_permissions_perm' + +email_template_id = "c73f1d71-4049-46d5-a647-d013bdeca3f0" +mobile_template_id = "8a31520f-4751-4789-8ea1-fe54496725eb" + + +def upgrade(): + template_insert = """ + INSERT INTO templates (id, name, template_type, created_at, content, archived, service_id, subject, + created_by_id, version, process_type, hidden) + VALUES ('{}', '{}', '{}', '{}', '{}', False, '{}', '{}', '{}', 1, '{}', false) + """ + template_history_insert = """ + INSERT INTO templates_history (id, name, template_type, created_at, content, archived, service_id, subject, + created_by_id, version, process_type, hidden) + VALUES ('{}', '{}', '{}', '{}', '{}', False, '{}', '{}', '{}', 1, '{}', false) + """ + + email_template_content = '\n'.join([ + "Dear ((name)),", + "", + "((servicemanagername)) changed your Notify account email address to:", + "", + "((email address))", + "", + "You’ll need to use this email address next time you sign in.", + "", + "Thanks", + "", + "GOV.​UK Notify team", + "https://www.gov.uk/notify" + ]) + + email_template_name = "Email address changed by service manager" + email_template_subject = 'Your GOV.UK Notify email address has changed' + + op.execute( + template_history_insert.format( + email_template_id, + email_template_name, + 'email', + datetime.utcnow(), + email_template_content, + current_app.config['NOTIFY_SERVICE_ID'], + email_template_subject, + current_app.config['NOTIFY_USER_ID'], + 'normal' + ) + ) + + op.execute( + template_insert.format( + email_template_id, + email_template_name, + 'email', + datetime.utcnow(), + email_template_content, + current_app.config['NOTIFY_SERVICE_ID'], + email_template_subject, + current_app.config['NOTIFY_USER_ID'], + 'normal' + ) + ) + + mobile_template_content = """Your mobile number was changed by ((servicemanagername)). Next time you sign in, your Notify authentication code will be sent to this phone.""" + + mobile_template_name = "Phone number changed by service manager" + + op.execute( + template_history_insert.format( + mobile_template_id, + mobile_template_name, + 'sms', + datetime.utcnow(), + mobile_template_content, + current_app.config['NOTIFY_SERVICE_ID'], + None, + current_app.config['NOTIFY_USER_ID'], + 'normal' + ) + ) + + op.execute( + template_insert.format( + mobile_template_id, + mobile_template_name, + 'sms', + datetime.utcnow(), + mobile_template_content, + current_app.config['NOTIFY_SERVICE_ID'], + None, + current_app.config['NOTIFY_USER_ID'], + 'normal' + ) + ) + + +def downgrade(): + op.execute("DELETE FROM templates_history WHERE id = '{}'".format(email_template_id)) + op.execute("DELETE FROM templates WHERE id = '{}'".format(email_template_id)) + + op.execute("DELETE FROM templates_history WHERE id = '{}'".format(mobile_template_id)) + op.execute("DELETE FROM templates WHERE id = '{}'".format(mobile_template_id)) diff --git a/tests/app/conftest.py b/tests/app/conftest.py index a48e8d673..50b86e4d4 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -949,6 +949,33 @@ def password_reset_email_template(notify_db, ) +@pytest.fixture(scope='function') +def team_member_email_edit_template(notify_db, notify_db_session): + service, user = notify_service(notify_db, notify_db_session) + + return create_custom_template( + service=service, + user=user, + template_config_name='TEAM_MEMBER_EDIT_EMAIL_TEMPLATE_ID', + content='Hi ((name)) ((servicemanagername)) changed your email to ((email address))', + subject='Your GOV.UK Notify email address has changed', + template_type='email' + ) + + +@pytest.fixture(scope='function') +def team_member_mobile_edit_template(notify_db, notify_db_session): + service, user = notify_service(notify_db, notify_db_session) + + return create_custom_template( + service=service, + user=user, + template_config_name='TEAM_MEMBER_EDIT_MOBILE_TEMPLATE_ID', + content='Your mobile number was changed by ((servicemanagername)).', + template_type='sms' + ) + + @pytest.fixture(scope='function') def already_registered_template(notify_db, notify_db_session): diff --git a/tests/app/db.py b/tests/app/db.py index 2aa6e3ae1..1b301a2f2 100644 --- a/tests/app/db.py +++ b/tests/app/db.py @@ -55,10 +55,16 @@ from app.models import ( ) -def create_user(mobile_number="+447700900986", email="notify@digital.cabinet-office.gov.uk", state='active', id_=None): +def create_user( + mobile_number="+447700900986", + email="notify@digital.cabinet-office.gov.uk", + state='active', + id_=None, + name="Test User" +): data = { 'id': id_ or uuid.uuid4(), - 'name': 'Test User', + 'name': name, 'email_address': email, 'password': 'password', 'mobile_number': mobile_number, diff --git a/tests/app/user/test_rest.py b/tests/app/user/test_rest.py index 451c9a62d..5babdf6eb 100644 --- a/tests/app/user/test_rest.py +++ b/tests/app/user/test_rest.py @@ -1,5 +1,7 @@ import json import pytest +import mock +from uuid import UUID from flask import url_for from freezegun import freeze_time @@ -257,6 +259,55 @@ def test_post_user_attribute(client, sample_user, user_attribute, user_value): assert json_resp['data'][user_attribute] == user_value +@pytest.mark.parametrize('user_attribute, user_value, arguments', [ + ('name', 'New User', None), + ('email_address', 'newuser@mail.com', dict( + api_key_id=None, key_type='normal', notification_type='email', + personalisation={ + 'name': 'Test User', 'servicemanagername': 'Service Manago', 'email address': 'newuser@mail.com' + }, + recipient='newuser@mail.com', reply_to_text='notify@gov.uk', + service=mock.ANY, + template_id=UUID('c73f1d71-4049-46d5-a647-d013bdeca3f0'), template_version=1 + )), + ('mobile_number', '+4407700900460', dict( + api_key_id=None, key_type='normal', notification_type='sms', + personalisation={ + 'name': 'Test User', 'servicemanagername': 'Service Manago', + 'email address': 'notify@digital.cabinet-office.gov.uk' + }, + recipient='+4407700900460', reply_to_text='testing', service=mock.ANY, + template_id=UUID('8a31520f-4751-4789-8ea1-fe54496725eb'), template_version=1 + )) +]) +def test_post_user_attribute_with_updated_by( + client, mocker, sample_user, user_attribute, + user_value, arguments, team_member_email_edit_template, team_member_mobile_edit_template +): + updater = create_user(name="Service Manago", email="notify_manago@digital.cabinet-office.gov.uk") + assert getattr(sample_user, user_attribute) != user_value + update_dict = { + user_attribute: user_value, + 'updated_by': str(updater.id) + } + auth_header = create_authorization_header() + headers = [('Content-Type', 'application/json'), auth_header] + mock_persist_notification = mocker.patch('app.user.rest.persist_notification') + mocker.patch('app.user.rest.send_notification_to_queue') + resp = client.post( + url_for('user.update_user_attribute', user_id=sample_user.id), + data=json.dumps(update_dict), + headers=headers) + + assert resp.status_code == 200, resp.get_data(as_text=True) + json_resp = json.loads(resp.get_data(as_text=True)) + assert json_resp['data'][user_attribute] == user_value + if arguments: + mock_persist_notification.assert_called_once_with(**arguments) + else: + mock_persist_notification.assert_not_called() + + def test_get_user_by_email(client, sample_service): sample_user = sample_service.users[0] header = create_authorization_header()