mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-03 05:11:03 -04:00
@@ -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")
|
||||
|
||||
@@ -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, 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 (
|
||||
@@ -25,6 +34,7 @@ from app.main.forms import (
|
||||
DateFilterForm,
|
||||
RequiredDateFilterForm,
|
||||
)
|
||||
from app.main.views.send import _send_notification
|
||||
from app.statistics_utils import (
|
||||
get_formatted_percentage,
|
||||
get_formatted_percentage_two_dp,
|
||||
@@ -771,3 +781,80 @@ 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():
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
service = _find_load_test_service()
|
||||
_prepare_load_test_service(service)
|
||||
example_template = _find_example_template(service)
|
||||
|
||||
# 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": current_app.config["SIMULATED_SMS_NUMBERS"][0],
|
||||
}
|
||||
_send_notification(service["id"], example_template["id"])
|
||||
# Simulated failure
|
||||
for _ in range(0, 250):
|
||||
session["recipient"] = current_app.config["SIMULATED_SMS_NUMBERS"][1]
|
||||
session["placeholders"] = {
|
||||
"day of week": "Wednesday",
|
||||
"color": "orange",
|
||||
"phone number": current_app.config["SIMULATED_SMS_NUMBERS"][1],
|
||||
}
|
||||
_send_notification(service["id"], example_template["id"])
|
||||
|
||||
# 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):
|
||||
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:
|
||||
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:
|
||||
current_app.logger.exception(
|
||||
"Couldnt add user, may already be part of service"
|
||||
)
|
||||
pass
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
from string import ascii_uppercase
|
||||
@@ -942,8 +943,8 @@ def preview_notification(service_id, template_id):
|
||||
)
|
||||
@user_has_permissions("send_messages", restrict_admin_usage=True)
|
||||
def send_notification(service_id, template_id):
|
||||
scheduled_for = session.pop("scheduled_for", "")
|
||||
recipient = get_recipient()
|
||||
|
||||
if not recipient:
|
||||
return redirect(
|
||||
url_for(
|
||||
@@ -952,53 +953,10 @@ def send_notification(service_id, template_id):
|
||||
template_id=template_id,
|
||||
)
|
||||
)
|
||||
upload_id = _send_notification(service_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",
|
||||
)
|
||||
|
||||
session.pop("recipient")
|
||||
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)
|
||||
@@ -1046,6 +1004,56 @@ 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():
|
||||
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"
|
||||
)
|
||||
)
|
||||
|
||||
# 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,
|
||||
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"])[
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from flask import abort, current_app, request, session
|
||||
@@ -219,6 +220,14 @@ class User(JSONModel, UserMixin):
|
||||
def has_permissions(
|
||||
self, *permissions, restrict_admin_usage=False, allow_org_user=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
|
||||
if unknown_permissions:
|
||||
raise TypeError(
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
{% if not service['active'] %}
|
||||
<span class="heading-medium hint"> Archived</span>
|
||||
{% endif %}
|
||||
{% if service['name'] == 'Test service' %}
|
||||
<a class="usa-link" href="{{ url_for('main.load_test') }}">Load Test</a>
|
||||
{% endif %}
|
||||
|
||||
{% endcall %}
|
||||
|
||||
{% endcall %}
|
||||
|
||||
Reference in New Issue
Block a user