From abe74f32f88dfde93f7a94b498236107c52d2031 Mon Sep 17 00:00:00 2001 From: Urtzi Alfaro Date: Sat, 2 Aug 2025 23:29:18 +0200 Subject: [PATCH] Fix user delete flow 9 --- gateway/app/middleware/auth.py | 19 ++++++++++++++++++- services/auth/app/core/security.py | 6 ++++++ services/auth/app/services/auth_service.py | 3 +++ services/tenant/app/api/tenants.py | 7 ++++++- shared/auth/decorators.py | 16 +++++++++++++++- shared/clients/base_service_client.py | 1 + 6 files changed, 49 insertions(+), 3 deletions(-) diff --git a/gateway/app/middleware/auth.py b/gateway/app/middleware/auth.py index 465c8188..f315c734 100644 --- a/gateway/app/middleware/auth.py +++ b/gateway/app/middleware/auth.py @@ -304,11 +304,28 @@ class AuthMiddleware(BaseHTTPMiddleware): b"x-user-email", user_context["email"].encode() )) + user_role = user_context.get("role", "user") + request.headers.__dict__["_list"].append(( + b"x-user-role", user_role.encode() + )) + + user_type = user_context.get("type", "") + if user_type: + request.headers.__dict__["_list"].append(( + b"x-user-type", user_type.encode() + )) + + service_name = user_context.get("service", "") + if service_name: + request.headers.__dict__["_list"].append(( + b"x-service-name", service_name.encode() + )) + # Add tenant context if available if tenant_id: request.headers.__dict__["_list"].append(( b"x-tenant-id", tenant_id.encode() - )) + )) # Add gateway identification request.headers.__dict__["_list"].append(( diff --git a/services/auth/app/core/security.py b/services/auth/app/core/security.py index 7e3f465e..52fe8591 100644 --- a/services/auth/app/core/security.py +++ b/services/auth/app/core/security.py @@ -99,6 +99,12 @@ class SecurityManager: payload["is_verified"] = user_data["is_verified"] if "is_active" in user_data: payload["is_active"] = user_data["is_active"] + + # ✅ CRITICAL FIX: Include role in access token! + if "role" in user_data: + payload["role"] = user_data["role"] + else: + payload["role"] = "user" # Default role if not specified logger.debug(f"Creating access token with payload keys: {list(payload.keys())}") diff --git a/services/auth/app/services/auth_service.py b/services/auth/app/services/auth_service.py index 5bbd1db4..bbc98178 100644 --- a/services/auth/app/services/auth_service.py +++ b/services/auth/app/services/auth_service.py @@ -62,6 +62,7 @@ class AuthService: "full_name": new_user.full_name, "is_verified": new_user.is_verified, "is_active": new_user.is_active, + "role": new_user.role, "type": "access" # ✅ Explicitly mark as access token } @@ -184,6 +185,7 @@ class AuthService: "full_name": user.full_name, "is_verified": user.is_verified, "is_active": user.is_active, + "role": user.role, "type": "access" # ✅ Explicitly mark as access token } @@ -345,6 +347,7 @@ class AuthService: "full_name": user.full_name, "is_verified": user.is_verified, "is_active": user.is_active, + "role": user.role, "type": "access" } diff --git a/services/tenant/app/api/tenants.py b/services/tenant/app/api/tenants.py index e0f847db..67d35313 100644 --- a/services/tenant/app/api/tenants.py +++ b/services/tenant/app/api/tenants.py @@ -301,10 +301,15 @@ async def get_user_tenants( # Check if this is a service call or admin user user_type = current_user.get('type', '') user_role = current_user.get('role', '').lower() + service_name = current_user.get('service', '') logger.info("The user_type and user_role", user_type=user_type, user_role=user_role) - if user_type != 'service' and user_role != 'admin': + # ✅ IMPROVED: Accept service tokens OR admin users + is_service_token = (user_type == 'service' or service_name in ['auth', 'admin']) + is_admin_user = (user_role == 'admin') + + if not (is_service_token or is_admin_user): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Admin role or service authentication required" diff --git a/shared/auth/decorators.py b/shared/auth/decorators.py index eed35df6..4aa9bf07 100644 --- a/shared/auth/decorators.py +++ b/shared/auth/decorators.py @@ -346,7 +346,7 @@ def extract_user_from_headers(request: Request) -> Optional[Dict[str, Any]]: if not user_id: return None - return { + user_context = { "user_id": user_id, "email": request.headers.get("x-user-email", ""), "role": request.headers.get("x-user-role", "user"), @@ -354,6 +354,20 @@ def extract_user_from_headers(request: Request) -> Optional[Dict[str, Any]]: "permissions": request.headers.get("X-User-Permissions", "").split(",") if request.headers.get("X-User-Permissions") else [], "full_name": request.headers.get("x-user-full-name", "") } + + # ✅ ADD THIS: Handle service tokens properly + user_type = request.headers.get("x-user-type", "") + service_name = request.headers.get("x-service-name", "") + + if user_type == "service" or service_name: + user_context.update({ + "type": "service", + "service": service_name, + "role": "admin", # Service tokens always have admin role + "is_service": True + }) + + return user_context def extract_tenant_from_headers(request: Request) -> Optional[str]: """Extract tenant ID from headers""" diff --git a/shared/clients/base_service_client.py b/shared/clients/base_service_client.py index f411ac2f..c6fe5702 100644 --- a/shared/clients/base_service_client.py +++ b/shared/clients/base_service_client.py @@ -44,6 +44,7 @@ class ServiceAuthenticator: "user_id": f"{self.service_name}-service", "email": f"{self.service_name}-service@internal", "type": "service", + "role": "admin", "exp": token_expires_at, "iat": current_time, "iss": f"{self.service_name}-service",