feat: Refactor rides app with unique constraints, mixins, and enhanced documentation

- Added migration to convert unique_together constraints to UniqueConstraint for RideModel.
- Introduced RideFormMixin for handling entity suggestions in ride forms.
- Created comprehensive code standards documentation outlining formatting, docstring requirements, complexity guidelines, and testing requirements.
- Established error handling guidelines with a structured exception hierarchy and best practices for API and view error handling.
- Documented view pattern guidelines, emphasizing the use of CBVs, FBVs, and ViewSets with examples.
- Implemented a benchmarking script for query performance analysis and optimization.
- Developed security documentation detailing measures, configurations, and a security checklist.
- Compiled a database optimization guide covering indexing strategies, query optimization patterns, and computed fields.
This commit is contained in:
pacnpal
2025-12-22 11:17:31 -05:00
parent 45d97b6e68
commit 2e35f8c5d9
71 changed files with 8036 additions and 1462 deletions

View File

@@ -115,6 +115,8 @@ MIDDLEWARE = [
"django.middleware.cache.UpdateCacheMiddleware",
"corsheaders.middleware.CorsMiddleware", # CORS middleware for API
"django.middleware.security.SecurityMiddleware",
"apps.core.middleware.security_headers.SecurityHeadersMiddleware", # Custom security headers (CSP, Permissions-Policy)
"apps.core.middleware.rate_limiting.AuthRateLimitMiddleware", # Rate limiting for auth endpoints
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
@@ -471,50 +473,91 @@ CACHES = {
}
# Use Redis for sessions
# =============================================================================
# Session Security Settings
# =============================================================================
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "sessions"
SESSION_COOKIE_AGE = 86400 # 24 hours
SESSION_COOKIE_AGE = 3600 # 1 hour (reduced from 24 hours for security)
SESSION_SAVE_EVERY_REQUEST = True # Update session on each request (sliding expiry)
SESSION_COOKIE_HTTPONLY = True # Prevent JavaScript access to session cookie
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Session persists until cookie expires
# Cache middleware settings
CACHE_MIDDLEWARE_SECONDS = 300 # 5 minutes
CACHE_MIDDLEWARE_KEY_PREFIX = "thrillwiki"
# =============================================================================
# JWT Settings
# =============================================================================
# Security considerations:
# - Short access token lifetime reduces window of vulnerability
# - Refresh token rotation prevents token reuse after refresh
# - Token blacklisting allows revocation of compromised tokens
# - JTI claim enables unique token identification for logging
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=60), # 1 hour
# Token lifetimes
# Security: Shorter access tokens (15 min) provide better security
# but may require more frequent refreshes
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15), # 15 minutes (reduced from 60)
"REFRESH_TOKEN_LIFETIME": timedelta(days=7), # 7 days
# Token rotation and blacklisting
# Security: Rotate refresh tokens on each use and blacklist old ones
"ROTATE_REFRESH_TOKENS": True,
"BLACKLIST_AFTER_ROTATION": True,
# Update last login on token refresh
"UPDATE_LAST_LOGIN": True,
# Cryptographic settings
"ALGORITHM": "HS256",
"SIGNING_KEY": SECRET_KEY,
"VERIFYING_KEY": None,
# Token validation
"AUDIENCE": None,
"ISSUER": None,
"ISSUER": "thrillwiki", # Added issuer for token validation
"JWK_URL": None,
"LEEWAY": 0,
"LEEWAY": 0, # No leeway for token expiration
# Authentication header
"AUTH_HEADER_TYPES": ("Bearer",),
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
# User identification
"USER_ID_FIELD": "id",
"USER_ID_CLAIM": "user_id",
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
# Token classes
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
"TOKEN_TYPE_CLAIM": "token_type",
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
# JTI claim for unique token identification
# Security: Enables token tracking and revocation
"JTI_CLAIM": "jti",
# Sliding token settings (if using sliding tokens)
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=60),
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=15),
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
}
# dj-rest-auth settings
# =============================================================================
# dj-rest-auth Settings
# =============================================================================
REST_AUTH = {
"USE_JWT": True,
"JWT_AUTH_COOKIE": "thrillwiki-auth",
"JWT_AUTH_REFRESH_COOKIE": "thrillwiki-refresh",
"JWT_AUTH_SECURE": not DEBUG, # Use secure cookies in production
# Security: Only send cookies over HTTPS in production
"JWT_AUTH_SECURE": not DEBUG,
# Security: Prevent JavaScript access to cookies
"JWT_AUTH_HTTPONLY": True,
# Security: SameSite cookie attribute (Lax is compatible with OAuth flows)
"JWT_AUTH_SAMESITE": "Lax",
"JWT_AUTH_RETURN_EXPIRATION": True,
"JWT_TOKEN_CLAIMS_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",

View File

@@ -24,14 +24,32 @@ ALLOWED_HOSTS = base.config("ALLOWED_HOSTS")
# CSRF trusted origins for production
CSRF_TRUSTED_ORIGINS = base.config("CSRF_TRUSTED_ORIGINS")
# Security settings for production
# =============================================================================
# Security Settings for Production
# =============================================================================
# SSL/HTTPS enforcement
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# HSTS (HTTP Strict Transport Security)
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# Session cookie security (stricter than development)
SESSION_COOKIE_SECURE = True # Only send over HTTPS
SESSION_COOKIE_SAMESITE = "Strict" # Stricter than Lax for production
# CSRF cookie security (stricter than development)
CSRF_COOKIE_SECURE = True # Only send over HTTPS
CSRF_COOKIE_SAMESITE = "Strict" # Stricter than Lax for production
# Additional security headers
X_FRAME_OPTIONS = "DENY" # Never allow framing
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"
SECURE_CROSS_ORIGIN_OPENER_POLICY = "same-origin"
# Production logging
LOGGING = {
"version": 1,