merge from main again

This commit is contained in:
Kenneth Kehl
2024-02-22 14:43:54 -08:00
5 changed files with 268 additions and 56 deletions

79
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,79 @@
<!--
Please follow the instructions found in this pull request template so that we
have all of the relevant details needed for our work.
At the minimum, please be sure to fill in all sections found below and also do
the following:
- Provide an appropriate and descriptive title for the pull request
- Link the pull request to its corresponding issue (must be done after creating
the pull request itself)
- Assign yourself as the author
- Attach the appropriate labels to it
- Set it to be on the Notify.gov project board
- Select one or more reviewers from the team or mark the pull request as a draft
depending on its current state
- If the pull request is a draft, please be sure to add reviewers once it is
ready for review and mark it ready for review
For each section, please delete the instructions/sample text (that includes this
text, though it is wrapped in an HTML comment just in case) and put in your own
information. Thank you!
-->
*A note to PR reviewers: it may be helpful to review our
[code review documentation](https://github.com/GSA/notifications-api/blob/main/docs/all.md#code-reviews)
to know what to keep in mind while reviewing pull requests.*
## Description
Please enter a clear description about your proposed changes and what the
expected outcome(s) is/are from there. If there are complex implementation
details within the changes, this is a great place to explain those details using
plain language.
This should include:
- Links to issues that this PR addresses
- Screenshots or screen captures of any visible changes, especially for UI work
- Dependency changes
If there are any caveats, known issues, follow-up items, etc., make a quick note
of them here as well, though more details are probably warranted in the issue
itself in this case.
## TODO (optional)
If you're opening a draft PR, it might be helpful to list any outstanding work,
especially if you're asking folks to take a look before it's ready for full
review. In this case, create a small checklist with the outstanding items:
- [ ] TODO item 1
- [ ] TODO item 2
- [ ] TODO item ...
## Security Considerations
Please think about the security compliance aspect of your changes and what the
potential impacts might be.
**NOTE: Please be mindful of sharing sensitive information here! If you're not
sure of what to write, please ask the team first before writing anything here.**
Relevant details could include (and are not limited to) the following:
- Handling secrets/credential management (or specifically calling out that there
is nothing to handle)
- Any adjustments to the flow of data in and out the system, or even within it
- Connecting or disconnecting any external services to the application
- Handling of any sensitive information, such as PII
- Handling of information within log statements or other application monitoring
services/hooks
- The inclusion of a new external dependency or the removal of an existing one
- ... (anything else relevant from a security compliance perspective)
There are some cases where there are no security considerations to be had, e.g.,
updating our documentation with publicly available information. In those cases
it is fine to simply put something like this:
- None; this is a documentation update with publicly available information.

View File

@@ -90,23 +90,39 @@ class AwsCloudwatchClient(Client):
account_number = ses_domain_arn.split(":") account_number = ses_domain_arn.split(":")
return account_number return account_number
def warn_if_dev_is_opted_out(self, provider_response, notification_id):
if (
"is opted out" in provider_response.lower()
or "has blocked sms" in provider_response.lower()
):
if os.getenv("NOTIFY_ENVIRONMENT") in ["development", "test"]:
ansi_red = "\033[31m"
ansi_reset = "\033[0m"
logline = (
ansi_red
+ f"The phone number for notification_id {notification_id} is OPTED OUT. You need to opt back in"
+ ansi_reset
)
current_app.logger.warning(logline)
return logline
return None
def check_sms(self, message_id, notification_id, created_at): def check_sms(self, message_id, notification_id, created_at):
current_app.logger.info(f"CREATED AT = {created_at}")
region = cloud_config.sns_region region = cloud_config.sns_region
# TODO this clumsy approach to getting the account number will be fixed as part of notify-api #258 # TODO this clumsy approach to getting the account number will be fixed as part of notify-api #258
account_number = self._extract_account_number(cloud_config.ses_domain_arn) account_number = self._extract_account_number(cloud_config.ses_domain_arn)
time_now = datetime.utcnow() time_now = datetime.utcnow()
log_group_name = f"sns/{region}/{account_number[4]}/DirectPublishToPhoneNumber" log_group_name = f"sns/{region}/{account_number[4]}/DirectPublishToPhoneNumber"
current_app.logger.info(
f"Log group name: {log_group_name} message id: {message_id}"
)
filter_pattern = '{$.notification.messageId="XXXXX"}' filter_pattern = '{$.notification.messageId="XXXXX"}'
filter_pattern = filter_pattern.replace("XXXXX", message_id) filter_pattern = filter_pattern.replace("XXXXX", message_id)
all_log_events = self._get_log(filter_pattern, log_group_name, created_at) all_log_events = self._get_log(filter_pattern, log_group_name, created_at)
if all_log_events and len(all_log_events) > 0: if all_log_events and len(all_log_events) > 0:
event = all_log_events[0] event = all_log_events[0]
message = json.loads(event["message"]) message = json.loads(event["message"])
self.warn_if_dev_is_opted_out(
message["delivery"]["providerResponse"], notification_id
)
return ( return (
"success", "success",
message["delivery"]["providerResponse"], message["delivery"]["providerResponse"],
@@ -116,13 +132,13 @@ class AwsCloudwatchClient(Client):
log_group_name = ( log_group_name = (
f"sns/{region}/{account_number[4]}/DirectPublishToPhoneNumber/Failure" f"sns/{region}/{account_number[4]}/DirectPublishToPhoneNumber/Failure"
) )
current_app.logger.info(f"Failure log group name: {log_group_name}")
all_failed_events = self._get_log(filter_pattern, log_group_name, created_at) all_failed_events = self._get_log(filter_pattern, log_group_name, created_at)
if all_failed_events and len(all_failed_events) > 0: if all_failed_events and len(all_failed_events) > 0:
current_app.logger.info("SHOULD RETURN FAILED BECAUSE WE FOUND A FAILURE")
event = all_failed_events[0] event = all_failed_events[0]
message = json.loads(event["message"]) message = json.loads(event["message"])
current_app.logger.info(f"MESSAGE {message}") self.warn_if_dev_is_opted_out(
message["delivery"]["providerResponse"], notification_id
)
return ( return (
"failure", "failure",
message["delivery"]["providerResponse"], message["delivery"]["providerResponse"],

View File

@@ -36,17 +36,20 @@
- [Celery scheduled tasks](#celery-scheduled-tasks) - [Celery scheduled tasks](#celery-scheduled-tasks)
- [Notify.gov](#notifygov) - [Notify.gov](#notifygov)
- [System Description](#system-description) - [System Description](#system-description)
- [Code Reviews](#code-reviews)
- [For the reviewer](#for-the-reviewer)
- [For the author](#for-the-author)
- [Run Book](#run-book) - [Run Book](#run-book)
- [ Alerts, Notifications, Monitoring](#-alerts-notifications-monitoring) - [Alerts, Notifications, Monitoring](#-alerts-notifications-monitoring)
- [ Restaging Apps](#-restaging-apps) - [Restaging Apps](#-restaging-apps)
- [ Smoke-testing the App](#-smoke-testing-the-app) - [Smoke-testing the App](#-smoke-testing-the-app)
- [ Simulated bulk send testing](#-simulated-bulk-send-testing) - [Simulated bulk send testing](#-simulated-bulk-send-testing)
- [ Configuration Management](#-configuration-management) - [Configuration Management](#-configuration-management)
- [ DNS Changes](#-dns-changes) - [DNS Changes](#-dns-changes)
- [Exporting test results for compliance monitoring](#exporting-test-results-for-compliance-monitoring) - [Exporting test results for compliance monitoring](#exporting-test-results-for-compliance-monitoring)
- [ Known Gotchas](#-known-gotchas) - [Known Gotchas](#-known-gotchas)
- [ User Account Management](#-user-account-management) - [User Account Management](#-user-account-management)
- [ SMS Phone Number Management](#-sms-phone-number-management) - [SMS Phone Number Management](#-sms-phone-number-management)
- [Data Storage Policies \& Procedures](#data-storage-policies--procedures) - [Data Storage Policies \& Procedures](#data-storage-policies--procedures)
- [Potential PII Locations](#potential-pii-locations) - [Potential PII Locations](#potential-pii-locations)
- [Data Retention Policy](#data-retention-policy) - [Data Retention Policy](#data-retention-policy)
@@ -711,10 +714,6 @@ make run-celery-beat
``` ```
Notify.gov Notify.gov
========= =========
@@ -755,6 +754,102 @@ Notify.gov also provisions and uses two AWS services via a [supplemental service
For further details of the system and how it connects to supporting services, see the [application boundary diagram](https://github.com/GSA/us-notify-compliance/blob/main/diagrams/rendered/apps/application.boundary.png) For further details of the system and how it connects to supporting services, see the [application boundary diagram](https://github.com/GSA/us-notify-compliance/blob/main/diagrams/rendered/apps/application.boundary.png)
Code Reviews
============
When conducting a code review there are several things to keep in mind to ensure
a quality and valuable review. Remember, we're trying to improve Notify.gov as
best we can; it does us no good if we do not double check that our work meets
our standards, especially before going out the door!
It also does us no good if we do not treat each other without mutual respect or
consideration either; if there are mistakes or oversights found in a pull
request, or even just suggestions for alternative ways of approaching something,
these become learning opportunities for all parties involved in addition to
modeling positive behavior and practices for the public and broader open source
community.
Given this basis of approaching code reviews, here are some general guidelines
and suggestions for how to approach a code review from the perspectives of both
the reviewer and the author.
### For the reviewer
When performing a code review, please be curious and critical while also being
respectful and appreciative of the work submitted. Code reviews are a chance
to check that things meet our standards and provide learning opportunities.
They are not places for belittling or disparaging someone's work or approach to
a task, and absolutely not the person(s) themselves.
That said, any responses to the code review should also be respectful and
considerate. Remember, this is a chance to not only improve our work and the
state of Notify.gov, it's also a chance to learn something new!
**Note: If a response is condescending, derogatory, disrespectful, etc., please
do not hesitate to either speak with the author(s) directly about this or reach
out to a team lead/supervisor for additional help to rectify the issue. Such
behavior and lack of professionalism is not acceptable or tolerated.**
When performing a code review, it is helpful to keep the following guidelines in
mind:
- Be on the lookout for any sensitive information and/or leaked credentials,
secrets, PII, etc.
- Ask and call out things that aren't clear to you; it never hurts to double
check your understanding of something!
- Check that things are named descriptively and appropriately and call out
anything that is not.
- Check that comments are present for complex areas when needed.
- Make sure the pull request itself is properly prepared - it has a clear
description, calls out security concerns, and has the necessary labels, flags,
issue link, etc., set on it.
- Do not be shy about using the suggested changes feature in GitHub pull request
comments; this can help save a lot of time!
- Do not be shy about marking a review with the `Request Changes` status - yes,
it looks big and red when it shows up, but this is completely fine and not to
be taken as a personal mark against the author(s) of the pull request!
Additionally, if you find yourself making a lot of comments and/or end up having
several concerns about the overall approach, it will likely be helpful to
schedule time to speak with the author(s) directly and talk through everything.
This can save folks a lot of misunderstanding and back-and-forth!
### For the author
When receiving a code review, please remember that someone took the time to look
over all of your work with a critical eye to make sure our standards are being
met and that we're producing the best quality work possible. It's completely
fine if there are specific changes requested and/or other parts are sent back
for additional work!
That said, the review should also be respectful, helpful, and a learning
opportunity where possible. Remember, this is a chance to not only improve your
work and the state of Notify.gov, it's also a chance to learn something new!
**Note: If a review is condescending, derogatory, disrespectful, etc., please do
not hesitate to either speak with the reviewer(s) directly about this or reach
out to a team lead/supervisor for additional help to rectify the issue. Such
behavior and lack of professionalism is not acceptable or tolerated.**
When going over a review, it may be helpful to keep these perspectives in mind:
- Approach the review with an open mind, curiosity, and appreciation.
- If anything the reviewer(s) mentions is unclear to you, please ask for
clarification and engage them in further dialogue!
- If you disagree with a suggestion or request, please say so and engage in an
open and respecful dialogue to come to a mutual understanding of what the
appropriate next step(S) should be - accept the change, reject the change,
take a different path entirely, etc.
- If there are no issues with any suggested edits or requested changes, make
the necessary adjustments and let the reviewer(s) know when the work is ready
for review again.
Additionally, if you find yourself responding to a lot of things and questioning
the feedback received throughout much of the code review, it will likely be
helpful to schedule time to speak with the reviewer(s) directly and talk through
everything. This can save folks a lot of misunderstanding and back-and-forth!
Run Book Run Book
======== ========

72
poetry.lock generated
View File

@@ -940,43 +940,43 @@ files = [
[[package]] [[package]]
name = "cryptography" name = "cryptography"
version = "42.0.2" version = "42.0.4"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be"}, {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449"},
{file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d"}, {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18"},
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4"}, {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2"},
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2"}, {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1"},
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8e88bb9eafbf6a4014d55fb222e7360eef53e613215085e65a13290577394529"}, {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b"},
{file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a047682d324ba56e61b7ea7c7299d51e61fd3bca7dad2ccc39b72bd0118d60a1"}, {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1"},
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1"}, {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992"},
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929"}, {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885"},
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b97fe7d7991c25e6a31e5d5e795986b18fbbb3107b873d5f3ae6dc9a103278e9"}, {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824"},
{file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5fa82a26f92871eca593b53359c12ad7949772462f887c35edaf36f87953c0e2"}, {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b"},
{file = "cryptography-42.0.2-cp37-abi3-win32.whl", hash = "sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee"}, {file = "cryptography-42.0.4-cp37-abi3-win32.whl", hash = "sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925"},
{file = "cryptography-42.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:841ec8af7a8491ac76ec5a9522226e287187a3107e12b7d686ad354bb78facee"}, {file = "cryptography-42.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923"},
{file = "cryptography-42.0.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242"}, {file = "cryptography-42.0.4-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7"},
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28cb2c41f131a5758d6ba6a0504150d644054fd9f3203a1e8e8d7ac3aea7f73a"}, {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52"},
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446"}, {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a"},
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:44c95c0e96b3cb628e8452ec060413a49002a247b2b9938989e23a2c8291fc90"}, {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9"},
{file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f14185962e6a04ab32d1abe34eae8a9001569ee4edb64d2304bf0d65c53f3"}, {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764"},
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:09a77e5b2e8ca732a19a90c5bca2d124621a1edb5438c5daa2d2738bfeb02589"}, {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff"},
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad28cff53f60d99a928dfcf1e861e0b2ceb2bc1f08a074fdd601b314e1cc9e0a"}, {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257"},
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:130c0f77022b2b9c99d8cebcdd834d81705f61c68e91ddd614ce74c657f8b3ea"}, {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929"},
{file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33"}, {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0"},
{file = "cryptography-42.0.2-cp39-abi3-win32.whl", hash = "sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635"}, {file = "cryptography-42.0.4-cp39-abi3-win32.whl", hash = "sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129"},
{file = "cryptography-42.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6"}, {file = "cryptography-42.0.4-cp39-abi3-win_amd64.whl", hash = "sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854"},
{file = "cryptography-42.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:087887e55e0b9c8724cf05361357875adb5c20dec27e5816b653492980d20380"}, {file = "cryptography-42.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298"},
{file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6"}, {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88"},
{file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4383b47f45b14459cab66048d384614019965ba6c1a1a141f11b5a551cace1b2"}, {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20"},
{file = "cryptography-42.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:fbeb725c9dc799a574518109336acccaf1303c30d45c075c665c0793c2f79a7f"}, {file = "cryptography-42.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce"},
{file = "cryptography-42.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008"}, {file = "cryptography-42.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74"},
{file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5ef9bc3d046ce83c4bbf4c25e1e0547b9c441c01d30922d812e887dc5f125c12"}, {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd"},
{file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a"}, {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b"},
{file = "cryptography-42.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65"}, {file = "cryptography-42.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660"},
{file = "cryptography-42.0.2.tar.gz", hash = "sha256:e0ec52ba3c7f1b7d813cd52649a5b3ef1fc0d433219dc8c93827c57eab6cf888"}, {file = "cryptography-42.0.4.tar.gz", hash = "sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb"},
] ]
[package.dependencies] [package.dependencies]
@@ -2582,7 +2582,7 @@ requests = ">=2.0.0"
[[package]] [[package]]
name = "notifications-utils" name = "notifications-utils"
version = "0.2.8" version = "0.2.9"
description = "" description = ""
optional = false optional = false
python-versions = ">=3.9,<3.12" python-versions = ">=3.9,<3.12"
@@ -2600,7 +2600,7 @@ certifi = "^2023.7.22"
cffi = "^1.16.0" cffi = "^1.16.0"
charset-normalizer = "^3.1.0" charset-normalizer = "^3.1.0"
click = "^8.1.3" click = "^8.1.3"
cryptography = "^42.0.0" cryptography = "^42.0.4"
flask = "^2.3.2" flask = "^2.3.2"
flask-redis = "^0.4.0" flask-redis = "^0.4.0"
geojson = "^3.0.1" geojson = "^3.0.1"
@@ -2634,7 +2634,7 @@ werkzeug = "^3.0.1"
type = "git" type = "git"
url = "https://github.com/GSA/notifications-utils.git" url = "https://github.com/GSA/notifications-utils.git"
reference = "HEAD" reference = "HEAD"
resolved_reference = "a48171e865eb83cf29c75751be7369f396cbe3e2" resolved_reference = "df8ece836cad303c5d161edf485cf9bbdc666688"
[[package]] [[package]]
name = "numpy" name = "numpy"

View File

@@ -1,6 +1,7 @@
# import pytest # import pytest
from datetime import datetime from datetime import datetime
import pytest
from flask import current_app from flask import current_app
from app import aws_cloudwatch_client from app import aws_cloudwatch_client
@@ -54,6 +55,27 @@ def side_effect(filterPattern, logGroupName, startTime, endTime):
return {"events": []} return {"events": []}
@pytest.mark.parametrize(
"response, notify_id, expected_message",
[
(
"Phone has blocked SMS",
"abc",
"\x1b[31mThe phone number for notification_id abc is OPTED OUT. You need to opt back in\x1b[0m",
),
(
"Some phone is opted out",
"xyz",
"\x1b[31mThe phone number for notification_id xyz is OPTED OUT. You need to opt back in\x1b[0m",
),
("Phone is A-OK", "123", None),
],
)
def test_warn_if_dev_is_opted_out(response, notify_id, expected_message):
result = aws_cloudwatch_client.warn_if_dev_is_opted_out(response, notify_id)
assert result == expected_message
def test_check_sms_success(notify_api, mocker): def test_check_sms_success(notify_api, mocker):
aws_cloudwatch_client.init_app(current_app) aws_cloudwatch_client.init_app(current_app)
boto_mock = mocker.patch.object(aws_cloudwatch_client, "_client", create=True) boto_mock = mocker.patch.object(aws_cloudwatch_client, "_client", create=True)