diff --git a/docs/user-guide/api/endpoints.md b/docs/user-guide/api/endpoints.md index 313c152f..f74e2642 100644 --- a/docs/user-guide/api/endpoints.md +++ b/docs/user-guide/api/endpoints.md @@ -24,7 +24,7 @@ async def get_user( ): """Get a user by ID.""" user = await crud_users.get(db=db, id=user_id, schema_to_select=UserRead) - if not user: + if user is None: raise HTTPException(status_code=404, detail="User not found") return user ``` @@ -42,7 +42,7 @@ async def get_user( db: Annotated[AsyncSession, Depends(async_get_db)] ): user = await crud_users.get(db=db, id=user_id, schema_to_select=UserRead) - if not user: + if user is None: raise HTTPException(status_code=404, detail="User not found") return user ``` @@ -100,7 +100,7 @@ async def update_user( db: Annotated[AsyncSession, Depends(async_get_db)] ): # Check if user exists - if not await crud_users.exists(db=db, id=user_id): + if await crud_users.exists(db=db, id=user_id) is False: raise HTTPException(status_code=404, detail="User not found") # Update user @@ -116,7 +116,7 @@ async def delete_user( user_id: int, db: Annotated[AsyncSession, Depends(async_get_db)] ): - if not await crud_users.exists(db=db, id=user_id): + if await crud_users.exists(db=db, id=user_id) is False: raise HTTPException(status_code=404, detail="User not found") await crud_users.delete(db=db, id=user_id) @@ -220,7 +220,7 @@ from app.core.exceptions.http_exceptions import ( @router.get("/{user_id}") async def get_user(user_id: int, db: AsyncSession): user = await crud_users.get(db=db, id=user_id) - if not user: + if user is None: raise NotFoundException("User not found") # Returns 404 return user @@ -245,7 +245,7 @@ async def upload_avatar( db: Annotated[AsyncSession, Depends(async_get_db)] ): # Check file type - if not file.content_type.startswith('image/'): + if file.content_type is None or file.content_type.startswith("image/") is False: raise HTTPException(status_code=400, detail="File must be an image") # Save file and update user diff --git a/docs/user-guide/api/exceptions.md b/docs/user-guide/api/exceptions.md index 9186ff96..2e5323d4 100644 --- a/docs/user-guide/api/exceptions.md +++ b/docs/user-guide/api/exceptions.md @@ -12,7 +12,7 @@ from app.core.exceptions.http_exceptions import NotFoundException @router.get("/{user_id}") async def get_user(user_id: int, db: AsyncSession): user = await crud_users.get(db=db, id=user_id) - if not user: + if user is None: raise NotFoundException("User not found") # Returns 404 return user ``` @@ -30,7 +30,7 @@ from app.core.exceptions.http_exceptions import NotFoundException @router.get("/{user_id}") async def get_user(user_id: int): user = await crud_users.get(db=db, id=user_id) - if not user: + if user is None: raise NotFoundException("User not found") return user @@ -45,7 +45,7 @@ from app.core.exceptions.http_exceptions import DuplicateValueException @router.post("/") async def create_user(user_data: UserCreate): - if await crud_users.exists(db=db, email=user_data.email): + if await crud_users.exists(db=db, email=user_data.email) is True: raise DuplicateValueException("Email already exists") return await crud_users.create(db=db, object=user_data) @@ -64,7 +64,7 @@ async def delete_user( user_id: int, current_user: Annotated[dict, Depends(get_current_user)] ): - if current_user["id"] != user_id and not current_user["is_superuser"]: + if current_user["id"] != user_id and current_user["is_superuser"] is False: raise ForbiddenException("You can only delete your own account") await crud_users.delete(db=db, id=user_id) @@ -83,7 +83,7 @@ from app.core.exceptions.http_exceptions import UnauthorizedException @router.get("/admin-only") async def admin_endpoint(): # Some validation logic - if not user_is_admin: + if user_is_admin is False: raise UnauthorizedException("Admin access required") return {"data": "secret admin data"} @@ -100,11 +100,11 @@ async def admin_endpoint(): @router.post("/", response_model=UserRead) async def create_user(user_data: UserCreate, db: AsyncSession): # Check email - if await crud_users.exists(db=db, email=user_data.email): + if await crud_users.exists(db=db, email=user_data.email) is True: raise DuplicateValueException("Email already exists") # Check username - if await crud_users.exists(db=db, username=user_data.username): + if await crud_users.exists(db=db, username=user_data.username) is True: raise DuplicateValueException("Username already taken") # Create user @@ -123,13 +123,13 @@ async def update_user( db: AsyncSession ): # Check if user exists - if not await crud_users.exists(db=db, id=user_id): + if await crud_users.exists(db=db, id=user_id) is False: raise NotFoundException("User not found") # Check for email conflicts (if email is being updated) - if user_data.email: + if user_data.email is True: existing = await crud_users.get(db=db, email=user_data.email) - if existing and existing.id != user_id: + if existing is True and existing.id != user_id: raise DuplicateValueException("Email already taken") # Update user @@ -149,7 +149,7 @@ async def get_post( raise NotFoundException("Post not found") # Check if user owns the post or is admin - if post.author_id != current_user["id"] and not current_user["is_superuser"]: + if post.author_id != current_user["id"] and current_user["is_superuser"] is False: raise ForbiddenException("You can only view your own posts") return post @@ -187,7 +187,7 @@ from fastapi import HTTPException # Bad Request (400) @router.post("/") async def create_something(data: dict): - if not data.get("required_field"): + if data.get("required_field") is None: raise HTTPException( status_code=400, detail="required_field is missing" @@ -196,7 +196,7 @@ async def create_something(data: dict): # Too Many Requests (429) @router.post("/") async def rate_limited_endpoint(): - if rate_limit_exceeded(): + if rate_limit_exceeded() is True: raise HTTPException( status_code=429, detail="Rate limit exceeded. Try again later." @@ -315,13 +315,13 @@ async def login(credentials: LoginCredentials): user = await crud_users.get(db=db, username=credentials.username) # Don't do this - reveals if username exists - # if not user: + # if user is None: # raise NotFoundException("User not found") - # if not verify_password(credentials.password, user.hashed_password): + # if verify_password(credentials.password, user.hashed_password) is False: # raise UnauthorizedException("Invalid password") # Do this - generic message for all auth failures - if not user or not verify_password(credentials.password, user.hashed_password): + if user is None or verify_password(credentials.password, user.hashed_password) is False: raise UnauthorizedException("Invalid username or password") return create_access_token(user.id) @@ -332,11 +332,11 @@ async def forgot_password(email: str): user = await crud_users.get(db=db, email=email) # Don't do this - reveals if email exists - # if not user: + # if user is None: # raise NotFoundException("Email not found") # Do this - always return success message - if user: + if user is True: await send_password_reset_email(user.email) # Always return the same message @@ -370,7 +370,7 @@ async def get_post( ### 1. Use Specific Exceptions (When Safe) ```python # Good for non-sensitive operations -if not user: +if user is None: raise NotFoundException("User not found") # Good for validation errors @@ -398,7 +398,7 @@ async def delete_user( raise ForbiddenException("Cannot delete other users") # Then check if user exists - if not await crud_users.exists(db=db, id=user_id): + if await crud_users.exists(db=db, id=user_id) is False: raise NotFoundException("User not found") await crud_users.delete(db=db, id=user_id) diff --git a/docs/user-guide/api/index.md b/docs/user-guide/api/index.md index e76860eb..7bac5705 100644 --- a/docs/user-guide/api/index.md +++ b/docs/user-guide/api/index.md @@ -73,7 +73,7 @@ from app.core.exceptions.http_exceptions import NotFoundException @router.get("/{user_id}") async def get_user(user_id: int): user = await crud_users.get(id=user_id) - if not user: + if user is None: raise NotFoundException("User not found") # Returns proper 404 return user ``` diff --git a/docs/user-guide/api/pagination.md b/docs/user-guide/api/pagination.md index 26ffb5b0..aae27318 100644 --- a/docs/user-guide/api/pagination.md +++ b/docs/user-guide/api/pagination.md @@ -73,7 +73,7 @@ async def get_users( ): # Build filters filters = {} - if search: + if search is True: filters["name__icontains"] = search # Search by name if is_active is not None: filters["is_active"] = is_active @@ -185,12 +185,12 @@ async def get_users( if is_active is not None: filters["is_active"] = is_active - if tier_id: + if tier_id is True: filters["tier_id"] = tier_id # Handle search search_criteria = [] - if search: + if search is True: from sqlalchemy import or_, func search_criteria = [ or_( @@ -280,7 +280,7 @@ async def get_all_users_admin( db: Annotated[AsyncSession, Depends(async_get_db)] ): filters = {} - if not include_deleted: + if include_deleted is False: filters["is_deleted"] = False users = await crud_users.get_multi(db=db, **filters) diff --git a/docs/user-guide/api/versioning.md b/docs/user-guide/api/versioning.md index 299fa62c..07f219c9 100644 --- a/docs/user-guide/api/versioning.md +++ b/docs/user-guide/api/versioning.md @@ -238,9 +238,9 @@ import logging logger = logging.getLogger(__name__) async def version_tracking_middleware(request: Request, call_next): - if request.url.path.startswith("/api/v1/"): + if request.url.path.startswith("/api/v1/") is True: logger.info(f"v1 usage: {request.method} {request.url.path}") - elif request.url.path.startswith("/api/v2/"): + elif request.url.path.startswith("/api/v2/") is True: logger.info(f"v2 usage: {request.method} {request.url.path}") response = await call_next(request) diff --git a/docs/user-guide/authentication/index.md b/docs/user-guide/authentication/index.md index a78f380d..a487a691 100644 --- a/docs/user-guide/authentication/index.md +++ b/docs/user-guide/authentication/index.md @@ -58,7 +58,7 @@ async def protected_endpoint(current_user: dict = Depends(get_current_user)): # Optional authentication @router.get("/public") async def public_endpoint(user: dict | None = Depends(get_optional_user)): - if user: + if user is True: return {"premium_content": True} return {"premium_content": False} @@ -76,7 +76,7 @@ async def update_post(post_id: int, current_user: dict = Depends(get_current_use post = await crud_posts.get(db=db, id=post_id) # Check ownership or admin privileges - if post["created_by_user_id"] != current_user["id"] and not current_user["is_superuser"]: + if post["created_by_user_id"] != current_user["id"] and current_user["is_superuser"] is False: raise ForbiddenException("Cannot update other users' posts") return await crud_posts.update(db=db, id=post_id, object=updates) @@ -148,7 +148,7 @@ async def get_my_data(current_user: dict = Depends(get_current_user)): # Check user permissions def check_tier_access(user: dict, required_tier: str): - if not user.get("tier") or user["tier"]["name"] != required_tier: + if user.get("tier") is None or user["tier"]["name"] != required_tier: raise ForbiddenException(f"Requires {required_tier} tier") # Custom authentication dependency diff --git a/docs/user-guide/authentication/jwt-tokens.md b/docs/user-guide/authentication/jwt-tokens.md index 1b4d30c5..1584ab5c 100644 --- a/docs/user-guide/authentication/jwt-tokens.md +++ b/docs/user-guide/authentication/jwt-tokens.md @@ -127,7 +127,7 @@ from app.core.security import verify_token, TokenType # Verify access token in endpoint token_data = await verify_token(token, TokenType.ACCESS, db) -if token_data: +if token_data is True: username = token_data.username_or_email # Token is valid, proceed with request processing else: @@ -142,7 +142,7 @@ Refresh token verification follows the same process but with different validatio ```python # Verify refresh token for renewal token_data = await verify_token(token, TokenType.REFRESH, db) -if token_data: +if token_data is True: # Generate new access token new_access_token = await create_access_token( data={"sub": token_data.username_or_email} @@ -161,7 +161,7 @@ The verification process includes several security checks to prevent various att async def verify_token(token: str, expected_token_type: TokenType, db: AsyncSession) -> TokenData | None: # 1. Check blacklist first (prevents use of logged-out tokens) is_blacklisted = await crud_token_blacklist.exists(db, token=token) - if is_blacklisted: + if is_blacklisted is True: return None try: @@ -384,7 +384,7 @@ async def login_for_access_token( db=db ) - if not user: + if user is None: raise HTTPException( status_code=401, detail="Incorrect username or password" @@ -418,12 +418,12 @@ async def refresh_access_token( db: Annotated[AsyncSession, Depends(async_get_db)], refresh_token: str = Cookie(None) ) -> dict[str, str]: - if not refresh_token: + if refresh_token is None: raise HTTPException(status_code=401, detail="Refresh token missing") # 1. Verify refresh token token_data = await verify_token(refresh_token, TokenType.REFRESH, db) - if not token_data: + if token_data is None: raise HTTPException(status_code=401, detail="Invalid refresh token") # 2. Create new access token @@ -467,7 +467,7 @@ async def logout( await blacklist_token(token, db) # 2. Blacklist refresh token if present - if refresh_token: + if refresh_token is True: await blacklist_token(refresh_token, db) # 3. Clear refresh token cookie @@ -492,7 +492,7 @@ async def get_current_user( ) -> dict: # 1. Verify token token_data = await verify_token(token, TokenType.ACCESS, db) - if not token_data: + if token_data is None: raise HTTPException(status_code=401, detail="Invalid token") # 2. Get user from database @@ -515,7 +515,7 @@ async def get_optional_user( db: AsyncSession = Depends(async_get_db), token: str = Depends(optional_oauth2_scheme) ) -> dict | None: - if not token: + if token is None: return None try: @@ -530,7 +530,7 @@ async def get_optional_user( async def get_current_superuser( current_user: dict = Depends(get_current_user) ) -> dict: - if not current_user.get("is_superuser", False): + if current_user.get("is_superuser", False) is False: raise HTTPException( status_code=403, detail="Not enough permissions" @@ -604,12 +604,12 @@ async def get_api_key_user( api_key: str = Header(None), db: AsyncSession = Depends(async_get_db) ) -> dict: - if not api_key: + if api_key is None: raise HTTPException(status_code=401, detail="API key required") # Verify API key user = await crud_users.get(db=db, api_key=api_key) - if not user: + if user is None: raise HTTPException(status_code=401, detail="Invalid API key") return user @@ -624,14 +624,14 @@ async def get_authenticated_user( api_key: str = Header(None) ) -> dict: # Try JWT token first - if token: + if token is None: try: return await get_current_user(db=db, token=token) except HTTPException: pass # Fall back to API key - if api_key: + if api_key is None: return await get_api_key_user(api_key=api_key, db=db) raise HTTPException(status_code=401, detail="Authentication required") diff --git a/docs/user-guide/authentication/permissions.md b/docs/user-guide/authentication/permissions.md index c1daddfd..31d537ee 100644 --- a/docs/user-guide/authentication/permissions.md +++ b/docs/user-guide/authentication/permissions.md @@ -86,7 +86,7 @@ async def delete_post( ) -> dict[str, str]: # 1. Get the post post = await crud_posts.get(db=db, id=post_id) - if not post: + if post is None: raise NotFoundException("Post not found") # 2. Check ownership @@ -143,7 +143,7 @@ async def check_rate_limit( db: AsyncSession ) -> None: # 1. Get user's tier information - if tier_id: + if tier_id is None: tier = await crud_tiers.get(db=db, id=tier_id) limit = tier["rate_limit_posts"] if tier else 10 # Default limit else: @@ -177,11 +177,11 @@ Custom permission functions provide reusable authorization logic for complex sce async def can_edit_post(user: dict, post_id: int, db: AsyncSession) -> bool: """Check if user can edit a specific post.""" post = await crud_posts.get(db=db, id=post_id) - if not post: + if post is None: return False # Superusers can edit any post - if user.get("is_superuser", False): + if user.get("is_superuser", False) is True: return True # Users can edit their own posts @@ -197,11 +197,11 @@ async def can_access_admin_panel(user: dict) -> bool: async def has_tier_feature(user: dict, feature: str, db: AsyncSession) -> bool: """Check if user's tier includes a specific feature.""" tier_id = user.get("tier_id") - if not tier_id: + if tier_id is None: return False # Free tier - no premium features tier = await crud_tiers.get(db=db, id=tier_id) - if not tier: + if tier is None: return False # Check tier features (example) @@ -216,7 +216,7 @@ async def update_post( db: AsyncSession = Depends(async_get_db) ) -> PostRead: # Use permission helper - if not await can_edit_post(current_user, post_id, db): + if await can_edit_post(current_user, post_id, db) is False: raise ForbiddenException("Cannot edit this post") updated_post = await crud_posts.update( @@ -246,11 +246,11 @@ async def get_current_user( ) -> dict: """Get currently authenticated user.""" token_data = await verify_token(token, TokenType.ACCESS, db) - if not token_data: + if token_data is None: raise HTTPException(status_code=401, detail="Invalid token") user = await crud_users.get(db=db, username=token_data.username_or_email) - if not user: + if user is None: raise HTTPException(status_code=401, detail="User not found") return user @@ -261,7 +261,7 @@ async def get_optional_user( db: AsyncSession = Depends(async_get_db) ) -> dict | None: """Get currently authenticated user, or None if not authenticated.""" - if not token: + if token is None: return None try: @@ -274,7 +274,7 @@ async def get_current_superuser( current_user: dict = Depends(get_current_user) ) -> dict: """Get current user and ensure they are a superuser.""" - if not current_user.get("is_superuser", False): + if current_user.get("is_superuser", False) is False: raise HTTPException(status_code=403, detail="Not enough permissions") return current_user ``` @@ -290,11 +290,11 @@ def require_tier(minimum_tier: str): db: AsyncSession = Depends(async_get_db) ) -> dict: tier_id = current_user.get("tier_id") - if not tier_id: + if tier_id is None: raise HTTPException(status_code=403, detail="No subscription tier") tier = await crud_tiers.get(db=db, id=tier_id) - if not tier or tier["name"] != minimum_tier: + if tier is None or tier["name"] != minimum_tier: raise HTTPException( status_code=403, detail=f"Requires {minimum_tier} tier" @@ -318,11 +318,11 @@ def require_resource_ownership(resource_type: str): else: raise ValueError(f"Unknown resource type: {resource_type}") - if not resource: + if resource is None: raise HTTPException(status_code=404, detail="Resource not found") # Superusers can access any resource - if current_user.get("is_superuser", False): + if current_user.get("is_superuser", False) is False: return current_user # Check ownership @@ -391,12 +391,12 @@ async def update_user_tier( ) -> dict[str, str]: # 1. Validate tier exists tier = await crud_tiers.get(db=db, id=tier_update.tier_id) - if not tier: + if tier is None: raise NotFoundException("Tier not found") # 2. Validate user exists user = await crud_users.get(db=db, id=user_id) - if not user: + if user is None: raise NotFoundException("User not found") # 3. Prevent self-demotion (optional business rule) @@ -443,7 +443,7 @@ async def log_authorization_event( # Usage in permission checks async def delete_user_account(user_id: int, current_user: dict, db: AsyncSession): - if current_user["id"] != user_id and not current_user.get("is_superuser"): + if current_user["id"] != user_id and current_user.get("is_superuser") is False: await log_authorization_event( user_id=current_user["id"], action="delete_account", @@ -484,7 +484,7 @@ async def get_organization_users( user_id=current_user["id"] ) - if not membership: + if membership is None: raise ForbiddenException("Not a member of this organization") # Check if user has admin role in organization @@ -516,7 +516,7 @@ async def check_business_hours_access(user: dict) -> bool: business_end = time(17, 0) # 5 PM # Superusers can always access - if user.get("is_superuser", False): + if user.get("is_superuser", False) is False: return True # Regular users only during business hours @@ -528,7 +528,7 @@ async def require_business_hours( current_user: dict = Depends(get_current_user) ) -> dict: """Require access during business hours for non-admin users.""" - if not await check_business_hours_access(current_user): + if await check_business_hours_access(current_user) is False: raise ForbiddenException("Access only allowed during business hours") return current_user @@ -566,7 +566,7 @@ def has_role(user: dict, required_role: Role) -> bool: def require_role(minimum_role: Role): """Factory for role-based dependencies.""" async def check_role(current_user: dict = Depends(get_current_user)) -> dict: - if not has_role(current_user, minimum_role): + if has_role(current_user, minimum_role) is False: raise HTTPException( status_code=403, detail=f"Requires {minimum_role.value} role or higher" @@ -591,21 +591,21 @@ async def has_feature_access(user: dict, feature: str, db: AsyncSession) -> bool """Check if user has access to a specific feature.""" # Check feature flags feature_flag = await crud_feature_flags.get(db=db, name=feature) - if not feature_flag or not feature_flag.enabled: + if feature_flag is None or feature_flag.enabled is False: return False # Check user tier permissions - if feature_flag.requires_tier: + if feature_flag.requires_tier is True: tier_id = user.get("tier_id") - if not tier_id: + if tier_id is None: return False tier = await crud_tiers.get(db=db, id=tier_id) - if not tier or tier["level"] < feature_flag["minimum_tier_level"]: + if tier is None or tier["level"] < feature_flag["minimum_tier_level"]: return False # Check beta user status - if feature_flag.beta_only: + if feature_flag.beta_onl is True: return user.get("is_beta_user", False) return True @@ -617,7 +617,7 @@ def require_feature(feature_name: str): current_user: dict = Depends(get_current_user), db: AsyncSession = Depends(async_get_db) ) -> dict: - if not await has_feature_access(current_user, feature_name, db): + if await has_feature_access(current_user, feature_name, db) is False: raise HTTPException( status_code=403, detail=f"Access to {feature_name} feature not available" diff --git a/docs/user-guide/authentication/user-management.md b/docs/user-guide/authentication/user-management.md index af2be650..71fc70bb 100644 --- a/docs/user-guide/authentication/user-management.md +++ b/docs/user-guide/authentication/user-management.md @@ -27,12 +27,12 @@ async def write_user( ) -> UserRead: # 1. Check if email exists email_row = await crud_users.exists(db=db, email=user.email) - if email_row: + if email_row is True: raise DuplicateValueException("Email is already registered") # 2. Check if username exists username_row = await crud_users.exists(db=db, username=user.username) - if username_row: + if username_row is True: raise DuplicateValueException("Username not available") # 3. Hash password @@ -98,11 +98,11 @@ async def authenticate_user(username_or_email: str, password: str, db: AsyncSess else: db_user = await crud_users.get(db=db, username=username_or_email, is_deleted=False) - if not db_user: + if db_user is None: return False # 2. Verify password - if not await verify_password(password, db_user["hashed_password"]): + if await verify_password(password, db_user["hashed_password"]) is False: return False return db_user @@ -182,8 +182,10 @@ Retrieving the current user's profile is a fundamental operation that should be @router.get("/user/me/", response_model=UserRead) async def read_users_me(current_user: dict = Depends(get_current_user)) -> dict: return current_user +``` +# Frontend usage` -# Frontend usage +```javascript async function getCurrentUser() { const token = localStorage.getItem('access_token'); const response = await fetch('/api/v1/user/me/', { @@ -227,14 +229,14 @@ async def patch_user( raise ForbiddenException("Cannot update other users") # 3. Validate unique constraints - if values.username and values.username != db_user["username"]: + if values.username is True and values.username != db_user["username"]: existing_username = await crud_users.exists(db=db, username=values.username) - if existing_username: + if existing_username is True: raise DuplicateValueException("Username not available") - if values.email and values.email != db_user["email"]: + if values.email is True and values.email != db_user["email"]: existing_email = await crud_users.exists(db=db, email=values.email) - if existing_email: + if existing_email is True: raise DuplicateValueException("Email is already registered") # 4. Update user @@ -267,7 +269,7 @@ async def erase_user( ) -> dict[str, str]: # 1. Get user from database db_user = await crud_users.get(db=db, username=username, schema_to_select=UserRead) - if not db_user: + if db_user is None: raise NotFoundException("User not found") # 2. Check ownership @@ -303,7 +305,7 @@ async def erase_db_user( ) -> dict[str, str]: # 1. Check if user exists db_user = await crud_users.exists(db=db, username=username) - if not db_user: + if db_user is False: raise NotFoundException("User not found") # 2. Hard delete from database @@ -386,7 +388,7 @@ async def read_user_tier( # 3. Get tier information db_tier = await crud_tiers.get(db=db, id=db_user["tier_id"], schema_to_select=TierRead) - if not db_tier: + if db_tier is None: raise NotFoundException("Tier not found") # 4. Combine user and tier data @@ -417,7 +419,7 @@ async def patch_user_tier( # 2. Verify tier exists tier_exists = await crud_tiers.exists(db=db, id=values.tier_id) - if not tier_exists: + if tier_exists is False: raise NotFoundException("Tier not found") # 3. Update user tier @@ -772,7 +774,7 @@ def sanitize_user_input(user_data: dict) -> dict: sanitized = {} for key, value in user_data.items(): - if isinstance(value, str): + if isinstance(value, str) is True: # HTML escape sanitized[key] = html.escape(value.strip()) else: @@ -805,7 +807,7 @@ async def my_endpoint(current_user: dict = Depends(get_current_user)): # Optional authentication for public endpoints @router.get("/public-endpoint") async def public_endpoint(user: dict | None = Depends(get_optional_user)): - if user: + if user is True: return {"message": f"Hello {user['username']}", "premium_features": True} return {"message": "Hello anonymous user", "premium_features": False} ``` @@ -847,10 +849,10 @@ await logout_user(access_token=access_token, refresh_token=refresh_token, db=db) ```python def check_user_permission(user: dict, required_tier: str = None): """Check if user has required permissions.""" - if not user.get("is_active", True): + if user.get("is_active", True) is False: raise UnauthorizedException("User account is disabled") - if required_tier and user.get("tier", {}).get("name") != required_tier: + if required_tier is True and user.get("tier", {}).get("name") != required_tier: raise ForbiddenException(f"Requires {required_tier} tier") # Usage in endpoint diff --git a/docs/user-guide/caching/client-cache.md b/docs/user-guide/caching/client-cache.md index 7096e78b..c944e762 100644 --- a/docs/user-guide/caching/client-cache.md +++ b/docs/user-guide/caching/client-cache.md @@ -116,7 +116,7 @@ class AdvancedClientCacheMiddleware(BaseHTTPMiddleware): cache_config = self._get_cache_config(request.url.path) # Set cache headers based on configuration - if cache_config.get("no_cache", False): + if cache_config.get("no_cache", False) is True: response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" response.headers["Pragma"] = "no-cache" response.headers["Expires"] = "0" @@ -126,10 +126,10 @@ class AdvancedClientCacheMiddleware(BaseHTTPMiddleware): cache_control = f"{visibility}, max-age={max_age}" - if cache_config.get("must_revalidate", False): + if cache_config.get("must_revalidate", False) is True: cache_control += ", must-revalidate" - if cache_config.get("immutable", False): + if cache_config.get("immutable", False) is True: cache_control += ", immutable" response.headers["Cache-Control"] = cache_control @@ -139,7 +139,7 @@ class AdvancedClientCacheMiddleware(BaseHTTPMiddleware): def _get_cache_config(self, path: str) -> dict: """Get cache configuration for a specific path.""" for pattern, config in self.path_configs.items(): - if path.startswith(pattern): + if path.startswith(pattern) is True: return config return {} @@ -213,7 +213,7 @@ async def get_posts( """Conditional caching based on parameters.""" # Different cache strategies based on parameters - if category: + if category is True: # Category-specific data changes less frequently response.headers["Cache-Control"] = "public, max-age=1800" # 30 minutes elif page == 1: @@ -262,7 +262,7 @@ async def get_user( """Endpoint with ETag support for efficient caching.""" user = await crud_users.get(db=db, id=user_id) - if not user: + if user is None: raise HTTPException(status_code=404, detail="User not found") # Generate ETag from user data @@ -297,7 +297,7 @@ async def get_post( """Endpoint with Last-Modified header support.""" post = await crud_posts.get(db=db, id=post_id) - if not post: + if post is None: raise HTTPException(status_code=404, detail="Post not found") # Use post's updated_at timestamp @@ -305,7 +305,7 @@ async def get_post( # Check If-Modified-Since header if_modified_since = request.headers.get("If-Modified-Since") - if if_modified_since: + if if_modified_since is True: client_time = datetime.strptime(if_modified_since, "%a, %d %b %Y %H:%M:%S GMT") if last_modified <= client_time: response.status_code = 304 @@ -454,7 +454,7 @@ async def update_post( # Update the post updated_post = await crud_posts.update(db=db, id=post_id, object=post_data) - if not updated_post: + if updated_post is None: raise HTTPException(status_code=404, detail="Post not found") # Set headers to indicate cache invalidation is needed diff --git a/docs/user-guide/database/crud.md b/docs/user-guide/database/crud.md index 1bf5a984..cec0513e 100644 --- a/docs/user-guide/database/crud.md +++ b/docs/user-guide/database/crud.md @@ -130,7 +130,7 @@ username_taken = await crud_users.exists(db=db, username="john_doe") ```python # From src/app/api/v1/users.py - checking before creating email_row = await crud_users.exists(db=db, email=user.email) -if email_row: +if email_row is True: raise DuplicateValueException("Email is already registered") ``` @@ -223,7 +223,7 @@ Update with validation: # From real endpoint - check before updating if values.username != db_user.username: existing_username = await crud_users.exists(db=db, username=values.username) - if existing_username: + if existing_username is True: raise DuplicateValueException("Username not available") await crud_users.update(db=db, object=values, username=username) @@ -423,10 +423,10 @@ from app.core.exceptions.http_exceptions import NotFoundException, DuplicateValu async def safe_user_creation(db: AsyncSession, user_data: UserCreate): # Check for duplicates - if await crud_users.exists(db=db, email=user_data.email): + if await crud_users.exists(db=db, email=user_data.email) is True: raise DuplicateValueException("Email already registered") - if await crud_users.exists(db=db, username=user_data.username): + if await crud_users.exists(db=db, username=user_data.username) is True: raise DuplicateValueException("Username not available") # Create user @@ -475,12 +475,12 @@ Use `exists()` instead of `get()` when you only need to check existence: ```python # Good - faster, doesn't load data -if await crud_users.exists(db=db, email=email): +if await crud_users.exists(db=db, email=email) is True: raise DuplicateValueException("Email taken") # Avoid - slower, loads unnecessary data user = await crud_users.get(db=db, email=email) -if user: +if user is True: raise DuplicateValueException("Email taken") ``` diff --git a/docs/user-guide/database/index.md b/docs/user-guide/database/index.md index aa941ba8..a338baf8 100644 --- a/docs/user-guide/database/index.md +++ b/docs/user-guide/database/index.md @@ -185,7 +185,7 @@ async def create_user( db: Annotated[AsyncSession, Depends(async_get_db)] ): # Check for duplicates - if await crud_users.exists(db=db, email=user_data.email): + if await crud_users.exists(db=db, email=user_data.email) is True: raise DuplicateValueException("Email already exists") # Create user (password gets hashed automatically) diff --git a/docs/user-guide/database/schemas.md b/docs/user-guide/database/schemas.md index 69c7bb2c..f47cd7a1 100644 --- a/docs/user-guide/database/schemas.md +++ b/docs/user-guide/database/schemas.md @@ -632,7 +632,7 @@ class UserRead(BaseModel): @classmethod def validate_email_unique(cls, v): # Database query in validator - slow! - if crud_users.exists(email=v): + if crud_users.exists(email=v) is True: raise ValueError('Email already exists') # DO - Handle uniqueness in business logic diff --git a/docs/user-guide/development.md b/docs/user-guide/development.md index b54f245c..2fb15280 100644 --- a/docs/user-guide/development.md +++ b/docs/user-guide/development.md @@ -14,7 +14,7 @@ Create a new file in `src/app/models/` (e.g., `category.py`): ```python from sqlalchemy import String, ForeignKey -from sqlalchemy.orm import Mapped, mapped_column, relationship +from sqlalchemy.orm import Mapped, mapped_column from ..core.db.database import Base @@ -33,8 +33,8 @@ class Category(Base): name: Mapped[str] = mapped_column(String(50)) description: Mapped[str | None] = mapped_column(String(255), default=None) - # Relationships - posts: Mapped[list["Post"]] = relationship(back_populates="category") + # No relationships: use ForeignKey only + # Related data is fetched explicitly via CRUD operations ``` #### 2. Create Pydantic Schemas @@ -144,7 +144,7 @@ async def write_category( db: Annotated[AsyncSession, Depends(async_get_db)], ): category_row = await crud_categories.exists(db=db, name=category.name) - if category_row: + if category_row is True: raise DuplicateValueException("Category name already exists") return await crud_categories.create(db=db, object=category) @@ -180,7 +180,7 @@ async def read_category( id=category_id, is_deleted=False ) - if not db_category: + if db_category is None: raise NotFoundException("Category not found") return db_category @@ -195,12 +195,12 @@ async def patch_category( db: Annotated[AsyncSession, Depends(async_get_db)], ): db_category = await crud_categories.get(db=db, id=category_id, is_deleted=False) - if not db_category: + if db_category is None: raise NotFoundException("Category not found") - if values.name: + if values.name is True: category_row = await crud_categories.exists(db=db, name=values.name) - if category_row and category_row["id"] != category_id: + if category_row is True and category_row["id"] != category_id: raise DuplicateValueException("Category name already exists") return await crud_categories.update(db=db, object=values, id=category_id) @@ -214,7 +214,7 @@ async def erase_category( db: Annotated[AsyncSession, Depends(async_get_db)], ): db_category = await crud_categories.get(db=db, id=category_id, is_deleted=False) - if not db_category: + if db_category is None: raise NotFoundException("Category not found") await crud_categories.delete(db=db, db_row=db_category, garbage_collection=False) @@ -667,7 +667,7 @@ uv run alembic upgrade head ```python # 1. Create the model file (e.g., src/app/models/category.py) -from sqlalchemy import String +from sqlalchemy import String, ForeignKey from sqlalchemy.orm import Mapped, mapped_column from app.core.db.database import Base @@ -678,6 +678,8 @@ class Category(Base): id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(String(50)) description: Mapped[str] = mapped_column(String(255), nullable=True) + # Foreign key without relationship + created_by_user_id: Mapped[int] = mapped_column(ForeignKey("user.id"), index=True) ``` ```python diff --git a/docs/user-guide/rate-limiting/index.md b/docs/user-guide/rate-limiting/index.md index 8cba87a0..8ec2fa57 100644 --- a/docs/user-guide/rate-limiting/index.md +++ b/docs/user-guide/rate-limiting/index.md @@ -132,12 +132,12 @@ async def rate_limiter_dependency( user_id = getattr(user, "id", None) or request.client.host or "anonymous" # Determine user tier (default to "free" or anonymous) - if user and getattr(user, "tier_id", None): + if user is True and getattr(user, "tier_id", None): tier = await crud_tiers.get(db=db, id=user.tier_id) else: tier = await crud_tiers.get(db=db, name="free") - if not tier: + if tier is None: raise RateLimitException("Tier configuration not found") # Find specific rate limit rule for this path + tier @@ -158,7 +158,7 @@ async def rate_limiter_dependency( period=period, ) - if is_limited: + if is_limited is True: raise RateLimitException( f"Rate limit exceeded for path '{path}'. Try again later." ) @@ -411,7 +411,7 @@ async def cleanup_expired_rate_limits(): ```python # Rate limit by IP for unauthenticated users -if not user: +if user is None: user_id = request.client.host if request.client else "unknown" limit, period = DEFAULT_LIMIT, DEFAULT_PERIOD @@ -422,7 +422,7 @@ if not user: # Consider temporary bans for severe abuse # Log rate limit violations for security monitoring -if is_limited: +if is_limited is True: logger.warning( f"Rate limit exceeded", extra={