Features implemented: - Application factory pattern with environment-based config - 7 modular blueprints (main, auth, admin, players, groups, content, api) - Flask-Caching with Redis support for production - Flask-Login authentication with bcrypt password hashing - API endpoints with rate limiting and Bearer token auth - Comprehensive error handling and logging - CLI commands (init-db, create-admin, seed-db) Blueprint Structure: - main: Dashboard with caching, health check endpoint - auth: Login, register, logout, password change - admin: User management, system settings, theme, logo upload - players: Full CRUD, fullscreen view, bulk operations, playlist management - groups: Group management, player assignments, content management - content: Upload with progress tracking, file management, preview/download - api: RESTful endpoints with authentication, rate limiting, player feedback Performance Optimizations: - Dashboard caching (60s timeout) - Playlist caching (5min timeout) - Redis caching for production - Memoized functions for expensive operations - Cache clearing on data changes Security Features: - Bcrypt password hashing - Flask-Login session management - admin_required decorator for authorization - Player authentication via auth codes - API Bearer token authentication - Rate limiting on API endpoints (60 req/min default) - Input validation and sanitization Documentation: - README.md: Full project documentation with quick start - PROGRESS.md: Detailed progress tracking and roadmap - BLUEPRINT_GUIDE.md: Quick reference for blueprint architecture Pending work: - Models migration from v1 with database indexes - Utils migration from v1 with type hints - Templates migration with updated route references - Docker multi-stage build configuration - Unit tests for all blueprints Ready for models and utils migration from digiserver v1
337 lines
9.3 KiB
Markdown
337 lines
9.3 KiB
Markdown
# Blueprint Architecture - Quick Reference
|
|
|
|
## 📦 Blueprint Structure
|
|
|
|
```
|
|
app/
|
|
├── blueprints/
|
|
│ ├── __init__.py # Package initialization
|
|
│ ├── main.py # Dashboard, health check
|
|
│ ├── auth.py # Login, register, logout
|
|
│ ├── admin.py # Admin panel, user management
|
|
│ ├── players.py # Player CRUD, fullscreen view
|
|
│ ├── groups.py # Group management, assignments
|
|
│ ├── content.py # Media upload, file management
|
|
│ └── api.py # REST API endpoints
|
|
```
|
|
|
|
---
|
|
|
|
## 🔗 URL Mapping
|
|
|
|
### Main Blueprint (`/`)
|
|
- `GET /` - Dashboard with statistics
|
|
- `GET /health` - Health check (database, disk)
|
|
|
|
### Auth Blueprint (`/auth`)
|
|
- `GET /auth/login` - Login page
|
|
- `POST /auth/login` - Process login
|
|
- `GET /auth/logout` - Logout
|
|
- `GET /auth/register` - Register page
|
|
- `POST /auth/register` - Process registration
|
|
- `GET /auth/change-password` - Change password page
|
|
- `POST /auth/change-password` - Update password
|
|
|
|
### Admin Blueprint (`/admin`)
|
|
- `GET /admin/` - Admin panel
|
|
- `POST /admin/user/create` - Create user
|
|
- `POST /admin/user/<id>/role` - Change user role
|
|
- `POST /admin/user/<id>/delete` - Delete user
|
|
- `POST /admin/theme` - Change theme
|
|
- `POST /admin/logo/upload` - Upload logo
|
|
- `POST /admin/logs/clear` - Clear logs
|
|
- `GET /admin/system/info` - System info (JSON)
|
|
|
|
### Players Blueprint (`/players`)
|
|
- `GET /players/` - List all players
|
|
- `GET /players/add` - Add player page
|
|
- `POST /players/add` - Create player
|
|
- `GET /players/<id>/edit` - Edit player page
|
|
- `POST /players/<id>/edit` - Update player
|
|
- `POST /players/<id>/delete` - Delete player
|
|
- `POST /players/<id>/regenerate-auth` - Regenerate auth code
|
|
- `GET /players/<id>` - Player page
|
|
- `GET /players/<id>/fullscreen` - Player fullscreen view
|
|
- `POST /players/<id>/reorder` - Reorder content
|
|
- `POST /players/bulk/delete` - Bulk delete players
|
|
- `POST /players/bulk/assign-group` - Bulk assign to group
|
|
|
|
### Groups Blueprint (`/groups`)
|
|
- `GET /groups/` - List all groups
|
|
- `GET /groups/create` - Create group page
|
|
- `POST /groups/create` - Create group
|
|
- `GET /groups/<id>/edit` - Edit group page
|
|
- `POST /groups/<id>/edit` - Update group
|
|
- `POST /groups/<id>/delete` - Delete group
|
|
- `GET /groups/<id>/manage` - Manage group page
|
|
- `GET /groups/<id>/fullscreen` - Group fullscreen view
|
|
- `POST /groups/<id>/add-player` - Add player to group
|
|
- `POST /groups/<id>/remove-player/<player_id>` - Remove player
|
|
- `POST /groups/<id>/add-content` - Add content to group
|
|
- `POST /groups/<id>/remove-content/<content_id>` - Remove content
|
|
- `POST /groups/<id>/reorder-content` - Reorder content
|
|
- `GET /groups/<id>/stats` - Group statistics (JSON)
|
|
|
|
### Content Blueprint (`/content`)
|
|
- `GET /content/` - List all content
|
|
- `GET /content/upload` - Upload page
|
|
- `POST /content/upload` - Upload file
|
|
- `GET /content/<id>/edit` - Edit content page
|
|
- `POST /content/<id>/edit` - Update content
|
|
- `POST /content/<id>/delete` - Delete content
|
|
- `POST /content/bulk/delete` - Bulk delete content
|
|
- `GET /content/upload-progress/<upload_id>` - Upload progress (JSON)
|
|
- `GET /content/preview/<id>` - Preview content
|
|
- `GET /content/<id>/download` - Download content
|
|
- `GET /content/statistics` - Content statistics (JSON)
|
|
- `GET /content/check-duplicates` - Check duplicates (JSON)
|
|
- `GET /content/<id>/groups` - Content groups info (JSON)
|
|
|
|
### API Blueprint (`/api`)
|
|
- `GET /api/health` - API health check
|
|
- `GET /api/playlists/<player_id>` - Get player playlist (auth required)
|
|
- `POST /api/player-feedback` - Submit player feedback (auth required)
|
|
- `GET /api/player-status/<player_id>` - Get player status
|
|
- `GET /api/upload-progress/<upload_id>` - Get upload progress
|
|
- `GET /api/system-info` - System statistics
|
|
- `GET /api/groups` - List all groups
|
|
- `GET /api/content` - List all content
|
|
- `GET /api/logs` - Get server logs (query params: limit, level, since)
|
|
|
|
---
|
|
|
|
## 🔒 Authentication & Authorization
|
|
|
|
### Login Required
|
|
Most routes require authentication via `@login_required` decorator:
|
|
```python
|
|
from flask_login import login_required
|
|
|
|
@players_bp.route('/')
|
|
@login_required
|
|
def players_list():
|
|
# Route logic
|
|
```
|
|
|
|
### Admin Required
|
|
Admin routes use custom `@admin_required` decorator:
|
|
```python
|
|
from app.blueprints.admin import admin_required
|
|
|
|
@admin_bp.route('/')
|
|
@login_required
|
|
@admin_required
|
|
def admin_panel():
|
|
# Route logic
|
|
```
|
|
|
|
### API Authentication
|
|
API routes use `@verify_player_auth` for player authentication:
|
|
```python
|
|
from app.blueprints.api import verify_player_auth
|
|
|
|
@api_bp.route('/playlists/<int:player_id>')
|
|
@verify_player_auth
|
|
def get_player_playlist(player_id):
|
|
# Access authenticated player via request.player
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Performance Features
|
|
|
|
### Caching
|
|
Routes with caching enabled:
|
|
- Dashboard: 60 seconds
|
|
- Player playlist: 5 minutes (memoized function)
|
|
|
|
Clear cache on data changes:
|
|
```python
|
|
from app.extensions import cache
|
|
|
|
# Clear specific memoized function
|
|
cache.delete_memoized(get_player_playlist, player_id)
|
|
|
|
# Clear all cache
|
|
cache.clear()
|
|
```
|
|
|
|
### Rate Limiting
|
|
API endpoints have rate limiting:
|
|
```python
|
|
@api_bp.route('/playlists/<int:player_id>')
|
|
@rate_limit(max_requests=30, window=60) # 30 requests per minute
|
|
def get_player_playlist(player_id):
|
|
# Route logic
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 Template Usage
|
|
|
|
### URL Generation
|
|
Always use blueprint-qualified names in templates:
|
|
|
|
**Old (v1):**
|
|
```html
|
|
<a href="{{ url_for('login') }}">Login</a>
|
|
<a href="{{ url_for('dashboard') }}">Dashboard</a>
|
|
<a href="{{ url_for('add_player') }}">Add Player</a>
|
|
```
|
|
|
|
**New (v2):**
|
|
```html
|
|
<a href="{{ url_for('auth.login') }}">Login</a>
|
|
<a href="{{ url_for('main.dashboard') }}">Dashboard</a>
|
|
<a href="{{ url_for('players.add_player') }}">Add Player</a>
|
|
```
|
|
|
|
### Context Processors
|
|
Available in all templates:
|
|
- `server_version` - Server version string
|
|
- `build_date` - Build date string
|
|
- `logo_exists` - Boolean, whether custom logo exists
|
|
- `theme` - Current theme ('light' or 'dark')
|
|
|
|
---
|
|
|
|
## 📝 Common Patterns
|
|
|
|
### Creating a New Route
|
|
|
|
1. **Choose the appropriate blueprint** based on functionality
|
|
2. **Add the route** with proper decorators:
|
|
```python
|
|
@blueprint_name.route('/path', methods=['GET', 'POST'])
|
|
@login_required # If authentication needed
|
|
def route_name():
|
|
try:
|
|
# Route logic
|
|
log_action('info', 'Success message')
|
|
flash('Success message', 'success')
|
|
return redirect(url_for('blueprint.route'))
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
log_action('error', f'Error: {str(e)}')
|
|
flash('Error message', 'danger')
|
|
return redirect(url_for('blueprint.route'))
|
|
```
|
|
|
|
### Adding Caching
|
|
|
|
For view caching:
|
|
```python
|
|
@cache.cached(timeout=60, key_prefix='my_key')
|
|
def my_route():
|
|
# Route logic
|
|
```
|
|
|
|
For function memoization:
|
|
```python
|
|
@cache.memoize(timeout=300)
|
|
def my_function(param):
|
|
# Function logic
|
|
```
|
|
|
|
### API Response Format
|
|
|
|
Consistent JSON responses:
|
|
```python
|
|
# Success
|
|
return jsonify({
|
|
'success': True,
|
|
'data': {...}
|
|
})
|
|
|
|
# Error
|
|
return jsonify({
|
|
'error': 'Error message'
|
|
}), 400
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 Extension Access
|
|
|
|
Import extensions from centralized location:
|
|
```python
|
|
from app.extensions import db, bcrypt, cache, login_manager
|
|
```
|
|
|
|
Never initialize extensions directly in blueprints - they're initialized in `extensions.py` and registered in `app.py`.
|
|
|
|
---
|
|
|
|
## 🧪 Testing Routes
|
|
|
|
### Manual Testing
|
|
```bash
|
|
# Start development server
|
|
flask run
|
|
|
|
# Test specific blueprint
|
|
curl http://localhost:5000/api/health
|
|
curl http://localhost:5000/health
|
|
|
|
# Test authenticated route
|
|
curl -H "Authorization: Bearer <auth_code>" http://localhost:5000/api/playlists/1
|
|
```
|
|
|
|
### Unit Testing
|
|
```python
|
|
def test_dashboard(client, auth):
|
|
auth.login()
|
|
response = client.get('/')
|
|
assert response.status_code == 200
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Blueprint Registration
|
|
|
|
Blueprints are registered in `app/app.py`:
|
|
```python
|
|
def register_blueprints(app: Flask) -> None:
|
|
"""Register all blueprints."""
|
|
from app.blueprints.main import main_bp
|
|
from app.blueprints.auth import auth_bp
|
|
from app.blueprints.admin import admin_bp
|
|
from app.blueprints.players import players_bp
|
|
from app.blueprints.groups import groups_bp
|
|
from app.blueprints.content import content_bp
|
|
from app.blueprints.api import api_bp
|
|
|
|
app.register_blueprint(main_bp)
|
|
app.register_blueprint(auth_bp)
|
|
app.register_blueprint(admin_bp)
|
|
app.register_blueprint(players_bp)
|
|
app.register_blueprint(groups_bp)
|
|
app.register_blueprint(content_bp)
|
|
app.register_blueprint(api_bp)
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Checklist for Adding New Features
|
|
|
|
- [ ] Choose appropriate blueprint
|
|
- [ ] Add route with proper decorators
|
|
- [ ] Implement error handling (try/except)
|
|
- [ ] Add logging with `log_action()`
|
|
- [ ] Add flash messages for user feedback
|
|
- [ ] Clear cache if data changes
|
|
- [ ] Add type hints to parameters
|
|
- [ ] Update this documentation
|
|
- [ ] Add unit tests
|
|
- [ ] Test manually in browser/API client
|
|
|
|
---
|
|
|
|
This architecture provides:
|
|
- ✅ **Separation of concerns** - Each blueprint handles specific functionality
|
|
- ✅ **Scalability** - Easy to add new blueprints
|
|
- ✅ **Maintainability** - Clear organization and naming
|
|
- ✅ **Performance** - Built-in caching and optimization
|
|
- ✅ **Security** - Proper authentication and authorization
|
|
- ✅ **API-first** - RESTful API alongside web interface
|