MukeshKapoor25 commited on
Commit
8cd913e
·
1 Parent(s): 1017c25

feat(system_users): Add merchant_id field to user model and authentication tokens

Browse files

- Add merchant_id field to SystemUserModel to track user's associated merchant
- Include merchant_id in JWT token payload for both auth and system_users login endpoints
- Update CreateUserRequest schema to require merchant_id during user creation
- Populate merchant_id when creating new users in service layer
- Initialize all default users with merchant_id in database setup script
- Fix refresh_token endpoint to return new_access_token instead of stale access_token
- Standardize token payload structure across auth endpoints to include merchant_id
- Update initial user creation logs to display merchant information and correct passwords

app/auth/controllers/router.py CHANGED
@@ -154,7 +154,7 @@ async def login(
154
  # Create tokens
155
  access_token_expires = timedelta(minutes=30)
156
  access_token = user_service.create_access_token(
157
- data={"sub": user.user_id, "username": user.username, "role": user.role},
158
  expires_delta=access_token_expires
159
  )
160
 
@@ -244,12 +244,12 @@ async def refresh_token(
244
  # Create new access token
245
  access_token_expires = timedelta(minutes=30)
246
  new_access_token = user_service.create_access_token(
247
- data={"sub": user_id, "username": username, "role": user.role},
248
  expires_delta=access_token_expires
249
  )
250
 
251
  return {
252
- "access_token": access_token,
253
  "token_type": "bearer",
254
  "expires_in": 1800
255
  }
 
154
  # Create tokens
155
  access_token_expires = timedelta(minutes=30)
156
  access_token = user_service.create_access_token(
157
+ data={"sub": user.user_id, "username": user.username, "role": user.role, "merchant_id": user.merchant_id},
158
  expires_delta=access_token_expires
159
  )
160
 
 
244
  # Create new access token
245
  access_token_expires = timedelta(minutes=30)
246
  new_access_token = user_service.create_access_token(
247
+ data={"sub": user_id, "username": username, "role": user.role, "merchant_id": user.merchant_id},
248
  expires_delta=access_token_expires
249
  )
250
 
251
  return {
252
+ "access_token": new_access_token,
253
  "token_type": "bearer",
254
  "expires_in": 1800
255
  }
app/system_users/controllers/router.py CHANGED
@@ -69,7 +69,7 @@ async def login(
69
  access_token_expires = timedelta(hours=24) # Longer expiry for remember me
70
 
71
  access_token = user_service.create_access_token(
72
- data={"sub": user.user_id, "username": user.username, "role_id": user.role},
73
  expires_delta=access_token_expires
74
  )
75
 
 
69
  access_token_expires = timedelta(hours=24) # Longer expiry for remember me
70
 
71
  access_token = user_service.create_access_token(
72
+ data={"sub": user.user_id, "username": user.username, "role": user.role, "merchant_id": user.merchant_id},
73
  expires_delta=access_token_expires
74
  )
75
 
app/system_users/models/model.py CHANGED
@@ -54,6 +54,7 @@ class SystemUserModel(BaseModel):
54
  user_id: str = Field(..., description="Unique user identifier (UUID/ULID)")
55
  username: str = Field(..., description="Unique username (lowercase alphanumeric)")
56
  email: EmailStr = Field(..., description="User email address")
 
57
 
58
  # Authentication
59
  password_hash: str = Field(..., description="Bcrypt hashed password")
 
54
  user_id: str = Field(..., description="Unique user identifier (UUID/ULID)")
55
  username: str = Field(..., description="Unique username (lowercase alphanumeric)")
56
  email: EmailStr = Field(..., description="User email address")
57
+ merchant_id: str = Field(..., description="User Merchant Information")
58
 
59
  # Authentication
60
  password_hash: str = Field(..., description="Bcrypt hashed password")
app/system_users/schemas/schema.py CHANGED
@@ -40,6 +40,7 @@ class CreateUserRequest(BaseModel):
40
  """Create user request schema."""
41
  username: str = Field(..., description="Unique username", min_length=3, max_length=30)
42
  email: EmailStr = Field(..., description="Email address")
 
43
  password: str = Field(..., description="Password", min_length=8, max_length=100)
44
  first_name: str = Field(..., description="First name", min_length=1, max_length=50)
45
  last_name: Optional[str] = Field(None, description="Last name", max_length=50)
 
40
  """Create user request schema."""
41
  username: str = Field(..., description="Unique username", min_length=3, max_length=30)
42
  email: EmailStr = Field(..., description="Email address")
43
+ merchant_id: str = Field(..., description="Merchant ID for the user")
44
  password: str = Field(..., description="Password", min_length=8, max_length=100)
45
  first_name: str = Field(..., description="First name", min_length=1, max_length=50)
46
  last_name: Optional[str] = Field(None, description="Last name", max_length=50)
app/system_users/services/service.py CHANGED
@@ -167,6 +167,7 @@ class SystemUserService:
167
  user_id=user_id,
168
  username=user_data.username.lower(),
169
  email=user_data.email.lower(),
 
170
  password_hash=password_hash,
171
  first_name=user_data.first_name,
172
  last_name=user_data.last_name,
 
167
  user_id=user_id,
168
  username=user_data.username.lower(),
169
  email=user_data.email.lower(),
170
+ merchant_id=user_data.merchant_id,
171
  password_hash=password_hash,
172
  first_name=user_data.first_name,
173
  last_name=user_data.last_name,
create_initial_users.py CHANGED
@@ -27,6 +27,7 @@ async def create_initial_users():
27
  "user_id": "usr_superadmin_001",
28
  "username": "superadmin",
29
  "email": "superadmin@cuatrolabs.com",
 
30
  "password_hash": pwd_context.hash("SuperAdmin@123!"),
31
  "first_name": "Super",
32
  "last_name": "Admin",
@@ -48,6 +49,7 @@ async def create_initial_users():
48
  "user_id": "usr_admin_001",
49
  "username": "admin",
50
  "email": "admin@cuatrolabs.com",
 
51
  "password_hash": pwd_context.hash("CompanyAdmin@123!"),
52
  "first_name": "Company",
53
  "last_name": "Admin",
@@ -69,10 +71,11 @@ async def create_initial_users():
69
  "user_id": "usr_manager_001",
70
  "username": "manager",
71
  "email": "manager@cuatrolabs.com",
 
72
  "password_hash": pwd_context.hash("Manager@123!"),
73
  "first_name": "Team",
74
  "last_name": "Manager",
75
- "phone": "+919999999997",
76
  "role_id": "manager",
77
 
78
  "status": "active",
@@ -97,9 +100,9 @@ async def create_initial_users():
97
  logger.info(f"Created user: {user['email']} (password: see script)")
98
 
99
  logger.info("\n=== Initial Users Created ===")
100
- logger.info("1. superadmin@cuatrolabs.com / SuperAdmin@123")
101
- logger.info("2. admin@cuatrolabs.com / CompanyAdmin@123")
102
- logger.info("3. manager@cuatrolabs.com / Manager@123")
103
  logger.info("=============================\n")
104
 
105
  except Exception as e:
 
27
  "user_id": "usr_superadmin_001",
28
  "username": "superadmin",
29
  "email": "superadmin@cuatrolabs.com",
30
+ "merchant_id": "company_cuatro_beauty_ltd",
31
  "password_hash": pwd_context.hash("SuperAdmin@123!"),
32
  "first_name": "Super",
33
  "last_name": "Admin",
 
49
  "user_id": "usr_admin_001",
50
  "username": "admin",
51
  "email": "admin@cuatrolabs.com",
52
+ "merchant_id": "company_cuatro_beauty_ltd",
53
  "password_hash": pwd_context.hash("CompanyAdmin@123!"),
54
  "first_name": "Company",
55
  "last_name": "Admin",
 
71
  "user_id": "usr_manager_001",
72
  "username": "manager",
73
  "email": "manager@cuatrolabs.com",
74
+ "merchant_id": "company_cuatro_beauty_ltd",
75
  "password_hash": pwd_context.hash("Manager@123!"),
76
  "first_name": "Team",
77
  "last_name": "Manager",
78
+ "phone": "+919999997",
79
  "role_id": "manager",
80
 
81
  "status": "active",
 
100
  logger.info(f"Created user: {user['email']} (password: see script)")
101
 
102
  logger.info("\n=== Initial Users Created ===")
103
+ logger.info("1. superadmin@cuatrolabs.com / SuperAdmin@123! (merchant: merchant_cuatrolabs_001)")
104
+ logger.info("2. admin@cuatrolabs.com / CompanyAdmin@123! (merchant: merchant_cuatrolabs_001)")
105
+ logger.info("3. manager@cuatrolabs.com / Manager@123! (merchant: merchant_cuatrolabs_001)")
106
  logger.info("=============================\n")
107
 
108
  except Exception as e: