mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-04 02:11:11 -05:00
Merge branch 'master' of github.com:alphagov/notifications-api
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
from flask import request, jsonify, _request_ctx_stack, current_app
|
from flask import request, jsonify, _request_ctx_stack, current_app
|
||||||
from notifications_python_client.authentication import decode_jwt_token, get_token_issuer
|
from notifications_python_client.authentication import decode_jwt_token, get_token_issuer
|
||||||
from notifications_python_client.errors import TokenDecodeError, TokenRequestError, TokenExpiredError, TokenPayloadError
|
from notifications_python_client.errors import TokenDecodeError, TokenExpiredError
|
||||||
from werkzeug.exceptions import abort
|
from werkzeug.exceptions import abort
|
||||||
from app.dao.api_key_dao import get_unsigned_secrets
|
from app.dao.api_key_dao import get_unsigned_secrets
|
||||||
from app import api_user
|
from app import api_user
|
||||||
@@ -43,12 +43,8 @@ def requires_auth():
|
|||||||
)
|
)
|
||||||
_request_ctx_stack.top.api_user = api_client
|
_request_ctx_stack.top.api_user = api_client
|
||||||
return
|
return
|
||||||
except TokenRequestError:
|
|
||||||
errors_resp = authentication_response("Invalid token: request", 403)
|
|
||||||
except TokenExpiredError:
|
except TokenExpiredError:
|
||||||
errors_resp = authentication_response("Invalid token: expired", 403)
|
errors_resp = authentication_response("Invalid token: expired", 403)
|
||||||
except TokenPayloadError:
|
|
||||||
errors_resp = authentication_response("Invalid token: payload", 403)
|
|
||||||
except TokenDecodeError:
|
except TokenDecodeError:
|
||||||
errors_resp = authentication_response("Invalid token: signature", 403)
|
errors_resp = authentication_response("Invalid token: signature", 403)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from app.clients.sms.mmg import MMGClientException
|
|||||||
from app.dao.services_dao import dao_fetch_service_by_id
|
from app.dao.services_dao import dao_fetch_service_by_id
|
||||||
from app.dao.templates_dao import dao_get_template_by_id
|
from app.dao.templates_dao import dao_get_template_by_id
|
||||||
|
|
||||||
from notifications_utils.template import Template
|
from notifications_utils.template import Template, unlink_govuk_escaped
|
||||||
|
|
||||||
from notifications_utils.recipients import (
|
from notifications_utils.recipients import (
|
||||||
RecipientCSV,
|
RecipientCSV,
|
||||||
@@ -296,7 +296,7 @@ def send_email(service_id, notification_id, from_address, encrypted_notification
|
|||||||
from_address,
|
from_address,
|
||||||
notification['to'],
|
notification['to'],
|
||||||
template.replaced_subject,
|
template.replaced_subject,
|
||||||
body=template.replaced,
|
body=template.replaced_govuk_escaped,
|
||||||
html_body=template.as_HTML_email,
|
html_body=template.as_HTML_email,
|
||||||
)
|
)
|
||||||
update_notification_reference_by_id(notification_id, reference)
|
update_notification_reference_by_id(notification_id, reference)
|
||||||
@@ -350,13 +350,17 @@ def invitation_template(user_name, service_name, url, expiry_date):
|
|||||||
'GOV.UK Notify makes it easy to keep people updated by helping you send text messages, emails and letters.\n\n'
|
'GOV.UK Notify makes it easy to keep people updated by helping you send text messages, emails and letters.\n\n'
|
||||||
'Click this link to create an account on GOV.UK Notify:\n$url\n\n'
|
'Click this link to create an account on GOV.UK Notify:\n$url\n\n'
|
||||||
'This invitation will stop working at midnight tomorrow. This is to keep $service_name secure.')
|
'This invitation will stop working at midnight tomorrow. This is to keep $service_name secure.')
|
||||||
return t.substitute(user_name=user_name, service_name=service_name, url=url, expiry_date=expiry_date)
|
return unlink_govuk_escaped(
|
||||||
|
t.substitute(user_name=user_name, service_name=service_name, url=url, expiry_date=expiry_date)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def invitation_subject_line(user_name, service_name):
|
def invitation_subject_line(user_name, service_name):
|
||||||
from string import Template
|
from string import Template
|
||||||
t = Template('$user_name has invited you to collaborate on $service_name on GOV.UK Notify')
|
t = Template('$user_name has invited you to collaborate on $service_name on GOV.UK Notify')
|
||||||
return t.substitute(user_name=user_name, service_name=service_name)
|
return unlink_govuk_escaped(
|
||||||
|
t.substitute(user_name=user_name, service_name=service_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def invited_user_url(base_url, token):
|
def invited_user_url(base_url, token):
|
||||||
@@ -391,7 +395,9 @@ def password_reset_message(name, url):
|
|||||||
"If you didn't request this email, you can ignore it – your password has not been changed.\n\n"
|
"If you didn't request this email, you can ignore it – your password has not been changed.\n\n"
|
||||||
"To reset your password, click this link:\n\n"
|
"To reset your password, click this link:\n\n"
|
||||||
"$url")
|
"$url")
|
||||||
return t.substitute(user_name=name, url=url)
|
return unlink_govuk_escaped(
|
||||||
|
t.substitute(user_name=name, url=url)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@notify_celery.task(name='email-reset-password')
|
@notify_celery.task(name='email-reset-password')
|
||||||
@@ -411,7 +417,9 @@ def registration_verification_template(name, url):
|
|||||||
from string import Template
|
from string import Template
|
||||||
t = Template("Hi $name,\n\n"
|
t = Template("Hi $name,\n\n"
|
||||||
"To complete your registration for GOV.UK Notify please click the link below\n\n $url")
|
"To complete your registration for GOV.UK Notify please click the link below\n\n $url")
|
||||||
return t.substitute(name=name, url=url)
|
return unlink_govuk_escaped(
|
||||||
|
t.substitute(name=name, url=url)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@notify_celery.task(name='email-registration-verification')
|
@notify_celery.task(name='email-registration-verification')
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ twilio==4.6.0
|
|||||||
monotonic==0.3
|
monotonic==0.3
|
||||||
|
|
||||||
|
|
||||||
git+https://github.com/alphagov/notifications-python-client.git@0.2.6#egg=notifications-python-client==0.2.6
|
git+https://github.com/alphagov/notifications-python-client.git@0.5.0#egg=notifications-python-client==0.5.0
|
||||||
|
|
||||||
git+https://github.com/alphagov/notifications-utils.git@4.1.1#egg=notifications-utils==4.1.1
|
|
||||||
|
git+https://github.com/alphagov/notifications-utils.git@4.2.0#egg=notifications-utils==4.2.0
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
import pytest
|
||||||
from notifications_python_client.authentication import create_jwt_token
|
from notifications_python_client.authentication import create_jwt_token
|
||||||
from flask import json, url_for, current_app
|
from flask import json, current_app
|
||||||
from app.dao.api_key_dao import get_unsigned_secrets, save_model_api_key, get_unsigned_secret
|
from app.dao.api_key_dao import get_unsigned_secrets, save_model_api_key, get_unsigned_secret
|
||||||
from app.models import ApiKey, Service
|
from app.models import ApiKey, Service
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ def test_should_not_allow_request_with_incorrect_token(notify_api, sample_user):
|
|||||||
assert data['message'] == 'Invalid token: signature'
|
assert data['message'] == 'Invalid token: signature'
|
||||||
|
|
||||||
|
|
||||||
def test_should_not_allow_incorrect_path(notify_api, sample_api_key):
|
def test_should_ignore_path(notify_api, sample_api_key):
|
||||||
with notify_api.test_request_context():
|
with notify_api.test_request_context():
|
||||||
with notify_api.test_client() as client:
|
with notify_api.test_client() as client:
|
||||||
token = create_jwt_token(
|
token = create_jwt_token(
|
||||||
@@ -49,12 +50,10 @@ def test_should_not_allow_incorrect_path(notify_api, sample_api_key):
|
|||||||
response = client.get(
|
response = client.get(
|
||||||
'/service',
|
'/service',
|
||||||
headers={'Authorization': "Bearer {}".format(token)})
|
headers={'Authorization': "Bearer {}".format(token)})
|
||||||
assert response.status_code == 403
|
assert response.status_code == 200
|
||||||
data = json.loads(response.get_data())
|
|
||||||
assert data['message'] == 'Invalid token: request'
|
|
||||||
|
|
||||||
|
|
||||||
def test_should_not_allow_incorrect_method(notify_api, sample_api_key):
|
def test_should_ignore_request(notify_api, sample_api_key):
|
||||||
with notify_api.test_request_context():
|
with notify_api.test_request_context():
|
||||||
with notify_api.test_client() as client:
|
with notify_api.test_client() as client:
|
||||||
token = __create_post_token(sample_api_key.service_id, {})
|
token = __create_post_token(sample_api_key.service_id, {})
|
||||||
@@ -62,9 +61,7 @@ def test_should_not_allow_incorrect_method(notify_api, sample_api_key):
|
|||||||
'/service',
|
'/service',
|
||||||
headers={'Authorization': "Bearer {}".format(token)}
|
headers={'Authorization': "Bearer {}".format(token)}
|
||||||
)
|
)
|
||||||
assert response.status_code == 403
|
assert response.status_code == 200
|
||||||
data = json.loads(response.get_data())
|
|
||||||
assert data['message'] == 'Invalid token: request'
|
|
||||||
|
|
||||||
|
|
||||||
def test_should_not_allow_invalid_secret(notify_api, sample_api_key):
|
def test_should_not_allow_invalid_secret(notify_api, sample_api_key):
|
||||||
@@ -152,17 +149,16 @@ def test_should_allow_valid_token_with_post_body(notify_api, sample_api_key):
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
def test_should_not_allow_valid_token_with_invalid_post_body(notify_api, notify_db, notify_db_session, sample_api_key):
|
def test_should_allow_valid_token_with_invalid_post_body_but_fail_at_endpoint(notify_api, sample_api_key):
|
||||||
with notify_api.test_request_context():
|
with notify_api.test_request_context():
|
||||||
with notify_api.test_client() as client:
|
with notify_api.test_client() as client:
|
||||||
token = __create_post_token(str(sample_api_key.service_id), JSON_BODY)
|
token = __create_post_token(str(sample_api_key.service_id), JSON_BODY)
|
||||||
response = client.post(
|
with pytest.raises(AttributeError):
|
||||||
'/service',
|
response = client.post(
|
||||||
data="spurious",
|
'/service',
|
||||||
headers={'Authorization': 'Bearer {}'.format(token)})
|
data="spurious",
|
||||||
assert response.status_code == 403
|
headers={'Authorization': 'Bearer {}'.format(token)})
|
||||||
data = json.loads(response.get_data())
|
assert response.status_code == 400
|
||||||
assert data['message'] == 'Invalid token: payload'
|
|
||||||
|
|
||||||
|
|
||||||
def test_authentication_passes_admin_client_token(notify_api,
|
def test_authentication_passes_admin_client_token(notify_api,
|
||||||
|
|||||||
Reference in New Issue
Block a user