📚 FastAPI Training Assignments
Product Catalog Service - Practical Exercises
Course: Building High-Performance APIs with FastAPI Version: 1.0.0 Last Updated: 2025-12-24
🎯 Project Overview
Business Context
You are tasked with building a Product Catalog Service - a RESTful API for an e-commerce company's product management system. The system needs to meet the following requirements:
- User Management: Registration, login, role assignment
- Product Management: CRUD operations with validation
- Security: JWT authentication, password hashing
- Documentation: Auto-generated API docs
Technical Requirements
| Component | Technology |
|---|---|
| Framework | FastAPI 0.104+ |
| Python | 3.11+ |
| ORM | SQLAlchemy 2.0 |
| Database | PostgreSQL or SQLite |
| Migrations | Alembic |
| Validation | Pydantic 2.0 |
Project Structure
mono-src/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI application
│ ├── api/ # Route handlers
│ │ ├── __init__.py
│ │ ├── auth.py
│ │ ├── products.py
│ │ └── deps.py # Dependencies
│ ├── config/
│ │ └── settings.py # Configuration
│ ├── database/
│ │ └── database.py # DB connection
│ ├── models/ # SQLAlchemy models
│ │ ├── user.py
│ │ └── product.py
│ ├── repositories/ # Data access layer
│ │ ├── base.py
│ │ ├── user_repository.py
│ │ └── product_repository.py
│ ├── schemas/ # Pydantic schemas
│ │ ├── user.py
│ │ └── product.py
│ ├── services/ # Business logic
│ │ ├── auth_service.py
│ │ └── product_service.py
│ └── utils/
│ └── security.py # JWT, hashing
├── alembic/ # Migrations
├── tests/ # Unit tests
├── requirements.txt
├── alembic.ini
└── .env
📝 Assignment 01: Foundation & Inputs
Unit 1 - Sessions 1-2
🎯 Learning Objectives
- Understand the basic structure of a FastAPI application
- Create endpoints with path and query parameters
- Explore automatic OpenAPI documentation
📖 Business Requirements
Scenario
The company needs a basic API to check system status and provide service information. This API will be used by:
- DevOps team: Monitoring health status
- Frontend team: Displaying API version information
- Integration team: Checking connectivity
✅ Required Tasks
Task 1.1: Project Setup (10 points)
Requirements:
- Create a virtual environment and install dependencies
- Create directory structure according to project structure
- Create
requirements.txtfile with necessary packages - Create
.env.examplefile with configuration template
Acceptance Criteria:
- Virtual environment is functional
- FastAPI import works without errors
- Directory structure is correct
Task 1.2: Root Endpoint (15 points)
Business Logic:
When a user accesses the root endpoint, the system must return introduction information regarding the API including:
- Service name
- Current version
- Path to documentation
Technical Requirements:
| Endpoint | Method | Response Code |
|---|---|---|
/ | GET | 200 |
Response Format:
{
"message": "Welcome to Product Catalog Service API",
"version": "1.0.0",
"docs": "/docs",
"redoc": "/redoc"
}
Acceptance Criteria:
- Endpoint returns correct JSON format
- Status code is 200
- Content-Type is application/json
Task 1.3: Health Check Endpoint (15 points)
Business Logic:
The Health check endpoint is used by load balancers and monitoring tools to check if the service is operational. This endpoint needs to:
- Be always available (no authentication required)
- Fast response (< 100ms)
- Return status information and metadata
Technical Requirements:
| Endpoint | Method | Response Code |
|---|---|---|
/health | GET | 200 |
Response Format:
{
"status": "healthy",
"service": "Product Catalog Service",
"version": "1.0.0",
"timestamp": "2025-12-24T10:00:00Z"
}
Acceptance Criteria:
- Endpoint accessible without authentication
- Response time < 100ms
- Timestamp is in ISO 8601 format
Task 1.4: Products List with Query Parameters (20 points)
Business Logic:
The API needs to support pagination for the product list. This is a critical feature because:
- The database may contain millions of products
- Frontend needs to load data page by page
- Reduce load on server and network
Technical Requirements:
| Endpoint | Method | Query Params |
|---|---|---|
/products | GET | skip, limit |
Query Parameters:
| Param | Type | Default | Constraints |
|---|---|---|---|
skip | integer | 0 | >= 0 |
limit | integer | 10 | 1-100 |
Acceptance Criteria:
- Default values applied when params are not passed
- Validation for negative values (skip) and out of range (limit)
- Automatic type conversion (string → int)
Task 1.5: Product Detail with Path Parameter (15 points)
Business Logic:
Each product has a unique ID. The API needs an endpoint to retrieve product details by ID.
Technical Requirements:
| Endpoint | Method | Path Param |
|---|---|---|
/products/{product_id} | GET | product_id (int) |
Acceptance Criteria:
- Path parameter validated as integer
- Returns 422 if product_id is not a number
- Response contains product_id in body (temporarily)
🌟 Bonus Tasks
Bonus 1.1: Request Metadata (5 points)
Guideline: Create endpoint /debug/request-info returning request metadata like headers, client IP, user-agent. Research FastAPI Request object.
Bonus 1.2: Environment-based Response (5 points)
Guideline: Root endpoint displays additional environment field (development/staging/production) based on environment variable.
Bonus 1.3: API Versioning (10 points)
Guideline: Implement URL-based API versioning (/api/v1/...). Create router prefix and organize code to support multiple versions.
📊 Rubric - Assignment 01
| Criteria | Excellent (100%) | Good (80%) | Satisfactory (60%) | Needs Improvement (40%) |
|---|---|---|---|---|
| Project Setup (10pts) | Complete structure, standard compliant, has .env.example | Correct structure, missing 1-2 files | Basic structure, missing many files | Failed to create project |
| Root Endpoint (15pts) | Correct response format, has description in docs | Correct response, missing docs description | Response missing fields | Endpoint not working |
| Health Check (15pts) | Full fields, dynamic timestamp, < 100ms | Full fields, static timestamp | Missing 1-2 fields | Endpoint not working |
| Query Params (20pts) | Complete validation, default values, error handling | Works correctly, basic validation | Missing validation | Pagination not implemented |
| Path Params (15pts) | Type validation, proper error response | Works correctly | Missing validation | Endpoint not working |
| Code Quality (10pts) | Clean code, type hints, docstrings | Full type hints | Readable code | Messy code |
| Documentation (15pts) | Complete Swagger UI with descriptions | Swagger UI present but missing descriptions | Basic Swagger UI | No documentation |
Total: 100 points Bonus: 20 points
📝 Assignment 02: Data Modeling with Pydantic
Unit 2 - Sessions 3-4
🎯 Learning Objectives
- Define Pydantic schemas for validation
- Use Field constraints and validators
- Understand response_model filtering
- Handle validation errors
📖 Business Requirements
Scenario
Product Catalog needs strict input data validation to ensure:
- Data integrity: Product price must be positive, name cannot be empty
- Security: Prevent invalid data injection
- User experience: Return clear error messages
✅ Required Tasks
Task 2.1: User Schemas (20 points)
Business Logic:
The system has 2 types of user data:
- Input data (UserCreate): Username and password during registration
- Output data (UserResponse): User info returned to client (does NOT contain password)
Validation Rules:
| Field | Rules |
|---|---|
username | Required, 3-50 characters, alphanumeric + underscore |
password | Required, min 6 characters |
Acceptance Criteria:
- UserCreate validates input according to rules
- UserResponse does not contain password field
- Validation error returns 422 with error details
Task 2.2: Product Schemas (25 points)
Business Logic:
Products in the system need the following information:
- Required: name, price, quantity
- Optional: description
- Automatic: id, timestamps
Schemas to create:
| Schema | Purpose |
|---|---|
ProductCreate | Input when creating product |
ProductUpdate | Input when updating (all optional) |
ProductResponse | Output returned to client |
Validation Rules:
| Field | Type | Rules |
|---|---|---|
name | string | Required, 1-100 chars |
description | string | Optional, max 500 chars |
price | decimal | Required, > 0, max 2 decimal places |
quantity | integer | Required, >= 0 |
Business Constraints:
- Price cannot be negative or 0 (free products use a different field)
- Quantity can be 0 (out of stock) but cannot be negative
- Name cannot contain only spaces
Acceptance Criteria:
- All validation rules are implemented
- ProductUpdate allows partial update
- Error messages descriptive and helpful
Task 2.3: POST Endpoint with Request Body (20 points)
Business Logic:
Implement endpoint to create a new product. This endpoint:
- Receives data from request body (JSON)
- Validates according to ProductCreate schema
- Returns ProductResponse (temporarily not saving to DB)
Technical Requirements:
| Endpoint | Method | Request Body | Response |
|---|---|---|---|
/products | POST | ProductCreate | ProductResponse |
Response Codes:
| Code | Condition |
|---|---|
| 201 | Created successfully |
| 422 | Validation error |
Acceptance Criteria:
- Request body is parsed and validated
- Response uses response_model
- Status code 201 for success
Task 2.4: Token Schema (10 points)
Business Logic:
Prepare schema for JWT token response (will be used in Assignment 05).
Schema:
Token:
- access_token: string (JWT token)
- token_type: string (default "bearer")
Acceptance Criteria:
- Token schema defined
- Default value for token_type
Task 2.5: Enhanced Documentation (10 points)
Business Logic:
API documentation needs to be clear so frontend team and third-parties can integrate. Each endpoint needs:
- Concise summary
- Detailed description
- Example request/response
- Possible error responses
Acceptance Criteria:
- All endpoints have summary and description
- Schemas have field descriptions
- Examples are provided in docs
🌟 Bonus Tasks
Bonus 2.1: Custom Validators (10 points)
Guideline: Implement custom validator for password (must contain at least 1 uppercase, 1 lowercase, 1 number). Use @field_validator decorator.
Bonus 2.2: Nested Models (10 points)
Guideline: Create ProductWithCategory schema with nested Category model. Category has id and name.
Bonus 2.3: Computed Fields (5 points)
Guideline: Add computed field is_in_stock (boolean) in ProductResponse, automatically calculated from quantity > 0.
📊 Rubric - Assignment 02
| Criteria | Excellent (100%) | Good (80%) | Satisfactory (60%) | Needs Improvement (40%) |
|---|---|---|---|---|
| User Schemas (20pts) | Complete validation, password excluded | Correct validation, missing 1 rule | Basic schemas | Failed to create schemas |
| Product Schemas (25pts) | All rules, clear error messages | Correct validation, generic error messages | Missing 1-2 validations | Schemas do not validate |
| POST Endpoint (20pts) | 201 response, proper response_model | Works correctly, different code | Response incorrect format | Endpoint error |
| Token Schema (10pts) | Complete with defaults | Correct schema | Missing default | No schema |
| Documentation (10pts) | Comprehensive with examples | Has descriptions | Basic descriptions | No descriptions |
| Code Quality (15pts) | Clean, organized, type hints | Full type hints | Readable code | Messy code |
Total: 100 points Bonus: 25 points
📝 Assignment 03: Database Setup
Unit 3 - Sessions 5-6
🎯 Learning Objectives
- Setup SQLAlchemy with FastAPI
- Create database models with SQLAlchemy 2.0
- Use Alembic for migrations
- Understand database session management
📖 Business Requirements
Scenario
Product Catalog needs persistent storage. Requirements:
- Data is not lost when restarting server
- Support multiple database types (PostgreSQL for production, SQLite for development)
- Schema changes are tracked and reversible
✅ Required Tasks
Task 3.1: Database Configuration (15 points)
Business Logic:
Database connection needs:
- Configurable via environment variables
- Connection pooling for performance
- Automatic reconnection when connection drops
Configuration needed:
| Variable | Description | Example |
|---|---|---|
DATABASE_URL | Connection string | postgresql://user:pass@localhost:5432/catalog |
Acceptance Criteria:
- Database URL from environment variable
- Support both PostgreSQL and SQLite
- Connection pool configured (for PostgreSQL)
Task 3.2: User Model (20 points)
Business Logic:
User model stores authentication info:
- Username unique for login
- Password hashed (not stored in plaintext)
- Track creation and update time of account
Model Definition:
| Column | Type | Constraints |
|---|---|---|
id | Integer | Primary Key, Auto-increment |
username | String(50) | Unique, Not Null, Indexed |
hashed_password | String(255) | Not Null |
is_active | Boolean | Default True, Not Null |
created_at | DateTime | Server default now() |
updated_at | DateTime | Auto-update on change |
Acceptance Criteria:
- Model uses SQLAlchemy 2.0 style
- Index on username column
- Timestamps automatically managed
Task 3.3: Product Model (20 points)
Business Logic:
Product model stores product information. Note:
- Price uses Numeric type to avoid floating point errors
- Quantity can be 0 (out of stock)
Model Definition:
| Column | Type | Constraints |
|---|---|---|
id | Integer | Primary Key, Auto-increment |
name | String(100) | Not Null, Indexed |
description | String(500) | Nullable |
price | Numeric(10,2) | Not Null |
quantity | Integer | Default 0, Not Null |
created_at | DateTime | Server default now() |
updated_at | DateTime | Auto-update on change |
Acceptance Criteria:
- Price uses Numeric type
- Default values set
- Timestamps work correctly
Task 3.4: Alembic Setup (20 points)
Business Logic:
Database migrations allow:
- Track schema changes in version control
- Apply changes incrementally
- Rollback if errors occur
- Sync schema between environments
Tasks:
- Initialize Alembic in project
- Configure env.py to read models
- Generate initial migration
- Apply migration to create tables
Acceptance Criteria:
-
alembic initcompleted - env.py configured correctly
- Initial migration generated
- Tables created after
alembic upgrade head
Task 3.5: Database Session Dependency (15 points)
Business Logic:
Each request needs a separate database session. Session must:
- Be created when request starts
- Automatically close when request ends
- Handle errors gracefully
Acceptance Criteria:
-
get_dbdependency function created - Session yielded and cleaned up in finally
- Dependency injectable in routes
🌟 Bonus Tasks
Bonus 3.1: Soft Delete (10 points)
Guideline: Add is_deleted and deleted_at columns. Products are not actually deleted but marked as deleted. Queries default to filtering out deleted items.
Bonus 3.2: Audit Fields (10 points)
Guideline: Add created_by and updated_by columns to track user making changes. Implement base mixin class for reusability.
Bonus 3.3: Database Seeding (5 points)
Guideline: Create script to seed initial data (sample users and products). Useful for development and testing.
📊 Rubric - Assignment 03
| Criteria | Excellent (100%) | Good (80%) | Satisfactory (60%) | Needs Improvement (40%) |
|---|---|---|---|---|
| DB Config (15pts) | Pooling, env vars, both DB types | Env vars, 1 DB type | Hardcoded config | Cannot connect |
| User Model (20pts) | All columns, constraints, indexes | Missing 1-2 constraints | Basic model | Model errors |
| Product Model (20pts) | Numeric price, all columns | Missing constraints | Basic model | Model errors |
| Alembic (20pts) | Full setup, migration works | Migration works, minor issues | Partial setup | Alembic not working |
| Session Dependency (15pts) | Proper yield/cleanup, injectable | Works but cleanup issues | Basic implementation | Not working |
| Code Organization (10pts) | Clean separation, imports correct | Minor organization issues | Code in wrong places | Messy structure |
Total: 100 points Bonus: 25 points
📝 Assignment 04: CRUD & Dependency Injection
Unit 4 - Sessions 7-8
🎯 Learning Objectives
- Implement Repository Pattern
- Use Dependency Injection in FastAPI
- Build complete CRUD operations
- Handle database exceptions
📖 Business Requirements
Scenario
Backend team needs to implement business logic layer separated from route handlers. This allows:
- Testability: Mock dependencies in tests
- Reusability: Repositories can be used in multiple services
- Maintainability: Business logic centralized in one place
✅ Required Tasks
Task 4.1: Base Repository (15 points)
Business Logic:
Generic repository provides basic CRUD operations for every model. Use Python Generics for type-safety.
Methods to implement:
| Method | Parameters | Return | Description |
|---|---|---|---|
create | obj_data: dict | T | Create new record |
get_by_id | id: int | Optional[T] | Get by ID |
get_all | skip: int, limit: int | List[T] | Get list with pagination |
update | id: int, obj_data: dict | Optional[T] | Update record |
delete | id: int | bool | Delete record |
Acceptance Criteria:
- Generic type parameter
Tused - All methods implemented correctly
- Return types correct
Task 4.2: User Repository (15 points)
Business Logic:
User repository extends BaseRepository with specific methods:
- Find user by username (for authentication)
- Check username existence (for registration)
Additional Methods:
| Method | Parameters | Return | Description |
|---|---|---|---|
get_by_username | username: str | Optional[User] | Find user by username |
exists_by_username | username: str | bool | Check username exists |
Acceptance Criteria:
- Inherits from BaseRepository
- Custom methods implemented
- Query only active users (is_active=True)
Task 4.3: Product Repository (15 points)
Business Logic:
Product repository with methods:
- Search by product name
- Filter products in stock
Additional Methods:
| Method | Parameters | Return | Description |
|---|---|---|---|
search_by_name | name: str | List[Product] | Search LIKE %name% |
get_in_stock | skip, limit | List[Product] | Only products with quantity > 0 |
Acceptance Criteria:
- Inherits from BaseRepository
- Search case-insensitive
- Pagination works with custom queries
Task 4.4: Product Service (15 points)
Business Logic:
Service layer contains business logic, orchestrates between repository and validation:
- Validate business rules (e.g., no duplicate names)
- Transform data between schemas and models
- Handle complex operations
Methods:
| Method | Description |
|---|---|
create_product | Validate and create new product |
get_product | Get product, raise exception if not found |
update_product | Partial update with validation |
delete_product | Delete product |
list_products | Get list with pagination |
Acceptance Criteria:
- Service uses repository (does not query directly)
- Business validation in service
- Proper exception handling
Task 4.5: CRUD Endpoints (30 points)
Business Logic:
Implement complete CRUD for Products:
| Endpoint | Method | Description | Response Code |
|---|---|---|---|
GET /products | GET | List with pagination | 200 |
GET /products/{id} | GET | Get single product | 200, 404 |
POST /products | POST | Create product | 201, 422 |
PUT /products/{id} | PUT | Update product | 200, 404, 422 |
DELETE /products/{id} | DELETE | Delete product | 204, 404 |
Error Handling:
| Scenario | Response |
|---|---|
| Product not found | 404 with message |
| Validation error | 422 with details |
| Server error | 500 with generic message |
Acceptance Criteria:
- All endpoints work correctly
- Proper status codes
- Error responses have clear messages
🌟 Bonus Tasks
Bonus 4.1: Search & Filter API (10 points)
Guideline: Extend GET /products with multiple query params: search (name), min_price, max_price, in_stock (boolean). Combine filters in query.
Bonus 4.2: Sorting (10 points)
Guideline: Add sort_by and sort_order query params. Support sort by price, name, created_at. Order: asc/desc.
Bonus 4.3: Bulk Operations (15 points)
Guideline: Implement POST /products/bulk to create multiple products at once. Handle partial failures (some succeed, some fail).
📊 Rubric - Assignment 04
| Criteria | Excellent (100%) | Good (80%) | Satisfactory (60%) | Needs Improvement (40%) |
|---|---|---|---|---|
| Base Repository (15pts) | Generic, all methods, type hints | All methods, no generics | Missing 1-2 methods | Not working |
| User Repository (15pts) | Custom methods, proper queries | Works, query issues | Basic implementation | Not working |
| Product Repository (15pts) | Search, filter, pagination | Missing 1 feature | Basic implementation | Not working |
| Product Service (15pts) | Business logic, validation, DI | Works, missing validation | Basic implementation | Not working |
| CRUD Endpoints (30pts) | All working, proper codes, errors | Minor issues | Some endpoints broken | Most not working |
| Code Quality (10pts) | Clean, DI pattern, separation | Good structure | Acceptable | Poor structure |
Total: 100 points Bonus: 35 points
📝 Assignment 05: Authentication (AuthN)
Unit 5 - Sessions 9-10
🎯 Learning Objectives
- Implement password hashing with bcrypt
- Create and validate JWT tokens
- Build authentication endpoints
- Understand OAuth2 Password Flow
📖 Business Requirements
Scenario
The system needs authentication to:
- Identity: Determine who the user is
- Security: Protect sensitive operations
- Audit: Track who performed actions
Authentication flow:
- User registers with username/password
- Password is hashed before saving
- User logs in to receive JWT token
- Token is sent in subsequent requests
✅ Required Tasks
Task 5.1: Password Hashing Utilities (20 points)
Business Logic:
Passwords must NEVER be stored in plaintext. Use bcrypt because:
- Automatically generates salt
- Configurable work factor
- Widely tested and trusted
Functions to implement:
| Function | Parameters | Return | Description |
|---|---|---|---|
get_password_hash | password: str | str | Hash password |
verify_password | plain: str, hashed: str | bool | Verify password |
Security Requirements:
- Salt generated for each hash
- Hash output is string (storable)
- Timing-safe comparison
Acceptance Criteria:
- bcrypt used
- Same password produces different hashes (salt)
- Verify works with correct password
- Verify fails with wrong password
Task 5.2: JWT Token Utilities (20 points)
Business Logic:
JWT token contains:
sub(subject): username or user_idexp(expiration): expiration time- Signed with secret key
Functions to implement:
| Function | Parameters | Return | Description |
|---|---|---|---|
create_access_token | data: dict | str | Create JWT token |
decode_access_token | token: str | Optional[str] | Decode and validate |
Configuration:
| Setting | Description | Default |
|---|---|---|
SECRET_KEY | Signing key | Required, min 32 chars |
ALGORITHM | JWT algorithm | HS256 |
ACCESS_TOKEN_EXPIRE_MINUTES | Token lifetime | 30 |
Acceptance Criteria:
- Token contains correct claims
- Expired tokens rejected
- Invalid tokens return None
- Secret key from environment
Task 5.3: Auth Service (15 points)
Business Logic:
Auth service handles:
- User registration with duplicate check
- User authentication (login)
- Token generation
Methods:
| Method | Description |
|---|---|
register_user | Create user with hashed password |
authenticate_user | Verify credentials, return user |
login | Authenticate and return token |
Acceptance Criteria:
- Duplicate username returns error
- Password hashed before save
- Authentication verifies password
- Login returns token
Task 5.4: Registration Endpoint (15 points)
Business Logic:
User registration endpoint:
- Validate input (username, password rules)
- Check duplicate username
- Hash password
- Create user
- Return user info (no password)
API Specification:
| Endpoint | Method | Request | Success | Error |
|---|---|---|---|---|
/register | POST | UserCreate | 201 + UserResponse | 400, 422 |
Acceptance Criteria:
- Successful registration returns 201
- Duplicate username returns 400
- Password NOT in response
- User is active by default
Task 5.5: Login Endpoint (20 points)
Business Logic:
Login endpoint implements OAuth2 Password Flow:
- Accepts form data (not JSON) per OAuth2 spec
- Returns JWT token
- Standard error for invalid credentials
API Specification:
| Endpoint | Method | Content-Type | Success | Error |
|---|---|---|---|---|
/login | POST | application/x-www-form-urlencoded | 200 + Token | 401 |
Form Fields:
username: stringpassword: string
Error Response:
{
"detail": "Incorrect username or password"
}
Security Note: Error message MUST NOT specify if username or password is incorrect (prevent enumeration).
Acceptance Criteria:
- Form data accepted (not JSON)
- Valid credentials return token
- Invalid credentials return 401
- Generic error message
🌟 Bonus Tasks
Bonus 5.1: Refresh Tokens (15 points)
Guideline: Implement refresh token flow. Access token short-lived (15 min), refresh token longer (7 days). Endpoint /refresh to get new access token.
Bonus 5.2: Password Strength Validation (10 points)
Guideline: Validate password strength: min 8 chars, uppercase, lowercase, number, special char. Return specific error for each failed rule.
Bonus 5.3: Account Lockout (10 points)
Guideline: Lock account after 5 failed login attempts. Track failed_attempts and locked_until in User model. Auto unlock after 15 minutes.
📊 Rubric - Assignment 05
| Criteria | Excellent (100%) | Good (80%) | Satisfactory (60%) | Needs Improvement (40%) |
|---|---|---|---|---|
| Password Hashing (20pts) | bcrypt, salt, timing-safe | Works correctly | Basic implementation | Not secure |
| JWT Utilities (20pts) | All claims, expiry, validation | Missing expiry check | Basic implementation | Not working |
| Auth Service (15pts) | All methods, proper errors | Missing 1 method | Basic implementation | Not working |
| Registration (15pts) | All validations, proper response | Minor issues | Works but issues | Not working |
| Login (20pts) | OAuth2 flow, form data, errors | Works, minor issues | JSON instead of form | Not working |
| Security (10pts) | No plaintext, generic errors, env vars | Minor security issues | Some security issues | Major security issues |
Total: 100 points Bonus: 35 points
📝 Assignment 06: Authorization (AuthZ)
Unit 6 - Sessions 11-12
🎯 Learning Objectives
- Implement OAuth2PasswordBearer
- Create authentication dependencies
- Protect endpoints with dependencies
- Implement Role-Based Access Control
📖 Business Requirements
Scenario
After authentication is in place, authorization is needed to control:
- Who can do what
- Public endpoints vs Protected endpoints
- Role-based permissions (user vs admin)
Access Control Matrix:
| Endpoint | Anonymous | User | Admin |
|---|---|---|---|
| GET /products | ✅ | ✅ | ✅ |
| GET /products/{id} | ✅ | ✅ | ✅ |
| POST /products | ❌ | ✅ | ✅ |
| PUT /products/{id} | ❌ | ✅ | ✅ |
| DELETE /products/{id} | ❌ | ❌ | ✅ |
✅ Required Tasks
Task 6.1: OAuth2PasswordBearer Setup (10 points)
Business Logic:
OAuth2PasswordBearer:
- Defines token URL for Swagger UI
- Extracts token from Authorization header
- Format:
Bearer <token>
Acceptance Criteria:
- oauth2_scheme configured with tokenUrl="login"
- Swagger UI shows Authorize button
- Token extracted from header
Task 6.2: Get Current User Dependency (25 points)
Business Logic:
Dependency chain:
- Extract token from header (oauth2_scheme)
- Decode and validate token
- Get user from database
- Return user object
Error Handling:
| Scenario | Response |
|---|---|
| No token | 401 Unauthorized |
| Invalid token | 401 Unauthorized |
| Expired token | 401 Unauthorized |
| User not found | 401 Unauthorized |
| User inactive | 401 Unauthorized |
Response Headers:
WWW-Authenticate: Bearer
Acceptance Criteria:
- Dependency returns User object
- All error scenarios handled
- Proper 401 response with header
- Active user check included
Task 6.3: Get Current Active User (10 points)
Business Logic:
Wrapper dependency to ensure user is active. Can be used for routes specifically requiring active user.
Acceptance Criteria:
- Depends on get_current_user
- Check is_active flag
- Return 401 if inactive
Task 6.4: Protect Product Endpoints (25 points)
Business Logic:
Apply authentication to modification endpoints:
- POST /products: Require authenticated user
- PUT /products/{id}: Require authenticated user
- DELETE /products/{id}: Require authenticated user (will add admin check)
Implementation Pattern:
- Add
current_userdependency to routes - Routes automatically protected
- Swagger UI shows lock icon
Acceptance Criteria:
- POST /products requires auth
- PUT /products/{id} requires auth
- DELETE /products/{id} requires auth
- GET endpoints remain public
- 401 returned without token
Task 6.5: Role-Based Access Control (20 points)
Business Logic:
Implement role system:
- Add
rolecolumn to User model - Default role: "user"
- Admin role: "admin"
- Delete operation requires admin
Model Update:
| Column | Type | Default |
|---|---|---|
role | String(20) | "user" |
Role Check Dependency:
- Create dependency factory for role checking
- Returns 403 Forbidden if insufficient permissions
- Reusable for different roles
Acceptance Criteria:
- Role column added via migration
- Default role is "user"
- DELETE /products/{id} requires admin
- 403 returned for insufficient role
- Other endpoints work with user role
🌟 Bonus Tasks
Bonus 6.1: Permission-Based Access (15 points)
Guideline: Instead of roles, implement permissions (can_create_product, can_delete_product, etc.). User has list of permissions. More granular than roles.
Bonus 6.2: Resource Ownership (10 points)
Guideline: Track creator of each product (created_by field). Users can only update/delete products they created. Admins can modify all.
Bonus 6.3: API Key Authentication (10 points)
Guideline: Alternative authentication with API keys for service-to-service communication. Header: X-API-Key. Separate from JWT auth.
📊 Rubric - Assignment 06
| Criteria | Excellent (100%) | Good (80%) | Satisfactory (60%) | Needs Improvement (40%) |
|---|---|---|---|---|
| OAuth2 Setup (10pts) | Swagger integration, proper config | Works, minor issues | Basic setup | Not working |
| Get Current User (25pts) | All error cases, proper responses | Missing 1-2 cases | Basic implementation | Not working |
| Active User Check (10pts) | Proper dependency chain | Works | Basic check | Not working |
| Protected Endpoints (25pts) | All routes protected correctly | Minor issues | Some routes unprotected | Most not working |
| RBAC (20pts) | Migration, role check, 403 | Missing migration | Basic role field | Not implemented |
| Security (10pts) | Proper 401/403, no leaks | Minor issues | Some security gaps | Major issues |
Total: 100 points Bonus: 35 points
📝 Assignment 07: Testing & Middleware
Unit 7 - Sessions 13-14
🎯 Learning Objectives
- Write unit tests with Pytest
- Use TestClient for API testing
- Implement CORS middleware
- Create custom exception handlers
📖 Business Requirements
Scenario
Before production deployment, we need:
- Test coverage: Ensure code works as expected
- CORS config: Allow frontend access from different origins
- Error handling: Consistent error responses
- Quality assurance: Prevent regressions
✅ Required Tasks
Task 7.1: Test Setup (15 points)
Business Logic:
Test environment needs:
- Separate test database (do not affect real data)
- Fresh database for each test (isolation)
- Fixtures for common setup
Test Structure:
tests/
├── __init__.py
├── conftest.py # Shared fixtures
├── test_health.py # Health check tests
├── test_auth.py # Auth tests
└── test_products.py # Product tests
Fixtures needed:
client: TestClient instancedb_session: Test database sessiontest_user: Pre-created user for auth testsauth_headers: Headers with valid JWT
Acceptance Criteria:
- Test database separate from development
- Database reset between tests
- Fixtures reusable across tests
Task 7.2: Health Check Tests (10 points)
Test Cases:
| Test | Description | Expected |
|---|---|---|
test_health_check | GET /health | 200, status="healthy" |
test_root_endpoint | GET / | 200, has version |
Acceptance Criteria:
- Both tests pass
- Response content verified
- Status codes checked
Task 7.3: Authentication Tests (25 points)
Test Cases:
| Test | Description | Expected |
|---|---|---|
test_register_success | Valid registration | 201, user created |
test_register_duplicate | Same username twice | 400, error message |
test_register_invalid_password | Short password | 422, validation error |
test_login_success | Valid credentials | 200, token returned |
test_login_wrong_password | Invalid password | 401, error |
test_login_nonexistent_user | Unknown username | 401, error |
Acceptance Criteria:
- All test cases implemented
- Tests are independent (do not depend on order)
- Assertions meaningful and specific
Task 7.4: Product CRUD Tests (25 points)
Test Cases:
| Test | Description | Expected |
|---|---|---|
test_get_products_empty | List when empty | 200, [] |
test_get_products_with_data | List with data | 200, list of products |
test_get_product_success | Get existing | 200, product data |
test_get_product_not_found | Get non-existing | 404 |
test_create_product_success | Create with auth | 201, product created |
test_create_product_unauthorized | Create without auth | 401 |
test_create_product_invalid | Invalid data | 422 |
test_update_product_success | Update with auth | 200, updated |
test_delete_product_success | Delete with admin | 204 |
test_delete_product_forbidden | Delete with user role | 403 |
Acceptance Criteria:
- All CRUD operations tested
- Auth scenarios covered
- Error cases tested
- Data integrity verified
Task 7.5: CORS Middleware (10 points)
Business Logic:
Frontend at http://localhost:3000 needs to access API at http://localhost:8000. CORS middleware:
- Allow specified origins
- Allow credentials (cookies, auth headers)
- Handle preflight requests
Configuration:
| Setting | Value |
|---|---|
allow_origins | From environment variable |
allow_credentials | True |
allow_methods | ["*"] |
allow_headers | ["*"] |
Acceptance Criteria:
- CORS headers in responses
- Origins configurable via env
- Preflight OPTIONS handled
Task 7.6: Custom Exception Handler (15 points)
Business Logic:
Standardize error responses across API:
- Consistent JSON structure
- Include request path
- Hide internal errors in production
Error Response Format:
{
"error": true,
"message": "Human readable message",
"detail": "Technical detail (dev only)",
"path": "/products/999"
}
Exception Handlers:
- HTTPException handler (customize format)
- ValidationError handler (422)
- Generic Exception handler (500)
Acceptance Criteria:
- All errors follow same format
- Path included in response
- 500 errors don't leak internals
🌟 Bonus Tasks
Bonus 7.1: Test Coverage Report (10 points)
Guideline: Configure pytest-cov to generate coverage report. Target: > 80% coverage. Add coverage badge to README.
Bonus 7.2: Integration Tests (15 points)
Guideline: Test complete flows: register → login → create product → update → delete. Verify data persistence across requests.
Bonus 7.3: Request Logging Middleware (10 points)
Guideline: Log each request: method, path, status code, duration. Structured logging with JSON format. Useful for debugging and monitoring.
Bonus 7.4: Rate Limiting (15 points)
Guideline: Implement rate limiting middleware. Limit: 100 requests/minute per IP. Return 429 Too Many Requests when exceeded.
📊 Rubric - Assignment 07
| Criteria | Excellent (100%) | Good (80%) | Satisfactory (60%) | Needs Improvement (40%) |
|---|---|---|---|---|
| Test Setup (15pts) | Fixtures, isolation, clean | Works, minor issues | Basic setup | Not working |
| Health Tests (10pts) | Both pass, good assertions | Pass with weak assertions | One test only | Not working |
| Auth Tests (25pts) | All 6 cases, thorough | Missing 1-2 cases | Basic tests only | Most failing |
| Product Tests (25pts) | All 10 cases, thorough | Missing 2-3 cases | Half implemented | Most failing |
| CORS (10pts) | Configurable, all headers | Works, hardcoded | Basic CORS | Not working |
| Exception Handler (15pts) | Consistent format, all types | Missing 1 handler | Basic handler | Not working |
Total: 100 points Bonus: 50 points
📊 Final Grade Calculation
Assignment Weights
| Assignment | Weight | Max Points | Bonus |
|---|---|---|---|
| Assignment 01 | 10% | 100 | 20 |
| Assignment 02 | 10% | 100 | 25 |
| Assignment 03 | 15% | 100 | 25 |
| Assignment 04 | 20% | 100 | 35 |
| Assignment 05 | 15% | 100 | 35 |
| Assignment 06 | 15% | 100 | 35 |
| Assignment 07 | 15% | 100 | 50 |
| Total | 100% | 700 | 225 |
Grade Scale
| Grade | Percentage | Description |
|---|---|---|
| A+ | 95-100% | Exceptional, all bonuses |
| A | 90-94% | Excellent |
| A- | 85-89% | Very Good |
| B+ | 80-84% | Good |
| B | 75-79% | Above Average |
| B- | 70-74% | Average |
| C+ | 65-69% | Below Average |
| C | 60-64% | Minimum Pass |
| F | < 60% | Fail |
Bonus Points
Bonus points are added to the final score, maximum 10% extra credit.
📚 Resources
Official Documentation
Security
Testing
Document Version: 1.0.0 Created: 2025-12-24 Author: Training Team