Allow admin to specify domain for email auth links

Similar to https://github.com/alphagov/notifications-api/pull/1515

This lets the admin app pass in a domain to use for email auth links,
so that when it’s running on a different URL users who try to sign in
will get an email auth link for the domain they sign in on, not the
default admin domain for the environment in which the API is running.
This commit is contained in:
Chris Hill-Scott
2018-02-09 14:16:10 +00:00
parent bb027a5d8c
commit c0e2a478f6
4 changed files with 29 additions and 9 deletions

View File

@@ -196,7 +196,7 @@ def send_user_email_code(user_to_send_to, data):
secret_code = str(uuid.uuid4())
personalisation = {
'name': user_to_send_to.name,
'url': _create_2fa_url(user_to_send_to, secret_code, data.get('next'))
'url': _create_2fa_url(user_to_send_to, secret_code, data.get('next'), data.get('email_auth_link_host'))
}
create_2fa_code(
@@ -413,10 +413,10 @@ def _create_confirmation_url(user, email_address):
return url_with_token(data, url, current_app.config)
def _create_2fa_url(user, secret_code, next_redir):
def _create_2fa_url(user, secret_code, next_redir, email_auth_link_host):
data = json.dumps({'user_id': str(user.id), 'secret_code': secret_code})
url = '/email-auth/'
ret = url_with_token(data, url, current_app.config)
ret = url_with_token(data, url, current_app.config, base_url=email_auth_link_host)
if next_redir:
ret += '?{}'.format(urlencode({'next': next_redir}))
return ret

View File

@@ -22,6 +22,7 @@ post_send_user_email_code_schema = {
# doesn't need 'to' as we'll just grab user.email_address. but lets keep it
# as allowed to keep admin code cleaner, but only as null to prevent confusion
'to': {'type': 'null'},
'email_auth_link_host': {'type': ['string', 'null']},
'next': {'type': ['string', 'null']},
},
'required': [],

View File

@@ -20,10 +20,10 @@ def pagination_links(pagination, endpoint, **kwargs):
return links
def url_with_token(data, url, config):
def url_with_token(data, url, config, base_url=None):
from notifications_utils.url_safe_token import generate_token
token = generate_token(data, config['SECRET_KEY'], config['DANGEROUS_SALT'])
base_url = config['ADMIN_BASE_URL'] + url
base_url = (base_url or config['ADMIN_BASE_URL']) + url
return base_url + token

View File

@@ -343,12 +343,30 @@ def test_reset_failed_login_count_returns_404_when_user_does_not_exist(client):
assert resp.status_code == 404
def test_send_user_email_code(admin_request, mocker, sample_user, email_2fa_code_template):
@pytest.mark.parametrize('data, expected_auth_url', (
(
{},
'http://localhost:6012/email-auth/.',
),
(
{'to': None},
'http://localhost:6012/email-auth/.',
),
(
{'to': None, 'email_auth_link_host': 'https://example.com'},
'https://example.com/email-auth/.',
),
))
def test_send_user_email_code(
admin_request,
mocker,
sample_user,
email_2fa_code_template,
data,
expected_auth_url,
):
deliver_email = mocker.patch('app.celery.provider_tasks.deliver_email.apply_async')
data = {
'to': None
}
admin_request.post(
'user.send_user_2fa_code',
code_type='email',
@@ -361,6 +379,7 @@ def test_send_user_email_code(admin_request, mocker, sample_user, email_2fa_code
assert noti.to == sample_user.email_address
assert str(noti.template_id) == current_app.config['EMAIL_2FA_TEMPLATE_ID']
assert noti.personalisation['name'] == 'Test User'
assert noti.personalisation['url'].startswith(expected_auth_url)
deliver_email.assert_called_once_with(
[str(noti.id)],
queue='notify-internal-tasks'