move invite error handler to top level

ensure we catch org errors as well as regular errors
This commit is contained in:
Leo Hemsted
2020-03-06 11:53:55 +00:00
parent be48f3bac5
commit 2d8d2d712a
5 changed files with 20 additions and 14 deletions

View File

@@ -13,6 +13,7 @@ from flask import (
flash, flash,
g, g,
make_response, make_response,
redirect,
render_template, render_template,
request, request,
session, session,
@@ -59,6 +60,7 @@ from app.navigation import (
MainNavigation, MainNavigation,
OrgNavigation, OrgNavigation,
) )
from app.notify_client import InviteTokenError
from app.notify_client.api_key_api_client import api_key_api_client from app.notify_client.api_key_api_client import api_key_api_client
from app.notify_client.billing_api_client import billing_api_client from app.notify_client.billing_api_client import billing_api_client
from app.notify_client.complaint_api_client import complaint_api_client from app.notify_client.complaint_api_client import complaint_api_client
@@ -702,6 +704,11 @@ def register_errorhandlers(application): # noqa (C901 too complex)
return _error_response(error.code) return _error_response(error.code)
@application.errorhandler(InviteTokenError)
def handle_bad_invite_token(error):
flash(str(error))
return redirect(url_for('main.sign_in'))
@application.errorhandler(500) @application.errorhandler(500)
@application.errorhandler(Exception) @application.errorhandler(Exception)
def handle_bad_request(error): def handle_bad_request(error):

View File

@@ -4,6 +4,7 @@ from itertools import chain
import pytz import pytz
from flask import request from flask import request
from flask_login import current_user
from flask_wtf import FlaskForm as Form from flask_wtf import FlaskForm as Form
from flask_wtf.file import FileAllowed from flask_wtf.file import FileAllowed
from flask_wtf.file import FileField as FileField_wtf from flask_wtf.file import FileField as FileField_wtf
@@ -500,7 +501,7 @@ class InviteUserForm(PermissionsForm):
self.invalid_email_address = invalid_email_address.lower() self.invalid_email_address = invalid_email_address.lower()
def validate_email_address(self, field): def validate_email_address(self, field):
if field.data.lower() == self.invalid_email_address: if field.data.lower() == self.invalid_email_address and not current_user.platform_admin:
raise ValidationError("You cannot send an invitation to yourself") raise ValidationError("You cannot send an invitation to yourself")
@@ -512,7 +513,7 @@ class InviteOrgUserForm(StripWhitespaceForm):
self.invalid_email_address = invalid_email_address.lower() self.invalid_email_address = invalid_email_address.lower()
def validate_email_address(self, field): def validate_email_address(self, field):
if field.data.lower() == self.invalid_email_address: if field.data.lower() == self.invalid_email_address and not current_user.platform_admin:
raise ValidationError("You cannot send an invitation to yourself") raise ValidationError("You cannot send an invitation to yourself")

View File

@@ -12,16 +12,11 @@ from app.models.user import (
User, User,
Users, Users,
) )
from app.notify_client import InviteTokenError
@main.route("/invitation/<token>") @main.route("/invitation/<token>")
def accept_invite(token): def accept_invite(token):
try: invited_user = InvitedUser.from_token(token)
invited_user = InvitedUser.from_token(token)
except InviteTokenError as exception:
flash(str(exception))
return redirect(url_for('main.sign_in'))
if not current_user.is_anonymous and current_user.email_address.lower() != invited_user.email_address.lower(): if not current_user.is_anonymous and current_user.email_address.lower() != invited_user.email_address.lower():
message = Markup(""" message = Markup("""
@@ -78,6 +73,7 @@ def accept_invite(token):
@main.route("/organisation-invitation/<token>") @main.route("/organisation-invitation/<token>")
def accept_org_invite(token): def accept_org_invite(token):
invited_org_user = InvitedOrgUser.from_token(token) invited_org_user = InvitedOrgUser.from_token(token)
if not current_user.is_anonymous and current_user.email_address.lower() != invited_org_user.email_address.lower(): if not current_user.is_anonymous and current_user.email_address.lower() != invited_org_user.email_address.lower():
message = Markup(""" message = Markup("""
Youre signed in as {}. Youre signed in as {}.

View File

@@ -77,7 +77,3 @@ class ModelList(ABC, Sequence):
def __radd__(self, other): def __radd__(self, other):
return list(other) + list(self) return list(other) + list(self)
class InviteTokenError(Exception):
pass

View File

@@ -308,12 +308,18 @@ def test_cancelled_invited_user_accepts_invited_redirect_to_cancelled_invitation
assert page.h1.string.strip() == 'The invitation you were sent has been cancelled' assert page.h1.string.strip() == 'The invitation you were sent has been cancelled'
@pytest.mark.parametrize('admin_endpoint, api_endpoint', [
('main.accept_invite', 'app.invite_api_client.check_token'),
('main.accept_org_invite', 'app.org_invite_api_client.check_token'),
])
def test_new_user_accept_invite_with_malformed_token( def test_new_user_accept_invite_with_malformed_token(
admin_endpoint,
api_endpoint,
client, client,
service_one, service_one,
mocker, mocker,
): ):
mocker.patch('app.invite_api_client.check_token', side_effect=HTTPError( mocker.patch(api_endpoint, side_effect=HTTPError(
response=Mock( response=Mock(
status_code=400, status_code=400,
json={ json={
@@ -328,7 +334,7 @@ def test_new_user_accept_invite_with_malformed_token(
message={'invitation': 'Somethings wrong with this link. Make sure youve copied the whole thing.'} message={'invitation': 'Somethings wrong with this link. Make sure youve copied the whole thing.'}
)) ))
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True) response = client.get(url_for(admin_endpoint, token='thisisnotarealtoken'), follow_redirects=True)
assert response.status_code == 200 assert response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')