Skip to content

Commit

Permalink
Move invite code check to start of login flow, and add tests (#514)
Browse files Browse the repository at this point in the history
  • Loading branch information
MelissaAutumn authored Jul 3, 2024
1 parent 6d15127 commit 9391f0a
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 5 deletions.
1 change: 1 addition & 0 deletions backend/src/appointment/l10n/en/main.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ slot-not-found = There are no available time slots to book.
slot-already-taken = The time slot you have selected is no longer available. Please try again.
slot-invalid-email = The email you have provided was not valid. Please try again.
invite-code-not-valid = The invite code you used is not valid.
not-in-allow-list = Your email is not in the allow list.
schedule-not-active = The schedule has been turned off. Please contact the schedule owner for more information.
Expand Down
21 changes: 16 additions & 5 deletions backend/src/appointment/routes/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,21 @@ def fxa_login(

fxa_client.setup()

try:
url, state = fxa_client.get_redirect_url(db, token_urlsafe(32), email)
except NotInAllowListException:
if not invite_code:
raise HTTPException(status_code=403, detail='Your email is not in the allow list')
# Check if they're in the allowed list, but only if they didn't provide an invite code
# This checks to see if they're already a user (bypasses allow list) or in the allow list.
is_in_allow_list = fxa_client.is_in_allow_list(db, email)

if not is_in_allow_list and not invite_code:
raise HTTPException(status_code=403, detail=l10n('not-in-allow-list'))
elif not is_in_allow_list and invite_code:
# For slightly nicer error handling do the invite code check now.
# Only if they're not in the allow list and have an invite code.
if not repo.invite.code_exists(db, invite_code):
raise HTTPException(404, l10n('invite-code-not-valid'))
if not repo.invite.code_is_available(db, invite_code):
raise HTTPException(403, l10n('invite-code-not-valid'))

url, state = fxa_client.get_redirect_url(db, token_urlsafe(32), email)

request.session['fxa_state'] = state
request.session['fxa_user_email'] = email
Expand Down Expand Up @@ -142,6 +152,7 @@ def fxa_callback(
new_subscriber_flow = not fxa_subscriber and not subscriber

if new_subscriber_flow:
# Double check:
# Ensure the invite code exists and is available
# Use some inline-errors for now. We don't have a good error flow!
is_in_allow_list = fxa_client.is_in_allow_list(db, email)
Expand Down
68 changes: 68 additions & 0 deletions backend/test/integration/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,74 @@ def test_fxa_login(self, with_client):
assert 'url' in data
assert data.get('url') == FXA_CLIENT_PATCH.get('authorization_url')

def test_fxa_with_allowlist_and_without_invite(self, with_client, with_l10n):
os.environ['AUTH_SCHEME'] = 'fxa'
os.environ['FXA_ALLOW_LIST'] = '@example.org'

email = '[email protected]'
response = with_client.get(
'/fxa_login',
params={
'email': email,
},
)
assert response.status_code == 403, response.text
data = response.json()
assert data.get('detail') == l10n('not-in-allow-list')

def test_fxa_with_allowlist_and_with_bad_invite_code(self, with_client, with_l10n):
os.environ['AUTH_SCHEME'] = 'fxa'
os.environ['FXA_ALLOW_LIST'] = '@example.org'

email = '[email protected]'
response = with_client.get(
'/fxa_login',
params={
'email': email,
'invite_code': 'absolute nonsense!'
},
)
assert response.status_code == 404, response.text
data = response.json()
assert data.get('detail') == l10n('invite-code-not-valid')

def test_fxa_with_allowlist_and_with_used_invite_code(self, with_client, with_l10n, make_invite, make_pro_subscriber):
os.environ['AUTH_SCHEME'] = 'fxa'
os.environ['FXA_ALLOW_LIST'] = '@example.org'

other_guy = make_pro_subscriber()
invite = make_invite(subscriber_id=other_guy.id)

email = '[email protected]'
response = with_client.get(
'/fxa_login',
params={
'email': email,
'invite_code': invite.code
},
)
assert response.status_code == 403, response.text
data = response.json()
assert data.get('detail') == l10n('invite-code-not-valid')

def test_fxa_with_allowlist_and_with_invite(self, with_client, with_l10n, make_invite):
os.environ['AUTH_SCHEME'] = 'fxa'
os.environ['FXA_ALLOW_LIST'] = '@example.org'

invite = make_invite()
email = '[email protected]'
response = with_client.get(
'/fxa_login',
params={
'email': email,
'invite_code': invite.code,
},
)
assert response.status_code == 200, response.text
data = response.json()
assert 'url' in data
assert data.get('url') == FXA_CLIENT_PATCH.get('authorization_url')

def test_fxa_callback_with_invite(self, with_db, with_client, monkeypatch, make_invite):
"""Test that our callback function correctly handles the session states, and creates a new subscriber"""
os.environ['AUTH_SCHEME'] = 'fxa'
Expand Down

0 comments on commit 9391f0a

Please sign in to comment.