mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-09 13:19:49 -04:00
rework how we display error message for disallowed phone numbers
This commit is contained in:
@@ -4,16 +4,7 @@ import uuid
|
|||||||
from string import ascii_uppercase
|
from string import ascii_uppercase
|
||||||
from zipfile import BadZipFile
|
from zipfile import BadZipFile
|
||||||
|
|
||||||
from flask import (
|
from flask import abort, flash, redirect, render_template, request, session, url_for
|
||||||
abort,
|
|
||||||
current_app,
|
|
||||||
flash,
|
|
||||||
redirect,
|
|
||||||
render_template,
|
|
||||||
request,
|
|
||||||
session,
|
|
||||||
url_for,
|
|
||||||
)
|
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from notifications_python_client.errors import HTTPError
|
from notifications_python_client.errors import HTTPError
|
||||||
from notifications_utils import SMS_CHAR_COUNT_LIMIT
|
from notifications_utils import SMS_CHAR_COUNT_LIMIT
|
||||||
@@ -497,7 +488,6 @@ def _check_messages(service_id, template_id, upload_id, preview_row):
|
|||||||
remaining_messages = current_service.message_limit - notification_count
|
remaining_messages = current_service.message_limit - notification_count
|
||||||
|
|
||||||
contents = s3download(service_id, upload_id)
|
contents = s3download(service_id, upload_id)
|
||||||
|
|
||||||
db_template = current_service.get_template_with_user_permission_or_403(
|
db_template = current_service.get_template_with_user_permission_or_403(
|
||||||
template_id, current_user
|
template_id, current_user
|
||||||
)
|
)
|
||||||
@@ -857,25 +847,25 @@ def send_notification(service_id, template_id):
|
|||||||
vals = ",".join(values)
|
vals = ",".join(values)
|
||||||
data = f"{data}\r\n{vals}"
|
data = f"{data}\r\n{vals}"
|
||||||
|
|
||||||
filename = f"{uuid.uuid4()}.csv"
|
filename = f"one-off:{current_user.name}:{uuid.uuid4()}.csv"
|
||||||
my_data = {"file_name": filename, "template_id": template_id, "data": data}
|
my_data = {"filename": filename, "template_id": template_id, "data": data}
|
||||||
upload_id = s3upload(service_id, my_data)
|
upload_id = s3upload(service_id, my_data)
|
||||||
form = CsvUploadForm()
|
form = CsvUploadForm()
|
||||||
form.file.data = my_data
|
form.file.data = my_data
|
||||||
form.file.name = filename
|
form.file.name = filename
|
||||||
job = None
|
|
||||||
try:
|
check_message_output = check_messages(service_id, template_id, upload_id, 2)
|
||||||
job = job_api_client.create_job(
|
if "You cannot send to" in check_message_output:
|
||||||
upload_id,
|
return check_messages(service_id, template_id, upload_id, 2)
|
||||||
service_id,
|
job_api_client.create_job(
|
||||||
scheduled_for="",
|
upload_id,
|
||||||
template_id=template_id,
|
service_id,
|
||||||
original_file_name=filename,
|
scheduled_for="",
|
||||||
notification_count=1,
|
template_id=template_id,
|
||||||
valid="True",
|
original_file_name=filename,
|
||||||
)
|
notification_count=1,
|
||||||
except Exception as e:
|
valid="True",
|
||||||
current_app.logger.error(e)
|
)
|
||||||
|
|
||||||
session.pop("recipient")
|
session.pop("recipient")
|
||||||
session.pop("placeholders")
|
session.pop("placeholders")
|
||||||
@@ -892,42 +882,31 @@ def send_notification(service_id, template_id):
|
|||||||
)
|
)
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
attempts = attempts + 1
|
attempts = attempts + 1
|
||||||
|
# TODO we are replacing the original 'one-off send' functionality with a job that
|
||||||
# TODO need some UI magic so the error message is displayed properly
|
# we create on the fly. The purpose for this is to ultimately remove the phone numbers
|
||||||
# and we don't just barf an exception
|
# from the db. However, by running a job we no longer get error messages we used to get.
|
||||||
|
# If the user is in trial mode and trying to send to a phone number they are not allowed
|
||||||
|
# to send to, right now they will see that their job started and the only way they will
|
||||||
|
# know something went wrong, is to sit and watch the status sit as pending for 3 hours
|
||||||
|
# and ultimately switch to failed with no reason why.
|
||||||
|
#
|
||||||
|
# In future, we should block the user from sending to phone numbers they aren't allowed
|
||||||
|
# to send to.
|
||||||
|
# the way to do that would be to make this available to the front end:
|
||||||
|
#
|
||||||
|
# <api>/service/utils/service_allowed_to_send_to
|
||||||
|
#
|
||||||
|
# After that the UI should be making this call as part of the phone number validation
|
||||||
|
# A user in trial mode should not be able to 'send message' to a phone number they are not
|
||||||
|
# allowed to send to
|
||||||
if notis["total"] == 0 and attempts == 5:
|
if notis["total"] == 0 and attempts == 5:
|
||||||
# raise Exception(
|
# This shows the job we auto-generated for the user
|
||||||
# "Could not send notification. Please check that you can send to that phone number"
|
return redirect(
|
||||||
# )
|
url_for(
|
||||||
|
"main.view_job",
|
||||||
db_template = current_service.get_template_with_user_permission_or_403(
|
service_id=service_id,
|
||||||
template_id, current_user
|
job_id=upload_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
return render_template(
|
|
||||||
"views/notifications/notification.html",
|
|
||||||
finished=True,
|
|
||||||
notification_status="failed",
|
|
||||||
error_message="This is bogus",
|
|
||||||
uploaded_file_name="Report",
|
|
||||||
template=db_template,
|
|
||||||
job=job,
|
|
||||||
# updates_url=url_for(
|
|
||||||
# ".view_notification_updates",
|
|
||||||
# service_id=service_id,
|
|
||||||
# notification_id=notification["id"],
|
|
||||||
# status=request.args.get("status"),
|
|
||||||
# help=get_help_argument(),
|
|
||||||
# ),
|
|
||||||
# partials=get_single_notification_partials(notification),
|
|
||||||
# created_by=notification.get("created_by"),
|
|
||||||
created_at="2023-12-15 00:00:00",
|
|
||||||
# updated_at=notification["updated_at"],
|
|
||||||
# help=get_help_argument(),
|
|
||||||
# notification_id=notification["id"],
|
|
||||||
# can_receive_inbound=(current_service.has_permission("inbound_sms")),
|
|
||||||
# sent_with_test_key=(notification.get("key_type") == KEY_TYPE_TEST),
|
|
||||||
# back_link=back_link,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return redirect(
|
return redirect(
|
||||||
|
|||||||
@@ -2117,11 +2117,13 @@ def test_route_permissions_send_check_notifications(
|
|||||||
route,
|
route,
|
||||||
response_code,
|
response_code,
|
||||||
method,
|
method,
|
||||||
|
mock_create_job,
|
||||||
):
|
):
|
||||||
with client_request.session_transaction() as session:
|
with client_request.session_transaction() as session:
|
||||||
session["recipient"] = "2028675301"
|
session["recipient"] = "2028675301"
|
||||||
session["placeholders"] = {"name": "a"}
|
session["placeholders"] = {"name": "a"}
|
||||||
|
|
||||||
|
mocker.patch("app.main.views.send.check_messages")
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
"app.notification_api_client.get_notifications_for_service",
|
"app.notification_api_client.get_notifications_for_service",
|
||||||
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
||||||
@@ -2657,6 +2659,8 @@ def test_send_notification_submits_data(
|
|||||||
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
mocker.patch("app.main.views.send.check_messages", return_value="")
|
||||||
|
|
||||||
client_request.post(
|
client_request.post(
|
||||||
"main.send_notification", service_id=SERVICE_ONE_ID, template_id=fake_uuid
|
"main.send_notification", service_id=SERVICE_ONE_ID, template_id=fake_uuid
|
||||||
)
|
)
|
||||||
@@ -2671,11 +2675,13 @@ def test_send_notification_clears_session(
|
|||||||
mock_send_notification,
|
mock_send_notification,
|
||||||
mock_get_service_template,
|
mock_get_service_template,
|
||||||
mocker,
|
mocker,
|
||||||
|
mock_create_job,
|
||||||
):
|
):
|
||||||
with client_request.session_transaction() as session:
|
with client_request.session_transaction() as session:
|
||||||
session["recipient"] = "2028675301"
|
session["recipient"] = "2028675301"
|
||||||
session["placeholders"] = {"a": "b"}
|
session["placeholders"] = {"a": "b"}
|
||||||
|
|
||||||
|
mocker.patch("app.main.views.send.check_messages")
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
"app.notification_api_client.get_notifications_for_service",
|
"app.notification_api_client.get_notifications_for_service",
|
||||||
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
||||||
@@ -2730,11 +2736,14 @@ def test_send_notification_redirects_to_view_page(
|
|||||||
extra_args,
|
extra_args,
|
||||||
extra_redirect_args,
|
extra_redirect_args,
|
||||||
mocker,
|
mocker,
|
||||||
|
mock_create_job,
|
||||||
):
|
):
|
||||||
with client_request.session_transaction() as session:
|
with client_request.session_transaction() as session:
|
||||||
session["recipient"] = "2028675301"
|
session["recipient"] = "2028675301"
|
||||||
session["placeholders"] = {"a": "b"}
|
session["placeholders"] = {"a": "b"}
|
||||||
|
|
||||||
|
mocker.patch("app.main.views.send.check_messages")
|
||||||
|
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
"app.notification_api_client.get_notifications_for_service",
|
"app.notification_api_client.get_notifications_for_service",
|
||||||
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
||||||
@@ -2783,6 +2792,7 @@ def test_send_notification_shows_error_if_400(
|
|||||||
fake_uuid,
|
fake_uuid,
|
||||||
mocker,
|
mocker,
|
||||||
mock_get_service_template_with_placeholders,
|
mock_get_service_template_with_placeholders,
|
||||||
|
mock_create_job,
|
||||||
exception_msg,
|
exception_msg,
|
||||||
expected_h1,
|
expected_h1,
|
||||||
expected_err_details,
|
expected_err_details,
|
||||||
@@ -2790,11 +2800,17 @@ def test_send_notification_shows_error_if_400(
|
|||||||
class MockHTTPError(HTTPError):
|
class MockHTTPError(HTTPError):
|
||||||
message = exception_msg
|
message = exception_msg
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
"app.main.views.send.check_messages",
|
||||||
|
)
|
||||||
|
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
"app.notification_api_client.get_notifications_for_service",
|
"app.notification_api_client.get_notifications_for_service",
|
||||||
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
mocker.patch("app.s3_client.s3_csv_client.s3upload")
|
||||||
|
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
"app.notification_api_client.send_notification",
|
"app.notification_api_client.send_notification",
|
||||||
side_effect=MockHTTPError(),
|
side_effect=MockHTTPError(),
|
||||||
@@ -2810,7 +2826,7 @@ def test_send_notification_shows_error_if_400(
|
|||||||
"main.send_notification",
|
"main.send_notification",
|
||||||
service_id=service_one["id"],
|
service_id=service_one["id"],
|
||||||
template_id=fake_uuid,
|
template_id=fake_uuid,
|
||||||
# _expected_status=200,
|
_expected_status=302,
|
||||||
)
|
)
|
||||||
|
|
||||||
# assert normalize_spaces(page.select(".banner-dangerous h1")[0].text) == expected_h1
|
# assert normalize_spaces(page.select(".banner-dangerous h1")[0].text) == expected_h1
|
||||||
@@ -2826,11 +2842,13 @@ def test_send_notification_shows_email_error_in_trial_mode(
|
|||||||
fake_uuid,
|
fake_uuid,
|
||||||
mocker,
|
mocker,
|
||||||
mock_get_service_email_template,
|
mock_get_service_email_template,
|
||||||
|
mock_create_job,
|
||||||
):
|
):
|
||||||
class MockHTTPError(HTTPError):
|
class MockHTTPError(HTTPError):
|
||||||
message = TRIAL_MODE_MSG
|
message = TRIAL_MODE_MSG
|
||||||
status_code = 400
|
status_code = 400
|
||||||
|
|
||||||
|
mocker.patch("app.main.views.send.check_messages")
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
"app.notification_api_client.get_notifications_for_service",
|
"app.notification_api_client.get_notifications_for_service",
|
||||||
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
return_value=FAKE_ONE_OFF_NOTIFICATION,
|
||||||
|
|||||||
@@ -1396,7 +1396,15 @@ def mock_check_verify_code_code_expired(mocker):
|
|||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def mock_create_job(mocker, api_user_active):
|
def mock_create_job(mocker, api_user_active):
|
||||||
def _create(job_id, service_id, scheduled_for=None):
|
def _create(
|
||||||
|
job_id,
|
||||||
|
service_id,
|
||||||
|
scheduled_for=None,
|
||||||
|
template_id=None,
|
||||||
|
original_file_name=None,
|
||||||
|
notification_count=None,
|
||||||
|
valid=None,
|
||||||
|
):
|
||||||
return job_json(
|
return job_json(
|
||||||
service_id,
|
service_id,
|
||||||
api_user_active,
|
api_user_active,
|
||||||
|
|||||||
Reference in New Issue
Block a user