Spaces:
Sleeping
Sleeping
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":
|
| 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, "
|
| 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": "+
|
| 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:
|