Add batch management APIs, API security, rate limiting, and optimizations
- Batch device CRUD: POST /api/devices/batch (create 500), PUT /api/devices/batch (update 500), POST /api/devices/batch-delete (delete 100) with WHERE IN bulk queries - Batch command: POST /api/commands/batch with model_validator mutual exclusion - API key auth (X-API-Key header, secrets.compare_digest timing-safe) - Rate limiting via SlowAPIMiddleware (60/min default, 30/min writes) - Real client IP extraction (X-Forwarded-For / CF-Connecting-IP) - Global exception handler (no stack trace leaks, passes HTTPException through) - CORS with auto-disable credentials on wildcard origins - Schema validation: IMEI pattern, lat/lon ranges, Literal enums, MAC/UUID patterns - Heartbeats router, per-ID endpoints for locations/attendance/bluetooth - Input dedup in batch create, result ordering preserved - Baidu reverse geocoding, Gaode map tiles with WGS84→GCJ02 conversion - Device detail panel with feature toggles and command controls - Side panel for location/beacon pages with auto-select active device via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
@@ -1,14 +1,49 @@
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import Field
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
# Project root directory (where config.py lives → parent = app/ → parent = project root)
|
||||
_PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
_DEFAULT_DB_PATH = _PROJECT_ROOT / "badge_admin.db"
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
APP_NAME: str = "KKS Badge Management System"
|
||||
DATABASE_URL: str = "sqlite+aiosqlite:///./badge_admin.db"
|
||||
DATABASE_URL: str = Field(
|
||||
default=f"sqlite+aiosqlite:///{_DEFAULT_DB_PATH}",
|
||||
description="Database connection URL (absolute path for SQLite)",
|
||||
)
|
||||
TCP_HOST: str = "0.0.0.0"
|
||||
TCP_PORT: int = 5000
|
||||
TCP_PORT: int = Field(default=5000, ge=1, le=65535)
|
||||
API_HOST: str = "0.0.0.0"
|
||||
API_PORT: int = 8088
|
||||
DEBUG: bool = True
|
||||
API_PORT: int = Field(default=8088, ge=1, le=65535)
|
||||
DEBUG: bool = Field(default=False, description="Enable debug mode (SQL echo, verbose errors)")
|
||||
|
||||
# API authentication
|
||||
API_KEY: str | None = Field(default=None, description="API key for authentication (None=disabled)")
|
||||
CORS_ORIGINS: str = Field(default="*", description="Comma-separated allowed CORS origins")
|
||||
|
||||
# Rate limiting
|
||||
RATE_LIMIT_DEFAULT: str = Field(default="60/minute", description="Default rate limit")
|
||||
RATE_LIMIT_WRITE: str = Field(default="30/minute", description="Rate limit for write operations")
|
||||
|
||||
# Geocoding API keys
|
||||
TIANDITU_API_KEY: str | None = Field(default=None, description="天地图 API key for reverse geocoding")
|
||||
GOOGLE_API_KEY: str | None = Field(default=None, description="Google Geolocation API key")
|
||||
UNWIRED_API_TOKEN: str | None = Field(default=None, description="Unwired Labs API token")
|
||||
AMAP_KEY: str | None = Field(default=None, description="高德地图 Web API key")
|
||||
AMAP_SECRET: str | None = Field(default=None, description="高德地图安全密钥")
|
||||
BAIDU_MAP_AK: str | None = Field(default=None, description="百度地图服务端 AK")
|
||||
|
||||
# Geocoding cache
|
||||
GEOCODING_CACHE_SIZE: int = Field(default=10000, description="Max geocoding cache entries")
|
||||
|
||||
# Track query limit
|
||||
TRACK_MAX_POINTS: int = Field(default=10000, description="Maximum points returned by track endpoint")
|
||||
|
||||
model_config = {"env_file": ".env", "env_file_encoding": "utf-8", "extra": "ignore"}
|
||||
|
||||
|
||||
settings = Settings()
|
||||
|
||||
Reference in New Issue
Block a user