- {/* Username */}
+ {/* Email */}
-
diff --git a/smoothschedule/schedule/serializers.py b/smoothschedule/schedule/serializers.py
index 9b8f5eb..9d4ae39 100644
--- a/smoothschedule/schedule/serializers.py
+++ b/smoothschedule/schedule/serializers.py
@@ -61,21 +61,15 @@ class CustomerSerializer(serializers.ModelSerializer):
read_only_fields = ['id']
def create(self, validated_data):
- """Create a customer with auto-generated username"""
+ """Create a customer with email as username"""
import uuid
email = validated_data.get('email', '')
- # Generate username from email or use a UUID if no email
+ # Use email as username, or generate a UUID-based username if no email
if email:
- base_username = email.split('@')[0]
- username = base_username
- counter = 1
- while User.objects.filter(username=username).exists():
- username = f"{base_username}{counter}"
- counter += 1
+ validated_data['username'] = email.lower()
else:
- username = f"customer_{uuid.uuid4().hex[:8]}"
+ validated_data['username'] = f"customer_{uuid.uuid4().hex[:8]}"
- validated_data['username'] = username
return super().create(validated_data)
def get_name(self, obj):
diff --git a/smoothschedule/smoothschedule/users/api_views.py b/smoothschedule/smoothschedule/users/api_views.py
index e65a66b..5a023b7 100644
--- a/smoothschedule/smoothschedule/users/api_views.py
+++ b/smoothschedule/smoothschedule/users/api_views.py
@@ -26,7 +26,7 @@ from django_tenants.utils import schema_context
@permission_classes([AllowAny])
def login_view(request):
"""
- Login user with username/email and password.
+ Login user with email and password.
POST /api/auth/login/
If MFA is enabled:
@@ -36,25 +36,24 @@ def login_view(request):
If MFA is not enabled or device is trusted:
- Returns access/refresh tokens and user data
"""
- username = request.data.get('username', '').strip()
+ # Accept both 'email' and 'username' fields for backward compatibility
+ email = request.data.get('email', '') or request.data.get('username', '')
+ email = email.strip().lower()
password = request.data.get('password', '')
- if not username or not password:
+ if not email or not password:
return Response(
- {'error': 'Username and password are required'},
+ {'error': 'Email and password are required'},
status=status.HTTP_400_BAD_REQUEST
)
- # Authenticate user (supports username or email)
- user = authenticate(request, username=username, password=password)
-
- # If authentication with username failed, try email
- if user is None:
- try:
- user_by_email = User.objects.get(email__iexact=username)
- user = authenticate(request, username=user_by_email.username, password=password)
- except User.DoesNotExist:
- pass
+ # Look up user by email and authenticate
+ user = None
+ try:
+ user_by_email = User.objects.get(email__iexact=email)
+ user = authenticate(request, username=user_by_email.username, password=password)
+ except User.DoesNotExist:
+ pass
if user is None:
return Response(
@@ -732,20 +731,12 @@ def accept_invitation_view(request, token):
status=status.HTTP_400_BAD_REQUEST
)
- # Create the user
- username = invitation.email.split('@')[0]
- # Ensure username is unique
- base_username = username
- counter = 1
- while User.objects.filter(username=username).exists():
- username = f"{base_username}{counter}"
- counter += 1
-
+ # Create the user with email as username
# Determine sandbox mode from request (set by middleware)
is_sandbox = getattr(request, 'sandbox_mode', False)
user = User.objects.create_user(
- username=username,
+ username=invitation.email.lower(), # Use email as username
email=invitation.email,
password=password,
first_name=first_name,
@@ -1010,7 +1001,7 @@ def signup_view(request):
# 5. Create User (Owner)
user = User.objects.create_user(
- username=email.split('@')[0], # Fallback username
+ username=email, # Use email as username
email=email,
password=password,
first_name=data.get('first_name', ''),
diff --git a/smoothschedule/smoothschedule/users/management/commands/create_test_users.py b/smoothschedule/smoothschedule/users/management/commands/create_test_users.py
index b495582..95c1ef7 100644
--- a/smoothschedule/smoothschedule/users/management/commands/create_test_users.py
+++ b/smoothschedule/smoothschedule/users/management/commands/create_test_users.py
@@ -21,9 +21,9 @@ class Command(BaseCommand):
)
test_users = [
- # Platform users (no tenant)
+ # Platform users (no tenant) - username is set to email
{
- 'username': 'superuser',
+ 'username': 'superuser@platform.com',
'email': 'superuser@platform.com',
'password': 'test123',
'role': User.Role.SUPERUSER,
@@ -32,7 +32,7 @@ class Command(BaseCommand):
'tenant': None,
},
{
- 'username': 'platform_manager',
+ 'username': 'manager@platform.com',
'email': 'manager@platform.com',
'password': 'test123',
'role': User.Role.PLATFORM_MANAGER,
@@ -41,7 +41,7 @@ class Command(BaseCommand):
'tenant': None,
},
{
- 'username': 'platform_sales',
+ 'username': 'sales@platform.com',
'email': 'sales@platform.com',
'password': 'test123',
'role': User.Role.PLATFORM_SALES,
@@ -50,7 +50,7 @@ class Command(BaseCommand):
'tenant': None,
},
{
- 'username': 'platform_support',
+ 'username': 'support@platform.com',
'email': 'support@platform.com',
'password': 'test123',
'role': User.Role.PLATFORM_SUPPORT,
@@ -58,9 +58,9 @@ class Command(BaseCommand):
'last_name': 'Agent',
'tenant': None,
},
- # Tenant users (with tenant)
+ # Tenant users (with tenant) - username is set to email
{
- 'username': 'tenant_owner',
+ 'username': 'owner@demo.com',
'email': 'owner@demo.com',
'password': 'test123',
'role': User.Role.TENANT_OWNER,
@@ -69,7 +69,7 @@ class Command(BaseCommand):
'tenant': demo_tenant,
},
{
- 'username': 'tenant_manager',
+ 'username': 'manager@demo.com',
'email': 'manager@demo.com',
'password': 'test123',
'role': User.Role.TENANT_MANAGER,
@@ -78,7 +78,7 @@ class Command(BaseCommand):
'tenant': demo_tenant,
},
{
- 'username': 'tenant_staff',
+ 'username': 'staff@demo.com',
'email': 'staff@demo.com',
'password': 'test123',
'role': User.Role.TENANT_STAFF,
@@ -87,7 +87,7 @@ class Command(BaseCommand):
'tenant': demo_tenant,
},
{
- 'username': 'customer',
+ 'username': 'customer@demo.com',
'email': 'customer@demo.com',
'password': 'test123',
'role': User.Role.CUSTOMER,