diff --git a/app/commands.py b/app/commands.py index 1718ea82d..5f0ffb91b 100644 --- a/app/commands.py +++ b/app/commands.py @@ -65,6 +65,8 @@ from app.models import ( Notification, Organisation, Service, + Template, + TemplateHistory, User, ) from app.utils import get_local_midnight_in_utc @@ -765,3 +767,28 @@ def create_user_jwt(token): service_id = token[-73:-37] api_key = token[-36:] print(create_jwt_token(api_key, service_id)) + + +def _update_template(id, name, template_type, content, subject): + + template = Template.query.filter_by(id=id).first() + template.name = name + template.template_type = template_type + template.content = '\n'.join(content) + template.subject = subject + + history = TemplateHistory.query.filter_by(id=id).first() + history.name = name + history.template_type = template_type + history.content = '\n'.join(content) + history.subject = subject + + db.session.commit() + + +@notify_command(name='update-templates') +def update_templates(): + with open(current_app.config['CONFIG_FILES'] + '/templates.json') as f: + data = json.load(f) + for d in data: + _update_template(d['id'], d['name'], d['type'], d['content'], d['subject']) diff --git a/app/config.py b/app/config.py index 10d4220c8..039da6a43 100644 --- a/app/config.py +++ b/app/config.py @@ -1,6 +1,6 @@ import json from datetime import timedelta -from os import getenv +from os import getenv, path from celery.schedules import crontab from kombu import Exchange, Queue @@ -147,6 +147,9 @@ class Config(object): MAX_LETTER_PDF_ZIP_FILESIZE = 40 * 1024 * 1024 # 40mb MAX_LETTER_PDF_COUNT_PER_ZIP = 500 + # Default data + CONFIG_FILES = path.dirname(__file__) + '/config_files/' + NOTIFY_SERVICE_ID = 'd6aa2c68-a2d9-4437-ab19-3ae8eb202553' NOTIFY_USER_ID = '6af522d0-2915-4e52-83a3-3690455a5fe6' INVITATION_EMAIL_TEMPLATE_ID = '4f46df42-f795-4cc4-83bb-65ca312f49cc' diff --git a/app/config_files/templates.json b/app/config_files/templates.json new file mode 100644 index 000000000..ae208541b --- /dev/null +++ b/app/config_files/templates.json @@ -0,0 +1,274 @@ +[ + { + "id": "42a23d19-504e-49bb-a95e-4976baff4757", + "name": "Example text message template", + "type": "sms", + "subject": "", + "content": ["Hi, I’m trying out U.S. Notify. Today is ((day of week)) and my favorite color is ((color))."] + }, + { + "id": "4f46df42-f795-4cc4-83bb-65ca312f49cc", + "name": "Notify invitation email", + "type": "email", + "subject": "((user_name)) has invited you to collaborate on ((service_name)) on U.S. Notify", + "content": ["((user_name)) has invited you to collaborate on ((service_name)) on U.S. Notify.", + "", + "", + "U.S. Notify makes it easy to keep people updated by helping you send text messages, emails and letters.", + "", + "", + "Click this link to create an account on U.S. Notify:", + "", + "((url))", + "", + "", + "This invitation will stop working at midnight tomorrow. This is to keep ((service_name)) secure."] + }, + { + "id": "36fb0730-6259-4da1-8a80-c8de22ad4246", + "name": "Notify SMS verify code", + "type": "sms", + "subject": "", + "content": ["((verify_code)) is your U.S. Notify authentication code"] + }, + { + "id": "474e9242-823b-4f99-813d-ed392e7f1201", + "name": "Notify password reset email", + "type": "email", + "subject": "Reset your U.S. Notify password", + "content": ["Hi ((user_name)),", + "", + "", + "We received a request to reset your password on U.S. Notify.", + "", + "", + "If you didn’t request this email, you can ignore it – your password has not been changed.", + "", + "", + "To reset your password, click this link:","","","((url))"] + }, + { + "id": "299726d2-dba6-42b8-8209-30e1d66ea164", + "name": "Notify email verify code", + "type": "email", + "subject": "Sign in to U.S. Notify", + "content": ["Hi ((name)),", + "", + "", + "To sign in to U.S. Notify please open this link:", + "", + "", + "((url))"] + }, + { + "id": "ece42649-22a8-4d06-b87f-d52d5d3f0a27", + "name": "Notify email verification code", + "type": "email", + "subject": "Confirm U.S. Notify registration", + "content": ["Hi ((name)),", + "", + "", + "To complete your registration for U.S. Notify please click the link below", + "", + "", + "((url))"] + }, + { + "id": "0880fbb1-a0c6-46f0-9a8e-36c986381ceb", + "name": "Your U.S. Notify account", + "type": "email", + "subject": "Your U.S. Notify account", + "content": ["You already have a U.S. Notify account with this email address.", + "", + "", + "Sign in here: ((signin_url))", + "", + "", + "If you’ve forgotten your password, you can reset it here: ((forgot_password_url))", + "", + "", + "", + "", + "If you didn’t try to register for a U.S. Notify account recently, please let us know here: ((feedback_url))"] + }, + { + "id": "eb4d9930-87ab-4aef-9bce-786762687884", + "name": "Confirm new email address", + "type": "email", + "subject": "Confirm your email address for U.S. Notify", + "content": ["Hi ((name)),","","","Click this link to confirm your new email address:", + "", + "", + "((url))", + "", + "", + "If you didn’t try to change the email address for your U.S. Notify account, let us know here:", + "", + "", + "((feedback_url))"] + }, + { + "id": "618185c6-3636-49cd-b7d2-6f6f5eb3bdde", + "name": "Automated \"You’re now live\" message", + "type": "email", + "subject": "((service name)) is now live on U.S. Notify", + "content": ["Hi ((name)),", + "", + "", + "((service name)) is now live on U.S. Notify.", + "", + "", + "You can send up to ((message limit)) messages per day.", + "", + "", + "As a live service, you’ll need to know who to contact if you have a question, or something goes wrong.", + "", + "", + "If our system status page shows a problem, then we’ve been alerted and are working on it – you don’t need to contact us.", + "", + "", + "#Problems or questions out of hours", + "", + "", + "We offer out of hours support for emergencies.", + "", + "", + "It’s only an emergency if:", + "", + "* no one in your team can log in", + "", + "* a ‘technical difficulties’ error appears when you try to upload a file", + "", + "* a 500 response code appears when you try to send messages using the API", + "", + "", + "If you have one of these emergencies, email details to:", + "", + "notify-support@gsa.gov", + "", + "", + "^Only use this email address for out of hours emergencies. Don’t share this address with people outside of your team.", + "", + "", + "We’ll get back to you within 30 minutes and give you hourly updates until the problem’s fixed.", + "", + "", + "For non-emergency problems or questions, use our support page and we’ll reply in office hours.", + "", + "", + "Thanks", + "", + "U.S. Notify team"] + }, + { + "id": "203566f0-d835-47c5-aa06-932439c86573", + "name": "Notify organization invitation email", + "type": "email", + "subject": "((user_name)) has invited you to collaborate on ((organisation_name)) on U.S. Notify", + "content": ["((user_name)) has invited you to collaborate on ((organisation_name)) on U.S. Notify.","","","U.S. Notify makes it easy to keep people updated by helping you send text messages, emails and letters.","","","Open this link to create an account on U.S. Notify:","","((url))","","","This invitation will stop working at midnight tomorrow. This is to keep ((organisation_name)) secure."] + }, + { + "id": "c73f1d71-4049-46d5-a647-d013bdeca3f0", + "name": "Email address changed by service manager", + "type": "email", + "subject": "Your U.S. Notify email address has changed", + "content": ["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","","","U.S. Notify team"] + }, + { + "id": "8a31520f-4751-4789-8ea1-fe54496725eb", + "name": "Phone number changed by service manager", + "type": "sms", + "subject": "", + "content": ["Your mobile number was changed by ((servicemanagername)). Next time you sign in, your U.S. Notify authentication code will be sent to this phone."] + }, + { + "id": "a42f1d17-9404-46d5-a647-d013bdfca3e1", + "name": "Verify email reply-to address for a service", + "type": "email", + "subject": "Your U.S. Notify reply-to email address", + "content": ["Hi,","","","This address has been provided as a reply-to email address for a U.S. Notify account.","","Any replies from users to emails they receive through U.S. Notify will come back to this email address.","","","This is just a quick check to make sure the address is valid.","","","No need to reply.","","","Thanks","","","U.S. Notify team"] + }, + { + "id": "4fd2e43c-309b-4e50-8fb8-1955852d9d71", + "name": "MOU Signed By Receipt", + "type": "email", + "subject": "You’ve accepted the U.S. Notify data sharing and financial agreement", + "content": [ + "Hi ((signed_by_name)),", + "", + "((org_name)) has accepted the U.S. Notify data sharing and financial agreement. ", + "", + "If you need another copy of the agreement you can download it here: ((mou_link))", + "", + "", + "Thanks,", + "U.S. Notify team" + ] + }, + { + "id": "c20206d5-bf03-4002-9a90-37d5032d9e84", + "name": "MOU Signed On Behalf Of Receipt - Signed by", + "type": "email", + "subject": "You’ve accepted the U.S. Notify data sharing and financial agreement", + "content": [ + "Hi ((signed_by_name)),", + "", + "((org_name)) has accepted the U.S. Notify data sharing and financial agreement. We’ve emailed ((on_behalf_of_name)) to let them know too.", + "", + "If you need another copy of the agreement you can download it here: ((mou_link))", + "", + "", + "Thanks,", + "U.S. Notify team" + ] + }, + { + "id": "522b6657-5ca5-4368-a294-6b527703bd0b", + "name": "MOU Signed On Behalf Of Receipt - On Behalf Of", + "type": "email", + "subject": "((org_name)) has accepted the U.S. Notify data sharing and financial agreement", + "content": [ + "Hi ((on_behalf_of_name)),", + "", + "((signed_by_name)) has accepted the U.S. Notify data sharing and financial agreement on your behalf, for ((org_name)).", + "", + "U.S. Notify lets teams in the public sector send emails, text messages and letters. It’s built and run by a team in the TTS Public Benefits Studio (part of GSA).", + "", + "If you need another copy of the agreement you can download it here: ((mou_link))", + "", + "", + "Thanks,", + "U.S. Notify team" + ] + }, + { + "id": "d0e66c4c-0c50-43f0-94f5-f85b613202d4", + "name": "MOU Signed Notify Team Alert", + "type": "email", + "subject": "Someone signed an MOU for an org on Notify", + "content": [ + "What’s up Notifiers,", + "", + "((signed_by_name)) just accepted the data sharing and financial agreement for ((org_name)).", + "", + "See how ((org_name)) is using Notify here: ((org_dashboard_link))" + ] + }, + { + "id": "11fad854-fd38-4a7c-bd17-805fb13dfc12", + "name": "Notify daily letter volumes", + "type": "email", + "subject": "Notify letter volume for ((date)): ((total_volume)) letters, ((total_sheets)) sheets", + "content": [ + "((total_volume)) letters (((total_sheets)) sheets) sent via Notify are coming in today’s batch. These include: ", + "", + "((first_class_volume)) first class letters (((first_class_sheets)) sheets).", + "((second_class_volume)) second class letters (((second_class_sheets)) sheets).", + "((international_volume)) international letters (((international_sheets)) sheets).", + "", + "Thanks", + "", + "U.S. Notify team" + ] + } +] diff --git a/migrations/alembic.ini b/migrations/alembic.ini index 8c9d61375..199797e0a 100644 --- a/migrations/alembic.ini +++ b/migrations/alembic.ini @@ -20,12 +20,12 @@ keys = console keys = generic [logger_root] -level = WARN +level = INFO handlers = qualname = [logger_sqlalchemy] -level = WARN +level = INFO handlers = qualname = sqlalchemy.engine diff --git a/migrations/versions/0383_update_default_templates.py b/migrations/versions/0383_update_default_templates.py new file mode 100644 index 000000000..3313abfa4 --- /dev/null +++ b/migrations/versions/0383_update_default_templates.py @@ -0,0 +1,55 @@ +""" + +Revision ID: 0383_update_default_templates.py +Revises: 0382_remove_old_providers +Create Date: 2023-01-10 11:42:25.633265 + +""" +import json +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql +from flask import current_app + +revision = '0383_update_default_templates.py' +down_revision = '0382_remove_old_providers' + + +def upgrade(): + update = """ + UPDATE {} SET name = '{}', template_type = '{}', content = '{}', subject = '{}' + WHERE id = '{}' + """ + + with open(current_app.config['CONFIG_FILES'] + '/templates.json') as f: + data = json.load(f) + for d in data: + for table_name in 'templates', 'templates_history': + op.execute( + update.format( + table_name, + d['name'], + d['type'], + '\n'.join(d['content']), + d.get('subject'), + d['id'] + ) + ) + + # op.execute( + # """ + # INSERT INTO template_redacted + # ( + # template_id, + # redact_personalisation, + # updated_at, + # updated_by_id + # ) VALUES ( '{}', false, current_timestamp, '{}' ) + # """.format(d['id'], current_app.config['NOTIFY_USER_ID']) + # ) + + +def downgrade(): + # with associated code changes, edits to templates should no longer be made via migration. + # instead, update the fixture and run the flask command to update. + pass diff --git a/tests/app/test_commands.py b/tests/app/test_commands.py index 6f50f30f7..fc6c85695 100644 --- a/tests/app/test_commands.py +++ b/tests/app/test_commands.py @@ -1,12 +1,13 @@ import pytest from app.commands import ( + _update_template, create_test_user, insert_inbound_numbers_from_file, populate_annual_billing_with_defaults, ) from app.dao.inbound_numbers_dao import dao_get_available_inbound_numbers -from app.models import AnnualBilling, User +from app.models import AnnualBilling, Template, User from tests.app.db import create_annual_billing, create_service @@ -88,3 +89,20 @@ def test_populate_annual_billing_with_defaults_sets_free_allowance_to_zero_if_pr assert len(results) == 1 assert results[0].free_sms_fragment_limit == 0 + + +def test_update_template( + notify_db_session, email_2fa_code_template +): + + _update_template( + "299726d2-dba6-42b8-8209-30e1d66ea164", + "Example text message template!", + "sms", + ["Hi, I’m trying out U.S. Notify! Today is ((day of week)) and my favorite color is ((color))."], + "" + ) + + t = Template.query.all() + + assert t[0].name == "Example text message template!"