Files
bakery-ia/shared/clients/auth_client.py
2025-12-13 23:57:54 +01:00

185 lines
6.7 KiB
Python
Executable File

# shared/clients/auth_client.py
"""
Auth Service Client for Inter-Service Communication
Provides methods to interact with the authentication/onboarding service
"""
from typing import Optional, Dict, Any, List
import structlog
from shared.clients.base_service_client import BaseServiceClient
from shared.config.base import BaseServiceSettings
logger = structlog.get_logger()
class AuthServiceClient(BaseServiceClient):
"""Client for interacting with the Auth Service"""
def __init__(self, config: BaseServiceSettings):
super().__init__("auth", config)
def get_service_base_path(self) -> str:
"""Return the base path for auth service APIs"""
return "/api/v1/auth"
async def get_user_onboarding_progress(self, user_id: str) -> Optional[Dict[str, Any]]:
"""
Get user's onboarding progress including step data
Args:
user_id: User ID to fetch progress for
Returns:
Dict with user progress including steps with data, or None if failed
"""
try:
# Use the service endpoint that accepts user_id as parameter
result = await self.get(f"/users/{user_id}/onboarding/progress")
if result:
logger.info("Retrieved user onboarding progress",
user_id=user_id,
current_step=result.get("current_step"))
return result
else:
logger.warning("No onboarding progress found",
user_id=user_id)
return None
except Exception as e:
logger.error("Failed to get user onboarding progress",
user_id=user_id,
error=str(e))
return None
async def get_user_step_data(self, user_id: str, step_name: str) -> Optional[Dict[str, Any]]:
"""
Get data for a specific onboarding step
Args:
user_id: User ID
step_name: Name of the step (e.g., "user_registered")
Returns:
Step data dictionary or None if not found
"""
try:
progress = await self.get_user_onboarding_progress(user_id)
if not progress:
logger.warning("No progress data returned",
user_id=user_id)
return None
logger.debug("Retrieved progress data",
user_id=user_id,
steps_count=len(progress.get("steps", [])),
current_step=progress.get("current_step"))
# Find the specific step
for step in progress.get("steps", []):
if step.get("step_name") == step_name:
step_data = step.get("data", {})
logger.info("Found step data",
user_id=user_id,
step_name=step_name,
data_keys=list(step_data.keys()) if step_data else [],
has_subscription_plan="subscription_plan" in step_data)
return step_data
logger.warning("Step not found in progress",
user_id=user_id,
step_name=step_name,
available_steps=[s.get("step_name") for s in progress.get("steps", [])])
return None
except Exception as e:
logger.error("Failed to get step data",
user_id=user_id,
step_name=step_name,
error=str(e))
return None
async def get_subscription_plan_from_registration(self, user_id: str) -> str:
"""
Get the subscription plan selected during user registration
Args:
user_id: User ID
Returns:
Plan name (e.g., "starter", "professional", "enterprise") or "starter" as default
"""
try:
step_data = await self.get_user_step_data(user_id, "user_registered")
if step_data and "subscription_plan" in step_data:
plan = step_data["subscription_plan"]
logger.info("Retrieved subscription plan from registration",
user_id=user_id,
plan=plan)
return plan
else:
logger.info("No subscription plan in registration data, using default",
user_id=user_id,
default_plan="starter")
return "starter"
except Exception as e:
logger.warning("Failed to retrieve subscription plan, using default",
user_id=user_id,
error=str(e),
default_plan="starter")
return "starter"
async def create_user_by_owner(self, user_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Create a new user account via the auth service (owner/admin only - pilot phase).
This method calls the auth service endpoint that allows tenant owners
to directly create users with passwords during the pilot phase.
Args:
user_data: Dictionary containing:
- email: User email (required)
- full_name: Full name (required)
- password: Password (required)
- phone: Phone number (optional)
- role: User role (optional, default: "user")
- language: Language preference (optional, default: "es")
- timezone: Timezone (optional, default: "Europe/Madrid")
Returns:
Dict with created user data including user ID
Raises:
Exception if user creation fails
"""
try:
logger.info(
"Creating user via auth service",
email=user_data.get("email"),
role=user_data.get("role", "user")
)
result = await self.post("/users/create-by-owner", user_data)
if result and result.get("id"):
logger.info(
"User created successfully via auth service",
user_id=result.get("id"),
email=result.get("email")
)
return result
else:
logger.error("User creation returned no user ID")
raise Exception("User creation failed: No user ID returned")
except Exception as e:
logger.error(
"Failed to create user via auth service",
email=user_data.get("email"),
error=str(e)
)
raise