From c36561ee4d86c745135af0fd1184e85595b72205 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Fri, 30 Aug 2024 09:50:01 -0700
Subject: [PATCH 01/17] start load test work
---
app/main/views/platform_admin.py | 43 ++++++++++++++++++-
app/main/views/send.py | 5 +++
.../views/platform-admin/services.html | 4 ++
poetry.lock | 5 +--
4 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index f0b5983b5..b0a3da7cc 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -5,7 +5,7 @@ from collections import OrderedDict
from datetime import datetime
from io import StringIO
-from flask import Response, abort, flash, render_template, request, url_for
+from flask import Response, abort, flash, render_template, request, session, url_for
from notifications_python_client.errors import HTTPError
from app import (
@@ -25,17 +25,19 @@ from app.main.forms import (
DateFilterForm,
RequiredDateFilterForm,
)
+from app.main.views.send import _send_notification, send_notification
from app.statistics_utils import (
get_formatted_percentage,
get_formatted_percentage_two_dp,
)
+from app.utils import hilite
from app.utils.csv import Spreadsheet
from app.utils.pagination import (
generate_next_dict,
generate_previous_dict,
get_page_from_request,
)
-from app.utils.user import user_is_platform_admin
+from app.utils.user import user_has_permissions, user_is_platform_admin
COMPLAINT_THRESHOLD = 0.02
FAILURE_THRESHOLD = 3
@@ -771,3 +773,40 @@ def _get_user_row(r):
row.append(r["password_changed_at"])
row.append(r["state"])
return row
+
+
+@main.route(
+ "/platform-admin/load-test",
+ methods=["POST", "GET"],
+)
+@user_is_platform_admin
+def load_test():
+ # SIMULATED_SMS_NUMBERS = ("+14254147755", "+14254147167")
+ print(hilite("ENTER LOAD TEST"))
+ session["recipient"] = "+14254147755"
+ session["placeholders"] = {"day of week": "Monday", "color": "blue"}
+ services = service_api_client.find_services_by_name("Test service")
+ services = services["data"]
+
+ for service in services:
+ # print(hilite(f"WHAT IS THE TYPE OF ONE SERVICE {type(service)} {service}"))
+ # print("\n")
+ # service = json.loads(service)
+ # print(hilite(f"SERVICE: {service}"))
+ # service = service['data']
+ if service["name"] is "Test service":
+ break
+ # print(hilite(f"SERVICE IS {service}"))
+ templates = service_api_client.get_service_templates(service["id"])
+ templates = templates["data"]
+ # templates = json.loads(templates)
+ # print(hilite(f"TEMPLATES are {templates}"))
+ example_template = None
+ for template in templates:
+ # template = json.loads(template)
+ print(hilite(f"TEMPLATE {template['name']}"))
+ if template["name"] == "Example text message template":
+ print(hilite(f"FOUND EXAMPLE TEMPLATE"))
+ example_template = template
+ print(f"GOING TO SEND NOTIFICATION NOW")
+ _send_notification(service["id"], example_template["id"])
diff --git a/app/main/views/send.py b/app/main/views/send.py
index e6843da18..dcaec8560 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -7,6 +7,7 @@ from flask import (
abort,
current_app,
flash,
+ json,
redirect,
render_template,
request,
@@ -942,6 +943,10 @@ def preview_notification(service_id, template_id):
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def send_notification(service_id, template_id):
+ return _send_notification(service_id, template_id)
+
+
+def _send_notification(service_id, template_id):
scheduled_for = session.pop("scheduled_for", "")
recipient = get_recipient()
if not recipient:
diff --git a/app/templates/views/platform-admin/services.html b/app/templates/views/platform-admin/services.html
index 65f10e281..13b6320dc 100644
--- a/app/templates/views/platform-admin/services.html
+++ b/app/templates/views/platform-admin/services.html
@@ -28,6 +28,10 @@
{% if not service['active'] %}
Archived
{% endif %}
+ {% if service['name'] == 'Test service' %}
+ Load Test
+ {% endif %}
+
{% endcall %}
{% endcall %}
diff --git a/poetry.lock b/poetry.lock
index 2684ecc21..96135cf31 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1285,13 +1285,9 @@ files = [
{file = "lxml-5.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196"},
{file = "lxml-5.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b"},
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8"},
- {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6"},
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716"},
- {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c"},
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905"},
- {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184"},
{file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6"},
- {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f"},
{file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61"},
{file = "lxml-5.2.2-cp37-cp37m-win32.whl", hash = "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f"},
{file = "lxml-5.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40"},
@@ -1626,6 +1622,7 @@ files = [
{file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"},
{file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"},
{file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"},
+ {file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"},
{file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"},
]
From dcc805537740f7886ee8e23ffb8e9ba0422ec753 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 07:51:57 -0700
Subject: [PATCH 02/17] more work on load test
---
app/main/views/platform_admin.py | 94 +++++++++----
app/main/views/send.py | 126 ++++++++++--------
app/models/user.py | 3 +
.../views/platform-admin/services.html | 2 +-
4 files changed, 142 insertions(+), 83 deletions(-)
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index b0a3da7cc..820287675 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -5,7 +5,16 @@ from collections import OrderedDict
from datetime import datetime
from io import StringIO
-from flask import Response, abort, flash, render_template, request, session, url_for
+from flask import (
+ Response,
+ abort,
+ current_app,
+ flash,
+ render_template,
+ request,
+ session,
+ url_for,
+)
from notifications_python_client.errors import HTTPError
from app import (
@@ -781,32 +790,69 @@ def _get_user_row(r):
)
@user_is_platform_admin
def load_test():
+ """
+ The load test assumes that a service called 'Test service' exists. It will make
+ the platform admin a member of this service if the platform is not already. All
+ messagese will be sent in this service.
+ """
# SIMULATED_SMS_NUMBERS = ("+14254147755", "+14254147167")
print(hilite("ENTER LOAD TEST"))
- session["recipient"] = "+14254147755"
- session["placeholders"] = {"day of week": "Monday", "color": "blue"}
+ service = _find_load_test_service()
+ _prepare_load_test_service(service)
+ example_template = _find_example_template(service)
+
+ for _ in range(0, 3):
+ session["recipient"] = "+14254147755"
+ session["placeholders"] = {
+ "day of week": "Monday",
+ "color": "blue",
+ "phone number": "+14254147755",
+ }
+ _send_notification(service["id"], example_template["id"])
+ for _ in range(0, 3):
+ session["recipient"] = "+14254147167"
+ session["placeholders"] = {
+ "day of week": "Monday",
+ "color": "blue",
+ "phone number": "+14254147167",
+ }
+ _send_notification(service["id"], example_template["id"])
+
+ return render_template("views/dashboard/dashboard.html")
+
+
+def _find_example_template(service):
+ templates = service_api_client.get_service_templates(service["id"])
+ templates = templates["data"]
+ for template in templates:
+ # template = json.loads(template)
+ if template["name"] == "Example text message template":
+ return template
+
+ raise Exception("Could not find example template for load test")
+
+
+def _find_load_test_service():
services = service_api_client.find_services_by_name("Test service")
services = services["data"]
for service in services:
- # print(hilite(f"WHAT IS THE TYPE OF ONE SERVICE {type(service)} {service}"))
- # print("\n")
- # service = json.loads(service)
- # print(hilite(f"SERVICE: {service}"))
- # service = service['data']
- if service["name"] is "Test service":
- break
- # print(hilite(f"SERVICE IS {service}"))
- templates = service_api_client.get_service_templates(service["id"])
- templates = templates["data"]
- # templates = json.loads(templates)
- # print(hilite(f"TEMPLATES are {templates}"))
- example_template = None
- for template in templates:
- # template = json.loads(template)
- print(hilite(f"TEMPLATE {template['name']}"))
- if template["name"] == "Example text message template":
- print(hilite(f"FOUND EXAMPLE TEMPLATE"))
- example_template = template
- print(f"GOING TO SEND NOTIFICATION NOW")
- _send_notification(service["id"], example_template["id"])
+ if service["name"] == "Test service":
+ return service
+
+ raise Exception("Could not find 'Test service' for load test")
+
+
+def _prepare_load_test_service(service):
+ users = user_api_client.get_all_users()
+ for user in users:
+ if user["platform_admin"] == "t":
+ try:
+ user_api_client.add_user_to_service(
+ service["id"], user["id"], ["send messages"]
+ )
+ except Exception as e:
+ current_app.logger.warning(
+ f"Couldnt add user, may already be part of service"
+ )
+ pass
diff --git a/app/main/views/send.py b/app/main/views/send.py
index dcaec8560..dc33cdbd9 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -621,6 +621,7 @@ def _check_messages(service_id, template_id, upload_id, preview_row, **kwargs):
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def check_messages(service_id, template_id, upload_id, row_index=2):
+ print(hilite("ENTER check_messages"))
data = _check_messages(service_id, template_id, upload_id, row_index)
data["allowed_file_extensions"] = Spreadsheet.ALLOWED_FILE_EXTENSIONS
@@ -943,64 +944,7 @@ def preview_notification(service_id, template_id):
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def send_notification(service_id, template_id):
- return _send_notification(service_id, template_id)
-
-
-def _send_notification(service_id, template_id):
- scheduled_for = session.pop("scheduled_for", "")
- recipient = get_recipient()
- if not recipient:
- return redirect(
- url_for(
- ".send_one_off",
- service_id=service_id,
- template_id=template_id,
- )
- )
-
- keys = []
- values = []
- for k, v in session["placeholders"].items():
- keys.append(k)
- values.append(v)
-
- data = ",".join(keys)
- vals = ",".join(values)
- data = f"{data}\r\n{vals}"
-
- filename = (
- f"one-off-{uuid.uuid4()}.csv" # {current_user.name} removed from filename
- )
- my_data = {"filename": filename, "template_id": template_id, "data": data}
- upload_id = s3upload(service_id, my_data)
-
- # To debug messages that the user reports have not been sent, we log
- # the csv filename and the job id. The user will give us the file name,
- # so we can search on that to obtain the job id, which we can use elsewhere
- # on the API side to find out what happens to the message.
- current_app.logger.info(
- hilite(
- f"One-off file: {filename} job_id: {upload_id} s3 location: service-{service_id}-notify/{upload_id}.csv"
- )
- )
-
- form = CsvUploadForm()
- form.file.data = my_data
- form.file.name = filename
-
- check_message_output = check_messages(service_id, template_id, upload_id, 2)
- if "You cannot send to" in check_message_output:
- return check_messages(service_id, template_id, upload_id, 2)
-
- job_api_client.create_job(
- upload_id,
- service_id,
- scheduled_for=scheduled_for,
- template_id=template_id,
- original_file_name=filename,
- notification_count=1,
- valid="True",
- )
+ upload_id = _send_notification(service_id, template_id)
session.pop("recipient")
session.pop("placeholders")
@@ -1051,6 +995,72 @@ def _send_notification(service_id, template_id):
)
+def _send_notification(service_id, template_id):
+ print(hilite(f"ENTER SEND NOTIFICATION"))
+ scheduled_for = session.pop("scheduled_for", "")
+ recipient = get_recipient()
+ print(hilite(f"RECIPIENT {recipient}"))
+
+ if not recipient:
+ return redirect(
+ url_for(
+ ".send_one_off",
+ service_id=service_id,
+ template_id=template_id,
+ )
+ )
+
+ keys = []
+ values = []
+ for k, v in session["placeholders"].items():
+ keys.append(k)
+ values.append(v)
+
+ data = ",".join(keys)
+ vals = ",".join(values)
+ data = f"{data}\r\n{vals}"
+ print(hilite(f"DATA {data}"))
+
+ filename = (
+ f"one-off-{uuid.uuid4()}.csv" # {current_user.name} removed from filename
+ )
+ my_data = {"filename": filename, "template_id": template_id, "data": data}
+ upload_id = s3upload(service_id, my_data)
+ print(hilite(f"UPLOAD ID {upload_id}"))
+ # To debug messages that the user reports have not been sent, we log
+ # the csv filename and the job id. The user will give us the file name,
+ # so we can search on that to obtain the job id, which we can use elsewhere
+ # on the API side to find out what happens to the message.
+ current_app.logger.info(
+ hilite(
+ f"One-off file: {filename} job_id: {upload_id} s3 location: service-{service_id}-notify/{upload_id}.csv"
+ )
+ )
+
+ form = CsvUploadForm()
+ form.file.data = my_data
+ form.file.name = filename
+ print(f"POPULATED FORM")
+ print(f"USER PERMISSIONS {current_user.permissions[service_id]}")
+ # TODO IF RUNNING LOAD TEST WE DONT NEED
+ # check_message_output = check_messages(service_id, template_id, upload_id, 2)
+ # print(hilite(hilite(f"CHECK MESSAGE OUTPUT {check_message_output}")))
+ # if "You cannot send to" in check_message_output:
+ # return check_messages(service_id, template_id, upload_id, 2)
+
+ print(f"GOING TO CREATE JOB")
+ job_api_client.create_job(
+ upload_id,
+ service_id,
+ scheduled_for=scheduled_for,
+ template_id=template_id,
+ original_file_name=filename,
+ notification_count=1,
+ valid="True",
+ )
+ return upload_id
+
+
def get_email_reply_to_address_from_session():
if session.get("sender_id"):
return current_service.get_email_reply_to_address(session["sender_id"])[
diff --git a/app/models/user.py b/app/models/user.py
index 6991dc035..4728259b6 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -219,6 +219,9 @@ class User(JSONModel, UserMixin):
def has_permissions(
self, *permissions, restrict_admin_usage=False, allow_org_user=False
):
+ if self.platform_admin:
+ return True
+
unknown_permissions = set(permissions) - all_ui_permissions
if unknown_permissions:
raise TypeError(
diff --git a/app/templates/views/platform-admin/services.html b/app/templates/views/platform-admin/services.html
index 13b6320dc..280ce796f 100644
--- a/app/templates/views/platform-admin/services.html
+++ b/app/templates/views/platform-admin/services.html
@@ -30,7 +30,7 @@
{% endif %}
{% if service['name'] == 'Test service' %}
Load Test
- {% endif %}
+ {% endif %}
{% endcall %}
From e8b12de581178bad60c749c4719bb531b23540e3 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 08:13:05 -0700
Subject: [PATCH 03/17] clean up
---
app/main/views/platform_admin.py | 8 ++++----
app/main/views/send.py | 16 ++++------------
2 files changed, 8 insertions(+), 16 deletions(-)
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index 820287675..17ca7d621 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -34,7 +34,7 @@ from app.main.forms import (
DateFilterForm,
RequiredDateFilterForm,
)
-from app.main.views.send import _send_notification, send_notification
+from app.main.views.send import _send_notification
from app.statistics_utils import (
get_formatted_percentage,
get_formatted_percentage_two_dp,
@@ -46,7 +46,7 @@ from app.utils.pagination import (
generate_previous_dict,
get_page_from_request,
)
-from app.utils.user import user_has_permissions, user_is_platform_admin
+from app.utils.user import user_is_platform_admin
COMPLAINT_THRESHOLD = 0.02
FAILURE_THRESHOLD = 3
@@ -851,8 +851,8 @@ def _prepare_load_test_service(service):
user_api_client.add_user_to_service(
service["id"], user["id"], ["send messages"]
)
- except Exception as e:
- current_app.logger.warning(
+ except Exception:
+ current_app.logger.exception(
f"Couldnt add user, may already be part of service"
)
pass
diff --git a/app/main/views/send.py b/app/main/views/send.py
index dc33cdbd9..eda5ae8fc 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -996,10 +996,8 @@ def send_notification(service_id, template_id):
def _send_notification(service_id, template_id):
- print(hilite(f"ENTER SEND NOTIFICATION"))
scheduled_for = session.pop("scheduled_for", "")
recipient = get_recipient()
- print(hilite(f"RECIPIENT {recipient}"))
if not recipient:
return redirect(
@@ -1019,14 +1017,11 @@ def _send_notification(service_id, template_id):
data = ",".join(keys)
vals = ",".join(values)
data = f"{data}\r\n{vals}"
- print(hilite(f"DATA {data}"))
-
filename = (
f"one-off-{uuid.uuid4()}.csv" # {current_user.name} removed from filename
)
my_data = {"filename": filename, "template_id": template_id, "data": data}
upload_id = s3upload(service_id, my_data)
- print(hilite(f"UPLOAD ID {upload_id}"))
# To debug messages that the user reports have not been sent, we log
# the csv filename and the job id. The user will give us the file name,
# so we can search on that to obtain the job id, which we can use elsewhere
@@ -1040,15 +1035,12 @@ def _send_notification(service_id, template_id):
form = CsvUploadForm()
form.file.data = my_data
form.file.name = filename
- print(f"POPULATED FORM")
- print(f"USER PERMISSIONS {current_user.permissions[service_id]}")
# TODO IF RUNNING LOAD TEST WE DONT NEED
- # check_message_output = check_messages(service_id, template_id, upload_id, 2)
- # print(hilite(hilite(f"CHECK MESSAGE OUTPUT {check_message_output}")))
- # if "You cannot send to" in check_message_output:
- # return check_messages(service_id, template_id, upload_id, 2)
+ check_message_output = check_messages(service_id, template_id, upload_id, 2)
+ print(hilite(hilite(f"CHECK MESSAGE OUTPUT {check_message_output}")))
+ if "You cannot send to" in check_message_output:
+ return check_messages(service_id, template_id, upload_id, 2)
- print(f"GOING TO CREATE JOB")
job_api_client.create_job(
upload_id,
service_id,
From f74bf271a5f128ab86229dae4ad3394de556aa65 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 08:22:03 -0700
Subject: [PATCH 04/17] clean up
---
app/main/views/platform_admin.py | 3 +--
app/main/views/send.py | 3 ---
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index 17ca7d621..182a25cfe 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -796,7 +796,6 @@ def load_test():
messagese will be sent in this service.
"""
# SIMULATED_SMS_NUMBERS = ("+14254147755", "+14254147167")
- print(hilite("ENTER LOAD TEST"))
service = _find_load_test_service()
_prepare_load_test_service(service)
example_template = _find_example_template(service)
@@ -853,6 +852,6 @@ def _prepare_load_test_service(service):
)
except Exception:
current_app.logger.exception(
- f"Couldnt add user, may already be part of service"
+ "Couldnt add user, may already be part of service"
)
pass
diff --git a/app/main/views/send.py b/app/main/views/send.py
index eda5ae8fc..14272d697 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -7,7 +7,6 @@ from flask import (
abort,
current_app,
flash,
- json,
redirect,
render_template,
request,
@@ -621,7 +620,6 @@ def _check_messages(service_id, template_id, upload_id, preview_row, **kwargs):
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def check_messages(service_id, template_id, upload_id, row_index=2):
- print(hilite("ENTER check_messages"))
data = _check_messages(service_id, template_id, upload_id, row_index)
data["allowed_file_extensions"] = Spreadsheet.ALLOWED_FILE_EXTENSIONS
@@ -1037,7 +1035,6 @@ def _send_notification(service_id, template_id):
form.file.name = filename
# TODO IF RUNNING LOAD TEST WE DONT NEED
check_message_output = check_messages(service_id, template_id, upload_id, 2)
- print(hilite(hilite(f"CHECK MESSAGE OUTPUT {check_message_output}")))
if "You cannot send to" in check_message_output:
return check_messages(service_id, template_id, upload_id, 2)
From ce74175be1842240463459e7875bc50b30a8f8f3 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 08:34:15 -0700
Subject: [PATCH 05/17] clean up
---
app/main/views/platform_admin.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index 182a25cfe..3a590de1c 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -39,7 +39,6 @@ from app.statistics_utils import (
get_formatted_percentage,
get_formatted_percentage_two_dp,
)
-from app.utils import hilite
from app.utils.csv import Spreadsheet
from app.utils.pagination import (
generate_next_dict,
From 8b81c5ce7ddb951238e0fe41ea41b7018b26ac04 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 08:43:23 -0700
Subject: [PATCH 06/17] add load_test to excluded
---
tests/app/test_navigation.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/app/test_navigation.py b/tests/app/test_navigation.py
index a9ce4ea87..58ff9f342 100644
--- a/tests/app/test_navigation.py
+++ b/tests/app/test_navigation.py
@@ -121,6 +121,7 @@ EXCLUDED_ENDPOINTS = tuple(
"link_service_to_organization",
"live_services",
"live_services_csv",
+ "load_test",
"manage_org_users",
"manage_template_folder",
"manage_users",
From f6a1f1af5b776f02efca65b986e6b19e34404d54 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 09:01:42 -0700
Subject: [PATCH 07/17] add load_test to excluded
---
app/main/views/send.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/app/main/views/send.py b/app/main/views/send.py
index 14272d697..3288eddc7 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -944,8 +944,10 @@ def preview_notification(service_id, template_id):
def send_notification(service_id, template_id):
upload_id = _send_notification(service_id, template_id)
- session.pop("recipient")
- session.pop("placeholders")
+ if session.get("recipient"):
+ session.pop("recipient")
+ if session.get("placeholders"):
+ session.pop("placeholders")
# We have to wait for the job to run and create the notification in the database
time.sleep(0.1)
From 66211440616e36f0fa31280efbc2f49676dd885a Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 09:17:51 -0700
Subject: [PATCH 08/17] add load_test to excluded
---
app/main/views/send.py | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/app/main/views/send.py b/app/main/views/send.py
index 3288eddc7..4aae2a576 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -944,10 +944,8 @@ def preview_notification(service_id, template_id):
def send_notification(service_id, template_id):
upload_id = _send_notification(service_id, template_id)
- if session.get("recipient"):
- session.pop("recipient")
- if session.get("placeholders"):
- session.pop("placeholders")
+ session.pop("recipient", "")
+ session.pop("placeholders", "")
# We have to wait for the job to run and create the notification in the database
time.sleep(0.1)
@@ -997,7 +995,9 @@ def send_notification(service_id, template_id):
def _send_notification(service_id, template_id):
scheduled_for = session.pop("scheduled_for", "")
+ print("GOING TO GET RECIPIENT") # noqa
recipient = get_recipient()
+ print(f"RECIPIENT IS {recipient}, redirecting if None") # noqa
if not recipient:
return redirect(
@@ -1035,7 +1035,6 @@ def _send_notification(service_id, template_id):
form = CsvUploadForm()
form.file.data = my_data
form.file.name = filename
- # TODO IF RUNNING LOAD TEST WE DONT NEED
check_message_output = check_messages(service_id, template_id, upload_id, 2)
if "You cannot send to" in check_message_output:
return check_messages(service_id, template_id, upload_id, 2)
From 9340069454ac3b13e63de2a25f6436893524d28f Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 09:33:23 -0700
Subject: [PATCH 09/17] try mock
---
tests/app/main/views/test_send.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py
index 24403e895..ec35a0689 100644
--- a/tests/app/main/views/test_send.py
+++ b/tests/app/main/views/test_send.py
@@ -2818,10 +2818,12 @@ def test_send_notification_redirects_if_missing_data(
client_request,
fake_uuid,
session_data,
+ mocker
):
with client_request.session_transaction() as session:
session.update(session_data)
+ mocker.patch("app.main.views.send._send_notification", return_value="aaa")
client_request.post(
"main.send_notification",
service_id=SERVICE_ONE_ID,
From da7d618460c815bf6bcf671d61b28e810cdc4be2 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 09:42:52 -0700
Subject: [PATCH 10/17] try mock
---
tests/app/main/views/test_send.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py
index ec35a0689..e82c641b6 100644
--- a/tests/app/main/views/test_send.py
+++ b/tests/app/main/views/test_send.py
@@ -2823,7 +2823,8 @@ def test_send_notification_redirects_if_missing_data(
with client_request.session_transaction() as session:
session.update(session_data)
- mocker.patch("app.main.views.send._send_notification", return_value="aaa")
+
+ mocker.patch("app.main.views.send.s3upload", return_value=sample_uuid())
client_request.post(
"main.send_notification",
service_id=SERVICE_ONE_ID,
From c075cacae9568e62a951e864c07c87f52b3c7a2f Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 09:46:27 -0700
Subject: [PATCH 11/17] try mock
---
app/main/views/send.py | 4 ++--
tests/app/main/views/test_send.py | 6 +-----
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/app/main/views/send.py b/app/main/views/send.py
index 4aae2a576..afdda5abe 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -995,9 +995,9 @@ def send_notification(service_id, template_id):
def _send_notification(service_id, template_id):
scheduled_for = session.pop("scheduled_for", "")
- print("GOING TO GET RECIPIENT") # noqa
+ print("GOING TO GET RECIPIENT") # noqa
recipient = get_recipient()
- print(f"RECIPIENT IS {recipient}, redirecting if None") # noqa
+ print(f"RECIPIENT IS {recipient}, redirecting if None") # noqa
if not recipient:
return redirect(
diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py
index e82c641b6..9da3c1333 100644
--- a/tests/app/main/views/test_send.py
+++ b/tests/app/main/views/test_send.py
@@ -2815,15 +2815,11 @@ def test_send_notification_clears_session(
],
)
def test_send_notification_redirects_if_missing_data(
- client_request,
- fake_uuid,
- session_data,
- mocker
+ client_request, fake_uuid, session_data, mocker
):
with client_request.session_transaction() as session:
session.update(session_data)
-
mocker.patch("app.main.views.send.s3upload", return_value=sample_uuid())
client_request.post(
"main.send_notification",
From 5ada9914b4c684fa76c90607e09086270db49854 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 09:57:22 -0700
Subject: [PATCH 12/17] try mock
---
app/main/views/send.py | 23 ++++++++++++-----------
tests/app/main/views/test_send.py | 1 -
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/app/main/views/send.py b/app/main/views/send.py
index afdda5abe..6e9f83970 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -942,6 +942,18 @@ def preview_notification(service_id, template_id):
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def send_notification(service_id, template_id):
+ print("GOING TO GET RECIPIENT") # noqa
+ recipient = get_recipient()
+ print(f"RECIPIENT IS {recipient}, redirecting if None") # noqa
+
+ if not recipient:
+ return redirect(
+ url_for(
+ ".send_one_off",
+ service_id=service_id,
+ template_id=template_id,
+ )
+ )
upload_id = _send_notification(service_id, template_id)
session.pop("recipient", "")
@@ -995,18 +1007,7 @@ def send_notification(service_id, template_id):
def _send_notification(service_id, template_id):
scheduled_for = session.pop("scheduled_for", "")
- print("GOING TO GET RECIPIENT") # noqa
- recipient = get_recipient()
- print(f"RECIPIENT IS {recipient}, redirecting if None") # noqa
- if not recipient:
- return redirect(
- url_for(
- ".send_one_off",
- service_id=service_id,
- template_id=template_id,
- )
- )
keys = []
values = []
diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py
index 9da3c1333..1d8e696f8 100644
--- a/tests/app/main/views/test_send.py
+++ b/tests/app/main/views/test_send.py
@@ -2820,7 +2820,6 @@ def test_send_notification_redirects_if_missing_data(
with client_request.session_transaction() as session:
session.update(session_data)
- mocker.patch("app.main.views.send.s3upload", return_value=sample_uuid())
client_request.post(
"main.send_notification",
service_id=SERVICE_ONE_ID,
From b5e2bf705de783213acb52bbed6f2078161bde29 Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 10:02:28 -0700
Subject: [PATCH 13/17] try mock
---
app/main/views/send.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/main/views/send.py b/app/main/views/send.py
index 6e9f83970..e6d308f6c 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -1008,7 +1008,6 @@ def send_notification(service_id, template_id):
def _send_notification(service_id, template_id):
scheduled_for = session.pop("scheduled_for", "")
-
keys = []
values = []
for k, v in session["placeholders"].items():
From 9e9ba9186aa80b809319c8574fddac0ca37ffdeb Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Mon, 2 Sep 2024 10:30:29 -0700
Subject: [PATCH 14/17] try mock
---
app/models/user.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/user.py b/app/models/user.py
index 4728259b6..b4b854bc5 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -219,7 +219,7 @@ class User(JSONModel, UserMixin):
def has_permissions(
self, *permissions, restrict_admin_usage=False, allow_org_user=False
):
- if self.platform_admin:
+ if self.platform_admin and restrict_admin_usage is False:
return True
unknown_permissions = set(permissions) - all_ui_permissions
From ddf9c6d3ec451e52e7f97017ee08d1db07b357cd Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Tue, 3 Sep 2024 10:37:05 -0700
Subject: [PATCH 15/17] fix tests maybe
---
.ds.baseline | 4 ++--
app/config.py | 1 +
app/main/views/platform_admin.py | 24 ++++++++++++++----------
app/main/views/send.py | 17 +++++++++++------
app/models/user.py | 8 +++++++-
5 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/.ds.baseline b/.ds.baseline
index 41cd12948..9e44afaf0 100644
--- a/.ds.baseline
+++ b/.ds.baseline
@@ -169,7 +169,7 @@
"filename": "app/config.py",
"hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc",
"is_verified": false,
- "line_number": 117,
+ "line_number": 118,
"is_secret": false
}
],
@@ -692,5 +692,5 @@
}
]
},
- "generated_at": "2024-08-20T14:14:36Z"
+ "generated_at": "2024-09-03T17:36:57Z"
}
diff --git a/app/config.py b/app/config.py
index 960d6331b..dece2728d 100644
--- a/app/config.py
+++ b/app/config.py
@@ -8,6 +8,7 @@ from notifications_utils import DAILY_MESSAGE_LIMIT
class Config(object):
+ SIMULATED_SMS_NUMBERS = ("+14254147755", "+14254147167")
NOTIFY_APP_NAME = "admin"
NOTIFY_ENVIRONMENT = getenv("NOTIFY_ENVIRONMENT", "development")
API_HOST_NAME = getenv("API_HOST_NAME", "localhost")
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index 3a590de1c..c232c9678 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -10,6 +10,7 @@ from flask import (
abort,
current_app,
flash,
+ redirect,
render_template,
request,
session,
@@ -34,6 +35,7 @@ from app.main.forms import (
DateFilterForm,
RequiredDateFilterForm,
)
+from app.main.views.dashboard import get_dashboard_partials
from app.main.views.send import _send_notification
from app.statistics_utils import (
get_formatted_percentage,
@@ -794,29 +796,31 @@ def load_test():
the platform admin a member of this service if the platform is not already. All
messagese will be sent in this service.
"""
- # SIMULATED_SMS_NUMBERS = ("+14254147755", "+14254147167")
service = _find_load_test_service()
_prepare_load_test_service(service)
example_template = _find_example_template(service)
- for _ in range(0, 3):
- session["recipient"] = "+14254147755"
+ # Simulated success
+ for _ in range(0, 250):
+ session["recipient"] = current_app.config["SIMULATED_SMS_NUMBERS"][0]
session["placeholders"] = {
"day of week": "Monday",
"color": "blue",
- "phone number": "+14254147755",
+ "phone number": current_app.config["SIMULATED_SMS_NUMBERS"][0],
}
_send_notification(service["id"], example_template["id"])
- for _ in range(0, 3):
- session["recipient"] = "+14254147167"
+ # Simulated failure
+ for _ in range(0, 250):
+ session["recipient"] = current_app.config["SIMULATED_SMS_NUMBERS"][1]
session["placeholders"] = {
- "day of week": "Monday",
- "color": "blue",
- "phone number": "+14254147167",
+ "day of week": "Wednesday",
+ "color": "orange",
+ "phone number": current_app.config["SIMULATED_SMS_NUMBERS"][1],
}
_send_notification(service["id"], example_template["id"])
- return render_template("views/dashboard/dashboard.html")
+ # For now, just hang out on the platform admin page
+ return redirect(request.referrer)
def _find_example_template(service):
diff --git a/app/main/views/send.py b/app/main/views/send.py
index e6d308f6c..c7acb5171 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -1,3 +1,4 @@
+import os
import time
import uuid
from string import ascii_uppercase
@@ -1032,12 +1033,16 @@ def _send_notification(service_id, template_id):
)
)
- form = CsvUploadForm()
- form.file.data = my_data
- form.file.name = filename
- check_message_output = check_messages(service_id, template_id, upload_id, 2)
- if "You cannot send to" in check_message_output:
- return check_messages(service_id, template_id, upload_id, 2)
+ # For load testing we want to skip these checks. They are doing some fine-grained
+ # comparison about what is in the preview, but the load test just blast messages
+ # and doesn't care about the preview.
+ if os.getenv("NOTIFY_ENVIRONMENT") not in ("development", "staging", "demo"):
+ form = CsvUploadForm()
+ form.file.data = my_data
+ form.file.name = filename
+ check_message_output = check_messages(service_id, template_id, upload_id, 2)
+ if "You cannot send to" in check_message_output:
+ return check_messages(service_id, template_id, upload_id, 2)
job_api_client.create_job(
upload_id,
diff --git a/app/models/user.py b/app/models/user.py
index b4b854bc5..ba478feda 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -1,3 +1,4 @@
+import os
from datetime import datetime
from flask import abort, current_app, request, session
@@ -219,7 +220,12 @@ class User(JSONModel, UserMixin):
def has_permissions(
self, *permissions, restrict_admin_usage=False, allow_org_user=False
):
- if self.platform_admin and restrict_admin_usage is False:
+ # TODO need this for load test, but breaks unit tests
+ if self.platform_admin and os.getenv("NOTIFY_ENVIRONMENT") in (
+ "development",
+ "staging",
+ "demo",
+ ):
return True
unknown_permissions = set(permissions) - all_ui_permissions
From 35dcfccd5f3573287fa97e65056c1b69bc29526f Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Tue, 3 Sep 2024 11:03:33 -0700
Subject: [PATCH 16/17] fix tests maybe
---
app/main/views/platform_admin.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index c232c9678..29eacd5ac 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -35,7 +35,6 @@ from app.main.forms import (
DateFilterForm,
RequiredDateFilterForm,
)
-from app.main.views.dashboard import get_dashboard_partials
from app.main.views.send import _send_notification
from app.statistics_utils import (
get_formatted_percentage,
From 13088941913dfbfb3ef41bba08fe748724f0019f Mon Sep 17 00:00:00 2001
From: Kenneth Kehl <@kkehl@flexion.us>
Date: Tue, 3 Sep 2024 14:01:17 -0700
Subject: [PATCH 17/17] cleanup
---
app/main/views/platform_admin.py | 7 ++++---
app/main/views/send.py | 2 --
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index 29eacd5ac..6a121ecc2 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -10,7 +10,6 @@ from flask import (
abort,
current_app,
flash,
- redirect,
render_template,
request,
session,
@@ -818,8 +817,10 @@ def load_test():
}
_send_notification(service["id"], example_template["id"])
- # For now, just hang out on the platform admin page
- return redirect(request.referrer)
+ # For now, just redirect to the splash page so we know it's done
+ return render_template(
+ "views/platform-admin/splash-page.html",
+ )
def _find_example_template(service):
diff --git a/app/main/views/send.py b/app/main/views/send.py
index c7acb5171..7899af5a8 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -943,9 +943,7 @@ def preview_notification(service_id, template_id):
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def send_notification(service_id, template_id):
- print("GOING TO GET RECIPIENT") # noqa
recipient = get_recipient()
- print(f"RECIPIENT IS {recipient}, redirecting if None") # noqa
if not recipient:
return redirect(