feat(stack): full overhaul — hardening, ops tooling, monitoring, analytics, chatbot
Security: deep /api/health (DB+MinIO probes, 503 on failure) + /api/live; rate-limited public forms with honeypots; real client IP behind Traefik (--proxy-headers); TipTap URL sanitization on write (nh3); non-root containers + slim .dockerignore; prod MinIO console bound to 127.0.0.1; HSTS/nosniff on TLS routers; JWT 8h; no default credentials in code. Reliability: Alembic migrations (create_all baseline); graceful shutdown (exec uvicorn); hardened backups (checksums, sanity check, freshness gauge, optional rclone off-site) + restore.sh + hourly db-backup sidecar (ops profile); stack.sh ops tooling (deploy/logs/health/backup/restore/monitoring); .gitattributes LF for shell scripts. Orchestration: json-file log rotation, pinned images, per-service memory limits, edge/internal networks, Traefik ping/accesslog/metrics + flood limiter, conditional minio-setup, pgvector db image, one-shot db-init (umami + aramesh_chatbot databases). Chatbot: unified from site-chatbot branch (RAG + pgvector, SSE, ChatWidget). Monitoring: Prometheus/Alertmanager/Loki/Promtail/Grafana + cAdvisor, node/postgres/blackbox exporters, provisioned dashboards and 10 alert rules; alerts delivered to Bale (tapi.bale.ai — Telegram-compatible). Analytics: Umami on shared Postgres, build-time tracker injection, custom events (contact/newsletter/phone/chat/lang) via frontend/src/analytics.ts. Hygiene: CSV export for contact messages and subscribers; upload image optimization (Pillow); CI script + GitHub-compatible workflow; audit.sh; gen-env.sh for strong credentials.
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
"""انتهای عمومی — خواندن محتوای سایت بدون نیاز به احراز هویت."""
|
||||
|
||||
import boto3
|
||||
from botocore.config import Config as BotoConfig
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ..config import settings
|
||||
from ..database import get_db
|
||||
from .. import models
|
||||
from ..schemas import (
|
||||
@@ -22,9 +27,44 @@ from ..schemas import (
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/live")
|
||||
def live():
|
||||
"""زندهبودن پروسه — بدون وابستگی؛ برای restart gate استفاده نمیشود."""
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
def health():
|
||||
return {"status": "ok", "app": "Aramesh Building Group API"}
|
||||
def health(db: Session = Depends(get_db)):
|
||||
"""بررسی عمق سلامت — اتصال DB و MinIO واقعاً آزموده میشود؛
|
||||
در صورت خرابی هر وابستگی، 503 با جزئیات برمیگردد."""
|
||||
checks: dict[str, str] = {}
|
||||
|
||||
try:
|
||||
db.execute(text("SELECT 1"))
|
||||
checks["database"] = "ok"
|
||||
except Exception:
|
||||
checks["database"] = "error"
|
||||
|
||||
try:
|
||||
s3 = boto3.client(
|
||||
"s3",
|
||||
endpoint_url=settings.s3_endpoint,
|
||||
aws_access_key_id=settings.s3_access_key,
|
||||
aws_secret_access_key=settings.s3_secret_key,
|
||||
region_name="us-east-1",
|
||||
config=BotoConfig(connect_timeout=2, read_timeout=2, retries={"max_attempts": 1}),
|
||||
)
|
||||
s3.head_bucket(Bucket=settings.s3_bucket)
|
||||
checks["storage"] = "ok"
|
||||
except Exception:
|
||||
checks["storage"] = "error"
|
||||
|
||||
if any(state != "ok" for state in checks.values()):
|
||||
return JSONResponse(
|
||||
status_code=503,
|
||||
content={"status": "degraded", "checks": checks},
|
||||
)
|
||||
return {"status": "ok", "app": "Aramesh Building Group API", "checks": checks}
|
||||
|
||||
|
||||
@router.get("/brand", response_model=BrandOut)
|
||||
|
||||
Reference in New Issue
Block a user