diff --git a/app/api/deps.py b/app/api/deps.py index 32fd6de9..1c80521a 100644 --- a/app/api/deps.py +++ b/app/api/deps.py @@ -51,8 +51,9 @@ from app.exceptions import ( from app.services.vendor_service import vendor_service from middleware.auth import AuthManager from middleware.rate_limiter import RateLimiter -from models.database.user import User +from models.database.user import User as UserModel from models.database.vendor import Vendor +from models.schema.auth import UserContext # Initialize dependencies security = HTTPBearer(auto_error=False) # auto_error=False prevents automatic 403 @@ -98,7 +99,7 @@ def _get_token_from_request( return None, None -def _validate_user_token(token: str, db: Session) -> User: +def _validate_user_token(token: str, db: Session) -> UserModel: """ Validate JWT token and return user. @@ -107,7 +108,7 @@ def _validate_user_token(token: str, db: Session) -> User: db: Database session Returns: - User: Authenticated user object + UserModel: Authenticated user object Raises: InvalidTokenException: If token is invalid @@ -116,6 +117,38 @@ def _validate_user_token(token: str, db: Session) -> User: return auth_manager.get_current_user(db, mock_credentials) +def _get_user_model(user_context: UserContext, db: Session) -> UserModel: + """ + Get User database model from UserContext. + + Used internally by permission-checking functions that need + access to User model methods like has_vendor_permission(). + + Args: + user_context: UserContext schema instance + db: Database session + + Returns: + UserModel: User database model + + Raises: + InvalidTokenException: If user not found + """ + user = db.query(UserModel).filter(UserModel.id == user_context.id).first() + if not user: + raise InvalidTokenException("User not found") + + # Copy token attributes from context to model for compatibility + if user_context.token_vendor_id: + user.token_vendor_id = user_context.token_vendor_id + if user_context.token_vendor_code: + user.token_vendor_code = user_context.token_vendor_code + if user_context.token_vendor_role: + user.token_vendor_role = user_context.token_vendor_role + + return user + + # ============================================================================ # ADMIN AUTHENTICATION # ============================================================================ @@ -126,7 +159,7 @@ def get_current_admin_from_cookie_or_header( credentials: HTTPAuthorizationCredentials | None = Depends(security), admin_token: str | None = Cookie(None), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Get current admin user from admin_token cookie or Authorization header. @@ -143,7 +176,7 @@ def get_current_admin_from_cookie_or_header( db: Database session Returns: - User: Authenticated admin user + UserContext: Authenticated admin user context Raises: InvalidTokenException: If no token or invalid token @@ -167,13 +200,13 @@ def get_current_admin_from_cookie_or_header( ) raise AdminRequiredException("Admin privileges required") - return user + return UserContext.from_user(user, include_vendor_context=False) def get_current_admin_api( credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Get current admin user from Authorization header ONLY. @@ -185,7 +218,7 @@ def get_current_admin_api( db: Database session Returns: - User: Authenticated admin user + UserContext: Authenticated admin user context Raises: InvalidTokenException: If no token or invalid token @@ -200,7 +233,7 @@ def get_current_admin_api( logger.warning(f"Non-admin user {user.username} attempted admin API") raise AdminRequiredException("Admin privileges required") - return user + return UserContext.from_user(user, include_vendor_context=False) # ============================================================================ @@ -213,7 +246,7 @@ def get_current_super_admin( credentials: HTTPAuthorizationCredentials | None = Depends(security), admin_token: str | None = Cookie(None), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Require super admin role. @@ -227,27 +260,27 @@ def get_current_super_admin( db: Database session Returns: - User: Authenticated super admin user + UserContext: Authenticated super admin user context Raises: InvalidTokenException: If no token or invalid token AdminRequiredException: If user is not admin or not super admin """ - user = get_current_admin_from_cookie_or_header(request, credentials, admin_token, db) + user_context = get_current_admin_from_cookie_or_header(request, credentials, admin_token, db) - if not user.is_super_admin: + if not user_context.is_super_admin: logger.warning( - f"Platform admin {user.username} attempted super admin route: {request.url.path}" + f"Platform admin {user_context.username} attempted super admin route: {request.url.path}" ) raise AdminRequiredException("Super admin privileges required") - return user + return user_context def get_current_super_admin_api( credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Require super admin role (API header only). @@ -258,19 +291,19 @@ def get_current_super_admin_api( db: Database session Returns: - User: Authenticated super admin user + UserContext: Authenticated super admin user context Raises: InvalidTokenException: If no token or invalid token AdminRequiredException: If user is not admin or not super admin """ - user = get_current_admin_api(credentials, db) + user_context = get_current_admin_api(credentials, db) - if not user.is_super_admin: - logger.warning(f"Platform admin {user.username} attempted super admin API") + if not user_context.is_super_admin: + logger.warning(f"Platform admin {user_context.username} attempted super admin API") raise AdminRequiredException("Super admin privileges required") - return user + return user_context def require_platform_access(platform_id: int): @@ -284,7 +317,7 @@ def require_platform_access(platform_id: int): @router.get("/platforms/{platform_id}/vendors") def list_vendors( platform_id: int, - admin: User = Depends(require_platform_access(platform_id)) + admin: UserContext = Depends(require_platform_access(platform_id)) ): ... """ @@ -294,20 +327,26 @@ def require_platform_access(platform_id: int): credentials: HTTPAuthorizationCredentials | None = Depends(security), admin_token: str | None = Cookie(None), db: Session = Depends(get_db), - ) -> User: - user = get_current_admin_from_cookie_or_header( + ) -> UserContext: + user_context = get_current_admin_from_cookie_or_header( request, credentials, admin_token, db ) - if not user.can_access_platform(platform_id): + # Super admins (accessible_platform_ids=None) can access all platforms + # Platform admins can only access their assigned platforms + can_access = ( + user_context.accessible_platform_ids is None or + platform_id in (user_context.accessible_platform_ids or []) + ) + if not can_access: logger.warning( - f"Admin {user.username} denied access to platform_id={platform_id}" + f"Admin {user_context.username} denied access to platform_id={platform_id}" ) raise InsufficientPermissionsException( f"Access denied to platform {platform_id}" ) - return user + return user_context return _check_platform_access @@ -317,7 +356,7 @@ def get_admin_with_platform_context( credentials: HTTPAuthorizationCredentials | None = Depends(security), admin_token: str | None = Cookie(None), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Get admin user and verify platform context from token. @@ -326,6 +365,9 @@ def get_admin_with_platform_context( Super admins bypass platform context check (they can access all platforms). + Note: This function needs the raw User model for token attributes and + platform access checks, so it uses _validate_user_token internally. + Args: request: FastAPI request credentials: Optional Bearer token from header @@ -333,7 +375,7 @@ def get_admin_with_platform_context( db: Database session Returns: - User: Authenticated admin with platform context + UserContext: Authenticated admin with platform context Raises: InvalidTokenException: If platform admin token missing platform info @@ -341,11 +383,22 @@ def get_admin_with_platform_context( """ from models.database.platform import Platform - user = get_current_admin_from_cookie_or_header(request, credentials, admin_token, db) + # Get raw token for platform_id extraction + token, source = _get_token_from_request( + credentials, admin_token, "admin_token", str(request.url.path) + ) + + if not token: + raise InvalidTokenException("Admin authentication required") + + user = _validate_user_token(token, db) + + if user.role != "admin": + raise AdminRequiredException("Admin privileges required") # Super admins bypass platform context if user.is_super_admin: - return user + return UserContext.from_user(user, include_vendor_context=False) # Platform admins need platform_id in token if not hasattr(user, "token_platform_id"): @@ -368,7 +421,7 @@ def get_admin_with_platform_context( platform = db.query(Platform).filter(Platform.id == platform_id).first() request.state.admin_platform = platform - return user + return UserContext.from_user(user, include_vendor_context=False) # ============================================================================ @@ -405,34 +458,33 @@ def require_module_access(module_code: str): admin_token: str | None = Cookie(None), vendor_token: str | None = Cookie(None), db: Session = Depends(get_db), - ) -> User: + ) -> UserContext: # Try admin auth first, then vendor - user = None + user_context = None platform_id = None # Check if this is an admin request if admin_token or (credentials and request.url.path.startswith("/admin")): try: - user = get_current_admin_from_cookie_or_header( + user_context = get_current_admin_from_cookie_or_header( request, credentials, admin_token, db ) # Get platform context for admin - if user.is_super_admin: + if user_context.is_super_admin: # Super admins bypass module checks - return user + return user_context else: platform = getattr(request.state, "admin_platform", None) if platform: platform_id = platform.id - elif hasattr(user, "token_platform_id"): - platform_id = user.token_platform_id + # Note: token_platform_id is not on UserContext, would need to be added except Exception: pass # Check if this is a vendor request - if not user and (vendor_token or (credentials and "/vendor/" in request.url.path)): + if not user_context and (vendor_token or (credentials and "/vendor/" in request.url.path)): try: - user = get_current_vendor_from_cookie_or_header( + user_context = get_current_vendor_from_cookie_or_header( request, credentials, vendor_token, db ) # Get platform from vendor context @@ -442,25 +494,25 @@ def require_module_access(module_code: str): except Exception: pass - if not user: + if not user_context: raise InvalidTokenException("Authentication required") # If no platform context, allow access (module checking requires platform) if not platform_id: logger.debug(f"No platform context for module check: {module_code}") - return user + return user_context # Check if module is enabled if not module_service.is_module_enabled(db, platform_id, module_code): logger.warning( f"Module access denied: {module_code} disabled for " - f"platform_id={platform_id}, user={user.username}" + f"platform_id={platform_id}, user={user_context.username}" ) raise InsufficientPermissionsException( f"The '{module_code}' module is not enabled for this platform" ) - return user + return user_context return _check_module_access @@ -509,33 +561,31 @@ def require_menu_access(menu_item_id: str, frontend_type: "FrontendType"): admin_token: str | None = Cookie(None), vendor_token: str | None = Cookie(None), db: Session = Depends(get_db), - ) -> User: + ) -> UserContext: # Get current user based on frontend type if frontend_type == FT.ADMIN: - user = get_current_admin_from_cookie_or_header( + user_context = get_current_admin_from_cookie_or_header( request, credentials, admin_token, db ) - if user.is_super_admin: + if user_context.is_super_admin: # Super admin: check user-level config platform_id = None - user_id = user.id + user_id = user_context.id else: # Platform admin: need platform context - # Try to get from request state or token + # Try to get from request state platform = getattr(request.state, "admin_platform", None) if platform: platform_id = platform.id - elif hasattr(user, "token_platform_id"): - platform_id = user.token_platform_id else: # No platform context - allow access (will be restricted elsewhere) # This handles routes that don't have platform context yet - return user + return user_context user_id = None elif frontend_type == FT.VENDOR: - user = get_current_vendor_from_cookie_or_header( + user_context = get_current_vendor_from_cookie_or_header( request, credentials, vendor_token, db ) @@ -546,7 +596,7 @@ def require_menu_access(menu_item_id: str, frontend_type: "FrontendType"): else: # No platform context for vendor - allow access # This handles edge cases where vendor doesn't have platform - return user + return user_context user_id = None else: @@ -558,7 +608,7 @@ def require_menu_access(menu_item_id: str, frontend_type: "FrontendType"): if module_code and not module_service.is_module_enabled(db, platform_id, module_code): logger.warning( f"Module access denied: {menu_item_id} (module={module_code}) for " - f"user={user.username}, platform_id={platform_id}" + f"user={user_context.username}, platform_id={platform_id}" ) raise InsufficientPermissionsException( f"The '{module_code}' module is not enabled for this platform. " @@ -573,7 +623,7 @@ def require_menu_access(menu_item_id: str, frontend_type: "FrontendType"): if not can_access: logger.warning( f"Menu visibility denied: {menu_item_id} for " - f"user={user.username}, frontend={frontend_type.value}, " + f"user={user_context.username}, frontend={frontend_type.value}, " f"platform_id={platform_id}, user_id={user_id}" ) raise InsufficientPermissionsException( @@ -581,7 +631,7 @@ def require_menu_access(menu_item_id: str, frontend_type: "FrontendType"): f"Contact your administrator if you need access." ) - return user + return user_context return _check_menu_access @@ -596,7 +646,7 @@ def get_current_vendor_from_cookie_or_header( credentials: HTTPAuthorizationCredentials | None = Depends(security), vendor_token: str | None = Cookie(None), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Get current vendor user from vendor_token cookie or Authorization header. @@ -613,7 +663,7 @@ def get_current_vendor_from_cookie_or_header( db: Database session Returns: - User: Authenticated vendor user + UserContext: Authenticated vendor user context Raises: InvalidTokenException: If no token or invalid token @@ -646,13 +696,13 @@ def get_current_vendor_from_cookie_or_header( ) raise InsufficientPermissionsException("Vendor privileges required") - return user + return UserContext.from_user(user) def get_current_vendor_api( credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Get current vendor user from Authorization header ONLY. @@ -666,7 +716,7 @@ def get_current_vendor_api( db: Database session Returns: - User: Authenticated vendor user (with token_vendor_id, token_vendor_code, token_vendor_role) + UserContext: Authenticated vendor user context (with token_vendor_id, token_vendor_code, token_vendor_role) Raises: InvalidTokenException: If no token, invalid token, or missing vendor context @@ -706,7 +756,7 @@ def get_current_vendor_api( f"vendor_code={getattr(user, 'token_vendor_code', 'N/A')}" ) - return user + return UserContext.from_user(user) # ============================================================================ @@ -884,7 +934,7 @@ def get_current_customer_api( def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db), -) -> User: +) -> UserContext: """ Get current authenticated user from Authorization header only. @@ -896,7 +946,7 @@ def get_current_user( db: Database session Returns: - User: Authenticated user (any role) + UserContext: Authenticated user context (any role) Raises: InvalidTokenException: If no token or invalid token @@ -904,7 +954,8 @@ def get_current_user( if not credentials: raise InvalidTokenException("Authorization header required") - return _validate_user_token(credentials.credentials, db) + user = _validate_user_token(credentials.credentials, db) + return UserContext.from_user(user) # ============================================================================ @@ -914,7 +965,7 @@ def get_current_user( def get_user_vendor( vendor_code: str, - current_user: User = Depends(get_current_vendor_from_cookie_or_header), + current_user: UserContext = Depends(get_current_vendor_from_cookie_or_header), db: Session = Depends(get_db), ) -> Vendor: """ @@ -976,7 +1027,7 @@ def require_vendor_permission(permission: str): @router.get("/products") def list_products( request: Request, - user: User = Depends(require_vendor_permission(VendorPermissions.PRODUCTS_VIEW.value)) + user: UserContext = Depends(require_vendor_permission(VendorPermissions.PRODUCTS_VIEW.value)) ): vendor = request.state.vendor # Vendor is set by this dependency ... @@ -985,10 +1036,10 @@ def require_vendor_permission(permission: str): def permission_checker( request: Request, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_from_cookie_or_header), - ) -> User: + current_user: UserContext = Depends(get_current_vendor_from_cookie_or_header), + ) -> UserContext: # Get vendor ID from JWT token - if not hasattr(current_user, "token_vendor_id"): + if not current_user.token_vendor_id: raise InvalidTokenException( "Token missing vendor information. Please login again." ) @@ -1001,8 +1052,9 @@ def require_vendor_permission(permission: str): # Store vendor in request state for endpoint use request.state.vendor = vendor - # Check if user has permission - if not current_user.has_vendor_permission(vendor.id, permission): + # Check if user has permission (need User model for this) + user_model = _get_user_model(current_user, db) + if not user_model.has_vendor_permission(vendor.id, permission): raise InsufficientVendorPermissionsException( required_permission=permission, vendor_code=vendor.vendor_code, @@ -1016,8 +1068,8 @@ def require_vendor_permission(permission: str): def require_vendor_owner( request: Request, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_from_cookie_or_header), -) -> User: + current_user: UserContext = Depends(get_current_vendor_from_cookie_or_header), +) -> UserContext: """ Dependency to require vendor owner role. @@ -1028,13 +1080,13 @@ def require_vendor_owner( @router.delete("/team/{user_id}") def remove_team_member( request: Request, - user: User = Depends(require_vendor_owner) + user: UserContext = Depends(require_vendor_owner) ): vendor = request.state.vendor # Vendor is set by this dependency ... """ # Get vendor ID from JWT token - if not hasattr(current_user, "token_vendor_id"): + if not current_user.token_vendor_id: raise InvalidTokenException( "Token missing vendor information. Please login again." ) @@ -1047,7 +1099,9 @@ def require_vendor_owner( # Store vendor in request state for endpoint use request.state.vendor = vendor - if not current_user.is_owner_of(vendor.id): + # Need User model for is_owner_of check + user_model = _get_user_model(current_user, db) + if not user_model.is_owner_of(vendor.id): raise VendorOwnerOnlyException( operation="team management", vendor_code=vendor.vendor_code, @@ -1067,7 +1121,7 @@ def require_any_vendor_permission(*permissions: str): @router.get("/dashboard") def dashboard( request: Request, - user: User = Depends(require_any_vendor_permission( + user: UserContext = Depends(require_any_vendor_permission( VendorPermissions.DASHBOARD_VIEW.value, VendorPermissions.REPORTS_VIEW.value )) @@ -1079,10 +1133,10 @@ def require_any_vendor_permission(*permissions: str): def permission_checker( request: Request, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_from_cookie_or_header), - ) -> User: + current_user: UserContext = Depends(get_current_vendor_from_cookie_or_header), + ) -> UserContext: # Get vendor ID from JWT token - if not hasattr(current_user, "token_vendor_id"): + if not current_user.token_vendor_id: raise InvalidTokenException( "Token missing vendor information. Please login again." ) @@ -1095,9 +1149,10 @@ def require_any_vendor_permission(*permissions: str): # Store vendor in request state for endpoint use request.state.vendor = vendor - # Check if user has ANY of the required permissions + # Check if user has ANY of the required permissions (need User model) + user_model = _get_user_model(current_user, db) has_permission = any( - current_user.has_vendor_permission(vendor.id, perm) for perm in permissions + user_model.has_vendor_permission(vendor.id, perm) for perm in permissions ) if not has_permission: @@ -1122,7 +1177,7 @@ def require_all_vendor_permissions(*permissions: str): @router.post("/products/bulk-delete") def bulk_delete_products( request: Request, - user: User = Depends(require_all_vendor_permissions( + user: UserContext = Depends(require_all_vendor_permissions( VendorPermissions.PRODUCTS_VIEW.value, VendorPermissions.PRODUCTS_DELETE.value )) @@ -1134,10 +1189,10 @@ def require_all_vendor_permissions(*permissions: str): def permission_checker( request: Request, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_from_cookie_or_header), - ) -> User: + current_user: UserContext = Depends(get_current_vendor_from_cookie_or_header), + ) -> UserContext: # Get vendor ID from JWT token - if not hasattr(current_user, "token_vendor_id"): + if not current_user.token_vendor_id: raise InvalidTokenException( "Token missing vendor information. Please login again." ) @@ -1150,11 +1205,12 @@ def require_all_vendor_permissions(*permissions: str): # Store vendor in request state for endpoint use request.state.vendor = vendor - # Check if user has ALL required permissions + # Check if user has ALL required permissions (need User model) + user_model = _get_user_model(current_user, db) missing_permissions = [ perm for perm in permissions - if not current_user.has_vendor_permission(vendor.id, perm) + if not user_model.has_vendor_permission(vendor.id, perm) ] if missing_permissions: @@ -1171,7 +1227,7 @@ def require_all_vendor_permissions(*permissions: str): def get_user_permissions( request: Request, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_from_cookie_or_header), + current_user: UserContext = Depends(get_current_vendor_from_cookie_or_header), ) -> list: """ Get all permissions for current user in current vendor. @@ -1182,7 +1238,7 @@ def get_user_permissions( Returns empty list if no vendor context in token. """ # Get vendor ID from JWT token - if not hasattr(current_user, "token_vendor_id"): + if not current_user.token_vendor_id: return [] vendor_id = current_user.token_vendor_id @@ -1193,14 +1249,17 @@ def get_user_permissions( # Store vendor in request state for endpoint use request.state.vendor = vendor + # Need User model for ownership and membership checks + user_model = _get_user_model(current_user, db) + # If owner, return all permissions - if current_user.is_owner_of(vendor.id): + if user_model.is_owner_of(vendor.id): from app.core.permissions import VendorPermissions return [p.value for p in VendorPermissions] # Get permissions from vendor membership - for vm in current_user.vendor_memberships: + for vm in user_model.vendor_memberships: if vm.vendor_id == vendor.id and vm.is_active: return vm.get_all_permissions() @@ -1217,7 +1276,7 @@ def get_current_admin_optional( credentials: HTTPAuthorizationCredentials | None = Depends(security), admin_token: str | None = Cookie(None), db: Session = Depends(get_db), -) -> User | None: +) -> UserContext | None: """ Get current admin user from admin_token cookie or Authorization header. @@ -1235,7 +1294,7 @@ def get_current_admin_optional( db: Database session Returns: - User: Authenticated admin user if valid token exists + UserContext: Authenticated admin user context if valid token exists None: If no token, invalid token, or user is not admin """ token, source = _get_token_from_request( @@ -1251,7 +1310,7 @@ def get_current_admin_optional( # Verify user is admin if user.role == "admin": - return user + return UserContext.from_user(user, include_vendor_context=False) except Exception: # Invalid token or other error pass @@ -1264,7 +1323,7 @@ def get_current_vendor_optional( credentials: HTTPAuthorizationCredentials | None = Depends(security), vendor_token: str | None = Cookie(None), db: Session = Depends(get_db), -) -> User | None: +) -> UserContext | None: """ Get current vendor user from vendor_token cookie or Authorization header. @@ -1282,7 +1341,7 @@ def get_current_vendor_optional( db: Database session Returns: - User: Authenticated vendor user if valid token exists + UserContext: Authenticated vendor user context if valid token exists None: If no token, invalid token, or user is not vendor """ token, source = _get_token_from_request( @@ -1298,7 +1357,7 @@ def get_current_vendor_optional( # Verify user is vendor if user.role == "vendor": - return user + return UserContext.from_user(user) except Exception: # Invalid token or other error pass diff --git a/app/api/v1/admin/admin_users.py b/app/api/v1/admin/admin_users.py index d014a914..8963a06f 100644 --- a/app/api/v1/admin/admin_users.py +++ b/app/api/v1/admin/admin_users.py @@ -23,7 +23,8 @@ from app.api.deps import get_current_super_admin, get_current_super_admin_api from app.core.database import get_db from app.exceptions import ValidationException from app.services.admin_platform_service import admin_platform_service -from models.database.user import User +from models.database.user import User # noqa: API-007 - Internal helper uses User model +from models.schema.auth import UserContext router = APIRouter(prefix="/admin-users") logger = logging.getLogger(__name__) @@ -142,7 +143,7 @@ def list_admin_users( limit: int = Query(100, ge=1, le=500), include_super_admins: bool = Query(True), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin), + current_admin: UserContext = Depends(get_current_super_admin), ): """ List all admin users with their platform assignments. @@ -165,7 +166,7 @@ def list_admin_users( def create_admin_user( request: CreateAdminUserRequest, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin_api), + current_admin: UserContext = Depends(get_current_super_admin_api), ): """ Create a new admin user (super admin or platform admin). @@ -225,7 +226,7 @@ def create_admin_user( def get_admin_user( user_id: int = Path(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin), + current_admin: UserContext = Depends(get_current_super_admin), ): """ Get admin user details with platform assignments. @@ -241,7 +242,7 @@ def assign_admin_to_platform( user_id: int = Path(...), platform_id: int = Path(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin_api), + current_admin: UserContext = Depends(get_current_super_admin_api), ): """ Assign an admin to a platform. @@ -268,7 +269,7 @@ def remove_admin_from_platform( user_id: int = Path(...), platform_id: int = Path(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin_api), + current_admin: UserContext = Depends(get_current_super_admin_api), ): """ Remove an admin's access to a platform. @@ -295,7 +296,7 @@ def toggle_super_admin_status( user_id: int = Path(...), request: ToggleSuperAdminRequest = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin_api), + current_admin: UserContext = Depends(get_current_super_admin_api), ): """ Promote or demote an admin to/from super admin. @@ -323,7 +324,7 @@ def toggle_super_admin_status( def get_admin_platforms( user_id: int = Path(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin), + current_admin: UserContext = Depends(get_current_super_admin), ): """ Get all platforms assigned to an admin. @@ -349,7 +350,7 @@ def get_admin_platforms( def toggle_admin_status( user_id: int = Path(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin_api), + current_admin: UserContext = Depends(get_current_super_admin_api), ): """ Toggle admin user active status. @@ -376,7 +377,7 @@ def toggle_admin_status( def delete_admin_user( user_id: int = Path(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_super_admin_api), + current_admin: UserContext = Depends(get_current_super_admin_api), ): """ Delete an admin user. diff --git a/app/api/v1/admin/audit.py b/app/api/v1/admin/audit.py index bf78a8eb..91729b7a 100644 --- a/app/api/v1/admin/audit.py +++ b/app/api/v1/admin/audit.py @@ -17,7 +17,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.admin_audit_service import admin_audit_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.admin import ( AdminAuditLogFilters, AdminAuditLogListResponse, @@ -38,7 +38,7 @@ def get_audit_logs( skip: int = Query(0, ge=0, description="Number of records to skip"), limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get filtered admin audit logs. @@ -68,7 +68,7 @@ def get_audit_logs( def get_recent_audit_logs( limit: int = Query(20, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get recent audit logs (last 20 by default).""" filters = AdminAuditLogFilters(limit=limit) @@ -79,7 +79,7 @@ def get_recent_audit_logs( def get_my_actions( limit: int = Query(50, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get audit logs for current admin's actions.""" return admin_audit_service.get_recent_actions_by_admin( @@ -93,7 +93,7 @@ def get_actions_by_target( target_id: str, limit: int = Query(50, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get all actions performed on a specific target. diff --git a/app/api/v1/admin/auth.py b/app/api/v1/admin/auth.py index 85527e24..8e5616df 100644 --- a/app/api/v1/admin/auth.py +++ b/app/api/v1/admin/auth.py @@ -21,8 +21,8 @@ from app.exceptions import InsufficientPermissionsException, InvalidCredentialsE from app.services.admin_platform_service import admin_platform_service from app.services.auth_service import auth_service from middleware.auth import AuthManager -from models.database.platform import Platform -from models.database.user import User +from models.database.platform import Platform # noqa: API-007 - Admin needs to query platforms +from models.schema.auth import UserContext from models.schema.auth import LoginResponse, LogoutResponse, UserLogin, UserResponse router = APIRouter(prefix="/auth") @@ -85,7 +85,7 @@ def admin_login( @router.get("/me", response_model=UserResponse) -def get_current_admin(current_user: User = Depends(get_current_admin_api)): +def get_current_admin(current_user: UserContext = Depends(get_current_admin_api)): """ Get current authenticated admin user. @@ -131,7 +131,7 @@ def admin_logout(response: Response): @router.get("/accessible-platforms") def get_accessible_platforms( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_from_cookie_or_header), + current_user: UserContext = Depends(get_current_admin_from_cookie_or_header), ): """ Get list of platforms this admin can access. @@ -165,7 +165,7 @@ def select_platform( platform_id: int, response: Response, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_from_cookie_or_header), + current_user: UserContext = Depends(get_current_admin_from_cookie_or_header), ): """ Select platform context for platform admin. diff --git a/app/api/v1/admin/background_tasks.py b/app/api/v1/admin/background_tasks.py index 66e54cd4..a4b6c1c7 100644 --- a/app/api/v1/admin/background_tasks.py +++ b/app/api/v1/admin/background_tasks.py @@ -13,7 +13,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.background_tasks_service import background_tasks_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter() @@ -156,7 +156,7 @@ async def list_background_tasks( ), limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ List all background tasks across the system @@ -198,7 +198,7 @@ async def list_background_tasks( @router.get("/tasks/stats", response_model=BackgroundTasksStatsResponse) async def get_background_tasks_stats( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get statistics for background tasks @@ -236,7 +236,7 @@ async def get_background_tasks_stats( @router.get("/tasks/running", response_model=list[BackgroundTaskResponse]) async def list_running_tasks( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ List currently running background tasks diff --git a/app/api/v1/admin/code_quality.py b/app/api/v1/admin/code_quality.py index 17f75a88..903c8159 100644 --- a/app/api/v1/admin/code_quality.py +++ b/app/api/v1/admin/code_quality.py @@ -20,7 +20,7 @@ from app.services.code_quality_service import ( ) from app.tasks.code_quality_tasks import execute_code_quality_scan from app.modules.dev_tools.models import ArchitectureScan -from models.database.user import User +from models.schema.auth import UserContext from app.modules.analytics.schemas import CodeQualityDashboardStatsResponse router = APIRouter() @@ -197,7 +197,7 @@ async def trigger_scan( request: ScanRequest = None, background_tasks: BackgroundTasks = None, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Trigger code quality scan(s) as background tasks. @@ -255,7 +255,7 @@ async def trigger_scan( async def get_scan_status( scan_id: int, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get status of a specific scan. @@ -272,7 +272,7 @@ async def get_scan_status( @router.get("/scans/running", response_model=list[ScanResponse]) async def get_running_scans( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get all currently running scans. @@ -290,7 +290,7 @@ async def list_scans( None, description="Filter by validator type" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get scan history @@ -326,7 +326,7 @@ async def list_violations( page: int = Query(1, ge=1, description="Page number"), page_size: int = Query(50, ge=1, le=200, description="Items per page"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get violations with filtering and pagination @@ -384,7 +384,7 @@ async def list_violations( async def get_violation( violation_id: int, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get single violation with details @@ -450,7 +450,7 @@ async def assign_violation( violation_id: int, request: AssignViolationRequest, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Assign violation to a developer @@ -483,7 +483,7 @@ async def resolve_violation( violation_id: int, request: ResolveViolationRequest, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Mark violation as resolved @@ -515,7 +515,7 @@ async def ignore_violation( violation_id: int, request: IgnoreViolationRequest, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Mark violation as ignored (won't fix) @@ -547,7 +547,7 @@ async def add_comment( violation_id: int, request: AddCommentRequest, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Add comment to violation @@ -577,7 +577,7 @@ async def get_dashboard_stats( None, description="Filter by validator type (returns combined stats if not specified)" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get dashboard statistics @@ -602,7 +602,7 @@ async def get_dashboard_stats( @router.get("/validator-types") async def get_validator_types( - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get list of available validator types diff --git a/app/api/v1/admin/companies.py b/app/api/v1/admin/companies.py index 25f234af..0ce1dc7c 100644 --- a/app/api/v1/admin/companies.py +++ b/app/api/v1/admin/companies.py @@ -13,7 +13,7 @@ from app.api.deps import get_current_admin_api from app.core.database import get_db from app.exceptions import CompanyHasVendorsException, ConfirmationRequiredException from app.services.company_service import company_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.company import ( CompanyCreate, CompanyCreateResponse, @@ -33,7 +33,7 @@ logger = logging.getLogger(__name__) def create_company_with_owner( company_data: CompanyCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Create a new company with owner user account (Admin only). @@ -87,7 +87,7 @@ def get_all_companies( is_active: bool | None = Query(None), is_verified: bool | None = Query(None), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get all companies with filtering (Admin only).""" companies, total = company_service.get_companies( @@ -128,7 +128,7 @@ def get_all_companies( def get_company_details( company_id: int = Path(..., description="Company ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get detailed company information including vendor counts (Admin only). @@ -179,7 +179,7 @@ def update_company( company_id: int = Path(..., description="Company ID"), company_update: CompanyUpdate = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Update company information (Admin only). @@ -218,7 +218,7 @@ def toggle_company_verification( company_id: int = Path(..., description="Company ID"), verification_data: dict = Body(..., example={"is_verified": True}), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Toggle company verification status (Admin only). @@ -251,7 +251,7 @@ def toggle_company_status( company_id: int = Path(..., description="Company ID"), status_data: dict = Body(..., example={"is_active": True}), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Toggle company active status (Admin only). @@ -287,7 +287,7 @@ def transfer_company_ownership( company_id: int = Path(..., description="Company ID"), transfer_data: CompanyTransferOwnership = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Transfer company ownership to another user (Admin only). @@ -333,7 +333,7 @@ def delete_company( company_id: int = Path(..., description="Company ID"), confirm: bool = Query(False, description="Must be true to confirm deletion"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Delete company and all associated vendors (Admin only). diff --git a/app/api/v1/admin/customers.py b/app/api/v1/admin/customers.py index b892a7b4..8291fcf2 100644 --- a/app/api/v1/admin/customers.py +++ b/app/api/v1/admin/customers.py @@ -11,7 +11,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.admin_customer_service import admin_customer_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.customers.schemas import ( CustomerDetailResponse, CustomerListResponse, @@ -35,7 +35,7 @@ def list_customers( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> CustomerListResponse: """ Get paginated list of customers across all vendors. @@ -68,7 +68,7 @@ def list_customers( def get_customer_stats( vendor_id: int | None = Query(None, description="Filter by vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> CustomerStatisticsResponse: """Get customer statistics.""" stats = admin_customer_service.get_customer_stats(db=db, vendor_id=vendor_id) @@ -84,7 +84,7 @@ def get_customer_stats( def get_customer( customer_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> CustomerDetailResponse: """Get customer details by ID.""" customer = admin_customer_service.get_customer(db=db, customer_id=customer_id) @@ -100,7 +100,7 @@ def get_customer( def toggle_customer_status( customer_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> CustomerMessageResponse: """Toggle customer active status.""" result = admin_customer_service.toggle_customer_status( diff --git a/app/api/v1/admin/dashboard.py b/app/api/v1/admin/dashboard.py index 1be31d38..760414e1 100644 --- a/app/api/v1/admin/dashboard.py +++ b/app/api/v1/admin/dashboard.py @@ -12,7 +12,7 @@ from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.admin_service import admin_service from app.services.stats_service import stats_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.analytics.schemas import ( AdminDashboardResponse, ImportStatsResponse, @@ -32,7 +32,7 @@ logger = logging.getLogger(__name__) @router.get("", response_model=AdminDashboardResponse) def get_admin_dashboard( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get admin dashboard with platform statistics (Admin only).""" user_stats = stats_service.get_user_statistics(db) @@ -62,7 +62,7 @@ def get_admin_dashboard( @router.get("/stats", response_model=StatsResponse) def get_comprehensive_stats( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get comprehensive platform statistics (Admin only).""" stats_data = stats_service.get_comprehensive_stats(db=db) @@ -81,7 +81,7 @@ def get_comprehensive_stats( @router.get("/stats/marketplace", response_model=list[MarketplaceStatsResponse]) def get_marketplace_stats( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get statistics broken down by marketplace (Admin only).""" marketplace_stats = stats_service.get_marketplace_breakdown_stats(db=db) @@ -100,7 +100,7 @@ def get_marketplace_stats( @router.get("/stats/platform", response_model=PlatformStatsResponse) def get_platform_statistics( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get comprehensive platform statistics (Admin only).""" user_stats = stats_service.get_user_statistics(db) diff --git a/app/api/v1/admin/email_templates.py b/app/api/v1/admin/email_templates.py index 1324c8ee..02b4973f 100644 --- a/app/api/v1/admin/email_templates.py +++ b/app/api/v1/admin/email_templates.py @@ -22,7 +22,7 @@ from app.core.database import get_db from app.exceptions.base import ResourceNotFoundException, ValidationException from app.services.email_service import EmailService from app.services.email_template_service import EmailTemplateService -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/email-templates") logger = logging.getLogger(__name__) @@ -92,7 +92,7 @@ class CategoriesResponse(BaseModel): @router.get("", response_model=TemplateListResponse) def list_templates( - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -106,7 +106,7 @@ def list_templates( @router.get("/categories", response_model=CategoriesResponse) def get_categories( - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """Get list of email template categories.""" @@ -117,7 +117,7 @@ def get_categories( @router.get("/{code}") def get_template( code: str, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -133,7 +133,7 @@ def get_template( def get_template_language( code: str, language: str, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -164,7 +164,7 @@ def update_template( code: str, language: str, template_data: TemplateUpdate, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -189,7 +189,7 @@ def update_template( def preview_template( code: str, preview_data: PreviewRequest, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -212,7 +212,7 @@ def preview_template( def send_test_email( code: str, test_data: TestEmailRequest, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -258,7 +258,7 @@ def get_template_logs( code: str, limit: int = 50, offset: int = 0, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/admin/features.py b/app/api/v1/admin/features.py index e61864ca..37d938a7 100644 --- a/app/api/v1/admin/features.py +++ b/app/api/v1/admin/features.py @@ -18,7 +18,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.feature_service import feature_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/features") logger = logging.getLogger(__name__) @@ -145,7 +145,7 @@ def _feature_to_response(feature) -> FeatureResponse: def list_features( category: str | None = Query(None, description="Filter by category"), active_only: bool = Query(False, description="Only active features"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """List all features with their tier assignments.""" @@ -161,7 +161,7 @@ def list_features( @router.get("/categories", response_model=CategoryListResponse) def list_categories( - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """List all feature categories.""" @@ -171,7 +171,7 @@ def list_categories( @router.get("/tiers", response_model=TierListWithFeaturesResponse) def list_tiers_with_features( - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """List all tiers with their feature assignments.""" @@ -195,7 +195,7 @@ def list_tiers_with_features( @router.get("/{feature_code}", response_model=FeatureResponse) def get_feature( feature_code: str, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -217,7 +217,7 @@ def get_feature( def update_feature( feature_code: str, request: UpdateFeatureRequest, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -253,7 +253,7 @@ def update_feature( def update_tier_features( tier_code: str, request: UpdateTierFeaturesRequest, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -282,7 +282,7 @@ def update_tier_features( @router.get("/tiers/{tier_code}/features", response_model=TierFeatureDetailResponse) def get_tier_features( tier_code: str, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/admin/images.py b/app/api/v1/admin/images.py index e5f11ed2..ed970ce9 100644 --- a/app/api/v1/admin/images.py +++ b/app/api/v1/admin/images.py @@ -14,7 +14,7 @@ from fastapi import APIRouter, Depends, File, Form, UploadFile from app.api.deps import get_current_admin_api from app.services.image_service import image_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.image import ( ImageDeleteResponse, ImageStorageStats, @@ -30,7 +30,7 @@ async def upload_image( file: UploadFile = File(...), vendor_id: int = Form(...), product_id: int | None = Form(None), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Upload and process an image. @@ -67,7 +67,7 @@ async def upload_image( @router.delete("/{image_hash}", response_model=ImageDeleteResponse) async def delete_image( image_hash: str, - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Delete an image and all its variants. @@ -88,7 +88,7 @@ async def delete_image( @router.get("/stats", response_model=ImageStorageStats) async def get_storage_stats( - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get image storage statistics. diff --git a/app/api/v1/admin/inventory.py b/app/api/v1/admin/inventory.py index 4e78065f..ceaef0bb 100644 --- a/app/api/v1/admin/inventory.py +++ b/app/api/v1/admin/inventory.py @@ -23,7 +23,7 @@ from app.core.database import get_db from app.services.inventory_import_service import inventory_import_service from app.services.inventory_service import inventory_service from app.services.inventory_transaction_service import inventory_transaction_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.inventory.schemas import ( AdminInventoryAdjust, AdminInventoryCreate, @@ -61,7 +61,7 @@ def get_all_inventory( low_stock: int | None = Query(None, ge=0, description="Filter items below threshold"), search: str | None = Query(None, description="Search by product title or SKU"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get inventory across all vendors with filtering. @@ -82,7 +82,7 @@ def get_all_inventory( @router.get("/stats", response_model=AdminInventoryStats) def get_inventory_stats( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get platform-wide inventory statistics.""" return inventory_service.get_inventory_stats_admin(db) @@ -94,7 +94,7 @@ def get_low_stock_items( vendor_id: int | None = Query(None, description="Filter by vendor"), limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get items with low stock levels.""" return inventory_service.get_low_stock_items_admin( @@ -108,7 +108,7 @@ def get_low_stock_items( @router.get("/vendors", response_model=AdminVendorsWithInventoryResponse) def get_vendors_with_inventory( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of vendors that have inventory entries.""" return inventory_service.get_vendors_with_inventory_admin(db) @@ -118,7 +118,7 @@ def get_vendors_with_inventory( def get_inventory_locations( vendor_id: int | None = Query(None, description="Filter by vendor"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of unique inventory locations.""" return inventory_service.get_inventory_locations_admin(db, vendor_id) @@ -137,7 +137,7 @@ def get_vendor_inventory( location: str | None = Query(None, description="Filter by location"), low_stock: int | None = Query(None, ge=0, description="Filter items below threshold"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get inventory for a specific vendor.""" return inventory_service.get_vendor_inventory_admin( @@ -154,7 +154,7 @@ def get_vendor_inventory( def get_product_inventory( product_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get inventory summary for a specific product across all locations.""" return inventory_service.get_product_inventory_admin(db, product_id) @@ -169,7 +169,7 @@ def get_product_inventory( def set_inventory( inventory_data: AdminInventoryCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Set exact inventory quantity for a product at a location. @@ -205,7 +205,7 @@ def set_inventory( def adjust_inventory( adjustment: AdminInventoryAdjust, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Adjust inventory by adding or removing quantity. @@ -245,7 +245,7 @@ def update_inventory( inventory_id: int, inventory_update: InventoryUpdate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Update inventory entry fields.""" # Get inventory to find vendor_id @@ -268,7 +268,7 @@ def update_inventory( def delete_inventory( inventory_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Delete inventory entry.""" # Get inventory to find vendor_id and log details @@ -324,7 +324,7 @@ async def import_inventory( warehouse: str = Form("strassen", description="Warehouse name"), clear_existing: bool = Form(False, description="Clear existing inventory before import"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Import inventory from a TSV/CSV file. @@ -398,7 +398,7 @@ def get_all_transactions( transaction_type: str | None = Query(None, description="Filter by type"), order_id: int | None = Query(None, description="Filter by order"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get inventory transaction history across all vendors. @@ -426,7 +426,7 @@ def get_all_transactions( @router.get("/transactions/stats", response_model=AdminTransactionStatsResponse) def get_transaction_stats( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get transaction statistics for the platform.""" stats = inventory_transaction_service.get_transaction_stats_admin(db) diff --git a/app/api/v1/admin/letzshop.py b/app/api/v1/admin/letzshop.py index f1c2a386..bf70114a 100644 --- a/app/api/v1/admin/letzshop.py +++ b/app/api/v1/admin/letzshop.py @@ -32,7 +32,7 @@ from app.services.letzshop import ( VendorNotFoundError, ) from app.tasks.letzshop_tasks import process_historical_import -from models.database.user import User +from models.schema.auth import UserContext from app.modules.marketplace.schemas import ( FulfillmentOperationResponse, LetzshopCachedVendorDetail, @@ -96,7 +96,7 @@ def list_vendors_letzshop_status( False, description="Only show vendors with Letzshop configured" ), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ List all vendors with their Letzshop integration status. @@ -130,7 +130,7 @@ def list_vendors_letzshop_status( def get_vendor_credentials( vendor_id: int = Path(..., description="Vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get Letzshop credentials for a vendor (API key is masked).""" order_service = get_order_service(db) @@ -173,7 +173,7 @@ def create_or_update_vendor_credentials( vendor_id: int = Path(..., description="Vendor ID"), credentials_data: LetzshopCredentialsCreate = ..., db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Create or update Letzshop credentials for a vendor.""" order_service = get_order_service(db) @@ -220,7 +220,7 @@ def update_vendor_credentials( vendor_id: int = Path(..., description="Vendor ID"), credentials_data: LetzshopCredentialsUpdate = ..., db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Partially update Letzshop credentials for a vendor.""" order_service = get_order_service(db) @@ -269,7 +269,7 @@ def update_vendor_credentials( def delete_vendor_credentials( vendor_id: int = Path(..., description="Vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Delete Letzshop credentials for a vendor.""" order_service = get_order_service(db) @@ -308,7 +308,7 @@ def delete_vendor_credentials( def test_vendor_connection( vendor_id: int = Path(..., description="Vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Test the Letzshop connection for a vendor using stored credentials.""" order_service = get_order_service(db) @@ -333,7 +333,7 @@ def test_vendor_connection( def test_api_key( test_request: LetzshopConnectionTestRequest, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Test a Letzshop API key without saving it.""" creds_service = get_credentials_service(db) @@ -372,7 +372,7 @@ def list_all_letzshop_orders( None, description="Search by order number, customer name, or email" ), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ List Letzshop orders across all vendors (or for a specific vendor). @@ -462,7 +462,7 @@ def list_vendor_letzshop_orders( None, description="Search by order number, customer name, or email" ), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """List Letzshop orders for a vendor.""" order_service = get_order_service(db) @@ -543,7 +543,7 @@ def list_vendor_letzshop_orders( def get_letzshop_order_detail( order_id: int = Path(..., description="Letzshop order ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get detailed information for a single Letzshop order.""" order_service = get_order_service(db) @@ -623,7 +623,7 @@ def trigger_vendor_sync( vendor_id: int = Path(..., description="Vendor ID"), sync_request: LetzshopSyncTriggerRequest = LetzshopSyncTriggerRequest(), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Trigger a sync operation for a vendor. @@ -721,7 +721,7 @@ def list_all_letzshop_jobs( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get unified list of all Letzshop-related jobs across all vendors. @@ -753,7 +753,7 @@ def list_vendor_letzshop_jobs( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get unified list of Letzshop-related jobs for a vendor. @@ -794,7 +794,7 @@ def start_historical_import( vendor_id: int = Path(..., description="Vendor ID"), background_tasks: BackgroundTasks = None, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Start historical order import from Letzshop as a background job. @@ -861,7 +861,7 @@ def get_historical_import_status( vendor_id: int = Path(..., description="Vendor ID"), job_id: int = Path(..., description="Import job ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get status of a historical import job. @@ -884,7 +884,7 @@ def get_historical_import_status( def get_import_summary( vendor_id: int = Path(..., description="Vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get summary statistics for imported Letzshop orders. @@ -919,7 +919,7 @@ def confirm_order( vendor_id: int = Path(..., description="Vendor ID"), order_id: int = Path(..., description="Order ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Confirm all inventory units for a Letzshop order. @@ -1004,7 +1004,7 @@ def reject_order( vendor_id: int = Path(..., description="Vendor ID"), order_id: int = Path(..., description="Order ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Decline all inventory units for a Letzshop order. @@ -1079,7 +1079,7 @@ def confirm_single_item( order_id: int = Path(..., description="Order ID"), item_id: str = Path(..., description="External Item ID (Letzshop inventory unit ID)"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Confirm a single inventory unit in an order. @@ -1144,7 +1144,7 @@ def decline_single_item( order_id: int = Path(..., description="Order ID"), item_id: str = Path(..., description="External Item ID (Letzshop inventory unit ID)"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Decline a single inventory unit in an order. @@ -1199,7 +1199,7 @@ def decline_single_item( def sync_tracking_for_vendor( vendor_id: int = Path(..., description="Vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Sync tracking information from Letzshop for confirmed orders. @@ -1297,7 +1297,7 @@ def get_vendor_sync_service(db: Session) -> LetzshopVendorSyncService: def trigger_vendor_directory_sync( background_tasks: BackgroundTasks, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Trigger a sync of the Letzshop vendor directory. @@ -1351,7 +1351,7 @@ def trigger_vendor_directory_sync( ) def get_vendor_directory_stats( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> LetzshopVendorDirectoryStatsResponse: """ Get statistics about the Letzshop vendor directory cache. @@ -1377,7 +1377,7 @@ def list_cached_vendors( page: int = Query(1, ge=1), limit: int = Query(20, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> LetzshopCachedVendorListResponse: """ List cached Letzshop vendors with search and filtering. @@ -1429,7 +1429,7 @@ def list_cached_vendors( def get_cached_vendor_detail( slug: str = Path(..., description="Letzshop vendor slug"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> LetzshopCachedVendorDetailResponse: """ Get detailed information about a cached Letzshop vendor. @@ -1487,7 +1487,7 @@ def create_vendor_from_letzshop( slug: str = Path(..., description="Letzshop vendor slug"), company_id: int = Query(..., description="Company ID to create vendor under"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> LetzshopCreateVendorFromCacheResponse: """ Create a platform vendor from a cached Letzshop vendor. diff --git a/app/api/v1/admin/logs.py b/app/api/v1/admin/logs.py index fd8ae8bb..e706bb6d 100644 --- a/app/api/v1/admin/logs.py +++ b/app/api/v1/admin/logs.py @@ -22,7 +22,7 @@ from app.exceptions import ConfirmationRequiredException, ResourceNotFoundExcept from app.services.admin_audit_service import admin_audit_service from app.services.admin_settings_service import admin_settings_service from app.services.log_service import log_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.admin import ( ApplicationLogFilters, ApplicationLogListResponse, @@ -56,7 +56,7 @@ def get_database_logs( skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get logs from database with filtering. @@ -82,7 +82,7 @@ def get_database_logs( def get_log_statistics( days: int = Query(7, ge=1, le=90, description="Number of days to analyze"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get log statistics for the last N days. @@ -97,7 +97,7 @@ def cleanup_old_logs( retention_days: int = Query(30, ge=1, le=365), confirm: bool = Query(False, description="Must be true to confirm cleanup"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Delete logs older than retention period. @@ -129,7 +129,7 @@ def cleanup_old_logs( def delete_log( log_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Delete a specific log entry.""" message = log_service.delete_log(db, log_id) @@ -154,7 +154,7 @@ def delete_log( @router.get("/files", response_model=LogFileListResponse) def list_log_files( - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ List all available log files. @@ -168,7 +168,7 @@ def list_log_files( def get_file_log( filename: str, lines: int = Query(500, ge=1, le=10000, description="Number of lines to read"), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Read log file content. @@ -181,7 +181,7 @@ def get_file_log( @router.get("/files/{filename}/download") def download_log_file( filename: str, - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Download log file. @@ -237,7 +237,7 @@ def download_log_file( @router.get("/settings", response_model=LogSettingsResponse) def get_log_settings( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get current log configuration settings.""" log_level = admin_settings_service.get_setting_value(db, "log_level", "INFO") @@ -271,7 +271,7 @@ def get_log_settings( def update_log_settings( settings_update: LogSettingsUpdate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Update log configuration settings. diff --git a/app/api/v1/admin/marketplace.py b/app/api/v1/admin/marketplace.py index d9cd9980..450e9a8e 100644 --- a/app/api/v1/admin/marketplace.py +++ b/app/api/v1/admin/marketplace.py @@ -14,7 +14,7 @@ from app.services.marketplace_import_job_service import marketplace_import_job_s from app.services.stats_service import stats_service from app.services.vendor_service import vendor_service from app.tasks.background_tasks import process_marketplace_import -from models.database.user import User +from models.schema.auth import UserContext from app.modules.marketplace.schemas import ( AdminMarketplaceImportJobListResponse, AdminMarketplaceImportJobRequest, @@ -37,7 +37,7 @@ def get_all_marketplace_import_jobs( page: int = Query(1, ge=1), limit: int = Query(100, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get all marketplace import jobs with pagination (Admin only).""" jobs, total = marketplace_import_job_service.get_all_import_jobs_paginated( @@ -64,7 +64,7 @@ async def create_marketplace_import_job( request: AdminMarketplaceImportJobRequest, background_tasks: BackgroundTasks, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Create a new marketplace import job (Admin only). @@ -122,7 +122,7 @@ async def create_marketplace_import_job( @router.get("/stats", response_model=ImportStatsResponse) def get_import_statistics( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get marketplace import statistics (Admin only).""" stats = stats_service.get_import_statistics(db) @@ -133,7 +133,7 @@ def get_import_statistics( def get_marketplace_import_job( job_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get a single marketplace import job by ID (Admin only).""" job = marketplace_import_job_service.get_import_job_by_id_admin(db, job_id) @@ -147,7 +147,7 @@ def get_import_job_errors( limit: int = Query(50, ge=1, le=100), error_type: str | None = Query(None, description="Filter by error type"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get import errors for a specific job (Admin only). diff --git a/app/api/v1/admin/media.py b/app/api/v1/admin/media.py index b53badbe..9fbac5ef 100644 --- a/app/api/v1/admin/media.py +++ b/app/api/v1/admin/media.py @@ -13,7 +13,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.media_service import media_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.media import ( MediaDetailResponse, MediaItemResponse, @@ -33,7 +33,7 @@ def get_vendor_media_library( media_type: str | None = Query(None, description="image, video, document"), folder: str | None = Query(None, description="Filter by folder"), search: str | None = Query(None), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -64,7 +64,7 @@ async def upload_vendor_media( vendor_id: int, file: UploadFile = File(...), folder: str | None = Query("products", description="products, general, etc."), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -98,7 +98,7 @@ async def upload_vendor_media( def get_vendor_media_detail( vendor_id: int, media_id: int, - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -118,7 +118,7 @@ def get_vendor_media_detail( def delete_vendor_media( vendor_id: int, media_id: int, - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/admin/menu_config.py b/app/api/v1/admin/menu_config.py index 3517979b..3f84c7f8 100644 --- a/app/api/v1/admin/menu_config.py +++ b/app/api/v1/admin/menu_config.py @@ -29,8 +29,8 @@ from app.api.deps import ( ) from app.services.menu_service import MenuItemConfig, menu_service from app.services.platform_service import platform_service -from models.database.admin_menu_config import FrontendType -from models.database.user import User +from models.database.admin_menu_config import FrontendType # noqa: API-007 - Enum for type safety +from models.schema.auth import UserContext logger = logging.getLogger(__name__) router = APIRouter(prefix="/menu-config") @@ -159,7 +159,7 @@ async def get_platform_menu_config( FrontendType.ADMIN, description="Frontend type (admin or vendor)" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Get menu configuration for a platform. @@ -188,7 +188,7 @@ async def update_platform_menu_visibility( FrontendType.ADMIN, description="Frontend type (admin or vendor)" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Update visibility for a single menu item for a platform. @@ -224,7 +224,7 @@ async def bulk_update_platform_menu_visibility( FrontendType.ADMIN, description="Frontend type (admin or vendor)" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Update visibility for multiple menu items at once. @@ -257,7 +257,7 @@ async def reset_platform_menu_config( FrontendType.ADMIN, description="Frontend type (admin or vendor)" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Reset menu configuration for a platform to defaults. @@ -287,7 +287,7 @@ async def reset_platform_menu_config( @router.get("/user", response_model=MenuConfigResponse) async def get_user_menu_config( db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Get the current super admin's personal menu configuration. @@ -309,7 +309,7 @@ async def get_user_menu_config( async def update_user_menu_visibility( update_data: MenuVisibilityUpdateRequest, db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Update visibility for a single menu item for the current super admin. @@ -336,7 +336,7 @@ async def update_user_menu_visibility( @router.post("/user/reset", response_model=MenuActionResponse) async def reset_user_menu_config( db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Reset the current super admin's menu configuration (hide all except mandatory). @@ -356,7 +356,7 @@ async def reset_user_menu_config( @router.post("/user/show-all", response_model=MenuActionResponse) async def show_all_user_menu_config( db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Show all menu items for the current super admin. @@ -380,7 +380,7 @@ async def show_all_platform_menu_config( FrontendType.ADMIN, description="Frontend type (admin or vendor)" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Show all menu items for a platform. @@ -409,7 +409,7 @@ async def show_all_platform_menu_config( @router.get("/render/admin", response_model=RenderedMenuResponse) async def get_rendered_admin_menu( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_from_cookie_or_header), + current_user: UserContext = Depends(get_current_admin_from_cookie_or_header), ): """ Get the rendered admin menu for the current user. diff --git a/app/api/v1/admin/messages.py b/app/api/v1/admin/messages.py index 62edf662..8fcea07e 100644 --- a/app/api/v1/admin/messages.py +++ b/app/api/v1/admin/messages.py @@ -46,7 +46,7 @@ from app.modules.messaging.schemas import ( ReopenConversationResponse, UnreadCountResponse, ) -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/messages") logger = logging.getLogger(__name__) @@ -184,7 +184,7 @@ def list_conversations( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> AdminConversationListResponse: """List conversations for admin (admin_vendor and admin_customer channels).""" conversations, total, total_unread = messaging_service.list_conversations( @@ -211,7 +211,7 @@ def list_conversations( @router.get("/unread-count", response_model=UnreadCountResponse) def get_unread_count( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> UnreadCountResponse: """Get total unread message count for header badge.""" count = messaging_service.get_unread_count( @@ -235,7 +235,7 @@ def get_recipients( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> RecipientListResponse: """Get list of available recipients for compose modal.""" if recipient_type == ParticipantType.VENDOR: @@ -291,7 +291,7 @@ def get_recipients( def create_conversation( data: ConversationCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> ConversationDetailResponse: """Create a new conversation.""" # Validate conversation type for admin @@ -428,7 +428,7 @@ def get_conversation( conversation_id: int, mark_read: bool = Query(True, description="Automatically mark as read"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> ConversationDetailResponse: """Get conversation detail with messages.""" conversation = messaging_service.get_conversation( @@ -465,7 +465,7 @@ async def send_message( content: str = Form(...), files: list[UploadFile] = File(default=[]), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> MessageResponse: """Send a message in a conversation, optionally with attachments.""" # Verify access @@ -522,7 +522,7 @@ async def send_message( def close_conversation( conversation_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> CloseConversationResponse: """Close a conversation.""" conversation = messaging_service.close_conversation( @@ -551,7 +551,7 @@ def close_conversation( def reopen_conversation( conversation_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> ReopenConversationResponse: """Reopen a closed conversation.""" conversation = messaging_service.reopen_conversation( @@ -580,7 +580,7 @@ def reopen_conversation( def mark_read( conversation_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> MarkReadResponse: """Mark conversation as read.""" success = messaging_service.mark_conversation_read( @@ -608,7 +608,7 @@ def update_preferences( conversation_id: int, preferences: NotificationPreferencesUpdate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> PreferencesUpdateResponse: """Update notification preferences for a conversation.""" success = messaging_service.update_notification_preferences( diff --git a/app/api/v1/admin/module_config.py b/app/api/v1/admin/module_config.py index e4b745fd..9cd5436c 100644 --- a/app/api/v1/admin/module_config.py +++ b/app/api/v1/admin/module_config.py @@ -22,7 +22,7 @@ from app.exceptions import ValidationException from app.modules.registry import MODULES from app.modules.service import module_service from app.services.platform_service import platform_service -from models.database.user import User +from models.schema.auth import UserContext logger = logging.getLogger(__name__) router = APIRouter(prefix="/module-config") @@ -267,7 +267,7 @@ async def get_module_config( platform_id: int = Path(..., description="Platform ID"), module_code: str = Path(..., description="Module code"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Get configuration for a specific module on a platform. @@ -311,7 +311,7 @@ async def update_module_config( platform_id: int = Path(..., description="Platform ID"), module_code: str = Path(..., description="Module code"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Update configuration for a specific module on a platform. @@ -354,7 +354,7 @@ async def update_module_config( @router.get("/defaults/{module_code}", response_model=ConfigDefaultsResponse) async def get_config_defaults( module_code: str = Path(..., description="Module code"), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Get default configuration for a module. @@ -386,7 +386,7 @@ async def reset_module_config( platform_id: int = Path(..., description="Platform ID"), module_code: str = Path(..., description="Module code"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Reset module configuration to defaults. diff --git a/app/api/v1/admin/modules.py b/app/api/v1/admin/modules.py index cc291903..2a580387 100644 --- a/app/api/v1/admin/modules.py +++ b/app/api/v1/admin/modules.py @@ -22,7 +22,7 @@ from app.api.deps import get_current_super_admin, get_db from app.modules.registry import MODULES, get_core_module_codes from app.modules.service import module_service from app.services.platform_service import platform_service -from models.database.user import User +from models.schema.auth import UserContext logger = logging.getLogger(__name__) router = APIRouter(prefix="/modules") @@ -100,7 +100,7 @@ def _build_module_response( is_enabled: bool, ) -> ModuleResponse: """Build ModuleResponse from module code.""" - from models.database.admin_menu_config import FrontendType + from models.database.admin_menu_config import FrontendType # noqa: API-007 - Enum for type safety module = MODULES.get(code) if not module: @@ -127,7 +127,7 @@ def _build_module_response( @router.get("", response_model=ModuleListResponse) async def list_all_modules( - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ List all available modules. @@ -157,7 +157,7 @@ async def list_all_modules( async def get_platform_modules( platform_id: int = Path(..., description="Platform ID"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Get module configuration for a platform. @@ -202,7 +202,7 @@ async def update_platform_modules( update_data: EnableModulesRequest, platform_id: int = Path(..., description="Platform ID"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Update enabled modules for a platform. @@ -250,7 +250,7 @@ async def enable_module( request: ToggleModuleRequest, platform_id: int = Path(..., description="Platform ID"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Enable a single module for a platform. @@ -293,7 +293,7 @@ async def disable_module( request: ToggleModuleRequest, platform_id: int = Path(..., description="Platform ID"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Disable a single module for a platform. @@ -341,7 +341,7 @@ async def disable_module( async def enable_all_modules( platform_id: int = Path(..., description="Platform ID"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Enable all modules for a platform. @@ -372,7 +372,7 @@ async def enable_all_modules( async def disable_optional_modules( platform_id: int = Path(..., description="Platform ID"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_super_admin), + current_user: UserContext = Depends(get_current_super_admin), ): """ Disable all optional modules for a platform, keeping only core modules. diff --git a/app/api/v1/admin/notifications.py b/app/api/v1/admin/notifications.py index 656aaae6..484e1f26 100644 --- a/app/api/v1/admin/notifications.py +++ b/app/api/v1/admin/notifications.py @@ -19,7 +19,7 @@ from app.services.admin_notification_service import ( admin_notification_service, platform_alert_service, ) -from models.database.user import User +from models.schema.auth import UserContext from models.schema.admin import ( AdminNotificationCreate, AdminNotificationListResponse, @@ -52,7 +52,7 @@ def get_notifications( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> AdminNotificationListResponse: """Get admin notifications with filtering.""" notifications, total, unread_count = admin_notification_service.get_notifications( @@ -93,7 +93,7 @@ def get_notifications( def create_notification( notification_data: AdminNotificationCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> AdminNotificationResponse: """Create a new admin notification (manual).""" notification = admin_notification_service.create_from_schema( @@ -123,7 +123,7 @@ def create_notification( def get_recent_notifications( limit: int = Query(5, ge=1, le=10), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> dict: """Get recent unread notifications for header dropdown.""" notifications = admin_notification_service.get_recent_notifications( @@ -151,7 +151,7 @@ def get_recent_notifications( @router.get("/unread-count", response_model=UnreadCountResponse) def get_unread_count( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> UnreadCountResponse: """Get count of unread notifications.""" count = admin_notification_service.get_unread_count(db) @@ -162,7 +162,7 @@ def get_unread_count( def mark_as_read( notification_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> MessageResponse: """Mark notification as read.""" notification = admin_notification_service.mark_as_read( @@ -178,7 +178,7 @@ def mark_as_read( @router.put("/mark-all-read", response_model=MessageResponse) def mark_all_as_read( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> MessageResponse: """Mark all notifications as read.""" count = admin_notification_service.mark_all_as_read( @@ -193,7 +193,7 @@ def mark_all_as_read( def delete_notification( notification_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> MessageResponse: """Delete a notification.""" deleted = admin_notification_service.delete_notification( @@ -220,7 +220,7 @@ def get_platform_alerts( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=100), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> PlatformAlertListResponse: """Get platform alerts with filtering.""" alerts, total, active_count, critical_count = platform_alert_service.get_alerts( @@ -266,7 +266,7 @@ def get_platform_alerts( def create_platform_alert( alert_data: PlatformAlertCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> PlatformAlertResponse: """Create new platform alert (manual).""" alert = platform_alert_service.create_from_schema(db=db, data=alert_data) @@ -299,7 +299,7 @@ def resolve_platform_alert( alert_id: int, resolve_data: PlatformAlertResolve, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> MessageResponse: """Resolve platform alert.""" alert = platform_alert_service.resolve_alert( @@ -320,7 +320,7 @@ def resolve_platform_alert( @router.get("/alerts/stats", response_model=AlertStatisticsResponse) def get_alert_statistics( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> AlertStatisticsResponse: """Get alert statistics for dashboard.""" stats = platform_alert_service.get_statistics(db) diff --git a/app/api/v1/admin/order_item_exceptions.py b/app/api/v1/admin/order_item_exceptions.py index dcf106fb..28ab643d 100644 --- a/app/api/v1/admin/order_item_exceptions.py +++ b/app/api/v1/admin/order_item_exceptions.py @@ -17,7 +17,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.order_item_exception_service import order_item_exception_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.orders.schemas import ( BulkResolveRequest, BulkResolveResponse, @@ -53,7 +53,7 @@ def list_exceptions( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ List order item exceptions with filtering and pagination. @@ -96,7 +96,7 @@ def list_exceptions( def get_exception_stats( vendor_id: int | None = Query(None, description="Filter by vendor"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get exception statistics. @@ -116,7 +116,7 @@ def get_exception_stats( def get_exception( exception_id: int = Path(..., description="Exception ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get details of a single exception. @@ -144,7 +144,7 @@ def resolve_exception( exception_id: int = Path(..., description="Exception ID"), request: ResolveExceptionRequest = ..., db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Resolve an exception by assigning a product. @@ -181,7 +181,7 @@ def ignore_exception( exception_id: int = Path(..., description="Exception ID"), request: IgnoreExceptionRequest = ..., db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Mark an exception as ignored. @@ -222,7 +222,7 @@ def bulk_resolve_by_gtin( request: BulkResolveRequest, vendor_id: int = Query(..., description="Vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Bulk resolve all pending exceptions for a GTIN. diff --git a/app/api/v1/admin/orders.py b/app/api/v1/admin/orders.py index f041efa1..63ecc930 100644 --- a/app/api/v1/admin/orders.py +++ b/app/api/v1/admin/orders.py @@ -20,7 +20,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.order_service import order_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.orders.schemas import ( AdminOrderItem, AdminOrderListResponse, @@ -50,7 +50,7 @@ def get_all_orders( channel: str | None = Query(None, description="Filter by channel"), search: str | None = Query(None, description="Search by order number or customer"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get orders across all vendors with filtering. @@ -78,7 +78,7 @@ def get_all_orders( @router.get("/stats", response_model=AdminOrderStats) def get_order_stats( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get platform-wide order statistics.""" return order_service.get_order_stats_admin(db) @@ -87,7 +87,7 @@ def get_order_stats( @router.get("/vendors", response_model=AdminVendorsWithOrdersResponse) def get_vendors_with_orders( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of vendors that have orders.""" vendors = order_service.get_vendors_with_orders_admin(db) @@ -103,7 +103,7 @@ def get_vendors_with_orders( def get_order_detail( order_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get order details including items and addresses.""" order = order_service.get_order_by_id_admin(db, order_id) @@ -122,7 +122,7 @@ def update_order_status( order_id: int, status_update: AdminOrderStatusUpdate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Update order status. @@ -152,7 +152,7 @@ def mark_order_as_shipped( order_id: int, ship_request: MarkAsShippedRequest, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Mark an order as shipped with optional tracking information. @@ -182,7 +182,7 @@ def mark_order_as_shipped( def get_shipping_label_info( order_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get shipping label information for an order. diff --git a/app/api/v1/admin/platform_health.py b/app/api/v1/admin/platform_health.py index 19d7f02f..fcd6585a 100644 --- a/app/api/v1/admin/platform_health.py +++ b/app/api/v1/admin/platform_health.py @@ -17,7 +17,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.platform_health_service import platform_health_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter() logger = logging.getLogger(__name__) @@ -115,7 +115,7 @@ class CapacityMetricsResponse(BaseModel): @router.get("/health", response_model=PlatformHealthResponse) async def get_platform_health( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get comprehensive platform health status. @@ -139,7 +139,7 @@ async def get_platform_health( @router.get("/capacity", response_model=CapacityMetricsResponse) async def get_capacity_metrics( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get capacity-focused metrics for planning.""" metrics = platform_health_service.get_capacity_metrics(db) @@ -149,7 +149,7 @@ async def get_capacity_metrics( @router.get("/subscription-capacity") async def get_subscription_capacity( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get subscription-based capacity metrics. @@ -163,7 +163,7 @@ async def get_subscription_capacity( async def get_growth_trends( days: int = 30, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get growth trends over the specified period. @@ -178,7 +178,7 @@ async def get_growth_trends( @router.get("/recommendations") async def get_scaling_recommendations( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get scaling recommendations based on current capacity and growth. @@ -193,7 +193,7 @@ async def get_scaling_recommendations( @router.post("/snapshot") async def capture_snapshot( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Manually capture a capacity snapshot. diff --git a/app/api/v1/admin/platforms.py b/app/api/v1/admin/platforms.py index bae6e1e5..1506dc44 100644 --- a/app/api/v1/admin/platforms.py +++ b/app/api/v1/admin/platforms.py @@ -23,7 +23,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_from_cookie_or_header, get_db from app.services.platform_service import platform_service -from models.database.user import User +from models.schema.auth import UserContext logger = logging.getLogger(__name__) router = APIRouter(prefix="/platforms") @@ -142,7 +142,7 @@ def _build_platform_response(db: Session, platform) -> PlatformResponse: @router.get("", response_model=PlatformListResponse) async def list_platforms( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_from_cookie_or_header), + current_user: UserContext = Depends(get_current_admin_from_cookie_or_header), include_inactive: bool = Query(False, description="Include inactive platforms"), ): """ @@ -163,7 +163,7 @@ async def list_platforms( async def get_platform( code: str = Path(..., description="Platform code (oms, loyalty, etc.)"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_from_cookie_or_header), + current_user: UserContext = Depends(get_current_admin_from_cookie_or_header), ): """ Get platform details by code. @@ -179,7 +179,7 @@ async def update_platform( update_data: PlatformUpdateRequest, code: str = Path(..., description="Platform code"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_from_cookie_or_header), + current_user: UserContext = Depends(get_current_admin_from_cookie_or_header), ): """ Update platform settings. @@ -201,7 +201,7 @@ async def update_platform( async def get_platform_stats( code: str = Path(..., description="Platform code"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_from_cookie_or_header), + current_user: UserContext = Depends(get_current_admin_from_cookie_or_header), ): """ Get detailed statistics for a platform. diff --git a/app/api/v1/admin/products.py b/app/api/v1/admin/products.py index 8d13fd2e..03171e87 100644 --- a/app/api/v1/admin/products.py +++ b/app/api/v1/admin/products.py @@ -19,7 +19,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.marketplace_product_service import marketplace_product_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/products") logger = logging.getLogger(__name__) @@ -161,7 +161,7 @@ def get_products( is_digital: bool | None = Query(None, description="Filter by digital products"), language: str = Query("en", description="Language for title lookup"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get all marketplace products with search and filtering. @@ -195,7 +195,7 @@ def get_product_stats( marketplace: str | None = Query(None, description="Filter by marketplace"), vendor_name: str | None = Query(None, description="Filter by vendor name"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get product statistics for admin dashboard.""" stats = marketplace_product_service.get_admin_product_stats( @@ -207,7 +207,7 @@ def get_product_stats( @router.get("/marketplaces", response_model=MarketplacesResponse) def get_marketplaces( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of unique marketplaces in the product catalog.""" marketplaces = marketplace_product_service.get_marketplaces_list(db) @@ -217,7 +217,7 @@ def get_marketplaces( @router.get("/vendors", response_model=VendorsResponse) def get_product_vendors( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of unique vendor names in the product catalog.""" vendors = marketplace_product_service.get_source_vendors_list(db) @@ -228,7 +228,7 @@ def get_product_vendors( def copy_products_to_vendor( request: CopyToVendorRequest, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Copy marketplace products to a vendor's catalog. @@ -253,7 +253,7 @@ def copy_products_to_vendor( def get_product_detail( product_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get detailed product information including all translations.""" product = marketplace_product_service.get_admin_product_detail(db, product_id) diff --git a/app/api/v1/admin/settings.py b/app/api/v1/admin/settings.py index 6e2e8411..66840b99 100644 --- a/app/api/v1/admin/settings.py +++ b/app/api/v1/admin/settings.py @@ -21,7 +21,7 @@ from app.core.database import get_db from app.exceptions import ConfirmationRequiredException, ResourceNotFoundException from app.services.admin_audit_service import admin_audit_service from app.services.admin_settings_service import admin_settings_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.admin import ( AdminSettingCreate, AdminSettingDefaultResponse, @@ -42,7 +42,7 @@ def get_all_settings( category: str | None = Query(None, description="Filter by category"), is_public: bool | None = Query(None, description="Filter by public flag"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get all platform settings. @@ -60,7 +60,7 @@ def get_all_settings( @router.get("/categories") def get_setting_categories( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of all setting categories.""" # This could be enhanced to return counts per category @@ -81,7 +81,7 @@ def get_setting( key: str, default: str | None = Query(None, description="Default value if setting not found"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> AdminSettingResponse | AdminSettingDefaultResponse: """Get specific setting by key. @@ -103,7 +103,7 @@ def get_setting( def create_setting( setting_data: AdminSettingCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Create new platform setting. @@ -136,7 +136,7 @@ def update_setting( key: str, update_data: AdminSettingUpdate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Update existing setting value.""" old_value = admin_settings_service.get_setting_value(db, key) @@ -163,7 +163,7 @@ def update_setting( def upsert_setting( setting_data: AdminSettingCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Create or update setting (upsert). @@ -196,7 +196,7 @@ def upsert_setting( @router.get("/display/rows-per-page", response_model=RowsPerPageResponse) def get_rows_per_page( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> RowsPerPageResponse: """Get the platform-wide rows per page setting.""" value = admin_settings_service.get_setting_value(db, "rows_per_page", default="20") @@ -207,7 +207,7 @@ def get_rows_per_page( def set_rows_per_page( rows: int = Query(..., ge=10, le=100, description="Rows per page (10-100)"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> RowsPerPageUpdateResponse: """ Set the platform-wide rows per page setting. @@ -268,7 +268,7 @@ def delete_setting( key: str, confirm: bool = Query(False, description="Must be true to confirm deletion"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Delete platform setting. @@ -473,7 +473,7 @@ class TestEmailResponse(BaseModel): @router.get("/email/status", response_model=EmailStatusResponse) def get_email_status( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> EmailStatusResponse: """ Get platform email configuration status. @@ -519,7 +519,7 @@ def get_email_status( def update_email_settings( settings_update: EmailSettingsUpdate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Update platform email settings. @@ -607,7 +607,7 @@ def update_email_settings( @router.delete("/email/settings") def reset_email_settings( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Reset email settings to use .env values. @@ -646,7 +646,7 @@ def reset_email_settings( def send_test_email( request: TestEmailRequest, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ) -> TestEmailResponse: """ Send a test email using the platform email configuration. diff --git a/app/api/v1/admin/subscriptions.py b/app/api/v1/admin/subscriptions.py index 22700495..f4743b90 100644 --- a/app/api/v1/admin/subscriptions.py +++ b/app/api/v1/admin/subscriptions.py @@ -18,7 +18,7 @@ from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.admin_subscription_service import admin_subscription_service from app.services.subscription_service import subscription_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.billing.schemas import ( BillingHistoryListResponse, BillingHistoryWithVendor, @@ -46,7 +46,7 @@ logger = logging.getLogger(__name__) @router.get("/tiers", response_model=SubscriptionTierListResponse) def list_subscription_tiers( include_inactive: bool = Query(False, description="Include inactive tiers"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -65,7 +65,7 @@ def list_subscription_tiers( @router.get("/tiers/{tier_code}", response_model=SubscriptionTierResponse) def get_subscription_tier( tier_code: str = Path(..., description="Tier code"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """Get a specific subscription tier by code.""" @@ -76,7 +76,7 @@ def get_subscription_tier( @router.post("/tiers", response_model=SubscriptionTierResponse, status_code=201) def create_subscription_tier( tier_data: SubscriptionTierCreate, - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """Create a new subscription tier.""" @@ -90,7 +90,7 @@ def create_subscription_tier( def update_subscription_tier( tier_data: SubscriptionTierUpdate, tier_code: str = Path(..., description="Tier code"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """Update a subscription tier.""" @@ -104,7 +104,7 @@ def update_subscription_tier( @router.delete("/tiers/{tier_code}", status_code=204) def delete_subscription_tier( tier_code: str = Path(..., description="Tier code"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -128,7 +128,7 @@ def list_vendor_subscriptions( status: str | None = Query(None, description="Filter by status"), tier: str | None = Query(None, description="Filter by tier"), search: str | None = Query(None, description="Search vendor name"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -165,7 +165,7 @@ def list_vendor_subscriptions( @router.get("/stats", response_model=SubscriptionStatsResponse) def get_subscription_stats( - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """Get subscription statistics for admin dashboard.""" @@ -184,7 +184,7 @@ def list_billing_history( per_page: int = Query(20, ge=1, le=100), vendor_id: int | None = Query(None, description="Filter by vendor"), status: str | None = Query(None, description="Filter by status"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """List billing history (invoices) across all vendors.""" @@ -234,7 +234,7 @@ def list_billing_history( def create_vendor_subscription( create_data: VendorSubscriptionCreate, vendor_id: int = Path(..., description="Vendor ID"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ @@ -280,7 +280,7 @@ def create_vendor_subscription( @router.get("/{vendor_id}", response_model=VendorSubscriptionWithVendor) def get_vendor_subscription( vendor_id: int = Path(..., description="Vendor ID"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """Get subscription details for a specific vendor.""" @@ -302,7 +302,7 @@ def get_vendor_subscription( def update_vendor_subscription( update_data: VendorSubscriptionUpdate, vendor_id: int = Path(..., description="Vendor ID"), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/admin/tests.py b/app/api/v1/admin/tests.py index 9269a4e8..b11cdc69 100644 --- a/app/api/v1/admin/tests.py +++ b/app/api/v1/admin/tests.py @@ -11,7 +11,7 @@ from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.test_runner_service import test_runner_service from app.tasks.test_runner_tasks import execute_test_run -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter() @@ -108,7 +108,7 @@ async def run_tests( background_tasks: BackgroundTasks, request: RunTestsRequest | None = None, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Start a pytest run in the background @@ -168,7 +168,7 @@ async def run_tests( async def list_runs( limit: int = Query(20, ge=1, le=100, description="Number of runs to return"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get test run history @@ -205,7 +205,7 @@ async def list_runs( async def get_run( run_id: int, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get a specific test run @@ -245,7 +245,7 @@ async def get_run_results( None, description="Filter by outcome (passed, failed, error, skipped)" ), db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get test results for a specific run @@ -272,7 +272,7 @@ async def get_run_results( async def get_run_failures( run_id: int, db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get failed tests from a specific run @@ -298,7 +298,7 @@ async def get_run_failures( @router.get("/stats", response_model=TestDashboardStatsResponse) async def get_dashboard_stats( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Get dashboard statistics @@ -317,7 +317,7 @@ async def get_dashboard_stats( @router.post("/collect") async def collect_tests( db: Session = Depends(get_db), - current_user: User = Depends(get_current_admin_api), + current_user: UserContext = Depends(get_current_admin_api), ): """ Collect test information without running tests diff --git a/app/api/v1/admin/users.py b/app/api/v1/admin/users.py index 72df3d72..222a1c48 100644 --- a/app/api/v1/admin/users.py +++ b/app/api/v1/admin/users.py @@ -16,7 +16,7 @@ from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.admin_service import admin_service from app.services.stats_service import stats_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.auth import ( UserCreate, UserDeleteResponse, @@ -40,7 +40,7 @@ def get_all_users( role: str = Query("", description="Filter by role"), is_active: str = Query("", description="Filter by active status"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get paginated list of all users (Admin only).""" # Convert string params to proper types @@ -70,7 +70,7 @@ def get_all_users( def create_user( user_data: UserCreate = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Create a new user (Admin only).""" user = admin_service.create_user( @@ -108,7 +108,7 @@ def create_user( @router.get("/stats") def get_user_statistics( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get user statistics for admin dashboard (Admin only).""" return stats_service.get_user_statistics(db) @@ -119,7 +119,7 @@ def search_users( q: str = Query(..., min_length=2, description="Search query (username or email)"), limit: int = Query(10, ge=1, le=50), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Search users by username or email (Admin only). @@ -134,7 +134,7 @@ def search_users( def get_user_details( user_id: int = Path(..., description="User ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get detailed user information (Admin only).""" user = admin_service.get_user_details(db=db, user_id=user_id) @@ -164,7 +164,7 @@ def update_user( user_id: int = Path(..., description="User ID"), user_update: UserUpdate = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Update user information (Admin only).""" update_data = user_update.model_dump(exclude_unset=True) @@ -206,7 +206,7 @@ def update_user( def toggle_user_status( user_id: int = Path(..., description="User ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Toggle user active status (Admin only).""" user, message = admin_service.toggle_user_status( @@ -223,7 +223,7 @@ def toggle_user_status( def delete_user( user_id: int = Path(..., description="User ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Delete a user (Admin only).""" message = admin_service.delete_user( diff --git a/app/api/v1/admin/vendor_domains.py b/app/api/v1/admin/vendor_domains.py index 797f54ae..c866f1df 100644 --- a/app/api/v1/admin/vendor_domains.py +++ b/app/api/v1/admin/vendor_domains.py @@ -18,7 +18,7 @@ from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.vendor_domain_service import vendor_domain_service from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.vendor_domain import ( DomainDeletionResponse, DomainVerificationInstructions, @@ -38,7 +38,7 @@ def add_vendor_domain( vendor_id: int = Path(..., description="Vendor ID", gt=0), domain_data: VendorDomainCreate = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Add a custom domain to vendor (Admin only). @@ -90,7 +90,7 @@ def add_vendor_domain( def list_vendor_domains( vendor_id: int = Path(..., description="Vendor ID", gt=0), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ List all domains for a vendor (Admin only). @@ -133,7 +133,7 @@ def list_vendor_domains( def get_domain_details( domain_id: int = Path(..., description="Domain ID", gt=0), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get detailed information about a specific domain (Admin only). @@ -166,7 +166,7 @@ def update_vendor_domain( domain_id: int = Path(..., description="Domain ID", gt=0), domain_update: VendorDomainUpdate = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Update domain settings (Admin only). @@ -209,7 +209,7 @@ def update_vendor_domain( def delete_vendor_domain( domain_id: int = Path(..., description="Domain ID", gt=0), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Delete a custom domain (Admin only). @@ -237,7 +237,7 @@ def delete_vendor_domain( def verify_domain_ownership( domain_id: int = Path(..., description="Domain ID", gt=0), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Verify domain ownership via DNS TXT record (Admin only). @@ -279,7 +279,7 @@ def verify_domain_ownership( def get_domain_verification_instructions( domain_id: int = Path(..., description="Domain ID", gt=0), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get DNS verification instructions for domain (Admin only). diff --git a/app/api/v1/admin/vendor_products.py b/app/api/v1/admin/vendor_products.py index 659786f3..c12a17fd 100644 --- a/app/api/v1/admin/vendor_products.py +++ b/app/api/v1/admin/vendor_products.py @@ -21,7 +21,7 @@ from app.api.deps import get_current_admin_api from app.core.database import get_db from app.services.subscription_service import subscription_service from app.services.vendor_product_service import vendor_product_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.catalog.schemas import ( CatalogVendor, CatalogVendorsResponse, @@ -54,7 +54,7 @@ def get_vendor_products( is_featured: bool | None = Query(None, description="Filter by featured status"), language: str = Query("en", description="Language for title lookup"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get all products in vendor catalogs with filtering. @@ -85,7 +85,7 @@ def get_vendor_products( def get_vendor_product_stats( vendor_id: int | None = Query(None, description="Filter stats by vendor ID"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get vendor product statistics for admin dashboard.""" stats = vendor_product_service.get_product_stats(db, vendor_id=vendor_id) @@ -95,7 +95,7 @@ def get_vendor_product_stats( @router.get("/vendors", response_model=CatalogVendorsResponse) def get_catalog_vendors( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get list of vendors with products in their catalogs.""" vendors = vendor_product_service.get_catalog_vendors(db) @@ -106,7 +106,7 @@ def get_catalog_vendors( def get_vendor_product_detail( product_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get detailed vendor product information including override info.""" product = vendor_product_service.get_product_detail(db, product_id) @@ -117,7 +117,7 @@ def get_vendor_product_detail( def create_vendor_product( data: VendorProductCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Create a new vendor product.""" # Check product limit before creating @@ -135,7 +135,7 @@ def update_vendor_product( product_id: int, data: VendorProductUpdate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Update a vendor product.""" # Only include fields that were explicitly set @@ -151,7 +151,7 @@ def update_vendor_product( def remove_vendor_product( product_id: int, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Remove a product from vendor catalog.""" result = vendor_product_service.remove_product(db, product_id) diff --git a/app/api/v1/admin/vendor_themes.py b/app/api/v1/admin/vendor_themes.py index 38fcdf46..4e5f0110 100644 --- a/app/api/v1/admin/vendor_themes.py +++ b/app/api/v1/admin/vendor_themes.py @@ -19,7 +19,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_admin_api, get_db from app.services.vendor_theme_service import vendor_theme_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.vendor_theme import ( ThemeDeleteResponse, ThemePresetListResponse, @@ -38,7 +38,7 @@ logger = logging.getLogger(__name__) @router.get("/presets", response_model=ThemePresetListResponse) -async def get_theme_presets(current_admin: User = Depends(get_current_admin_api)): +async def get_theme_presets(current_admin: UserContext = Depends(get_current_admin_api)): """ Get all available theme presets with preview information. @@ -65,7 +65,7 @@ async def get_theme_presets(current_admin: User = Depends(get_current_admin_api) async def get_vendor_theme( vendor_code: str = Path(..., description="Vendor code"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get theme configuration for a vendor. @@ -101,7 +101,7 @@ async def update_vendor_theme( vendor_code: str = Path(..., description="Vendor code"), theme_data: VendorThemeUpdate = None, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Update or create theme for a vendor. @@ -150,7 +150,7 @@ async def apply_theme_preset( vendor_code: str = Path(..., description="Vendor code"), preset_name: str = Path(..., description="Preset name"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Apply a theme preset to a vendor. @@ -203,7 +203,7 @@ async def apply_theme_preset( async def delete_vendor_theme( vendor_code: str = Path(..., description="Vendor code"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Delete custom theme for a vendor. diff --git a/app/api/v1/admin/vendors.py b/app/api/v1/admin/vendors.py index 0f9e1439..3ae3ec26 100644 --- a/app/api/v1/admin/vendors.py +++ b/app/api/v1/admin/vendors.py @@ -19,7 +19,7 @@ from app.exceptions import ConfirmationRequiredException from app.services.admin_service import admin_service from app.services.stats_service import stats_service from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.analytics.schemas import VendorStatsResponse from models.schema.vendor import ( LetzshopExportRequest, @@ -39,7 +39,7 @@ logger = logging.getLogger(__name__) def create_vendor( vendor_data: VendorCreate, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Create a new vendor (storefront/brand) under an existing company (Admin only). @@ -89,7 +89,7 @@ def get_all_vendors_admin( is_active: bool | None = Query(None), is_verified: bool | None = Query(None), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get all vendors with filtering (Admin only).""" vendors, total = admin_service.get_all_vendors( @@ -106,7 +106,7 @@ def get_all_vendors_admin( @router.get("/stats", response_model=VendorStatsResponse) def get_vendor_statistics_endpoint( db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """Get vendor statistics for admin dashboard (Admin only).""" stats = stats_service.get_vendor_statistics(db) @@ -164,7 +164,7 @@ def _build_vendor_detail_response(vendor) -> VendorDetailResponse: def get_vendor_details( vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Get detailed vendor information including company and owner details (Admin only). @@ -186,7 +186,7 @@ def update_vendor( vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"), vendor_update: VendorUpdate = Body(...), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Update vendor information (Admin only). @@ -222,7 +222,7 @@ def toggle_vendor_verification( vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"), verification_data: dict = Body(..., example={"is_verified": True}), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Set vendor verification status (Admin only). @@ -251,7 +251,7 @@ def toggle_vendor_status( vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"), status_data: dict = Body(..., example={"is_active": True}), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Set vendor active status (Admin only). @@ -280,7 +280,7 @@ def delete_vendor( vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"), confirm: bool = Query(False, description="Must be true to confirm deletion"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Delete vendor and all associated data (Admin only). @@ -325,7 +325,7 @@ def export_vendor_products_letzshop( ), include_inactive: bool = Query(False, description="Include inactive products"), db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Export vendor products in Letzshop CSV format (Admin only). @@ -372,7 +372,7 @@ def export_vendor_products_letzshop_to_folder( vendor_identifier: str = Path(..., description="Vendor ID or vendor_code"), request: LetzshopExportRequest = None, db: Session = Depends(get_db), - current_admin: User = Depends(get_current_admin_api), + current_admin: UserContext = Depends(get_current_admin_api), ): """ Export vendor products to Letzshop pickup folder (Admin only). diff --git a/app/api/v1/vendor/analytics.py b/app/api/v1/vendor/analytics.py index e44d3a22..659e19e9 100644 --- a/app/api/v1/vendor/analytics.py +++ b/app/api/v1/vendor/analytics.py @@ -20,7 +20,7 @@ from app.core.database import get_db from app.core.feature_gate import RequireFeature from app.services.stats_service import stats_service from app.modules.billing.models import FeatureCode -from models.database.user import User +from models.schema.auth import UserContext from app.modules.analytics.schemas import ( VendorAnalyticsCatalog, VendorAnalyticsImports, @@ -35,7 +35,7 @@ logger = logging.getLogger(__name__) @router.get("", response_model=VendorAnalyticsResponse) def get_vendor_analytics( period: str = Query("30d", description="Time period: 7d, 30d, 90d, 1y"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), _: None = Depends(RequireFeature(FeatureCode.BASIC_REPORTS, FeatureCode.ANALYTICS_DASHBOARD)), ): diff --git a/app/api/v1/vendor/auth.py b/app/api/v1/vendor/auth.py index 30527772..8e02fdda 100644 --- a/app/api/v1/vendor/auth.py +++ b/app/api/v1/vendor/auth.py @@ -24,7 +24,7 @@ from app.core.environment import should_use_secure_cookies from app.exceptions import InvalidCredentialsException from app.services.auth_service import auth_service from middleware.vendor_context import get_current_vendor -from models.database.user import User +from models.schema.auth import UserContext from models.schema.auth import LogoutResponse, UserLogin, VendorUserResponse router = APIRouter(prefix="/auth") @@ -179,7 +179,7 @@ def vendor_logout(response: Response): @router.get("/me", response_model=VendorUserResponse) def get_current_vendor_user( - user: User = Depends(get_current_vendor_api), db: Session = Depends(get_db) + user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db) ): """ Get current authenticated vendor user. diff --git a/app/api/v1/vendor/billing.py b/app/api/v1/vendor/billing.py index 5f627d55..74e96838 100644 --- a/app/api/v1/vendor/billing.py +++ b/app/api/v1/vendor/billing.py @@ -21,7 +21,7 @@ from app.core.config import settings from app.core.database import get_db from app.services.billing_service import billing_service from app.services.subscription_service import subscription_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/billing") logger = logging.getLogger(__name__) @@ -217,7 +217,7 @@ class AddOnCancelResponse(BaseModel): @router.get("/subscription", response_model=SubscriptionStatusResponse) def get_subscription_status( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get current subscription status and usage metrics.""" @@ -260,7 +260,7 @@ def get_subscription_status( @router.get("/tiers", response_model=TierListResponse) def get_available_tiers( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get available subscription tiers for upgrade/downgrade.""" @@ -278,7 +278,7 @@ def get_available_tiers( @router.post("/checkout", response_model=CheckoutResponse) def create_checkout_session( request: CheckoutRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Create a Stripe checkout session for subscription.""" @@ -305,7 +305,7 @@ def create_checkout_session( @router.post("/portal", response_model=PortalResponse) def create_portal_session( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Create a Stripe customer portal session.""" @@ -322,7 +322,7 @@ def create_portal_session( def get_invoices( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get invoice history.""" @@ -352,7 +352,7 @@ def get_invoices( @router.get("/addons", response_model=list[AddOnResponse]) def get_available_addons( category: str | None = Query(None, description="Filter by category"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get available add-on products.""" @@ -376,7 +376,7 @@ def get_available_addons( @router.get("/my-addons", response_model=list[VendorAddOnResponse]) def get_vendor_addons( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get vendor's purchased add-ons.""" @@ -402,7 +402,7 @@ def get_vendor_addons( @router.post("/cancel", response_model=CancelResponse) def cancel_subscription( request: CancelRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Cancel subscription.""" @@ -424,7 +424,7 @@ def cancel_subscription( @router.post("/reactivate") def reactivate_subscription( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Reactivate a cancelled subscription.""" @@ -438,7 +438,7 @@ def reactivate_subscription( @router.get("/upcoming-invoice", response_model=UpcomingInvoiceResponse) def get_upcoming_invoice( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Preview the upcoming invoice.""" @@ -457,7 +457,7 @@ def get_upcoming_invoice( @router.post("/change-tier", response_model=ChangeTierResponse) def change_tier( request: ChangeTierRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Change subscription tier (upgrade/downgrade).""" @@ -481,7 +481,7 @@ def change_tier( @router.post("/addons/purchase") def purchase_addon( request: AddOnPurchaseRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Purchase an add-on product.""" @@ -510,7 +510,7 @@ def purchase_addon( @router.delete("/addons/{addon_id}", response_model=AddOnCancelResponse) def cancel_addon( addon_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Cancel a purchased add-on.""" diff --git a/app/api/v1/vendor/customers.py b/app/api/v1/vendor/customers.py index ee2be475..85c236a0 100644 --- a/app/api/v1/vendor/customers.py +++ b/app/api/v1/vendor/customers.py @@ -14,7 +14,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.customer_service import customer_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.customers.schemas import ( CustomerDetailResponse, CustomerMessageResponse, @@ -35,7 +35,7 @@ def get_vendor_customers( limit: int = Query(100, ge=1, le=1000), search: str | None = Query(None), is_active: bool | None = Query(None), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -66,7 +66,7 @@ def get_vendor_customers( @router.get("/{customer_id}", response_model=CustomerDetailResponse) def get_customer_details( customer_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -112,7 +112,7 @@ def get_customer_orders( customer_id: int, skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=100), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -152,7 +152,7 @@ def get_customer_orders( def update_customer( customer_id: int, customer_data: CustomerUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -177,7 +177,7 @@ def update_customer( @router.put("/{customer_id}/status", response_model=CustomerMessageResponse) def toggle_customer_status( customer_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -202,7 +202,7 @@ def toggle_customer_status( @router.get("/{customer_id}/stats", response_model=CustomerStatisticsResponse) def get_customer_statistics( customer_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/dashboard.py b/app/api/v1/vendor/dashboard.py index a2827d19..c501e168 100644 --- a/app/api/v1/vendor/dashboard.py +++ b/app/api/v1/vendor/dashboard.py @@ -16,7 +16,7 @@ from app.core.database import get_db from app.exceptions import VendorNotActiveException from app.services.stats_service import stats_service from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.analytics.schemas import ( VendorCustomerStats, VendorDashboardStatsResponse, @@ -33,7 +33,7 @@ logger = logging.getLogger(__name__) @router.get("/stats", response_model=VendorDashboardStatsResponse) def get_vendor_dashboard_stats( request: Request, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/email_settings.py b/app/api/v1/vendor/email_settings.py index b818979b..c5f0112d 100644 --- a/app/api/v1/vendor/email_settings.py +++ b/app/api/v1/vendor/email_settings.py @@ -22,7 +22,7 @@ from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.vendor_email_settings_service import VendorEmailSettingsService from app.services.subscription_service import subscription_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/email-settings") logger = logging.getLogger(__name__) @@ -128,7 +128,7 @@ class EmailDeleteResponse(BaseModel): @router.get("", response_model=EmailSettingsResponse) def get_email_settings( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ) -> EmailSettingsResponse: """ @@ -156,7 +156,7 @@ def get_email_settings( @router.get("/status", response_model=EmailStatusResponse) def get_email_status( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ) -> EmailStatusResponse: """ @@ -172,7 +172,7 @@ def get_email_status( @router.get("/providers", response_model=ProvidersResponse) def get_available_providers( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ) -> ProvidersResponse: """ @@ -195,7 +195,7 @@ def get_available_providers( @router.put("", response_model=EmailUpdateResponse) def update_email_settings( data: EmailSettingsUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ) -> EmailUpdateResponse: """ @@ -229,7 +229,7 @@ def update_email_settings( @router.post("/verify", response_model=EmailVerifyResponse) def verify_email_settings( data: VerifyEmailRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ) -> EmailVerifyResponse: """ @@ -254,7 +254,7 @@ def verify_email_settings( @router.delete("", response_model=EmailDeleteResponse) def delete_email_settings( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ) -> EmailDeleteResponse: """ diff --git a/app/api/v1/vendor/email_templates.py b/app/api/v1/vendor/email_templates.py index f3167ceb..f7860d5b 100644 --- a/app/api/v1/vendor/email_templates.py +++ b/app/api/v1/vendor/email_templates.py @@ -20,7 +20,7 @@ from app.core.database import get_db from app.services.email_service import EmailService from app.services.email_template_service import EmailTemplateService from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/email-templates") logger = logging.getLogger(__name__) @@ -62,7 +62,7 @@ class TemplateTestRequest(BaseModel): @router.get("") def list_overridable_templates( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -79,7 +79,7 @@ def list_overridable_templates( @router.get("/{code}") def get_template( code: str, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -96,7 +96,7 @@ def get_template( def get_template_language( code: str, language: str, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -114,7 +114,7 @@ def update_template_override( code: str, language: str, template_data: VendorTemplateUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -144,7 +144,7 @@ def update_template_override( def delete_template_override( code: str, language: str, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -168,7 +168,7 @@ def delete_template_override( def preview_template( code: str, preview_data: TemplatePreviewRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -201,7 +201,7 @@ def preview_template( def send_test_email( code: str, test_data: TemplateTestRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/features.py b/app/api/v1/vendor/features.py index 28cff02b..7270b152 100644 --- a/app/api/v1/vendor/features.py +++ b/app/api/v1/vendor/features.py @@ -24,7 +24,7 @@ from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.exceptions import FeatureNotFoundError from app.services.feature_service import feature_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/features") logger = logging.getLogger(__name__) @@ -114,7 +114,7 @@ class FeatureCheckResponse(BaseModel): @router.get("/available", response_model=FeatureCodeListResponse) def get_available_features( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -148,7 +148,7 @@ def get_available_features( def get_features( category: str | None = Query(None, description="Filter by category"), include_unavailable: bool = Query(True, description="Include features not available to vendor"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -211,7 +211,7 @@ def get_features( @router.get("/categories", response_model=CategoryListResponse) def get_feature_categories( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -226,7 +226,7 @@ def get_feature_categories( @router.get("/grouped", response_model=FeatureGroupedResponse) def get_features_grouped( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -273,7 +273,7 @@ def get_features_grouped( @router.get("/{feature_code}", response_model=FeatureDetailResponse) def get_feature_detail( feature_code: str, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -328,7 +328,7 @@ def get_feature_detail( @router.get("/check/{feature_code}", response_model=FeatureCheckResponse) def check_feature( feature_code: str, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/inventory.py b/app/api/v1/vendor/inventory.py index 7455b464..91d7f835 100644 --- a/app/api/v1/vendor/inventory.py +++ b/app/api/v1/vendor/inventory.py @@ -15,7 +15,7 @@ from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.inventory_service import inventory_service from app.services.inventory_transaction_service import inventory_transaction_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.inventory.schemas import ( InventoryAdjust, InventoryCreate, @@ -38,7 +38,7 @@ logger = logging.getLogger(__name__) @router.post("/inventory/set", response_model=InventoryResponse) def set_inventory( inventory: InventoryCreate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Set exact inventory quantity (replaces existing).""" @@ -52,7 +52,7 @@ def set_inventory( @router.post("/inventory/adjust", response_model=InventoryResponse) def adjust_inventory( adjustment: InventoryAdjust, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Adjust inventory (positive to add, negative to remove).""" @@ -66,7 +66,7 @@ def adjust_inventory( @router.post("/inventory/reserve", response_model=InventoryResponse) def reserve_inventory( reservation: InventoryReserve, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Reserve inventory for an order.""" @@ -80,7 +80,7 @@ def reserve_inventory( @router.post("/inventory/release", response_model=InventoryResponse) def release_reservation( reservation: InventoryReserve, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Release reserved inventory (cancel order).""" @@ -94,7 +94,7 @@ def release_reservation( @router.post("/inventory/fulfill", response_model=InventoryResponse) def fulfill_reservation( reservation: InventoryReserve, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Fulfill reservation (complete order, remove from stock).""" @@ -108,7 +108,7 @@ def fulfill_reservation( @router.get("/inventory/product/{product_id}", response_model=ProductInventorySummary) def get_product_inventory( product_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get inventory summary for a product.""" @@ -123,7 +123,7 @@ def get_vendor_inventory( limit: int = Query(100, ge=1, le=1000), location: str | None = Query(None), low_stock: int | None = Query(None, ge=0), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get all inventory for vendor.""" @@ -143,7 +143,7 @@ def get_vendor_inventory( def update_inventory( inventory_id: int, inventory_update: InventoryUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Update inventory entry.""" @@ -157,7 +157,7 @@ def update_inventory( @router.delete("/inventory/{inventory_id}", response_model=InventoryMessageResponse) def delete_inventory( inventory_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Delete inventory entry.""" @@ -177,7 +177,7 @@ def get_inventory_transactions( limit: int = Query(50, ge=1, le=200), product_id: int | None = Query(None, description="Filter by product"), transaction_type: str | None = Query(None, description="Filter by type"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -210,7 +210,7 @@ def get_inventory_transactions( def get_product_transaction_history( product_id: int, limit: int = Query(50, ge=1, le=200), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -234,7 +234,7 @@ def get_product_transaction_history( ) def get_order_transaction_history( order_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/invoices.py b/app/api/v1/vendor/invoices.py index f512f14c..f1ffa904 100644 --- a/app/api/v1/vendor/invoices.py +++ b/app/api/v1/vendor/invoices.py @@ -42,7 +42,7 @@ from app.exceptions.invoice import ( ) from app.services.invoice_service import invoice_service from app.modules.billing.models import FeatureCode -from models.database.user import User +from models.schema.auth import UserContext from app.modules.orders.schemas import ( InvoiceCreate, InvoiceListPaginatedResponse, @@ -67,7 +67,7 @@ logger = logging.getLogger(__name__) @router.get("/settings", response_model=VendorInvoiceSettingsResponse | None) def get_invoice_settings( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), _: None = Depends(RequireFeature(FeatureCode.INVOICE_LU)), ): @@ -86,7 +86,7 @@ def get_invoice_settings( @router.post("/settings", response_model=VendorInvoiceSettingsResponse, status_code=201) def create_invoice_settings( data: VendorInvoiceSettingsCreate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -106,7 +106,7 @@ def create_invoice_settings( @router.put("/settings", response_model=VendorInvoiceSettingsResponse) def update_invoice_settings( data: VendorInvoiceSettingsUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -127,7 +127,7 @@ def update_invoice_settings( @router.get("/stats", response_model=InvoiceStatsResponse) def get_invoice_stats( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -160,7 +160,7 @@ def list_invoices( page: int = Query(1, ge=1, description="Page number"), per_page: int = Query(20, ge=1, le=100, description="Items per page"), status: str | None = Query(None, description="Filter by status"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -207,7 +207,7 @@ def list_invoices( @router.get("/{invoice_id}", response_model=InvoiceResponse) def get_invoice( invoice_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -224,7 +224,7 @@ def get_invoice( @router.post("", response_model=InvoiceResponse, status_code=201) def create_invoice( data: InvoiceCreate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -248,7 +248,7 @@ def create_invoice( def update_invoice_status( invoice_id: int, data: InvoiceStatusUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -280,7 +280,7 @@ def update_invoice_status( def generate_invoice_pdf( invoice_id: int, regenerate: bool = Query(False, description="Force regenerate if exists"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -301,7 +301,7 @@ def generate_invoice_pdf( @router.get("/{invoice_id}/pdf") def download_invoice_pdf( invoice_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/letzshop.py b/app/api/v1/vendor/letzshop.py index cbfc3929..e37ec577 100644 --- a/app/api/v1/vendor/letzshop.py +++ b/app/api/v1/vendor/letzshop.py @@ -31,7 +31,7 @@ from app.services.letzshop import ( LetzshopOrderService, OrderNotFoundError, ) -from models.database.user import User +from models.schema.auth import UserContext from app.modules.marketplace.schemas import ( FulfillmentConfirmRequest, FulfillmentOperationResponse, @@ -81,7 +81,7 @@ def get_credentials_service(db: Session) -> LetzshopCredentialsService: @router.get("/status", response_model=LetzshopCredentialsStatus) def get_letzshop_status( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get Letzshop integration status for the current vendor.""" @@ -92,7 +92,7 @@ def get_letzshop_status( @router.get("/credentials", response_model=LetzshopCredentialsResponse) def get_credentials( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get Letzshop credentials for the current vendor (API key is masked).""" @@ -122,7 +122,7 @@ def get_credentials( @router.post("/credentials", response_model=LetzshopCredentialsResponse) def save_credentials( credentials_data: LetzshopCredentialsCreate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Create or update Letzshop credentials for the current vendor.""" @@ -158,7 +158,7 @@ def save_credentials( @router.patch("/credentials", response_model=LetzshopCredentialsResponse) def update_credentials( credentials_data: LetzshopCredentialsUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Partially update Letzshop credentials for the current vendor.""" @@ -194,7 +194,7 @@ def update_credentials( @router.delete("/credentials", response_model=LetzshopSuccessResponse) def delete_credentials( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Delete Letzshop credentials for the current vendor.""" @@ -218,7 +218,7 @@ def delete_credentials( @router.post("/test", response_model=LetzshopConnectionTestResponse) def test_connection( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Test the Letzshop connection using stored credentials.""" @@ -239,7 +239,7 @@ def test_connection( @router.post("/test-key", response_model=LetzshopConnectionTestResponse) def test_api_key( test_request: LetzshopConnectionTestRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Test a Letzshop API key without saving it.""" @@ -268,7 +268,7 @@ def list_orders( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=200), status: str | None = Query(None, description="Filter by order status"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """List Letzshop orders for the current vendor.""" @@ -319,7 +319,7 @@ def list_orders( @router.get("/orders/{order_id}", response_model=LetzshopOrderDetailResponse) def get_order( order_id: int = Path(..., description="Order ID"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get a specific Letzshop order with full details.""" @@ -381,7 +381,7 @@ def get_order( @router.post("/orders/import", response_model=LetzshopSyncTriggerResponse) def import_orders( sync_request: LetzshopSyncTriggerRequest = LetzshopSyncTriggerRequest(), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Import new orders from Letzshop.""" @@ -455,7 +455,7 @@ def import_orders( def confirm_order( order_id: int = Path(..., description="Order ID"), confirm_request: FulfillmentConfirmRequest | None = None, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -525,7 +525,7 @@ def confirm_order( def reject_order( order_id: int = Path(..., description="Order ID"), reject_request: FulfillmentRejectRequest | None = None, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Reject inventory units for a Letzshop order.""" @@ -580,7 +580,7 @@ def reject_order( def set_order_tracking( order_id: int = Path(..., description="Order ID"), tracking_request: FulfillmentTrackingRequest = ..., - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Set tracking information for a Letzshop order.""" @@ -642,7 +642,7 @@ def set_order_tracking( def list_sync_logs( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=200), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """List Letzshop sync logs for the current vendor.""" @@ -691,7 +691,7 @@ def list_fulfillment_queue( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=200), status: str | None = Query(None, description="Filter by status"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """List fulfillment queue items for the current vendor.""" @@ -743,7 +743,7 @@ def export_products_letzshop( "en", description="Language for title/description (en, fr, de)" ), include_inactive: bool = Query(False, description="Include inactive products"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/marketplace.py b/app/api/v1/vendor/marketplace.py index 3a98f5e7..adc1f44c 100644 --- a/app/api/v1/vendor/marketplace.py +++ b/app/api/v1/vendor/marketplace.py @@ -17,7 +17,7 @@ from app.services.marketplace_import_job_service import marketplace_import_job_s from app.services.vendor_service import vendor_service from app.tasks.background_tasks import process_marketplace_import from middleware.decorators import rate_limit -from models.database.user import User +from models.schema.auth import UserContext from app.modules.marketplace.schemas import ( MarketplaceImportJobRequest, MarketplaceImportJobResponse, @@ -32,7 +32,7 @@ logger = logging.getLogger(__name__) async def import_products_from_marketplace( request: MarketplaceImportJobRequest, background_tasks: BackgroundTasks, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Import products from marketplace CSV with background processing (Protected). @@ -96,7 +96,7 @@ async def import_products_from_marketplace( @router.get("/imports/{job_id}", response_model=MarketplaceImportJobResponse) def get_marketplace_import_status( job_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get status of marketplace import job (Protected).""" @@ -113,7 +113,7 @@ def get_marketplace_import_jobs( marketplace: str | None = Query(None, description="Filter by marketplace"), skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=100), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get marketplace import jobs for current vendor (Protected).""" diff --git a/app/api/v1/vendor/media.py b/app/api/v1/vendor/media.py index e778c2f6..d5f729c2 100644 --- a/app/api/v1/vendor/media.py +++ b/app/api/v1/vendor/media.py @@ -15,7 +15,7 @@ from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.exceptions.media import MediaOptimizationException from app.services.media_service import media_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.media import ( MediaDetailResponse, MediaItemResponse, @@ -40,7 +40,7 @@ def get_media_library( media_type: str | None = Query(None, description="image, video, document"), folder: str | None = Query(None, description="Filter by folder"), search: str | None = Query(None), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -74,7 +74,7 @@ def get_media_library( async def upload_media( file: UploadFile = File(...), folder: str | None = Query("general", description="products, general, etc."), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -116,7 +116,7 @@ async def upload_media( async def upload_multiple_media( files: list[UploadFile] = File(...), folder: str | None = Query("general"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -170,7 +170,7 @@ async def upload_multiple_media( @router.get("/{media_id}", response_model=MediaDetailResponse) def get_media_details( media_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -194,7 +194,7 @@ def get_media_details( def update_media_metadata( media_id: int, metadata: MediaMetadataUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -225,7 +225,7 @@ def update_media_metadata( @router.delete("/{media_id}", response_model=MediaDetailResponse) def delete_media( media_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -251,7 +251,7 @@ def delete_media( @router.get("/{media_id}/usage", response_model=MediaUsageResponse) def get_media_usage( media_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -273,7 +273,7 @@ def get_media_usage( @router.post("/optimize/{media_id}", response_model=OptimizationResultResponse) def optimize_media( media_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/messages.py b/app/api/v1/vendor/messages.py index 4198f711..0051e7a6 100644 --- a/app/api/v1/vendor/messages.py +++ b/app/api/v1/vendor/messages.py @@ -47,7 +47,7 @@ from app.modules.messaging.schemas import ( ReopenConversationResponse, UnreadCountResponse, ) -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/messages") logger = logging.getLogger(__name__) @@ -177,7 +177,7 @@ def list_conversations( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> ConversationListResponse: """List conversations for vendor (vendor_customer and admin_vendor channels).""" vendor_id = current_user.token_vendor_id @@ -208,7 +208,7 @@ def list_conversations( @router.get("/unread-count", response_model=UnreadCountResponse) def get_unread_count( db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> UnreadCountResponse: """Get total unread message count for header badge.""" vendor_id = current_user.token_vendor_id @@ -234,7 +234,7 @@ def get_recipients( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=100), db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> RecipientListResponse: """Get list of available recipients for compose modal.""" vendor_id = current_user.token_vendor_id @@ -275,7 +275,7 @@ def get_recipients( def create_conversation( data: ConversationCreate, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> ConversationDetailResponse: """Create a new conversation with a customer.""" vendor_id = current_user.token_vendor_id @@ -399,7 +399,7 @@ def get_conversation( conversation_id: int, mark_read: bool = Query(True, description="Automatically mark as read"), db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> ConversationDetailResponse: """Get conversation detail with messages.""" vendor_id = current_user.token_vendor_id @@ -442,7 +442,7 @@ async def send_message( content: str = Form(...), files: list[UploadFile] = File(default=[]), db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> MessageResponse: """Send a message in a conversation, optionally with attachments.""" vendor_id = current_user.token_vendor_id @@ -505,7 +505,7 @@ async def send_message( def close_conversation( conversation_id: int, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> CloseConversationResponse: """Close a conversation.""" vendor_id = current_user.token_vendor_id @@ -547,7 +547,7 @@ def close_conversation( def reopen_conversation( conversation_id: int, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> ReopenConversationResponse: """Reopen a closed conversation.""" vendor_id = current_user.token_vendor_id @@ -589,7 +589,7 @@ def reopen_conversation( def mark_read( conversation_id: int, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> MarkReadResponse: """Mark conversation as read.""" success = messaging_service.mark_conversation_read( @@ -617,7 +617,7 @@ def update_preferences( conversation_id: int, preferences: NotificationPreferencesUpdate, db: Session = Depends(get_db), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ) -> PreferencesUpdateResponse: """Update notification preferences for a conversation.""" success = messaging_service.update_notification_preferences( diff --git a/app/api/v1/vendor/notifications.py b/app/api/v1/vendor/notifications.py index c9c2545e..2d4ba26e 100644 --- a/app/api/v1/vendor/notifications.py +++ b/app/api/v1/vendor/notifications.py @@ -14,7 +14,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.messaging.schemas import ( MessageResponse, NotificationListResponse, @@ -35,7 +35,7 @@ def get_notifications( skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=100), unread_only: bool | None = Query(False), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -58,7 +58,7 @@ def get_notifications( @router.get("/unread-count", response_model=UnreadCountResponse) def get_unread_count( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -75,7 +75,7 @@ def get_unread_count( @router.put("/{notification_id}/read", response_model=MessageResponse) def mark_as_read( notification_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -91,7 +91,7 @@ def mark_as_read( @router.put("/mark-all-read", response_model=MessageResponse) def mark_all_as_read( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -108,7 +108,7 @@ def mark_all_as_read( @router.delete("/{notification_id}", response_model=MessageResponse) def delete_notification( notification_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -124,7 +124,7 @@ def delete_notification( @router.get("/settings", response_model=NotificationSettingsResponse) def get_notification_settings( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -147,7 +147,7 @@ def get_notification_settings( @router.put("/settings", response_model=MessageResponse) def update_notification_settings( settings: NotificationSettingsUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -164,7 +164,7 @@ def update_notification_settings( @router.get("/templates", response_model=NotificationTemplateListResponse) def get_notification_templates( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -185,7 +185,7 @@ def get_notification_templates( def update_notification_template( template_id: int, template_data: NotificationTemplateUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -204,7 +204,7 @@ def update_notification_template( @router.post("/test", response_model=MessageResponse) def send_test_notification( notification_data: TestNotificationRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/onboarding.py b/app/api/v1/vendor/onboarding.py index 7e6cce68..6fd73cf0 100644 --- a/app/api/v1/vendor/onboarding.py +++ b/app/api/v1/vendor/onboarding.py @@ -20,7 +20,7 @@ from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.onboarding_service import OnboardingService from app.tasks.letzshop_tasks import process_historical_import -from models.database.user import User +from models.schema.auth import UserContext from app.modules.marketplace.schemas import ( CompanyProfileRequest, CompanyProfileResponse, @@ -49,7 +49,7 @@ logger = logging.getLogger(__name__) @router.get("/status", response_model=OnboardingStatusResponse) def get_onboarding_status( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -69,7 +69,7 @@ def get_onboarding_status( @router.get("/step/company-profile") def get_company_profile( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -84,7 +84,7 @@ def get_company_profile( @router.post("/step/company-profile", response_model=CompanyProfileResponse) def save_company_profile( request: CompanyProfileRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -118,7 +118,7 @@ def save_company_profile( @router.post("/step/letzshop-api/test", response_model=LetzshopApiTestResponse) def test_letzshop_api( request: LetzshopApiTestRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -136,7 +136,7 @@ def test_letzshop_api( @router.post("/step/letzshop-api", response_model=LetzshopApiConfigResponse) def save_letzshop_api( request: LetzshopApiConfigRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -162,7 +162,7 @@ def save_letzshop_api( @router.get("/step/product-import") def get_product_import_config( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -177,7 +177,7 @@ def get_product_import_config( @router.post("/step/product-import", response_model=ProductImportConfigResponse) def save_product_import_config( request: ProductImportConfigRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -208,7 +208,7 @@ def save_product_import_config( def trigger_order_sync( request: OrderSyncTriggerRequest, background_tasks: BackgroundTasks, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -253,7 +253,7 @@ def trigger_order_sync( ) def get_order_sync_progress( job_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -271,7 +271,7 @@ def get_order_sync_progress( @router.post("/step/order-sync/complete", response_model=OrderSyncCompleteResponse) def complete_order_sync( request: OrderSyncCompleteRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/order_item_exceptions.py b/app/api/v1/vendor/order_item_exceptions.py index 38a862b0..c8512444 100644 --- a/app/api/v1/vendor/order_item_exceptions.py +++ b/app/api/v1/vendor/order_item_exceptions.py @@ -16,7 +16,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.order_item_exception_service import order_item_exception_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.orders.schemas import ( BulkResolveRequest, BulkResolveResponse, @@ -50,7 +50,7 @@ def list_vendor_exceptions( ), skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=200), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -91,7 +91,7 @@ def list_vendor_exceptions( @router.get("/stats", response_model=OrderItemExceptionStats) def get_vendor_exception_stats( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -112,7 +112,7 @@ def get_vendor_exception_stats( @router.get("/{exception_id}", response_model=OrderItemExceptionResponse) def get_vendor_exception( exception_id: int = Path(..., description="Exception ID"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -145,7 +145,7 @@ def get_vendor_exception( def resolve_vendor_exception( exception_id: int = Path(..., description="Exception ID"), request: ResolveExceptionRequest = ..., - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -185,7 +185,7 @@ def resolve_vendor_exception( def ignore_vendor_exception( exception_id: int = Path(..., description="Exception ID"), request: IgnoreExceptionRequest = ..., - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -228,7 +228,7 @@ def ignore_vendor_exception( @router.post("/bulk-resolve", response_model=BulkResolveResponse) def bulk_resolve_vendor_exceptions( request: BulkResolveRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/orders.py b/app/api/v1/vendor/orders.py index 6c890604..26256ac3 100644 --- a/app/api/v1/vendor/orders.py +++ b/app/api/v1/vendor/orders.py @@ -16,7 +16,7 @@ from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.order_inventory_service import order_inventory_service from app.services.order_service import order_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.orders.schemas import ( OrderDetailResponse, OrderListResponse, @@ -34,7 +34,7 @@ def get_vendor_orders( limit: int = Query(100, ge=1, le=1000), status: str | None = Query(None, description="Filter by order status"), customer_id: int | None = Query(None, description="Filter by customer"), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -67,7 +67,7 @@ def get_vendor_orders( @router.get("/{order_id}", response_model=OrderDetailResponse) def get_order_details( order_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -86,7 +86,7 @@ def get_order_details( def update_order_status( order_id: int, order_update: OrderUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -174,7 +174,7 @@ class ShipmentStatusResponse(BaseModel): @router.get("/{order_id}/shipment-status", response_model=ShipmentStatusResponse) def get_shipment_status( order_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -210,7 +210,7 @@ def ship_order_item( order_id: int, item_id: int, request: ShipItemRequest | None = None, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/payments.py b/app/api/v1/vendor/payments.py index b09e2e0c..3ba5334f 100644 --- a/app/api/v1/vendor/payments.py +++ b/app/api/v1/vendor/payments.py @@ -14,7 +14,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.payments.schemas import ( PaymentBalanceResponse, PaymentConfigResponse, @@ -35,7 +35,7 @@ logger = logging.getLogger(__name__) @router.get("/config", response_model=PaymentConfigResponse) def get_payment_configuration( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -60,7 +60,7 @@ def get_payment_configuration( @router.put("/config", response_model=PaymentConfigUpdateResponse) def update_payment_configuration( payment_config: PaymentConfigUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -81,7 +81,7 @@ def update_payment_configuration( @router.post("/stripe/connect", response_model=StripeConnectResponse) def connect_stripe_account( stripe_data: StripeConnectRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -99,7 +99,7 @@ def connect_stripe_account( @router.delete("/stripe/disconnect", response_model=StripeDisconnectResponse) def disconnect_stripe_account( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -116,7 +116,7 @@ def disconnect_stripe_account( @router.get("/methods", response_model=PaymentMethodsResponse) def get_payment_methods( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -135,7 +135,7 @@ def get_payment_methods( @router.get("/transactions", response_model=TransactionsResponse) def get_payment_transactions( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -157,7 +157,7 @@ def get_payment_transactions( @router.get("/balance", response_model=PaymentBalanceResponse) def get_payment_balance( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -183,7 +183,7 @@ def get_payment_balance( def refund_payment( payment_id: int, refund_data: RefundRequest, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/products.py b/app/api/v1/vendor/products.py index c51f9664..30e4165f 100644 --- a/app/api/v1/vendor/products.py +++ b/app/api/v1/vendor/products.py @@ -16,7 +16,7 @@ from app.core.database import get_db from app.services.product_service import product_service from app.services.subscription_service import subscription_service from app.services.vendor_product_service import vendor_product_service -from models.database.user import User +from models.schema.auth import UserContext from app.modules.catalog.schemas import ( ProductCreate, ProductDeleteResponse, @@ -41,7 +41,7 @@ def get_vendor_products( limit: int = Query(100, ge=1, le=1000), is_active: bool | None = Query(None), is_featured: bool | None = Query(None), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -73,7 +73,7 @@ def get_vendor_products( @router.get("/{product_id}", response_model=ProductDetailResponse) def get_product_details( product_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get detailed product information including inventory.""" @@ -87,7 +87,7 @@ def get_product_details( @router.post("", response_model=ProductResponse) def add_product_to_catalog( product_data: ProductCreate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -114,7 +114,7 @@ def add_product_to_catalog( @router.post("/create", response_model=VendorProductCreateResponse) def create_product_direct( product_data: VendorDirectProductCreate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -159,7 +159,7 @@ def create_product_direct( def update_product( product_id: int, product_data: ProductUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Update product in vendor catalog.""" @@ -182,7 +182,7 @@ def update_product( @router.delete("/{product_id}", response_model=ProductDeleteResponse) def remove_product_from_catalog( product_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Remove product from vendor catalog.""" @@ -202,7 +202,7 @@ def remove_product_from_catalog( @router.post("/from-import/{marketplace_product_id}", response_model=ProductResponse) def publish_from_marketplace( marketplace_product_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -233,7 +233,7 @@ def publish_from_marketplace( @router.put("/{product_id}/toggle-active", response_model=ProductToggleResponse) def toggle_product_active( product_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Toggle product active status.""" @@ -256,7 +256,7 @@ def toggle_product_active( @router.put("/{product_id}/toggle-featured", response_model=ProductToggleResponse) def toggle_product_featured( product_id: int, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Toggle product featured status.""" diff --git a/app/api/v1/vendor/profile.py b/app/api/v1/vendor/profile.py index 913885da..fefc1239 100644 --- a/app/api/v1/vendor/profile.py +++ b/app/api/v1/vendor/profile.py @@ -14,7 +14,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.vendor import VendorResponse, VendorUpdate router = APIRouter(prefix="/profile") @@ -23,7 +23,7 @@ logger = logging.getLogger(__name__) @router.get("", response_model=VendorResponse) def get_vendor_profile( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get current vendor profile information.""" @@ -34,7 +34,7 @@ def get_vendor_profile( @router.put("", response_model=VendorResponse) def update_vendor_profile( vendor_update: VendorUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Update vendor profile information.""" diff --git a/app/api/v1/vendor/settings.py b/app/api/v1/vendor/settings.py index 349ce530..9a149f94 100644 --- a/app/api/v1/vendor/settings.py +++ b/app/api/v1/vendor/settings.py @@ -16,7 +16,7 @@ from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.platform_settings_service import platform_settings_service from app.services.vendor_service import vendor_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/settings") logger = logging.getLogger(__name__) @@ -156,7 +156,7 @@ class LetzshopFeedSettingsUpdate(BaseModel): @router.get("") def get_vendor_settings( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Get comprehensive vendor settings and configuration.""" @@ -321,7 +321,7 @@ def get_vendor_settings( @router.put("/business-info") def update_business_info( business_info: BusinessInfoUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -363,7 +363,7 @@ def update_business_info( @router.put("/letzshop") def update_letzshop_settings( letzshop_config: LetzshopFeedSettingsUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """Update Letzshop marketplace feed settings. @@ -397,7 +397,7 @@ def update_letzshop_settings( @router.put("/localization") def update_localization_settings( localization_config: LocalizationSettingsUpdate, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/app/api/v1/vendor/team.py b/app/api/v1/vendor/team.py index 8ce61792..e82eeaef 100644 --- a/app/api/v1/vendor/team.py +++ b/app/api/v1/vendor/team.py @@ -24,7 +24,7 @@ from app.api.deps import ( from app.core.database import get_db from app.core.permissions import VendorPermissions from app.services.vendor_team_service import vendor_team_service -from models.database.user import User +from models.schema.auth import UserContext from models.schema.team import ( BulkRemoveRequest, BulkRemoveResponse, @@ -54,7 +54,7 @@ def list_team_members( request: Request, include_inactive: bool = False, db: Session = Depends(get_db), - current_user: User = Depends( + current_user: UserContext = Depends( require_vendor_permission(VendorPermissions.TEAM_VIEW.value) ), ): @@ -96,7 +96,7 @@ def invite_team_member( invitation: TeamMemberInvite, request: Request, db: Session = Depends(get_db), - current_user: User = Depends(require_vendor_owner), # Owner only + current_user: UserContext = Depends(require_vendor_owner), # Owner only ): """ Invite a new team member to the vendor. @@ -220,7 +220,7 @@ def get_team_member( user_id: int, request: Request, db: Session = Depends(get_db), - current_user: User = Depends( + current_user: UserContext = Depends( require_vendor_permission(VendorPermissions.TEAM_VIEW.value) ), ): @@ -250,7 +250,7 @@ def update_team_member( update_data: TeamMemberUpdate, request: Request, db: Session = Depends(get_db), - current_user: User = Depends(require_vendor_owner), # Owner only + current_user: UserContext = Depends(require_vendor_owner), # Owner only ): """ Update a team member's role or status. @@ -293,7 +293,7 @@ def remove_team_member( user_id: int, request: Request, db: Session = Depends(get_db), - current_user: User = Depends(require_vendor_owner), # Owner only + current_user: UserContext = Depends(require_vendor_owner), # Owner only ): """ Remove a team member from the vendor. @@ -325,7 +325,7 @@ def bulk_remove_team_members( bulk_remove: BulkRemoveRequest, request: Request, db: Session = Depends(get_db), - current_user: User = Depends(require_vendor_owner), + current_user: UserContext = Depends(require_vendor_owner), ): """ Remove multiple team members at once. @@ -369,7 +369,7 @@ def bulk_remove_team_members( def list_roles( request: Request, db: Session = Depends(get_db), - current_user: User = Depends( + current_user: UserContext = Depends( require_vendor_permission(VendorPermissions.TEAM_VIEW.value) ), ): @@ -399,7 +399,7 @@ def list_roles( def get_my_permissions( request: Request, permissions: list[str] = Depends(get_user_permissions), - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), ): """ Get current user's permissions in this vendor. @@ -438,7 +438,7 @@ def get_my_permissions( def get_team_statistics( request: Request, db: Session = Depends(get_db), - current_user: User = Depends( + current_user: UserContext = Depends( require_vendor_permission(VendorPermissions.TEAM_VIEW.value) ), ): diff --git a/app/api/v1/vendor/usage.py b/app/api/v1/vendor/usage.py index e0e6d16c..800d5c32 100644 --- a/app/api/v1/vendor/usage.py +++ b/app/api/v1/vendor/usage.py @@ -17,7 +17,7 @@ from sqlalchemy.orm import Session from app.api.deps import get_current_vendor_api from app.core.database import get_db from app.services.usage_service import usage_service -from models.database.user import User +from models.schema.auth import UserContext router = APIRouter(prefix="/usage") logger = logging.getLogger(__name__) @@ -91,7 +91,7 @@ class LimitCheckResponse(BaseModel): @router.get("", response_model=UsageResponse) def get_usage( - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ @@ -146,7 +146,7 @@ def get_usage( @router.get("/check/{limit_type}", response_model=LimitCheckResponse) def check_limit( limit_type: str, - current_user: User = Depends(get_current_vendor_api), + current_user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db), ): """ diff --git a/models/schema/auth.py b/models/schema/auth.py index 8237608f..522c6954 100644 --- a/models/schema/auth.py +++ b/models/schema/auth.py @@ -163,3 +163,109 @@ class VendorUserResponse(BaseModel): is_active: bool model_config = {"from_attributes": True} + + +class UserContext(BaseModel): + """ + User context for dependency injection in API endpoints. + + This schema replaces direct use of the User database model in API routes, + following the principle that routes should not import database models directly. + + Used by: + - get_current_admin_api / get_current_admin_from_cookie_or_header + - get_current_vendor_api / get_current_vendor_from_cookie_or_header + - get_current_super_admin + + For admin users: + - is_super_admin indicates full platform access + - accessible_platform_ids is None for super admins (all platforms) + - accessible_platform_ids is a list for platform admins + + For vendor users: + - token_vendor_id/code/role come from JWT token + - These indicate which vendor context the user is operating in + """ + + # Core user fields + id: int + email: str + username: str + role: str # "admin" or "vendor" + is_active: bool = True + + # Admin-specific fields + is_super_admin: bool = False + accessible_platform_ids: list[int] | None = None # None = all platforms (super admin) + + # Vendor-specific fields (from JWT token) + token_vendor_id: int | None = None + token_vendor_code: str | None = None + token_vendor_role: str | None = None + + # Optional profile fields + first_name: str | None = None + last_name: str | None = None + preferred_language: str | None = None + + model_config = ConfigDict(from_attributes=True) + + @property + def full_name(self) -> str: + """Returns the full name of the user.""" + if self.first_name and self.last_name: + return f"{self.first_name} {self.last_name}" + return self.username + + @property + def is_admin(self) -> bool: + """Check if user is a platform admin.""" + return self.role == "admin" + + @property + def is_vendor(self) -> bool: + """Check if user is a vendor.""" + return self.role == "vendor" + + @classmethod + def from_user(cls, user, include_vendor_context: bool = True) -> "UserContext": + """ + Create UserContext from a User database model. + + Args: + user: User database model instance + include_vendor_context: Whether to include token_vendor_* fields + + Returns: + UserContext instance + """ + data = { + "id": user.id, + "email": user.email, + "username": user.username, + "role": user.role, + "is_active": user.is_active, + "is_super_admin": getattr(user, "is_super_admin", False), + "first_name": getattr(user, "first_name", None), + "last_name": getattr(user, "last_name", None), + "preferred_language": getattr(user, "preferred_language", None), + } + + # Add admin platform access info + if user.role == "admin": + if getattr(user, "is_super_admin", False): + data["accessible_platform_ids"] = None # All platforms + else: + # Get platform IDs from admin_platforms relationship + admin_platforms = getattr(user, "admin_platforms", []) + data["accessible_platform_ids"] = [ + ap.platform_id for ap in admin_platforms if ap.is_active + ] + + # Add vendor context from JWT token if present + if include_vendor_context: + data["token_vendor_id"] = getattr(user, "token_vendor_id", None) + data["token_vendor_code"] = getattr(user, "token_vendor_code", None) + data["token_vendor_role"] = getattr(user, "token_vendor_role", None) + + return cls(**data)