Skip to content

Commit

Permalink
Log out before accepting an invitation
Browse files Browse the repository at this point in the history
If a user is already logged in, then accepting an invitation by clicking
on the invitation link would lead to weird behaviour. Instead of
displaying the sign-up page as expected, the user may be redirected to
another page. The invitation may still be accepted though, leaving to an
undesired state where the invitation is accepted, but the new user
account has not been created.

For these reasons, it is best to log out any existing user sesion before
accepting an invitation and displaying the sign-up page.
  • Loading branch information
Flimm committed Jun 12, 2024
1 parent 3583738 commit f52c37c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 1 deletion.
10 changes: 9 additions & 1 deletion invitations/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json

from django.contrib import messages
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth import REDIRECT_FIELD_NAME, logout
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
Expand Down Expand Up @@ -150,6 +150,7 @@ def post(self, *args, **kwargs):
# The invitation was previously accepted, redirect to the login
# view.
if invitation.accepted:
logout(self.request) # prepare for redirection to login page
get_invitations_adapter().add_message(
self.request,
messages.ERROR,
Expand All @@ -161,6 +162,7 @@ def post(self, *args, **kwargs):

# The key was expired.
if invitation.key_expired():
logout(self.request) # prepare for redirection to signup page
get_invitations_adapter().add_message(
self.request,
messages.ERROR,
Expand All @@ -171,6 +173,12 @@ def post(self, *args, **kwargs):
return HttpResponseRedirect(self.get_signup_redirect())

# The invitation is valid.

# Log out (if logged in) and clear session. Do this in order to prevent
# user confusion and to ensure that the sign up page is displayed
# correctly
logout(self.request)

# Mark it as accepted now if ACCEPT_INVITE_AFTER_SIGNUP is False.
if not app_settings.ACCEPT_INVITE_AFTER_SIGNUP:
accept_invitation(
Expand Down
24 changes: 24 additions & 0 deletions tests/allauth/test_allauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,30 @@ def test_accept_already_accepted_invite_with_login_redirect(
resp.url == f"{app_settings.LOGIN_REDIRECT}?{REDIRECT_FIELD_NAME}={next_}"
)

@pytest.mark.django_db
@pytest.mark.parametrize(
"method",
[
("get"),
("post"),
],
)
def test_accept_inviter_logged_in(
self, settings, sent_invitation_by_user_a, method
):
assert self.client.login(username="flibble", password="password")
admin_resp = self.client.get(reverse("admin:index"), follow=True)
assert admin_resp.wsgi_request.user.is_authenticated

client_with_method = getattr(self.client, method)
resp = client_with_method(
reverse(
app_settings.CONFIRMATION_URL_NAME,
kwargs={"key": sent_invitation_by_user_a.key},
)
)
assert not resp.wsgi_request.user.is_authenticated

def test_fetch_adapter(self):
assert isinstance(self.adapter, InvitationsAdapter)

Expand Down
25 changes: 25 additions & 0 deletions tests/basic/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,31 @@ def test_accept_invite(self, settings, sent_invitation_by_user_a, user_a, method
assert invite.inviter == user_a
assert resp.request["PATH_INFO"] == "/non-existent-url/"

@pytest.mark.parametrize(
"method",
[
("get"),
("post"),
],
)
def test_accept_invite_when_logged_in(
self, settings, sent_invitation_by_user_a, method
):
assert self.client.login(username="flibble", password="password")
admin_resp = self.client.get(reverse("admin:index"), follow=True)
assert admin_resp.wsgi_request.user.is_authenticated

settings.INVITATIONS_SIGNUP_REDIRECT = "/non-existent-url/"
client_with_method = getattr(self.client, method)
resp = client_with_method(
reverse(
app_settings.CONFIRMATION_URL_NAME,
kwargs={"key": sent_invitation_by_user_a.key},
),
follow=True,
)
assert not resp.wsgi_request.user.is_authenticated

def test_signup_redirect(self, settings, sent_invitation_by_user_a):
settings.INVITATIONS_SIGNUP_REDIRECT = "/non-existent-url/"
resp = self.client.post(
Expand Down

0 comments on commit f52c37c

Please sign in to comment.