Merge branch 'main' of https://github.com/GSA/notifications-admin into notify-678

This commit is contained in:
Andrew Shumway
2023-10-03 14:37:04 -06:00
15 changed files with 88 additions and 42 deletions
+5 -5
View File
@@ -112,14 +112,14 @@ jobs:
env: env:
NOTIFY_ENVIRONMENT: scanning NOTIFY_ENVIRONMENT: scanning
- name: Run OWASP Baseline Scan - name: Run OWASP Baseline Scan
uses: zaproxy/action-baseline@v0.7.0 uses: zaproxy/action-baseline@v0.9.0
with: with:
docker_name: "owasp/zap2docker-stable" docker_name: 'ghcr.io/zaproxy/zaproxy:weekly'
target: "http://localhost:6012" target: 'http://localhost:6012'
fail_action: true fail_action: true
allow_issue_writing: false allow_issue_writing: false
rules_file_name: "zap.conf" rules_file_name: 'zap.conf'
cmd_options: "-I" cmd_options: '-I'
a11y-scan: a11y-scan:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
+2 -2
View File
@@ -50,9 +50,9 @@ jobs:
env: env:
NOTIFY_ENVIRONMENT: scanning NOTIFY_ENVIRONMENT: scanning
- name: Run OWASP Full Scan - name: Run OWASP Full Scan
uses: zaproxy/action-full-scan@v0.4.0 uses: zaproxy/action-full-scan@v0.7.0
with: with:
docker_name: 'owasp/zap2docker-stable' docker_name: 'ghcr.io/zaproxy/zaproxy:weekly'
target: 'http://localhost:6012' target: 'http://localhost:6012'
fail_action: true fail_action: true
allow_issue_writing: false allow_issue_writing: false
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

+1 -1
View File
@@ -1980,7 +1980,7 @@ class TemplateAndFoldersSelectionForm(Form):
None, None,
[ [
# ('email', 'Email') if 'email' in available_template_types else None, # ('email', 'Email') if 'email' in available_template_types else None,
("sms", "Text message") ("sms", "Start with a blank template")
if "sms" in available_template_types if "sms" in available_template_types
else None, else None,
("copy-existing", "Copy an existing template") ("copy-existing", "Copy an existing template")
+1 -1
View File
@@ -1,5 +1,5 @@
{% macro mapping_table(caption='', field_headings=[], field_headings_visible=True, caption_visible=True, equal_length=False) -%} {% macro mapping_table(caption='', field_headings=[], field_headings_visible=True, caption_visible=True, equal_length=False) -%}
<table class="usa-table usa-table--borderless"> <table class="usa-table usa-table--borderless width-full">
<caption class="font-body-lg table-heading{{ ' usa-sr-only' if not caption_visible}}"> <caption class="font-body-lg table-heading{{ ' usa-sr-only' if not caption_visible}}">
{{ caption }} {{ caption }}
</caption> </caption>
@@ -14,7 +14,6 @@
{% call mapping_table( {% call mapping_table(
caption='General', caption='General',
field_headings=['Label', 'Value', 'Action'],
field_headings_visible=False, field_headings_visible=False,
caption_visible=False caption_visible=False
) %} ) %}
+9 -6
View File
@@ -20,15 +20,18 @@
<div id='pill-selected-item'> <div id='pill-selected-item'>
<div class='grid-row'> <div class='grid-row'>
<div class='grid-col-6'> <div class='grid-col-12'>
<h2 class='heading-small'>Text messages</h2> <h2 class='heading-small'>Text messages</h2>
<div class="keyline-block"> <div class="keyline-block">
{{ big_number(sms_sent, 'sent', smaller=True) }} You have sent
{{ big_number(sms_free_allowance, 'free allowance', smaller=True) }} {{ big_number(sms_sent, 'messages of your', smaller=True) }}
{{ big_number(sms_free_allowance, 'free messages allowance.', smaller=True) }}
<br />
You have
{% if sms_free_allowance > 0 %} {% if sms_free_allowance > 0 %}
{{ big_number(sms_allowance_remaining, 'free allowance remaining', smaller=True) }} {{ big_number(sms_allowance_remaining, 'messages remaining.', smaller=True) }}
{% endif %} {% endif %}
{% for row in sms_breakdown %} {# {% for row in sms_breakdown %}
{% if row.charged_units > 0 %} {% if row.charged_units > 0 %}
{{ big_number( {{ big_number(
row.charged_units, row.charged_units,
@@ -36,7 +39,7 @@
smaller=True smaller=True
) }} ) }}
{% endif %} {% endif %}
{% endfor %} {% endfor %} #}
</div> </div>
</div> </div>
{# <div class='grid-col-6'> {# <div class='grid-col-6'>
-1
View File
@@ -13,7 +13,6 @@
<div class="body-copy-table"> <div class="body-copy-table">
{% call mapping_table( {% call mapping_table(
caption='Your profile', caption='Your profile',
field_headings=['Label', 'Value', 'Action'],
field_headings_visible=False, field_headings_visible=False,
caption_visible=False caption_visible=False
) %} ) %}
+32
View File
@@ -0,0 +1,32 @@
# Downloadable reports for sent messages and how they work
Downloadable reports related to sending messages are a little mysterious. They can have a variable number of columns,
some of which contain PII, and it is not immediately clear what drives what gets displayed. This is an explanation.
## Downloadable reports for one-off messages
When a user sends an ad-hoc message by typing in a phone number and sending, the downloadable report is only going to
show the bare minimum of columns. There will be a column that shows the name of what template was used, but otherwise
there will be nothing beyond the bare basics of the phone number and the time sent, etc.
## Downloadable reports for jobs (uploaded csv files)
When a user uploads a csv file -- creating a job -- the downloadable report becomes more complex and interesting.
(Sample report)
|Row number|Phone number|name|date|time|address|English|Spanish|Template|Type|Job|Status|Time|
|----------|------------|----|----|----|-------|-------|-------|--------|----|---|------|----|
|1|17169829002|Tim|10/16|2:00 PM|5678 Tom St.|no|yes|Appointment reminder - 1 week|sms|US Notify Demo CSV - Copy of Sheet1 (11).csv|Sending|2023-07-18 15:25:54|
In notifications_admin, in app.util.csv.py, there is a method called generate_notifications_csv().
It is using the service_id and job_id to look up the csv file in s3. It is then merging the standard
downloadable report (what we see in the one-off case mentioned above) with the custom csv data.
This means that the PII displayed is mostly not stored in the database, but rather is stored in S3.
The only PII stored in the database is the recipient's phone number, and that data is scrubbed. If the
sms message is delivered successfully, the phone number is scrubbed immediately. If the sms message
cannot be delivered, the PII will be scrubbed after seven days.
+1 -1
View File
@@ -100,8 +100,8 @@ To get involved, email us at [tts-benefits-studio@gsa.gov](mailto:tts-benefits-s
## Notify.gov Demo ## Notify.gov Demo
https://github.com/GSA/notifications-admin/assets/6556888/b87e12a3-6963-4fab-8124-7d0d2bb59901
https://user-images.githubusercontent.com/6556888/208711970-eb70e618-fd13-4e38-bb61-3ddbf6e21a6d.mp4
+11 -1
View File
@@ -1,6 +1,16 @@
# Notify Sprint Goals Log # Notify Sprint Goals Log
## Sprint: S (9/14/23) ## Sprint: T (9/28/23)
| | Goals | Impact |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| Engineering | Finish retention and [quota strategy](https://github.com/GSA/notifications-api/issues/443), obtain access to [Login.gov sandbox](https://github.com/GSA/notifications-admin/issues/338) and begin integration work, tend to remaining low/medium bugs, request more toll-free [partner numbers](https://github.com/GSA/notifications-admin/issues/764), create a formal [manual qa script](https://github.com/GSA/notifications-admin/issues/809) | Greater sending volume for partners, start down path of ATO-required auth solution |
| UX | Perform observational and formal user feedback sessions with partners to inform flow and look/feel redesign, surface and remedy straightforward UI changes | Inform future features, flow, and feel of the application |
| Security | Complete pre-requisite documentation, start project planning timelines and control group deadlines | Aim to have package completed with enough time to allow for long assessment|
| Content | Work on cloud.gov pages IAA mod for content site | Enable an easy static website for future content |
| Ops | Onboard new back-end dev, get access to tools for them, meet with POC and team, get them oriented to start work | Add valuable dev resources to increase our capacity
## Sprint: Snowy Owl (9/14/23)
| | Goals | Impact | | | Goals | Impact |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------| |-------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
Generated
+4 -4
View File
@@ -3270,17 +3270,17 @@ files = [
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "1.26.16" version = "1.26.17"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [ files = [
{file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, {file = "urllib3-1.26.17-py2.py3-none-any.whl", hash = "sha256:94a757d178c9be92ef5539b8840d48dc9cf1b2709c9d6b588232a055c524458b"},
{file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, {file = "urllib3-1.26.17.tar.gz", hash = "sha256:24d6a242c28d29af46c3fae832c36db3bbebcc533dd1bb549172cd739c82df21"},
] ]
[package.extras] [package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
@@ -54,7 +54,7 @@ def mock_get_service_settings_page_common(
( (
create_active_user_with_permissions(), create_active_user_with_permissions(),
[ [
"Label Value Action", "",
"Service name Test Service Change service name", "Service name Test Service Change service name",
"Sign-in method Text message code Change sign-in method", "Sign-in method Text message code Change sign-in method",
"Send text messages On Change your settings for sending text messages", "Send text messages On Change your settings for sending text messages",
@@ -66,7 +66,7 @@ def mock_get_service_settings_page_common(
( (
create_platform_admin_user(), create_platform_admin_user(),
[ [
"Label Value Action", "",
"Service name Test Service Change service name", "Service name Test Service Change service name",
"Sign-in method Text message code Change sign-in method", "Sign-in method Text message code Change sign-in method",
"Send text messages On Change your settings for sending text messages", "Send text messages On Change your settings for sending text messages",
+17 -14
View File
@@ -819,7 +819,7 @@ def test_usage_page(
assert normalize_spaces(unselected_nav_links[0].text) == "2010 to 2011 fiscal year" assert normalize_spaces(unselected_nav_links[0].text) == "2010 to 2011 fiscal year"
assert normalize_spaces(unselected_nav_links[1].text) == "2009 to 2010 fiscal year" assert normalize_spaces(unselected_nav_links[1].text) == "2009 to 2010 fiscal year"
annual_usage = page.find_all("div", {"class": "grid-col-6"}) annual_usage = page.find_all("div", {"class": "keyline-block"})
# annual stats are shown in two rows, each with three column; email is col 1 # annual stats are shown in two rows, each with three column; email is col 1
# email_column = normalize_spaces(annual_usage[0].text + annual_usage[2].text) # email_column = normalize_spaces(annual_usage[0].text + annual_usage[2].text)
@@ -827,13 +827,13 @@ def test_usage_page(
# assert '1,000 sent' in email_column # assert '1,000 sent' in email_column
sms_column = normalize_spaces(annual_usage[0].text) sms_column = normalize_spaces(annual_usage[0].text)
assert "Text messages" in sms_column assert (
assert "251,800 sent" in sms_column "You have sent 251,800 messages of your 250,000 free messages allowance. You have 0 messages remaining."
assert "250,000 free allowance" in sms_column in sms_column
assert "0 free allowance remaining" in sms_column )
assert "$29.85 spent" not in sms_column assert "$29.85 spent" not in sms_column
assert "1,500 at 1.65 pence" in sms_column assert "1,500 at 1.65 pence" not in sms_column
assert "300 at 1.70 pence" in sms_column assert "300 at 1.70 pence" not in sms_column
@freeze_time("2012-03-31 12:12:12") @freeze_time("2012-03-31 12:12:12")
@@ -862,12 +862,12 @@ def test_usage_page_no_sms_spend(
service_id=SERVICE_ONE_ID, service_id=SERVICE_ONE_ID,
) )
annual_usage = page.find_all("div", {"class": "grid-col-6"}) annual_usage = page.find_all("div", {"class": "keyline-block"})
sms_column = normalize_spaces(annual_usage[0].text) sms_column = normalize_spaces(annual_usage[0].text)
assert "Text messages" in sms_column assert (
assert "1,000 sent" in sms_column "You have sent 1,000 messages of your 250,000 free messages allowance. You have 249,000 messages remaining."
assert "250,000 free allowance" in sms_column in sms_column
assert "249,000 free allowance remaining" in sms_column )
assert "$0.00 spent" not in sms_column assert "$0.00 spent" not in sms_column
assert "pence per message" not in sms_column assert "pence per message" not in sms_column
@@ -938,10 +938,13 @@ def test_usage_page_with_0_free_allowance(
year=2020, year=2020,
) )
annual_usage = page.select("main .grid-col-6") annual_usage = page.select("main .grid-col-12 .keyline-block")
sms_column = normalize_spaces(annual_usage[0].text) sms_column = normalize_spaces(annual_usage[0].text)
assert "0 free allowance" in sms_column assert (
"You have sent 251,800 messages of your 0 free messages allowance. You have"
in sms_column
)
assert "free allowance remaining" not in sms_column assert "free allowance remaining" not in sms_column
+2 -2
View File
@@ -310,7 +310,7 @@ def test_should_show_live_search_if_service_has_lots_of_folders(
], ],
[ [
# 'Email', # 'Email',
"Text message", "Start with a blank template",
"Copy an existing template", "Copy an existing template",
], ],
), ),
@@ -323,7 +323,7 @@ def test_should_show_live_search_if_service_has_lots_of_folders(
], ],
[ [
# 'Email', # 'Email',
"Text message", "Start with a blank template",
"Copy an existing template", "Copy an existing template",
], ],
), ),