department-of-veterans-affairs / notification-api

Notification API
MIT License
16 stars 8 forks source link

v3 POST notification (part 1) #1360

Closed kalbfled closed 1 year ago

kalbfled commented 1 year ago

User Story - Business Need

User Story(ies)

As a Notify developer, I want creating and sending notifications to be fast So that we can scale to many more messages sent.

As a Notify client, I want clean and descriptive HTTP responses So that we can easily parse and capture the result of our attempt to send a notification.

Additional Info and Resources

Engineering Checklist

Do not use any code from the app/dao/ folder. Make all queries directly using flask-sqlalchemy.

Acceptance Criteria

QA Considerations

For QA to populate. Leave blank if QA is not applicable on this ticket.

mjones-oddball commented 1 year ago

Hey team! Please add your planning poker estimate with Zenhub @babyjunior56 @cris-oddball @EvanParish @k-macmillan @kalbfled @ldraney @nikolai-efimov

tabinda-syed commented 1 year ago

A note to Engs. from our 8/7 Refinement: We've pointed this at a 5 with QA considered. This means about 3 of the points are available to you - if your effort on this ticket begins to go beyond that, please bring it up to the team ASAP. Thank you.

kalbfled commented 1 year ago

I finished the initial development work for this issue, but I still need to create the new openapi and Postman documentation.

@cris-oddball As discussed, the new unit tests provide relevant post request bodies.

cris-oddball commented 1 year ago

Code approved, merged to master, deployed to Perf. regression: 134 passed, 3 xfailed in 143.46s (0:02:23)

Will do manual testing tomorrow.

kalbfled commented 1 year ago

@mjones-oddball

User-Facing Differences Between V2 and V3 for Notifications

{
    "errors": [
        {
            "error": "AuthError",
            "message": "Unauthorized, authentication token must be provided"
        }
    ]
}

. . . where the values of "error" reflects the exception that was handled, and "message" provides details.

Other Differences Between V2 and V3 for Notifications

cris-oddball commented 1 year ago

Happy Path email test cases pass (automated) Tests check for the 202 response, that only an "id" is returned and that the "id" is a UUID

Private Zenhub Image

test_send_v3_email[Email: Basic Formatting] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'email_address': 'vanotify.qa@gmail.com'}

test_send_v3_email[Email: Personalization] PASSED

{'template_id': 'c1616f63-2f9a-45e9-8ea9-e00072987451', 'email_address': '<redacted>', 'personalisation': {'name': 'Veteran', 'adjective': 'happy'}}

test_send_v3_email[Email: Basic Formatting and Optional Properties] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'email_address': '<redacted>', 'client_reference': 'string', 'reference': 'string', 'billing_code': 'qa-test-003'}

test_send_v3_email[Email: Basic Formatting w/ VAPROFILEID] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'recipient_identifier': {'id_type': 'VAPROFILEID', 'id_value': '120451'}}

test_send_v3_email[Email: Basic Formatting w/ email and VAPROFILEID] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'email_address': '<redacted>', 'recipient_identifier': {'id_type': 'VAPROFILEID', 'id_value': '120451'}}

test_send_v3_email[Email: Basic Formatting w/ ICN] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'recipient_identifier': {'id_type': 'ICN', 'id_value': '1012858648V984772'}}

test_send_v3_email[Email: Basic Formatting w/ email and ICN] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'email_address': '<redacted>', 'recipient_identifier': {'id_type': 'ICN', 'id_value': '1012858648V984772'}}

test_send_v3_email[Email: Basic Formatting w/ BIRLSID] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'recipient_identifier': {'id_type': 'BIRLSID', 'id_value': '858131208'}}

test_send_v3_email[Email: Basic Formatting w/ email and BIRLSID] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'email_address': '<redacted>', 'recipient_identifier': {'id_type': 'BIRLSID', 'id_value': '858131208'}}

test_send_v3_email[Email: Basic Formatting w/ EDIPI] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'recipient_identifier': {'id_type': 'EDIPI', 'id_value': '1607380704'}}

test_send_v3_email[Email: Basic Formatting w/ email and EDIPI] PASSED

{'template_id': '324a5b71-8f3e-4617-9ba4-9e0da94bfe30', 'email_address': '<redacted>', 'recipient_identifier': {'id_type': 'EDIPI', 'id_value': '1607380704'}}

Test Response Private Zenhub Image

cris-oddball commented 1 year ago

Happy Path sms test cases (automated) Tests check for the 202 response, that only an "id" is returned and that the "id" is a UUID Private Zenhub Image

test_send_v3_sms[SMS: Short] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+14254147755'}

test_send_v3_sms[SMS: Short Personalized] PASSED

{'template_id': '6a2a27bf-8ede-4f67-9b21-01d4dd007356', 'phone_number': '+14254147755', 'personalisation': {'name': 'Friend', 'place': 'D.C.', 'year': '2023'}}

test_send_v3_sms[SMS: Short w/ optional properties] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+14254147755', 'reference': 'string', 'billing_code': 'qa-test-004'}

test_send_v3_sms[SMS: Short w/ alternate Pinpoint SMS Sender ID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+14254147755', 'sms_sender_id': 'b6288085-824f-4ee5-864e-8f2db5d7d0c9'}

test_send_v3_sms[SMS: Twilio w/ alternate Twilio SMS Sender ID] PASSED

{'template_id': '438a2240-ea2e-42d0-b0b8-4d63fc172a55', 'phone_number': '+14254147755', 'sms_sender_id': '6db4c815-fe8b-4c34-bea8-536a0976993d', 'billing_code': 'vanotify-testing'}

test_send_v3_sms[SMS: Short w/ BIRLSID recipient ID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'recipient_identifier': {'id_type': 'BIRLSID', 'id_value': '858131208'}}

test_send_v3_sms[SMS: Short w/ sms and BIRLSID recipient ID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+14254147755', 'recipient_identifier': {'id_type': 'BIRLSID', 'id_value': '858131208'}}

test_send_v3_sms[SMS: Short w/ ICN recipient ID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'recipient_identifier': {'id_type': 'ICN', 'id_value': '1012858648V984772'}}

test_send_v3_sms[SMS: Short w/ sms and ICN recipient ID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+14254147755', 'recipient_identifier': {'id_type': 'ICN', 'id_value': '1012858648V984772'}}

test_send_v3_sms[SMS: Short w/ EDIPI recipient ID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'recipient_identifier': {'id_type': 'EDIPI', 'id_value': '1607380704'}}

test_send_v3_sms[SMS: Short w/ sms and EDIPI recipient ID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+14254147755', 'recipient_identifier': {'id_type': 'EDIPI', 'id_value': '1607380704'}}

test_send_v3_sms[SMS: Short w/ VAPROFILEID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'recipient_identifier': {'id_type': 'VAPROFILEID', 'id_value': '120451'}}

test_send_v3_sms[SMS: Short w/ sms and VAPROFILEID] PASSED

{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+14254147755', 'recipient_identifier': {'id_type': 'VAPROFILEID', 'id_value': '120451'}}

test_send_v3_sms[SMS: Twilio w/ VAPROFILEID w/ Twilio SMS Sender ID] PASSED

{'template_id': '438a2240-ea2e-42d0-b0b8-4d63fc172a55', 'recipient_identifier': {'id_type': 'VAPROFILEID', 'id_value': '120451'}, 'sms_sender_id': '6db4c815-fe8b-4c34-bea8-536a0976993d', 'billing_code': 'vanotify-testing'}

Test Response Private Zenhub Image

cris-oddball commented 1 year ago

TEST FAILURE on negative test cases (email and sms)

The template_id should be a valid UUID. There is a unit test for this in the code.

However, sending a template_id with some string that is not a valid UUID is allowed, and the response is a 202, created, with a notification ID returned.

Private Zenhub Image

Private Zenhub Image

cris-oddball commented 1 year ago

TEST FAILURE Same as above, except for email validation. Unit test also exists for this.

However, posting an email_address with some string that is not a valid email is allowed, and the response is a 202, created, with a notification ID returned.

cris-oddball commented 1 year ago

TEST FAILURE ? Same as above, except for phone_number validation. I could not find a unit test so not sure what to expect here.

However, posting a phone_number with some string that is not a valid number is allowed, and the response is a 202, created, with a notification ID returned. By valid, I means of the format "+11234567890"

kalbfled commented 1 year ago

The phone number failure is expected because Json-schema does not have a formatter for phone numbers. (See here.) Valid phone numbers should be checked downstream. I could try using a regex formatter, but that would probably be error prone given that we support international numbers.

The UUID failures probably have something to do with my use of Draft202012Validator not working the same as jsonschema.validator, which is what the unit tests use, although it's not obvious to me from the docs why there would be a difference.

According to these docs, Draft202012Validator should verify "email" and "uuid" formats out of the box. ------- Original Message ------- On Thursday, August 31st, 2023 at 2:10 PM, Cris Stoddard @.***> wrote:

TEST FAILURE ? Same as above, except for phone_number validation. I could not find a unit test so not sure what to expect here.

However, posting a phone_number with some string that is not a valid number is allowed, and the response is a 202, created, with a notification ID returned. By valid, I means of the format "+11234567890"

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were assigned.Message ID: @.***>

cris-oddball commented 1 year ago

TEST FAILURE ? Sending a valid UUID for template_id but for a template that does not exist results in a 202 and a notification_id is created.

cris-oddball commented 1 year ago

@kalbfled

The phone number failure is expected because Json-schema does not have a formatter for phone numbers. (See here.) Valid phone numbers should be checked downstream. I could try using a regex formatter, but that would probably be error prone given that we support international numbers.

There is a python library to validate phone numbers

Let's discuss when you get back.

cris-oddball commented 1 year ago

TEST FAILURE

Sending an invalid email_reply_to_id (one that does not exist in the service) also fails, a 202 is returned and a notification_id is created.

Expected something like...

{
  "errors": [
    {
      "error": "ValidationError",
      "message": "email_reply_to_id 3720b5c1-f7af-4220-bb28-7f132fc011aa does not exist in database for service id 17adae4d-8207-40b4-ba4c-1a24a5369bce"
    }
  ],
}

Also, email_reply_to_id should be a UUID, not a string. When sent as a string and not a UUID, a 202 is returned and a notification_id is created.

cris-oddball commented 1 year ago

End result email testing. I have XFAILED and not run the failing email tests for now.

Screen Shot 2023-08-31 at 12 58 28 PM

cris-oddball commented 1 year ago

End result sms testing. I have XFAILED and not run the failing sms tests Screen Shot 2023-08-31 at 1 32 37 PM

cris-oddball commented 1 year ago

@mjones-oddball and @EvanParish and I discussed holding this ticket into the next sprint when @kalbfled is back and we are back from holiday to revisit what should and should not be working here.

Testing is complete, but with (I think) failed test cases.

Added blocker internal just to remind me that there is nothing more to do until next Tuesday.

A draft QA PR is up here.

cris-oddball commented 1 year ago

Swagger change needed for email_address, in v3, this is just listed as string it should be listed as string($email_address) as seen in v2

Private Zenhub Image

More swagger changes for email and sms:

scheduled_for is present in example but missing from schema and should be added asstring($datetime) with a descriptor as to the date parameters (not before today, not after 96 hours).

scheduled_for example should be a datetime, not "string" (please change)

client_reference is present in schema but missing from example (please add)

@kalbfled

cris-oddball commented 1 year ago

More swagger issues

EMAIL & SMS The 401 authorization message shown in the example is incorrect, it includes the status_code property Private Zenhub Image

The response is actually

{
  "errors": [
    {
      "error": "AuthError",
      "message": "Unauthorized, authentication token must be provided"
    }
  ]
}

The schema is also incorrect for this example and includes a required property. Private Zenhub Image

cris-oddball commented 1 year ago

QA FAILS

So to summarize...

This ticket fails validation, sending back to the TODO column.

kalbfled commented 1 year ago

I recreated the validation problems in the unit tests and am working on a revision. I will also use "phonenumbers" to test for a valid phone number.

cris-oddball commented 1 year ago

Hey @kalbfled , I just caught one more issue.

For /sms, if I pass a payload without the required property phone_number, the response is as follows:

{
    "errors": [
        {
            "error": "ValidationError",
            "message": "{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'notification_type': 'sms'} is not valid under any of the given schemas"
        }
    ]
}

I had expected that the response would indicate that a required property is missing, as it does when you omit the template_id. The error is more understandable to a human that the above, can this be changed?

{
    "errors": [
        {
            "error": "ValidationError",
            "message": "'template_id' is a required property"
        }
    ]
}
cris-oddball commented 1 year ago

One more issue sending an sms with an email_address gives a very unexpected error message, I would have thought more along the lines of ""Additional properties are not allowed ('email_address' was unexpected)"). The same holds for sending an email with a phone_number

{
    "errors": [
        {
            "error": "ValidationError",
            "message": "{'template_id': 'd46ee87b-8a71-4c5c-8654-ed766a9599ff', 'phone_number': '+17192445254', 'email_address': 'test@example.com', 'notification_type': 'sms'} should not be valid under {'anyOf': [{'properties': {'notification_type': {'const': 'email'}}, 'anyOf': [{'required': ['phone_number']}, {'required': ['sms_sender_id']}]}, {'properties': {'notification_type': {'const': 'sms'}}, 'anyOf': [{'required': ['email_address']}, {'required': ['email_reply_to_id']}]}]}"
        }
    ]
}
cris-oddball commented 1 year ago

Deployed to DEV, there are still swagger issues and one route error message that needs to be changed. Left comments on the PR with requests for changes.

Encountering some errors with the v3 routes only

requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='dev-api.va.gov', port=443): Read timed out. (read timeout=30)

This seems to be related to my local network not getting responses back from the public routes in sufficient time. I pushed my branches container to up and ran the v3 regression from the cloud, and did not see any timeout messages. The two failures are expected since they relate to a change requested in the PR.

 =========================== short test summary info ============================
XFAIL tests/test_service_api_key.py::test_create_api_key_incorrect_value_key_type_400 - reason: [NOTRUN] App returns 500, not 400, defect in API-1031
XFAIL tests/test_v2_notifications_email.py::test_send_email_expired_bearer_token_403 - reason: [NOTRUN] Need to write a new method to test expired
XFAIL tests/test_v2_notifications_sms.py::test_send_sms_expired_bearer_token_403 - reason: [NOTRUN] Need to write a new method to test expired
FAILED tests/test_v3_notifications_email.py::test_send_v3_email_invalid_payload_400[400 EMAIL: Missing required property 'email_address' or 'recipient_identifier]
FAILED tests/test_v3_notifications_sms.py::test_send_v3_sms_invalid_payload_400[400 SMS: Missing required property 'phone_number' or 'recipient_identifier]
============= 2 failed, 188 passed, 3 xfailed in 185.10s (0:03:05) =============

Sitting on this one until tomorrow since the QA Suite in the cloud against the v2 routes ran just fine.

cris-oddball commented 1 year ago

Successfully merged to master and deployed to Perf. Regression passes. ================== 190 passed, 3 xfailed in 154.09s (0:02:34) ==================