I proceeded with Phase 1 step 1 (phone-first auth + OTP hardening) and updated the plan context. Here’s the current state and the next steps.
What I implemented Phone-first auth endpoints with OTP → JWT issuance. views.py urls.py Phone normalization (KSA-focused, E.164 or Saudi mobile) and validation. phone.py serializers.py OTP protections: rate limit, resend cooldown, attempt counting. otp.py models.py Email is now optional to allow phone-only users. models.py 0002_phone_auth_fields.py Admin OTP visibility improved. admin.py Risks updated. risks.md
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import re
|
||||
|
||||
|
||||
def normalize_phone_number(raw_phone: str) -> str:
|
||||
if not raw_phone:
|
||||
raise ValueError("Phone number is required")
|
||||
|
||||
phone = re.sub(r"[\s\-\(\)]", "", raw_phone)
|
||||
if phone.startswith("00"):
|
||||
phone = "+" + phone[2:]
|
||||
|
||||
if phone.startswith("+"):
|
||||
digits = phone[1:]
|
||||
if not digits.isdigit() or not (8 <= len(digits) <= 15):
|
||||
raise ValueError("Invalid phone number format")
|
||||
return "+" + digits
|
||||
|
||||
digits = re.sub(r"\D", "", phone)
|
||||
|
||||
if digits.startswith("0") and len(digits) == 10 and digits[1] == "5":
|
||||
return "+966" + digits[1:]
|
||||
|
||||
if digits.startswith("5") and len(digits) == 9:
|
||||
return "+966" + digits
|
||||
|
||||
raise ValueError("Phone number must be in E.164 format or a valid Saudi mobile")
|
||||
Reference in New Issue
Block a user