Coverage for baibu/users/adapters.py: 100%

40 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-10-06 13:07 +0000

1from allauth.account.adapter import DefaultAccountAdapter 

2from django.conf import settings 

3from django.contrib import messages 

4from django.db import transaction 

5from django.http import HttpRequest 

6from django.template.loader import render_to_string 

7from django.utils.translation import gettext 

8 

9from . import messaging 

10from .models import User 

11from .phone import normalize_phone 

12 

13 

14class AccountAdapter(DefaultAccountAdapter): 

15 def is_open_for_signup(self, request: HttpRequest) -> bool: 

16 return settings.ACCOUNT_ALLOW_REGISTRATION 

17 

18 # Phone sign-in. allauth only calls these when PHONE_SIGN_IN_ENABLED puts 

19 # "phone" in ACCOUNT_LOGIN_METHODS and ACCOUNT_SIGNUP_FIELDS. 

20 

21 def phone_form_field(self, **kwargs): 

22 from .forms import PhoneNumberField 

23 

24 return PhoneNumberField(**kwargs) 

25 

26 def get_phone(self, user: User) -> tuple[str, bool] | None: 

27 return (user.phone, user.phone_verified) if user.phone else None 

28 

29 def set_phone(self, user: User, phone: str, verified: bool) -> None: # noqa: FBT001 

30 if verified: 

31 self.set_phone_verified(user, phone) 

32 return 

33 user.phone = phone 

34 user.phone_verified = False 

35 user.save(update_fields=["phone", "phone_verified"]) 

36 

37 def set_phone_verified(self, user: User, phone: str) -> None: 

38 with transaction.atomic(): 

39 # Someone else may have typed this number without verifying it. 

40 User.objects.filter(phone=phone, phone_verified=False).exclude(pk=user.pk).update(phone=None) 

41 user.phone = phone 

42 user.phone_verified = True 

43 user.save(update_fields=["phone", "phone_verified"]) 

44 

45 def get_user_by_phone(self, phone: str) -> User | None: 

46 # Only a verified number identifies an account. Sign-in with a password 

47 # passes the number as typed, so normalise it here too. 

48 return User.objects.filter(phone=normalize_phone(phone), phone_verified=True).first() 

49 

50 def send_verification_code_sms(self, user: User, phone: str, code: str, **kwargs) -> None: 

51 text = render_to_string( 

52 "users/messages/verification_code.txt", 

53 {"code": code, "user": user, "platform_name": settings.PLATFORM_NAME}, 

54 request=self.request, 

55 ).strip() 

56 try: 

57 messaging.send_text(phone, text) 

58 except messaging.MessagingError: 

59 if self.request is not None: 

60 messages.error( 

61 self.request, 

62 gettext("We could not send a text message to that number. Please try again later."), 

63 )