initial commit

This commit is contained in:
2025-10-19 22:09:35 +03:00
commit 6d593b4554
114 changed files with 23622 additions and 0 deletions

View File

@ -0,0 +1,480 @@
# Adding Models
Learn how to extend the admin interface with your new models by following the patterns established in the FastAPI boilerplate. The boilerplate already includes User, Tier, and Post models - we'll show you how to add your own models using these working examples.
> **CRUDAdmin Features**: This guide shows boilerplate-specific patterns. For advanced model configuration options and features, see the [CRUDAdmin documentation](https://benavlabs.github.io/crudadmin/).
## Understanding the Existing Setup
The boilerplate comes with three models already registered in the admin interface. Understanding how they're implemented will help you add your own models successfully.
### Current Model Registration
The admin interface is configured in `src/app/admin/views.py`:
```python
def register_admin_views(admin: CRUDAdmin) -> None:
"""Register all models and their schemas with the admin interface."""
# User model with password handling
password_transformer = PasswordTransformer(
password_field="password",
hashed_field="hashed_password",
hash_function=get_password_hash,
required_fields=["name", "username", "email"],
)
admin.add_view(
model=User,
create_schema=UserCreate,
update_schema=UserUpdate,
allowed_actions={"view", "create", "update"},
password_transformer=password_transformer,
)
admin.add_view(
model=Tier,
create_schema=TierCreate,
update_schema=TierUpdate,
allowed_actions={"view", "create", "update", "delete"}
)
admin.add_view(
model=Post,
create_schema=PostCreateAdmin, # Special admin-only schema
update_schema=PostUpdate,
allowed_actions={"view", "create", "update", "delete"}
)
```
Each model registration follows the same pattern: specify the SQLAlchemy model, appropriate Pydantic schemas for create/update operations, and define which actions are allowed.
## Step-by-Step Model Addition
Let's walk through adding a new model to your admin interface using a product catalog example.
### Step 1: Create Your Model
First, create your SQLAlchemy model following the boilerplate's patterns:
```python
# src/app/models/product.py
from decimal import Decimal
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import String, Numeric, ForeignKey, Text, Boolean
from sqlalchemy.types import DateTime
from datetime import datetime
from ..core.db.database import Base
class Product(Base):
__tablename__ = "products"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
price: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
# Foreign key relationship (similar to Post.created_by_user_id)
category_id: Mapped[int] = mapped_column(ForeignKey("categories.id"))
```
### Step 2: Create Pydantic Schemas
Create schemas for the admin interface following the boilerplate's pattern:
```python
# src/app/schemas/product.py
from decimal import Decimal
from pydantic import BaseModel, Field
from typing import Annotated
class ProductCreate(BaseModel):
name: Annotated[str, Field(min_length=2, max_length=100)]
description: Annotated[str | None, Field(max_length=1000, default=None)]
price: Annotated[Decimal, Field(gt=0, le=999999.99)]
is_active: Annotated[bool, Field(default=True)]
category_id: Annotated[int, Field(gt=0)]
class ProductUpdate(BaseModel):
name: Annotated[str | None, Field(min_length=2, max_length=100, default=None)]
description: Annotated[str | None, Field(max_length=1000, default=None)]
price: Annotated[Decimal | None, Field(gt=0, le=999999.99, default=None)]
is_active: Annotated[bool | None, Field(default=None)]
category_id: Annotated[int | None, Field(gt=0, default=None)]
```
### Step 3: Register with Admin Interface
Add your model to `src/app/admin/views.py`:
```python
# Add import at the top
from ..models.product import Product
from ..schemas.product import ProductCreate, ProductUpdate
def register_admin_views(admin: CRUDAdmin) -> None:
"""Register all models and their schemas with the admin interface."""
# ... existing model registrations ...
# Add your new model
admin.add_view(
model=Product,
create_schema=ProductCreate,
update_schema=ProductUpdate,
allowed_actions={"view", "create", "update", "delete"}
)
```
### Step 4: Create and Run Migration
Generate the database migration for your new model:
```bash
# Generate migration
uv run alembic revision --autogenerate -m "Add product model"
# Apply migration
uv run alembic upgrade head
```
### Step 5: Test Your New Model
Start your application and test the new model in the admin interface:
```bash
# Start the application
uv run fastapi dev
# Visit http://localhost:8000/admin
# Login with your admin credentials
# You should see "Products" in the admin navigation
```
## Learning from Existing Models
Each model in the boilerplate demonstrates different admin interface patterns you can follow.
### User Model - Password Handling
The User model shows how to handle sensitive fields like passwords:
```python
# Password transformer for secure password handling
password_transformer = PasswordTransformer(
password_field="password", # Field in the schema
hashed_field="hashed_password", # Field in the database model
hash_function=get_password_hash, # Your app's hash function
required_fields=["name", "username", "email"], # Fields required for user creation
)
admin.add_view(
model=User,
create_schema=UserCreate,
update_schema=UserUpdate,
allowed_actions={"view", "create", "update"}, # No delete for users
password_transformer=password_transformer,
)
```
**When to use this pattern:**
- Models with password fields
- Any field that needs transformation before storage
- Fields requiring special security handling
### Tier Model - Simple CRUD
The Tier model demonstrates straightforward CRUD operations:
```python
admin.add_view(
model=Tier,
create_schema=TierCreate,
update_schema=TierUpdate,
allowed_actions={"view", "create", "update", "delete"} # Full CRUD
)
```
**When to use this pattern:**
- Reference data (categories, types, statuses)
- Configuration models
- Simple data without complex relationships
### Post Model - Admin-Specific Schemas
The Post model shows how to create admin-specific schemas when the regular API schemas don't work for admin purposes:
```python
# Special admin schema (different from regular PostCreate)
class PostCreateAdmin(BaseModel):
title: Annotated[str, Field(min_length=2, max_length=30)]
text: Annotated[str, Field(min_length=1, max_length=63206)]
created_by_user_id: int # Required in admin, but not in API
media_url: Annotated[str | None, Field(pattern=r"^(https?|ftp)://[^\s/$.?#].[^\s]*$", default=None)]
admin.add_view(
model=Post,
create_schema=PostCreateAdmin, # Admin-specific schema
update_schema=PostUpdate, # Regular update schema works fine
allowed_actions={"view", "create", "update", "delete"}
)
```
**When to use this pattern:**
- Models where admins need to set fields that users can't
- Models requiring additional validation for admin operations
- Cases where API schemas are too restrictive or too permissive for admin use
## Advanced Model Configuration
### Customizing Field Display
You can control how fields appear in the admin interface by modifying your schemas:
```python
class ProductCreateAdmin(BaseModel):
name: Annotated[str, Field(
min_length=2,
max_length=100,
description="Product name as shown to customers"
)]
description: Annotated[str | None, Field(
max_length=1000,
description="Detailed product description (supports HTML)"
)]
price: Annotated[Decimal, Field(
gt=0,
le=999999.99,
description="Price in USD (up to 2 decimal places)"
)]
category_id: Annotated[int, Field(
gt=0,
description="Product category (creates dropdown automatically)"
)]
```
### Restricting Actions
Control what operations are available for each model:
```python
# Read-only model (reports, logs, etc.)
admin.add_view(
model=AuditLog,
create_schema=None, # No creation allowed
update_schema=None, # No updates allowed
allowed_actions={"view"} # Only viewing
)
# No deletion allowed (users, critical data)
admin.add_view(
model=User,
create_schema=UserCreate,
update_schema=UserUpdate,
allowed_actions={"view", "create", "update"} # No delete
)
```
### Handling Complex Fields
Some models may have fields that don't work well in the admin interface. Use select schemas to exclude problematic fields:
```python
from pydantic import BaseModel
# Create a simplified view schema
class ProductAdminView(BaseModel):
id: int
name: str
price: Decimal
is_active: bool
# Exclude complex fields like large text or binary data
admin.add_view(
model=Product,
create_schema=ProductCreate,
update_schema=ProductUpdate,
select_schema=ProductAdminView, # Controls what's shown in lists
allowed_actions={"view", "create", "update", "delete"}
)
```
## Common Model Patterns
### Reference Data Models
For categories, types, and other reference data:
```python
# Simple reference model
class Category(Base):
__tablename__ = "categories"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50), unique=True)
description: Mapped[str | None] = mapped_column(Text)
# Simple schemas
class CategoryCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
description: str | None = None
# Registration
admin.add_view(
model=Category,
create_schema=CategoryCreate,
update_schema=CategoryCreate, # Same schema for create and update
allowed_actions={"view", "create", "update", "delete"}
)
```
### User-Generated Content
For content models with user associations:
```python
class BlogPost(Base):
__tablename__ = "blog_posts"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(200))
content: Mapped[str] = mapped_column(Text)
author_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
published_at: Mapped[datetime | None] = mapped_column(DateTime)
# Admin schema with required author
class BlogPostCreateAdmin(BaseModel):
title: str = Field(..., min_length=5, max_length=200)
content: str = Field(..., min_length=10)
author_id: int = Field(..., gt=0) # Admin must specify author
published_at: datetime | None = None
admin.add_view(
model=BlogPost,
create_schema=BlogPostCreateAdmin,
update_schema=BlogPostUpdate,
allowed_actions={"view", "create", "update", "delete"}
)
```
### Configuration Models
For application settings and configuration:
```python
class SystemSetting(Base):
__tablename__ = "system_settings"
id: Mapped[int] = mapped_column(primary_key=True)
key: Mapped[str] = mapped_column(String(100), unique=True)
value: Mapped[str] = mapped_column(Text)
description: Mapped[str | None] = mapped_column(Text)
# Restricted actions - settings shouldn't be deleted
admin.add_view(
model=SystemSetting,
create_schema=SystemSettingCreate,
update_schema=SystemSettingUpdate,
allowed_actions={"view", "create", "update"} # No delete
)
```
## Testing Your Models
After adding models to the admin interface, test them thoroughly:
### Manual Testing
1. **Access**: Navigate to `/admin` and log in
2. **Create**: Try creating new records with valid and invalid data
3. **Edit**: Test updating existing records
4. **Validation**: Verify that your schema validation works correctly
5. **Relationships**: Test foreign key relationships (dropdowns should populate)
### Development Testing
```python
# Test your admin configuration
# src/scripts/test_admin.py
from app.admin.initialize import create_admin_interface
def test_admin_setup():
admin = create_admin_interface()
if admin:
print("Admin interface created successfully")
print(f"Models registered: {len(admin._views)}")
for model_name in admin._views:
print(f" - {model_name}")
else:
print("Admin interface disabled")
if __name__ == "__main__":
test_admin_setup()
```
```bash
# Run the test
uv run python src/scripts/test_admin.py
```
## Updating Model Registration
When you need to modify how existing models appear in the admin interface:
### Adding Actions
```python
# Enable deletion for a model that previously didn't allow it
admin.add_view(
model=Product,
create_schema=ProductCreate,
update_schema=ProductUpdate,
allowed_actions={"view", "create", "update", "delete"} # Added delete
)
```
### Changing Schemas
```python
# Switch to admin-specific schemas
admin.add_view(
model=User,
create_schema=UserCreateAdmin, # New admin schema
update_schema=UserUpdateAdmin, # New admin schema
allowed_actions={"view", "create", "update"},
password_transformer=password_transformer,
)
```
### Performance Optimization
For models with many records, consider using select schemas to limit data:
```python
# Only show essential fields in lists
class UserListView(BaseModel):
id: int
username: str
email: str
is_active: bool
admin.add_view(
model=User,
create_schema=UserCreate,
update_schema=UserUpdate,
select_schema=UserListView, # Faster list loading
allowed_actions={"view", "create", "update"},
password_transformer=password_transformer,
)
```
## What's Next
With your models successfully added to the admin interface, you're ready to:
1. **[User Management](user-management.md)** - Learn how to manage admin users and implement security best practices
Your models are now fully integrated into the admin interface and ready for production use. The admin panel will automatically handle form generation, validation, and database operations based on your model and schema definitions.

View File

@ -0,0 +1,378 @@
# Configuration
Learn how to configure the admin panel (powered by [CRUDAdmin](https://github.com/benavlabs/crudadmin)) using the FastAPI boilerplate's built-in environment variable system. The admin panel is fully integrated with your application's configuration and requires no additional setup files or complex initialization.
> **About CRUDAdmin**: For complete configuration options and advanced features, see the [CRUDAdmin documentation](https://benavlabs.github.io/crudadmin/).
## Environment-Based Configuration
The FastAPI boilerplate handles all admin panel configuration through environment variables defined in your `.env` file. This approach provides consistent configuration across development, staging, and production environments.
```bash
# Basic admin panel configuration in .env
CRUD_ADMIN_ENABLED=true
ADMIN_USERNAME="admin"
ADMIN_PASSWORD="SecurePassword123!"
CRUD_ADMIN_MOUNT_PATH="/admin"
```
The configuration system automatically:
- Validates all environment variables at startup
- Provides sensible defaults for optional settings
- Adapts security settings based on your environment (local/staging/production)
- Integrates with your application's existing security and database systems
## Core Configuration Settings
### Enable/Disable Admin Panel
Control whether the admin panel is available:
```bash
# Enable admin panel (default: true)
CRUD_ADMIN_ENABLED=true
# Disable admin panel completely
CRUD_ADMIN_ENABLED=false
```
When disabled, the admin interface is not mounted and consumes no resources.
### Admin Access Credentials
Configure the initial admin user that's created automatically:
```bash
# Required: Admin user credentials
ADMIN_USERNAME="your-admin-username" # Admin login username
ADMIN_PASSWORD="YourSecurePassword123!" # Admin login password
# Optional: Additional admin user details (uses existing settings)
ADMIN_NAME="Administrator" # Display name (from FirstUserSettings)
ADMIN_EMAIL="admin@yourcompany.com" # Admin email (from FirstUserSettings)
```
**How this works:**
- The admin user is created automatically when the application starts
- Only created if no admin users exist (safe for restarts)
- Uses your application's existing password hashing system
- Credentials are validated according to CRUDAdmin requirements
### Interface Configuration
Customize where and how the admin panel appears:
```bash
# Admin panel URL path (default: "/admin")
CRUD_ADMIN_MOUNT_PATH="/admin" # Access at http://localhost:8000/admin
CRUD_ADMIN_MOUNT_PATH="/management" # Access at http://localhost:8000/management
CRUD_ADMIN_MOUNT_PATH="/internal" # Access at http://localhost:8000/internal
```
The admin panel is mounted as a sub-application at your specified path.
## Session Management Configuration
Control how admin users stay logged in and how sessions are managed.
### Basic Session Settings
```bash
# Session limits and timeouts
CRUD_ADMIN_MAX_SESSIONS=10 # Max concurrent sessions per user
CRUD_ADMIN_SESSION_TIMEOUT=1440 # Session timeout in minutes (24 hours)
# Cookie security
SESSION_SECURE_COOKIES=true # Require HTTPS for cookies (production)
```
**Session behavior:**
- Each admin login creates a new session
- Sessions expire after the timeout period of inactivity
- When max sessions are exceeded, oldest sessions are removed
- Session cookies are HTTP-only and secure (when HTTPS is enabled)
### Memory Sessions (Development)
For local development, sessions are stored in memory by default:
```bash
# Development configuration
ENVIRONMENT="local" # Enables memory sessions
CRUD_ADMIN_REDIS_ENABLED=false # Explicitly disable Redis (default)
```
**Memory session characteristics:**
- Fast performance with no external dependencies
- Sessions lost when application restarts
- Suitable for single-developer environments
- Not suitable for load-balanced deployments
### Redis Sessions (Production)
For production deployments, enable Redis session storage:
```bash
# Enable Redis sessions
CRUD_ADMIN_REDIS_ENABLED=true
# Redis connection settings
CRUD_ADMIN_REDIS_HOST="localhost" # Redis server hostname
CRUD_ADMIN_REDIS_PORT=6379 # Redis server port
CRUD_ADMIN_REDIS_DB=0 # Redis database number
CRUD_ADMIN_REDIS_PASSWORD="secure-pass" # Redis authentication
CRUD_ADMIN_REDIS_SSL=false # Enable SSL/TLS connection
```
**Redis session benefits:**
- Sessions persist across application restarts
- Supports multiple application instances (load balancing)
- Configurable expiration and cleanup
- Production-ready scalability
**Redis URL construction:**
The boilerplate automatically constructs the Redis URL from your environment variables:
```python
# Automatic URL generation in src/app/admin/initialize.py
redis_url = f"redis{'s' if settings.CRUD_ADMIN_REDIS_SSL else ''}://"
if settings.CRUD_ADMIN_REDIS_PASSWORD:
redis_url += f":{settings.CRUD_ADMIN_REDIS_PASSWORD}@"
redis_url += f"{settings.CRUD_ADMIN_REDIS_HOST}:{settings.CRUD_ADMIN_REDIS_PORT}/{settings.CRUD_ADMIN_REDIS_DB}"
```
## Security Configuration
The admin panel automatically adapts its security settings based on your deployment environment.
### Environment-Based Security
```bash
# Environment setting affects security behavior
ENVIRONMENT="local" # Development mode
ENVIRONMENT="staging" # Staging mode
ENVIRONMENT="production" # Production mode with enhanced security
```
**Security changes by environment:**
| Setting | Local | Staging | Production |
|---------|-------|---------|------------|
| **HTTPS Enforcement** | Disabled | Optional | Enabled |
| **Secure Cookies** | Optional | Recommended | Required |
| **Session Tracking** | Optional | Recommended | Enabled |
| **Event Logging** | Optional | Recommended | Enabled |
### Audit and Tracking
Enable comprehensive logging for compliance and security monitoring:
```bash
# Event and session tracking
CRUD_ADMIN_TRACK_EVENTS=true # Log all admin actions
CRUD_ADMIN_TRACK_SESSIONS=true # Track session lifecycle
# Available in admin interface
# - View all admin actions with timestamps
# - Monitor active sessions
# - Track user activity patterns
```
### Access Restrictions
The boilerplate supports IP and network-based access restrictions (configured in code):
```python
# In src/app/admin/initialize.py - customize as needed
admin = CRUDAdmin(
# ... other settings ...
allowed_ips=settings.CRUD_ADMIN_ALLOWED_IPS_LIST, # Specific IP addresses
allowed_networks=settings.CRUD_ADMIN_ALLOWED_NETWORKS_LIST, # CIDR network ranges
)
```
To implement IP restrictions, extend the `CRUDAdminSettings` class in `src/app/core/config.py`.
## Integration with Application Settings
The admin panel leverages your existing application configuration for seamless integration.
### Shared Security Settings
```bash
# Uses your application's main secret key
SECRET_KEY="your-application-secret-key" # Shared with admin panel
# Inherits database settings
POSTGRES_USER="dbuser" # Admin uses same database
POSTGRES_PASSWORD="dbpass"
POSTGRES_SERVER="localhost"
POSTGRES_DB="yourapp"
```
### Automatic Configuration Loading
The admin panel automatically inherits settings from your application:
```python
# In src/app/admin/initialize.py
admin = CRUDAdmin(
session=async_get_db, # Your app's database session
SECRET_KEY=settings.SECRET_KEY.get_secret_value(), # Your app's secret key
enforce_https=settings.ENVIRONMENT == EnvironmentOption.PRODUCTION,
# ... other settings from your app configuration
)
```
## Deployment Examples
### Development Environment
Perfect for local development with minimal setup:
```bash
# .env.development
ENVIRONMENT="local"
CRUD_ADMIN_ENABLED=true
ADMIN_USERNAME="dev-admin"
ADMIN_PASSWORD="dev123"
CRUD_ADMIN_MOUNT_PATH="/admin"
# Memory sessions - no external dependencies
CRUD_ADMIN_REDIS_ENABLED=false
# Optional tracking for testing
CRUD_ADMIN_TRACK_EVENTS=false
CRUD_ADMIN_TRACK_SESSIONS=false
```
### Staging Environment
Staging environment with Redis but relaxed security:
```bash
# .env.staging
ENVIRONMENT="staging"
CRUD_ADMIN_ENABLED=true
ADMIN_USERNAME="staging-admin"
ADMIN_PASSWORD="StagingPassword123!"
# Redis sessions for testing production behavior
CRUD_ADMIN_REDIS_ENABLED=true
CRUD_ADMIN_REDIS_HOST="staging-redis.example.com"
CRUD_ADMIN_REDIS_PASSWORD="staging-redis-pass"
# Enable tracking for testing
CRUD_ADMIN_TRACK_EVENTS=true
CRUD_ADMIN_TRACK_SESSIONS=true
SESSION_SECURE_COOKIES=true
```
### Production Environment
Production-ready configuration with full security:
```bash
# .env.production
ENVIRONMENT="production"
CRUD_ADMIN_ENABLED=true
ADMIN_USERNAME="prod-admin"
ADMIN_PASSWORD="VerySecureProductionPassword123!"
# Redis sessions for scalability
CRUD_ADMIN_REDIS_ENABLED=true
CRUD_ADMIN_REDIS_HOST="redis.internal.company.com"
CRUD_ADMIN_REDIS_PORT=6379
CRUD_ADMIN_REDIS_PASSWORD="ultra-secure-redis-password"
CRUD_ADMIN_REDIS_SSL=true
# Full security and tracking
SESSION_SECURE_COOKIES=true
CRUD_ADMIN_TRACK_EVENTS=true
CRUD_ADMIN_TRACK_SESSIONS=true
CRUD_ADMIN_MAX_SESSIONS=5
CRUD_ADMIN_SESSION_TIMEOUT=480 # 8 hours for security
```
### Docker Deployment
Configure for containerized deployments:
```yaml
# docker-compose.yml
version: '3.8'
services:
web:
build: .
environment:
- ENVIRONMENT=production
- ADMIN_USERNAME=${ADMIN_USERNAME}
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
# Redis connection
- CRUD_ADMIN_REDIS_ENABLED=true
- CRUD_ADMIN_REDIS_HOST=redis
- CRUD_ADMIN_REDIS_PORT=6379
- CRUD_ADMIN_REDIS_PASSWORD=${REDIS_PASSWORD}
depends_on:
- redis
- postgres
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
```
```bash
# .env file for Docker
ADMIN_USERNAME="docker-admin"
ADMIN_PASSWORD="DockerSecurePassword123!"
REDIS_PASSWORD="docker-redis-password"
```
## Configuration Validation
The boilerplate automatically validates your configuration at startup and provides helpful error messages.
### Common Configuration Issues
**Missing Required Variables:**
```bash
# Error: Admin credentials not provided
# Solution: Add to .env
ADMIN_USERNAME="your-admin"
ADMIN_PASSWORD="your-password"
```
**Invalid Redis Configuration:**
```bash
# Error: Redis connection failed
# Check Redis server and credentials
CRUD_ADMIN_REDIS_HOST="correct-redis-host"
CRUD_ADMIN_REDIS_PASSWORD="correct-password"
```
**Security Warnings:**
```bash
# Warning: Weak admin password
# Use stronger password with mixed case, numbers, symbols
ADMIN_PASSWORD="StrongerPassword123!"
```
## What's Next
With your admin panel configured, you're ready to:
1. **[Adding Models](adding-models.md)** - Register your application models with the admin interface
2. **[User Management](user-management.md)** - Manage admin users and implement security best practices
The configuration system provides flexibility for any deployment scenario while maintaining consistency across environments.

View File

@ -0,0 +1,295 @@
# Admin Panel
The FastAPI boilerplate comes with a pre-configured web-based admin interface powered by [CRUDAdmin](https://github.com/benavlabs/crudadmin) that provides instant database management capabilities. Learn how to access, configure, and customize the admin panel for your development and production needs.
> **Powered by CRUDAdmin**: This admin panel is built with [CRUDAdmin](https://github.com/benavlabs/crudadmin), a modern admin interface generator for FastAPI applications.
>
> - **📚 CRUDAdmin Documentation**: [benavlabs.github.io/crudadmin](https://benavlabs.github.io/crudadmin/)
> - **💻 CRUDAdmin GitHub**: [github.com/benavlabs/crudadmin](https://github.com/benavlabs/crudadmin)
## What You'll Learn
- **[Configuration](configuration.md)** - Environment variables and deployment settings
- **[Adding Models](adding-models.md)** - Register your new models with the admin interface
- **[User Management](user-management.md)** - Manage admin users and security
## Admin Panel Overview
Your FastAPI boilerplate includes a fully configured admin interface that's ready to use out of the box. The admin panel automatically provides web-based management for your database models without requiring any additional setup.
**What's Already Configured:**
- Complete admin interface mounted at `/admin`
- User, Tier, and Post models already registered
- Automatic form generation and validation
- Session management with configurable backends
- Security features and access controls
**Accessing the Admin Panel:**
1. Start your application: `uv run fastapi dev`
2. Navigate to: `http://localhost:8000/admin`
3. Login with default credentials (configured via environment variables)
## Pre-Registered Models
The boilerplate comes with three models already set up in the admin interface:
### User Management
```python
# Already registered in your admin
admin.add_view(
model=User,
create_schema=UserCreate,
update_schema=UserUpdate,
allowed_actions={"view", "create", "update"},
password_transformer=password_transformer, # Automatic password hashing
)
```
**Features:**
- Create and manage application users
- Automatic password hashing with bcrypt
- User profile management (name, username, email)
- Tier assignment for subscription management
### Tier Management
```python
# Subscription tiers for your application
admin.add_view(
model=Tier,
create_schema=TierCreate,
update_schema=TierUpdate,
allowed_actions={"view", "create", "update", "delete"}
)
```
**Features:**
- Manage subscription tiers and pricing
- Configure rate limits per tier
- Full CRUD operations available
### Content Management
```python
# Post/content management
admin.add_view(
model=Post,
create_schema=PostCreateAdmin, # Special admin schema
update_schema=PostUpdate,
allowed_actions={"view", "create", "update", "delete"}
)
```
**Features:**
- Manage user-generated content
- Handle media URLs and content validation
- Associate posts with users
## Quick Start
### 1. Set Up Admin Credentials
Configure your admin login in your `.env` file:
```bash
# Admin Panel Access
ADMIN_USERNAME="your-admin-username"
ADMIN_PASSWORD="YourSecurePassword123!"
# Basic Configuration
CRUD_ADMIN_ENABLED=true
CRUD_ADMIN_MOUNT_PATH="/admin"
```
### 2. Start the Application
```bash
# Development
uv run fastapi dev
# The admin panel will be available at:
# http://localhost:8000/admin
```
### 3. Login and Explore
1. **Access**: Navigate to `/admin` in your browser
2. **Login**: Use the credentials from your environment variables
3. **Explore**: Browse the pre-configured models (Users, Tiers, Posts)
## Environment Configuration
The admin panel is configured entirely through environment variables, making it easy to adapt for different deployment environments.
### Basic Settings
```bash
# Enable/disable admin panel
CRUD_ADMIN_ENABLED=true # Set to false to disable completely
# Admin interface path
CRUD_ADMIN_MOUNT_PATH="/admin" # Change the URL path
# Admin user credentials (created automatically)
ADMIN_USERNAME="admin" # Your admin username
ADMIN_PASSWORD="SecurePassword123!" # Your admin password
```
### Session Management
```bash
# Session configuration
CRUD_ADMIN_MAX_SESSIONS=10 # Max concurrent sessions per user
CRUD_ADMIN_SESSION_TIMEOUT=1440 # Session timeout (24 hours)
SESSION_SECURE_COOKIES=true # HTTPS-only cookies
```
### Production Security
```bash
# Security settings for production
ENVIRONMENT="production" # Enables HTTPS enforcement
CRUD_ADMIN_TRACK_EVENTS=true # Log admin actions
CRUD_ADMIN_TRACK_SESSIONS=true # Track session activity
```
### Redis Session Storage
For production deployments with multiple server instances:
```bash
# Enable Redis sessions
CRUD_ADMIN_REDIS_ENABLED=true
CRUD_ADMIN_REDIS_HOST="localhost"
CRUD_ADMIN_REDIS_PORT=6379
CRUD_ADMIN_REDIS_DB=0
CRUD_ADMIN_REDIS_PASSWORD="your-redis-password"
CRUD_ADMIN_REDIS_SSL=false
```
## How It Works
The admin panel integrates seamlessly with your FastAPI application through several key components:
### Automatic Initialization
```python
# In src/app/main.py - already configured
admin = create_admin_interface()
@asynccontextmanager
async def lifespan_with_admin(app: FastAPI):
async with default_lifespan(app):
if admin:
await admin.initialize() # Sets up admin database
yield
# Admin is mounted automatically at your configured path
if admin:
app.mount(settings.CRUD_ADMIN_MOUNT_PATH, admin.app)
```
### Configuration Integration
```python
# In src/app/admin/initialize.py - uses your existing settings
admin = CRUDAdmin(
session=async_get_db, # Your database session
SECRET_KEY=settings.SECRET_KEY, # Your app's secret key
mount_path=settings.CRUD_ADMIN_MOUNT_PATH, # Configurable path
secure_cookies=settings.SESSION_SECURE_COOKIES,
enforce_https=settings.ENVIRONMENT == EnvironmentOption.PRODUCTION,
# ... all configured via environment variables
)
```
### Model Registration
```python
# In src/app/admin/views.py - pre-configured models
def register_admin_views(admin: CRUDAdmin):
# Password handling for User model
password_transformer = PasswordTransformer(
password_field="password",
hashed_field="hashed_password",
hash_function=get_password_hash, # Uses your app's password hashing
)
# Register your models with appropriate schemas
admin.add_view(model=User, create_schema=UserCreate, ...)
admin.add_view(model=Tier, create_schema=TierCreate, ...)
admin.add_view(model=Post, create_schema=PostCreateAdmin, ...)
```
## Development vs Production
### Development Setup
For local development, minimal configuration is needed:
```bash
# .env for development
CRUD_ADMIN_ENABLED=true
ADMIN_USERNAME="admin"
ADMIN_PASSWORD="admin123"
ENVIRONMENT="local"
# Uses memory sessions (fast, no external dependencies)
CRUD_ADMIN_REDIS_ENABLED=false
```
### Production Setup
For production deployments, enable additional security features:
```bash
# .env for production
CRUD_ADMIN_ENABLED=true
ADMIN_USERNAME="production-admin"
ADMIN_PASSWORD="VerySecureProductionPassword123!"
ENVIRONMENT="production"
# Redis sessions for scalability
CRUD_ADMIN_REDIS_ENABLED=true
CRUD_ADMIN_REDIS_HOST="your-redis-host"
CRUD_ADMIN_REDIS_PASSWORD="secure-redis-password"
CRUD_ADMIN_REDIS_SSL=true
# Enhanced security
SESSION_SECURE_COOKIES=true
CRUD_ADMIN_TRACK_EVENTS=true
CRUD_ADMIN_TRACK_SESSIONS=true
```
## Getting Started Guide
### 1. **[Configuration](configuration.md)** - Environment Setup
Learn about all available environment variables and how to configure the admin panel for different deployment scenarios. Understand session backends and security settings.
Perfect for setting up development environments and preparing for production deployment.
### 2. **[Adding Models](adding-models.md)** - Extend the Admin Interface
Discover how to register your new models with the admin interface. Learn from the existing User, Tier, and Post implementations to add your own models.
Essential when you create new database models and want them managed through the admin interface.
### 3. **[User Management](user-management.md)** - Admin Security
Understand how admin authentication works, how to create additional admin users, and implement security best practices for production environments.
Critical for production deployments where multiple team members need admin access.
## What's Next
Ready to start using your admin panel? Follow this path:
1. **[Configuration](configuration.md)** - Set up your environment variables and understand deployment options
2. **[Adding Models](adding-models.md)** - Add your new models to the admin interface
3. **[User Management](user-management.md)** - Implement secure admin authentication
The admin panel is ready to use immediately with sensible defaults, and each guide shows you how to customize it for your specific needs.

View File

@ -0,0 +1,213 @@
# User Management
Learn how to manage admin users in your FastAPI boilerplate's admin panel. The boilerplate automatically creates admin users from environment variables and provides a separate authentication system (powered by [CRUDAdmin](https://github.com/benavlabs/crudadmin)) from your application users.
> **CRUDAdmin Authentication**: For advanced authentication features and session management, see the [CRUDAdmin documentation](https://benavlabs.github.io/crudadmin/).
## Initial Admin Setup
### Configure Admin Credentials
Set your admin credentials in your `.env` file:
```bash
# Required admin credentials
ADMIN_USERNAME="admin"
ADMIN_PASSWORD="SecurePassword123!"
# Optional details
ADMIN_NAME="Administrator"
ADMIN_EMAIL="admin@yourcompany.com"
```
### Access the Admin Panel
Start your application and access the admin panel:
```bash
# Start application
uv run fastapi dev
# Visit: http://localhost:8000/admin
# Login with your ADMIN_USERNAME and ADMIN_PASSWORD
```
The boilerplate automatically creates the initial admin user from your environment variables when the application starts.
## Managing Admin Users
### Creating Additional Admin Users
Once logged in, you can create more admin users through the admin interface:
1. Navigate to the admin users section in the admin panel
2. Click "Create" or "Add New"
3. Fill in the required fields:
- Username (must be unique)
- Password (will be hashed automatically)
- Email (optional)
### Admin User Requirements
- **Username**: 3-50 characters, letters/numbers/underscores/hyphens
- **Password**: Minimum 8 characters with mixed case, numbers, and symbols
- **Email**: Valid email format (optional)
### Updating and Removing Users
- **Update**: Find the user in the admin panel and click "Edit"
- **Remove**: Click "Delete" (ensure you have alternative admin access first)
## Security Configuration
### Environment-Specific Settings
Configure different security levels for each environment:
```bash
# Development
ADMIN_USERNAME="dev-admin"
ADMIN_PASSWORD="DevPass123!"
ENVIRONMENT="local"
# Production
ADMIN_USERNAME="prod-admin"
ADMIN_PASSWORD="VerySecurePassword123!"
ENVIRONMENT="production"
CRUD_ADMIN_TRACK_EVENTS=true
CRUD_ADMIN_TRACK_SESSIONS=true
SESSION_SECURE_COOKIES=true
```
### Session Management
Control admin sessions with these settings:
```bash
# Session limits and timeouts
CRUD_ADMIN_MAX_SESSIONS=10 # Max concurrent sessions per user
CRUD_ADMIN_SESSION_TIMEOUT=1440 # Timeout in minutes (24 hours)
SESSION_SECURE_COOKIES=true # HTTPS-only cookies
```
### Enable Tracking
Monitor admin activity by enabling event tracking:
```bash
# Track admin actions and sessions
CRUD_ADMIN_TRACK_EVENTS=true # Log all admin actions
CRUD_ADMIN_TRACK_SESSIONS=true # Track session lifecycle
```
## Production Deployment
### Secure Credential Management
For production, use Docker secrets or Kubernetes secrets instead of plain text:
```yaml
# docker-compose.yml
services:
web:
secrets:
- admin_username
- admin_password
environment:
- ADMIN_USERNAME_FILE=/run/secrets/admin_username
- ADMIN_PASSWORD_FILE=/run/secrets/admin_password
secrets:
admin_username:
file: ./secrets/admin_username.txt
admin_password:
file: ./secrets/admin_password.txt
```
### Production Security Settings
```bash
# Production .env
ENVIRONMENT="production"
ADMIN_USERNAME="prod-admin"
ADMIN_PASSWORD="UltraSecurePassword123!"
# Enhanced security
CRUD_ADMIN_REDIS_ENABLED=true
CRUD_ADMIN_REDIS_HOST="redis.internal.company.com"
CRUD_ADMIN_REDIS_PASSWORD="secure-redis-password"
CRUD_ADMIN_REDIS_SSL=true
# Monitoring
CRUD_ADMIN_TRACK_EVENTS=true
CRUD_ADMIN_TRACK_SESSIONS=true
SESSION_SECURE_COOKIES=true
CRUD_ADMIN_MAX_SESSIONS=5
CRUD_ADMIN_SESSION_TIMEOUT=480 # 8 hours
```
## Application User Management
### Admin vs Application Users
Your boilerplate maintains two separate user systems:
- **Admin Users**: Access the admin panel (stored by CRUDAdmin)
- **Application Users**: Use your application (stored in your User model)
### Managing Application Users
Through the admin panel, you can manage your application's users:
1. Navigate to "Users" section (your application users)
2. View, create, update user profiles
3. Manage user tiers and subscriptions
4. View user-generated content (posts)
The User model is already registered with password hashing and proper permissions.
## Emergency Recovery
### Lost Admin Password
If you lose admin access, update your environment variables:
```bash
# Update .env file
ADMIN_USERNAME="emergency-admin"
ADMIN_PASSWORD="EmergencyPassword123!"
# Restart application
uv run fastapi dev
```
### Database Recovery (Advanced)
For direct database password reset:
```python
# Generate bcrypt hash
import bcrypt
password = "NewPassword123!"
hashed = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
print(hashed.decode('utf-8'))
```
```sql
-- Update in database
UPDATE admin_users
SET password_hash = '<bcrypt-hash>'
WHERE username = 'admin';
```
## What's Next
Your admin user management is now configured with:
- Automatic admin user creation from environment variables
- Secure authentication separate from application users
- Environment-specific security settings
- Production-ready credential management
- Emergency recovery procedures
You can now securely manage both admin users and your application users through the admin panel.