feat: HR Portal - Complete Multi-Tenant System with Redis Session Storage
Major Features: - ✅ Multi-tenant architecture (tenant isolation) - ✅ Employee CRUD with lifecycle management (onboarding/offboarding) - ✅ Department tree structure with email domain management - ✅ Company info management (single-record editing) - ✅ System functions CRUD (permission management) - ✅ Email account management (multi-account per employee) - ✅ Keycloak SSO integration (auth.lab.taipei) - ✅ Redis session storage (10.1.0.254:6379) - Solves Cookie 4KB limitation - Cross-system session sharing - Sliding expiration (8 hours) - Automatic token refresh Technical Stack: Backend: - FastAPI + SQLAlchemy - PostgreSQL 16 (10.1.0.20:5433) - Keycloak Admin API integration - Docker Mailserver integration (SSH) - Alembic migrations Frontend: - Next.js 14 (App Router) - NextAuth 4 with Keycloak Provider - Redis session storage (ioredis) - Tailwind CSS Infrastructure: - Redis 7 (10.1.0.254:6379) - Session + Cache - Keycloak 26.1.0 (auth.lab.taipei) - Docker Mailserver (10.1.0.254) Architecture Highlights: - Session管理由 Keycloak + Redis 統一控制 - 支援多系統 (HR/WebMail/Calendar/Drive/Office) 共享 session - Token 自動刷新,異質服務整合 - 未來可無縫遷移到雲端 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
105
backend/app/main.py
Normal file
105
backend/app/main.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
HR Portal Backend API
|
||||
FastAPI 主應用程式
|
||||
"""
|
||||
import traceback
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.logging_config import setup_logging
|
||||
from app.db.session import get_engine
|
||||
from app.db.base import Base
|
||||
|
||||
# 設置日誌
|
||||
setup_logging()
|
||||
|
||||
# 創建 FastAPI 應用
|
||||
app = FastAPI(
|
||||
title=settings.PROJECT_NAME,
|
||||
version=settings.VERSION,
|
||||
description="HR Portal - 人力資源管理系統 API",
|
||||
docs_url="/docs",
|
||||
redoc_url="/redoc",
|
||||
openapi_url="/openapi.json",
|
||||
)
|
||||
|
||||
# CORS 設定
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=settings.get_allowed_origins(),
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
# 全局異常處理器
|
||||
@app.exception_handler(Exception)
|
||||
async def global_exception_handler(request: Request, exc: Exception):
|
||||
"""全局異常處理器 - 記錄所有未捕獲的異常"""
|
||||
print(f"\n{'=' * 80}")
|
||||
print(f"[ERROR] Unhandled Exception in {request.method} {request.url.path}")
|
||||
print(f"Exception Type: {type(exc).__name__}")
|
||||
print(f"Exception Message: {str(exc)}")
|
||||
print(f"Traceback:")
|
||||
print(traceback.format_exc())
|
||||
print(f"{'=' * 80}\n")
|
||||
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"detail": str(exc),
|
||||
"type": type(exc).__name__,
|
||||
"path": request.url.path
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# 啟動事件
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
"""應用啟動時執行"""
|
||||
# 資料庫表格由 Alembic 管理,不需要在啟動時創建
|
||||
print(f"[OK] {settings.PROJECT_NAME} v{settings.VERSION} started!")
|
||||
print(f"[*] Environment: {settings.ENVIRONMENT}")
|
||||
print(f"[*] API Documentation: http://{settings.HOST}:{settings.PORT}/docs")
|
||||
|
||||
|
||||
# 關閉事件
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown_event():
|
||||
"""應用關閉時執行"""
|
||||
print(f"[*] {settings.PROJECT_NAME} stopped")
|
||||
|
||||
|
||||
# 健康檢查端點
|
||||
@app.get("/health", tags=["Health"])
|
||||
async def health_check():
|
||||
"""健康檢查"""
|
||||
return JSONResponse(
|
||||
content={
|
||||
"status": "healthy",
|
||||
"service": settings.PROJECT_NAME,
|
||||
"version": settings.VERSION,
|
||||
"environment": settings.ENVIRONMENT,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# 根路徑
|
||||
@app.get("/", tags=["Root"])
|
||||
async def root():
|
||||
"""根路徑"""
|
||||
return {
|
||||
"message": f"Welcome to {settings.PROJECT_NAME}",
|
||||
"version": settings.VERSION,
|
||||
"docs": "/docs",
|
||||
"redoc": "/redoc",
|
||||
}
|
||||
|
||||
|
||||
# 導入並註冊 API 路由
|
||||
from app.api.v1.router import api_router
|
||||
app.include_router(api_router, prefix="/api/v1")
|
||||
Reference in New Issue
Block a user