Skip to content

Commit 2baf0c0

Browse files
committed
refactor(account): Extract login
1 parent e29d02b commit 2baf0c0

File tree

8 files changed

+93
-81
lines changed

8 files changed

+93
-81
lines changed

allauth/account/authentication.py

+4
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,7 @@ def record_authentication(request, method, **extra_data):
3838
}
3939
methods.append(data)
4040
request.session[AUTHENTICATION_METHODS_SESSION_KEY] = methods
41+
42+
43+
def get_authentication_records(request):
44+
return request.session.get(AUTHENTICATION_METHODS_SESSION_KEY, [])

allauth/account/forms.py

+4-12
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from django.utils.safestring import mark_safe
99
from django.utils.translation import gettext, gettext_lazy as _, pgettext
1010

11-
from allauth.account.authentication import record_authentication
1211
from allauth.account.internal import flows
1312

1413
from ..utils import (
@@ -19,12 +18,11 @@
1918
from . import app_settings
2019
from .adapter import get_adapter
2120
from .app_settings import AuthenticationMethod
22-
from .models import EmailAddress
21+
from .models import EmailAddress, Login
2322
from .utils import (
2423
assess_unique_email,
2524
filter_users_by_email,
2625
get_user_model,
27-
perform_login,
2826
setup_user_email,
2927
sync_user_email_addresses,
3028
url_str_to_user_pk,
@@ -202,18 +200,12 @@ def clean(self):
202200

203201
def login(self, request, redirect_url=None):
204202
credentials = self.user_credentials()
205-
extra_data = {
206-
field: credentials.get(field)
207-
for field in ["email", "username"]
208-
if field in credentials
209-
}
210-
record_authentication(request, method="password", **extra_data)
211-
ret = perform_login(
212-
request,
213-
self.user,
203+
login = Login(
204+
user=self.user,
214205
redirect_url=redirect_url,
215206
email=credentials.get("email"),
216207
)
208+
ret = flows.login.perform_password_login(request, credentials, login)
217209
remember = app_settings.SESSION_REMEMBER
218210
if remember is None:
219211
remember = self.cleaned_data["remember"]
+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
from allauth.account.internal.flows import password_change, password_reset
1+
from allauth.account.internal.flows import (
2+
login,
3+
password_change,
4+
password_reset,
5+
)
26

37

4-
__all__ = ["password_reset", "password_change"]
8+
__all__ = ["password_reset", "password_change", "login"]
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from allauth.account.adapter import get_adapter
2+
from allauth.account.authentication import record_authentication
3+
from allauth.core.exceptions import ImmediateHttpResponse
4+
5+
6+
def _get_login_hook_kwargs(login):
7+
"""
8+
TODO: Just break backwards compatibility and pass only `login` to
9+
`pre/post_login()`.
10+
"""
11+
return dict(
12+
email_verification=login.email_verification,
13+
redirect_url=login.redirect_url,
14+
signal_kwargs=login.signal_kwargs,
15+
signup=login.signup,
16+
email=login.email,
17+
)
18+
19+
20+
def perform_password_login(request, credentials, login):
21+
extra_data = {
22+
field: credentials.get(field)
23+
for field in ["email", "username"]
24+
if credentials.get(field)
25+
}
26+
record_authentication(request, method="password", **extra_data)
27+
return perform_login(request, login)
28+
29+
30+
def perform_login(request, login):
31+
adapter = get_adapter()
32+
hook_kwargs = _get_login_hook_kwargs(login)
33+
response = adapter.pre_login(request, login.user, **hook_kwargs)
34+
if response:
35+
return response
36+
return resume_login(request, login)
37+
38+
39+
def resume_login(request, login):
40+
from allauth.account.stages import LoginStageController
41+
42+
adapter = get_adapter()
43+
ctrl = LoginStageController(request, login)
44+
try:
45+
response = ctrl.handle()
46+
if response:
47+
return response
48+
adapter.login(request, login.user)
49+
hook_kwargs = _get_login_hook_kwargs(login)
50+
response = adapter.post_login(request, login.user, **hook_kwargs)
51+
if response:
52+
return response
53+
except ImmediateHttpResponse as e:
54+
response = e.response
55+
return response

allauth/account/internal/flows/password_change.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from django.contrib import messages
2+
from django.contrib.auth import update_session_auth_hash
23

3-
from allauth.account import signals
4+
from allauth.account import app_settings, signals
45
from allauth.account.adapter import get_adapter
5-
from allauth.account.utils import logout_on_password_change
66

77

88
def change_password(user, password):
@@ -35,3 +35,11 @@ def finalize_password_set(request, user):
3535
request=request,
3636
user=user,
3737
)
38+
39+
40+
def logout_on_password_change(request, user):
41+
# Since it is the default behavior of Django to invalidate all sessions on
42+
# password change, this function actually has to preserve the session when
43+
# logout isn't desired.
44+
if not app_settings.LOGOUT_ON_PASSWORD_CHANGE:
45+
update_session_auth_hash(request, user)

allauth/account/models.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -209,19 +209,27 @@ def from_key(cls, key):
209209
class Login:
210210
"""
211211
Represents a user that is in the process of logging in.
212+
213+
Keyword arguments:
214+
215+
signup -- Indicates whether or not sending the
216+
email is essential (during signup), or if it can be skipped (e.g. in
217+
case email verification is optional and we are only logging in).
212218
"""
213219

214220
def __init__(
215221
self,
216222
user,
217-
email_verification,
223+
email_verification=None,
218224
redirect_url=None,
219225
signal_kwargs=None,
220226
signup=False,
221227
email=None,
222228
state=None,
223229
):
224230
self.user = user
231+
if not email_verification:
232+
email_verification = app_settings.EMAIL_VERIFICATION
225233
self.email_verification = email_verification
226234
self.redirect_url = redirect_url
227235
self.signal_kwargs = signal_kwargs

allauth/account/utils.py

+4-63
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from django.conf import settings
66
from django.contrib import messages
7-
from django.contrib.auth import get_user_model, update_session_auth_hash
7+
from django.contrib.auth import get_user_model
88
from django.core.exceptions import FieldDoesNotExist
99
from django.db import models
1010
from django.db.models import Q
@@ -13,8 +13,8 @@
1313

1414
from allauth.account import app_settings, signals
1515
from allauth.account.adapter import get_adapter
16+
from allauth.account.internal import flows
1617
from allauth.account.models import Login
17-
from allauth.core.exceptions import ImmediateHttpResponse
1818
from allauth.utils import (
1919
get_request_param,
2020
import_callable,
@@ -63,14 +63,6 @@ def get_login_redirect_url(request, url=None, redirect_field_name="next", signup
6363
_user_display_callable = None
6464

6565

66-
def logout_on_password_change(request, user):
67-
# Since it is the default behavior of Django to invalidate all sessions on
68-
# password change, this function actually has to preserve the session when
69-
# logout isn't desired.
70-
if not app_settings.LOGOUT_ON_PASSWORD_CHANGE:
71-
update_session_auth_hash(request, user)
72-
73-
7466
def default_user_display(user):
7567
if app_settings.USER_MODEL_USERNAME_FIELD:
7668
return getattr(user, app_settings.USER_MODEL_USERNAME_FIELD)
@@ -148,15 +140,6 @@ def perform_login(
148140
signup=False,
149141
email=None,
150142
):
151-
"""
152-
Keyword arguments:
153-
154-
signup -- Indicates whether or not sending the
155-
email is essential (during signup), or if it can be skipped (e.g. in
156-
case email verification is optional and we are only logging in).
157-
"""
158-
if not email_verification:
159-
email_verification = app_settings.EMAIL_VERIFICATION
160143
login = Login(
161144
user=user,
162145
email_verification=email_verification,
@@ -165,53 +148,11 @@ def perform_login(
165148
signup=signup,
166149
email=email,
167150
)
168-
return _perform_login(request, login)
169-
170-
171-
def _perform_login(request, login):
172-
# Local users are stopped due to form validation checking
173-
# is_active, yet, adapter methods could toy with is_active in a
174-
# `user_signed_up` signal. Furthermore, social users should be
175-
# stopped anyway.
176-
adapter = get_adapter()
177-
hook_kwargs = _get_login_hook_kwargs(login)
178-
response = adapter.pre_login(request, login.user, **hook_kwargs)
179-
if response:
180-
return response
181-
return resume_login(request, login)
182-
183-
184-
def _get_login_hook_kwargs(login):
185-
"""
186-
TODO: Just break backwards compatibility and pass only `login` to
187-
`pre/post_login()`.
188-
"""
189-
return dict(
190-
email_verification=login.email_verification,
191-
redirect_url=login.redirect_url,
192-
signal_kwargs=login.signal_kwargs,
193-
signup=login.signup,
194-
email=login.email,
195-
)
151+
return flows.login.perform_login(request, login)
196152

197153

198154
def resume_login(request, login):
199-
from allauth.account.stages import LoginStageController
200-
201-
adapter = get_adapter()
202-
ctrl = LoginStageController(request, login)
203-
try:
204-
response = ctrl.handle()
205-
if response:
206-
return response
207-
adapter.login(request, login.user)
208-
hook_kwargs = _get_login_hook_kwargs(login)
209-
response = adapter.post_login(request, login.user, **hook_kwargs)
210-
if response:
211-
return response
212-
except ImmediateHttpResponse as e:
213-
response = e.response
214-
return response
155+
return flows.login.resume_login(request, login)
215156

216157

217158
def unstash_login(request, peek=False):

allauth/socialaccount/helpers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def record_authentication(request, sociallogin):
106106

107107
def _login_social_account(request, sociallogin):
108108
sociallogin._accept_login()
109+
record_authentication(request, sociallogin)
109110
return perform_login(
110111
request,
111112
sociallogin.user,
@@ -232,7 +233,6 @@ def _complete_social_login(request, sociallogin):
232233
if request.user.is_authenticated:
233234
get_account_adapter(request).logout(request)
234235
if sociallogin.is_existing:
235-
record_authentication(request, sociallogin)
236236
# Login existing user
237237
ret = _login_social_account(request, sociallogin)
238238
else:

0 commit comments

Comments
 (0)