From 8018710d31ca59709df8b83c241155744c623d3f Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 1 Mar 2026 23:58:02 +0300 Subject: [PATCH] fix: use phone_number as USERNAME_FIELD on User model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - USERNAME_FIELD = "phone_number" (was "email") — email is optional on this platform; most customers will be phone-only - Add REQUIRED_FIELDS = [] to make the intent explicit - Update create_superuser to accept phone_number as the identifier and pass it through to create_user as a keyword argument - All 35 backend tests pass Co-Authored-By: Claude Sonnet 4.6 --- backend/apps/accounts/models.py | 7 ++++--- docs/risks.md | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/apps/accounts/models.py b/backend/apps/accounts/models.py index c451775..1a45202 100644 --- a/backend/apps/accounts/models.py +++ b/backend/apps/accounts/models.py @@ -29,7 +29,7 @@ class UserManager(BaseUserManager): user.save(using=self._db) return user - def create_superuser(self, email, password=None, **extra_fields): + def create_superuser(self, phone_number, password=None, **extra_fields): extra_fields.setdefault("is_staff", True) extra_fields.setdefault("is_superuser", True) extra_fields.setdefault("role", UserRole.ADMIN) @@ -37,7 +37,7 @@ class UserManager(BaseUserManager): raise ValueError("Superuser must have is_staff=True") if extra_fields.get("is_superuser") is not True: raise ValueError("Superuser must have is_superuser=True") - return self.create_user(email, password, **extra_fields) + return self.create_user(phone_number=phone_number, password=password, **extra_fields) class User(AbstractBaseUser, PermissionsMixin): @@ -59,7 +59,8 @@ class User(AbstractBaseUser, PermissionsMixin): objects = UserManager() - USERNAME_FIELD = "email" + USERNAME_FIELD = "phone_number" + REQUIRED_FIELDS = [] # email is optional; phone_number is the identifier def __str__(self): return self.email or self.phone_number or str(self.id) diff --git a/docs/risks.md b/docs/risks.md index 69fe7eb..c56cd40 100644 --- a/docs/risks.md +++ b/docs/risks.md @@ -7,7 +7,7 @@ This file tracks known gaps and risks to address in future iterations. - OTP protections are basic; add device fingerprinting and IP throttling if needed. - Authentica OTP provider is implemented (SMS + WhatsApp via Authentica OTP); Unifonic remains a scaffold. - Social login is a placeholder. -- `USERNAME_FIELD = "email"` while `email` is nullable — concrete impact: Django admin user list shows blank for most customers (phone-only users); `create_superuser` requires email by default; DRF Simple JWT uses email as the lookup field. Fix: change `USERNAME_FIELD` to `"phone_number"` and update `UserManager.create_superuser` accordingly. +- `USERNAME_FIELD` is now `"phone_number"`; `REQUIRED_FIELDS = []`; `create_superuser` accepts `phone_number`. Admin and `createsuperuser` work correctly for phone-only users. ## Booking Integrity - Availability checks and overlap prevention are now enforced for staff bookings.