From 986edfa317f5eebe5a3e325df370e3be39da7de4 Mon Sep 17 00:00:00 2001 From: Adam Shimali Date: Thu, 10 Mar 2016 11:57:40 +0000 Subject: [PATCH] Check user invite status not accepted before proceeding with flow. --- app/main/views/invites.py | 11 +++++++++-- tests/app/main/views/test_accept_invite.py | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/app/main/views/invites.py b/app/main/views/invites.py index 44d00296c..72c63771d 100644 --- a/app/main/views/invites.py +++ b/app/main/views/invites.py @@ -3,7 +3,8 @@ from flask import ( url_for, session, abort, - render_template + render_template, + flash ) from notifications_python_client.errors import HTTPError @@ -20,8 +21,8 @@ from app import ( def accept_invite(token): try: - invited_user = invite_api_client.check_token(token) + if invited_user.status == 'cancelled': from_user = user_api_client.get_user(invited_user.from_user) service = get_service_by_id_or_404(invited_user.service) @@ -29,6 +30,11 @@ def accept_invite(token): from_user=from_user.name, service_name=service['name']) + if invited_user.status == 'accepted': + session.pop('invited_user', None) + flash('You have already accepted this invitation', 'default') + return redirect(url_for('main.service_dashboard', service_id=invited_user.service)) + existing_user = user_api_client.get_user_by_email(invited_user.email_address) session['invited_user'] = invited_user.serialize() @@ -43,6 +49,7 @@ def accept_invite(token): return redirect(url_for('main.register_from_invite')) except HTTPError as e: + if e.status_code == 404: abort(404) else: diff --git a/tests/app/main/views/test_accept_invite.py b/tests/app/main/views/test_accept_invite.py index 3e48e1f73..eaa796198 100644 --- a/tests/app/main/views/test_accept_invite.py +++ b/tests/app/main/views/test_accept_invite.py @@ -3,6 +3,8 @@ from flask import url_for from bs4 import BeautifulSoup import app + +from app.notify_client.models import InvitedUser from tests.conftest import sample_invite as create_sample_invite from tests.conftest import mock_check_invite_token as mock_check_token_invite @@ -34,6 +36,25 @@ def test_existing_user_accept_invite_calls_api_and_redirects_to_dashboard(app_, assert response.location == expected_redirect_location +def test_existing_user_cant_accept_twice(app_, + mocker, + sample_invite): + + sample_invite['status'] = 'accepted' + invite = InvitedUser(**sample_invite) + mocker.patch('app.invite_api_client.check_token', return_value=invite) + + with app_.test_request_context(): + with app_.test_client() as client: + response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True) + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + assert page.h1.string.strip() == 'Sign in' + flash_banners = page.find_all('div', class_='banner-default') + assert len(flash_banners) == 2 + assert flash_banners[0].text.strip() == 'You have already accepted this invitation' + + def test_existing_signed_out_user_accept_invite_redirects_to_sign_in(app_, service_one, api_user_active,