88"""
99
1010import logging
11- from typing import Any
11+ from typing import TYPE_CHECKING
1212
1313from allauth .mfa .adapter import get_adapter as get_mfa_adapter
14+
15+ if TYPE_CHECKING :
16+ from django .contrib .auth .models import AbstractUser
1417from asgiref .sync import sync_to_async
1518from django .conf import settings
1619from django .contrib import messages
@@ -73,7 +76,7 @@ def _is_static_request(self, request: HttpRequest) -> bool:
7376
7477 return request .path .startswith ((static_url , media_url ))
7578
76- def _user_has_2fa (self , user : Any ) -> bool :
79+ def _user_has_2fa (self , user : "AbstractUser" ) -> bool :
7780 """Check if user has 2FA enabled."""
7881 mfa_adapter = get_mfa_adapter ()
7982 return mfa_adapter .is_mfa_enabled (user )
@@ -90,9 +93,9 @@ def _is_exempt_url(self, request: HttpRequest) -> bool:
9093 # Can't resolve = probably 404 = let it through
9194 security_logger .debug ("2FA: path %s doesn't resolve, allowing" , request .path )
9295 return True
93- except Exception as e :
96+ except Exception as resolution_error : # noqa: BLE001
9497 # Unexpected error during resolution - log and don't exempt
95- security_logger .warning ("2FA: error resolving path %s: %s" , request .path , str (e ))
98+ security_logger .warning ("2FA: error resolving path %s: %s" , request .path , str (resolution_error ))
9699 return False
97100
98101 # Check by URL name
@@ -109,28 +112,55 @@ def _is_exempt_url(self, request: HttpRequest) -> bool:
109112
110113 return False
111114
112- # Sync version
113- def __call__ (self , request : HttpRequest ) -> HttpResponse :
114- """Process the request and enforce 2FA if required."""
115+ def _should_enforce_2fa (self , request : HttpRequest ) -> bool :
116+ """Check if 2FA should be enforced for this request."""
115117 # Skip static/media files
116118 if self ._is_static_request (request ):
117- return self . get_response ( request )
119+ return False
118120
119121 # Skip if user not authenticated
120122 if not request .user .is_authenticated :
121- return self . get_response ( request )
123+ return False
122124
123125 # Skip exempt URLs
124126 if self ._is_exempt_url (request ):
125- return self . get_response ( request )
127+ return False
126128
127129 # Check if 2FA is required by site configuration
128130 site_config = SiteConfiguration .objects .get ()
129131 if not site_config .required_2fa :
130- return self . get_response ( request )
132+ return False
131133
132134 # Check if user has 2FA
133- if self ._user_has_2fa (request .user ):
135+ return not self ._user_has_2fa (request .user )
136+
137+ async def _should_enforce_2fa_async (self , request : HttpRequest ) -> bool :
138+ """Async version: Check if 2FA should be enforced for this request."""
139+ # Skip static/media files
140+ if self ._is_static_request (request ):
141+ return False
142+
143+ # Skip if user not authenticated
144+ if not request .user .is_authenticated :
145+ return False
146+
147+ # Skip exempt URLs
148+ if self ._is_exempt_url (request ):
149+ return False
150+
151+ # Check if 2FA is required by site configuration
152+ site_config = await sync_to_async (SiteConfiguration .objects .get )()
153+ if not site_config .required_2fa :
154+ return False
155+
156+ # Check if user has 2FA
157+ has_2fa = await sync_to_async (self ._user_has_2fa )(request .user )
158+ return not has_2fa
159+
160+ # Sync version
161+ def __call__ (self , request : HttpRequest ) -> HttpResponse :
162+ """Process the request and enforce 2FA if required."""
163+ if not self ._should_enforce_2fa (request ):
134164 return self .get_response (request )
135165
136166 # User needs 2FA - log and redirect
@@ -150,26 +180,7 @@ def __call__(self, request: HttpRequest) -> HttpResponse:
150180 # Async version
151181 async def __acall__ (self , request : HttpRequest ) -> HttpResponse :
152182 """Process the request and enforce 2FA if required."""
153- # Skip static/media files
154- if self ._is_static_request (request ):
155- return await self .get_response (request )
156-
157- # Skip if user not authenticated
158- if not request .user .is_authenticated :
159- return await self .get_response (request )
160-
161- # Skip exempt URLs
162- if self ._is_exempt_url (request ):
163- return await self .get_response (request )
164-
165- # Check if 2FA is required by site configuration
166- site_config = await sync_to_async (SiteConfiguration .objects .get )()
167- if not site_config .required_2fa :
168- return await self .get_response (request )
169-
170- # Check if user has 2FA
171- has_2fa = await sync_to_async (self ._user_has_2fa )(request .user )
172- if has_2fa :
183+ if not await self ._should_enforce_2fa_async (request ):
173184 return await self .get_response (request )
174185
175186 # User needs 2FA - log and redirect
0 commit comments