diff --git a/data/model/legacy.py b/data/model/legacy.py index 3df2669aa..ccc893d99 100644 --- a/data/model/legacy.py +++ b/data/model/legacy.py @@ -1988,6 +1988,12 @@ def delete_team_invite(code, user=None): def confirm_team_invite(code, user): found = lookup_team_invite(code) + # If the invite is for a specific user, we have to confirm that here. + if found.user is not None and found.user != user: + message = """This invite is intended for user "%s". + Please login to that account and try again.""" % found.user.username + raise DataModelException(message) + # Add the user to the team. try: add_user_to_team(user, found.team) diff --git a/endpoints/api/team.py b/endpoints/api/team.py index 24243f911..a1c687af9 100644 --- a/endpoints/api/team.py +++ b/endpoints/api/team.py @@ -11,10 +11,7 @@ from util.useremails import send_org_invite_email from util.gravatar import compute_hash def try_accept_invite(code, user): - try: - (team, inviter) = model.confirm_team_invite(code, user) - except model.DataModelException: - return None + (team, inviter) = model.confirm_team_invite(code, user) model.delete_matching_notifications(user, 'org_team_invite', code=code) @@ -355,10 +352,7 @@ class TeamMemberInvite(ApiResource): @require_user_admin def delete(self, code): """ Delete an existing member of a team. """ - try: - (team, inviter) = model.delete_team_invite(code, get_authenticated_user()) - except model.DataModelException: - raise NotFound() + (team, inviter) = model.delete_team_invite(code, get_authenticated_user()) model.delete_matching_notifications(get_authenticated_user(), 'org_team_invite', code=code) diff --git a/endpoints/api/user.py b/endpoints/api/user.py index 0ba8a8db6..fc8fdb0a3 100644 --- a/endpoints/api/user.py +++ b/endpoints/api/user.py @@ -215,7 +215,10 @@ class User(ApiResource): if parsed_invite is not None: if parsed_invite[0] == 'teaminvite': # Add the user to the team. - try_accept_invite(invite_code, new_user) + try: + try_accept_invite(invite_code, new_user) + except model.DataModelException: + pass return 'Created', 201 except model.TooManyUsersException as ex: diff --git a/static/js/controllers.js b/static/js/controllers.js index ef0b16223..e37abc333 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -2785,9 +2785,9 @@ function ConfirmInviteCtrl($scope, $location, UserService, ApiService, Notificat ApiService.acceptOrganizationTeamInvite(null, params).then(function(resp) { NotificationService.update(); $location.path('/organization/' + resp.org + '/teams/' + resp.team); - }, function() { + }, function(resp) { $scope.loading = false; - $scope.invalid = true; + $scope.invalid = ApiService.getErrorMessage(resp, 'Invalid confirmation code'); }); } }); diff --git a/static/partials/confirm-invite.html b/static/partials/confirm-invite.html index 64f116fb1..e3d883e53 100644 --- a/static/partials/confirm-invite.html +++ b/static/partials/confirm-invite.html @@ -7,7 +7,7 @@
- Invalid confirmation code + {{ invalid }}
diff --git a/test/test_api_security.py b/test/test_api_security.py index a3f3ea63a..230be1153 100644 --- a/test/test_api_security.py +++ b/test/test_api_security.py @@ -3518,25 +3518,25 @@ class TestTeamMemberInvite(ApiTestCase): self._run_test('PUT', 401, None, None) def test_put_freshuser(self): - self._run_test('PUT', 404, 'freshuser', None) + self._run_test('PUT', 400, 'freshuser', None) def test_put_reader(self): - self._run_test('PUT', 404, 'reader', None) + self._run_test('PUT', 400, 'reader', None) def test_put_devtable(self): - self._run_test('PUT', 404, 'devtable', None) + self._run_test('PUT', 400, 'devtable', None) def test_delete_anonymous(self): self._run_test('DELETE', 401, None, None) def test_delete_freshuser(self): - self._run_test('DELETE', 404, 'freshuser', None) + self._run_test('DELETE', 400, 'freshuser', None) def test_delete_reader(self): - self._run_test('DELETE', 404, 'reader', None) + self._run_test('DELETE', 400, 'reader', None) def test_delete_devtable(self): - self._run_test('DELETE', 404, 'devtable', None) + self._run_test('DELETE', 400, 'devtable', None) class TestSuperUserList(ApiTestCase): diff --git a/test/test_api_usage.py b/test/test_api_usage.py index 5c3cf7cf1..4a9f1fbdc 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -891,7 +891,7 @@ class TestAcceptTeamMemberInvite(ApiTestCase): # Verify the accept now fails. self.putResponse(TeamMemberInvite, params=dict(code=invites[0].invite_token), - expected_code=404) + expected_code=400) @@ -914,7 +914,7 @@ class TestDeclineTeamMemberInvite(ApiTestCase): self.deleteResponse(TeamMemberInvite, params=dict(code=invites[0].invite_token), - expected_code=404) + expected_code=400) def test_decline(self): @@ -942,7 +942,7 @@ class TestDeclineTeamMemberInvite(ApiTestCase): # Make sure the invite was deleted. self.deleteResponse(TeamMemberInvite, params=dict(code=invites[0].invite_token), - expected_code=404) + expected_code=400) class TestDeleteOrganizationTeamMember(ApiTestCase):