Template
- 用户管理:增删改、批量导入(Excel模板)、admin保护 - 部门管理:增删改(含回收站恢复机制)、删除保护(有用户不可删) - 权限管理:部门内角色(admin/readwrite/readonly/none) - 监控页面:CPU/内存/磁盘实时监控 - 日志页面:操作日志查询 - SMB权限:用户文件夹700(member)/750(admin)、ACL继承 - admin跨目录访问:通过setfacl ACL实现
108 lines
3.5 KiB
Python
108 lines
3.5 KiB
Python
"""FastAPI 主应用入口"""
|
|
import os
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import HTMLResponse, FileResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
DATA_DIR = os.environ.get("DATA_DIR", "/data/smb")
|
|
DB_DIR = os.environ.get("DB_DIR", "/data/db")
|
|
DB_PATH = os.path.join(DB_DIR, "app.db")
|
|
|
|
_BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
TEMPLATES_DIR = os.path.join(_BASE_DIR, "templates")
|
|
STATIC_DIR = os.path.join(_BASE_DIR, "static")
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
os.makedirs(DATA_DIR, exist_ok=True)
|
|
os.makedirs(DB_DIR, exist_ok=True)
|
|
from app.database import init_db
|
|
await init_db(DB_PATH)
|
|
# 确保交换站目录存在
|
|
from app.services.samba_service import ensure_exchange_folder
|
|
ensure_exchange_folder()
|
|
yield
|
|
|
|
|
|
app = FastAPI(
|
|
title="SMB 文件服务器",
|
|
description="基于 Docker Compose 的 SMB 共享文件服务器管理后台",
|
|
version="1.0.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
from app.routers import auth, departments, users, permissions, monitor, logs
|
|
|
|
app.include_router(auth.router, prefix="/api/auth", tags=["认证"])
|
|
app.include_router(departments.router, prefix="/api/departments", tags=["部门管理"])
|
|
app.include_router(users.router, prefix="/api/users", tags=["用户管理"])
|
|
app.include_router(permissions.router, prefix="/api/permissions", tags=["权限管理"])
|
|
app.include_router(monitor.router, prefix="/api/monitor", tags=["监控"])
|
|
app.include_router(logs.router, prefix="/api/logs", tags=["日志"])
|
|
|
|
# 静态文件(css/js 从 templates 目录暴露)
|
|
CSS_DIR = os.path.join(TEMPLATES_DIR, "css")
|
|
JS_DIR = os.path.join(TEMPLATES_DIR, "js")
|
|
if os.path.exists(CSS_DIR):
|
|
app.mount("/css", StaticFiles(directory=CSS_DIR), name="css")
|
|
if os.path.exists(JS_DIR):
|
|
app.mount("/js", StaticFiles(directory=JS_DIR), name="js")
|
|
if os.path.exists(STATIC_DIR):
|
|
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
|
|
|
|
|
|
def read_html(path):
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
return f.read()
|
|
|
|
|
|
@app.get("/api/health")
|
|
async def health_check():
|
|
return {"status": "ok", "service": "SMB File Server"}
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
async def root():
|
|
return HTMLResponse(read_html(os.path.join(TEMPLATES_DIR, "login.html")))
|
|
|
|
|
|
@app.get("/dashboard", response_class=HTMLResponse)
|
|
async def dashboard():
|
|
return HTMLResponse(read_html(os.path.join(TEMPLATES_DIR, "views", "dashboard.html")))
|
|
|
|
|
|
@app.get("/departments", response_class=HTMLResponse)
|
|
async def departments_page():
|
|
return HTMLResponse(read_html(os.path.join(TEMPLATES_DIR, "views", "departments.html")))
|
|
|
|
|
|
@app.get("/users", response_class=HTMLResponse)
|
|
async def users_page():
|
|
return HTMLResponse(read_html(os.path.join(TEMPLATES_DIR, "views", "users.html")))
|
|
|
|
|
|
@app.get("/permissions", response_class=HTMLResponse)
|
|
async def permissions_page():
|
|
return HTMLResponse(read_html(os.path.join(TEMPLATES_DIR, "views", "permissions.html")))
|
|
|
|
|
|
@app.get("/monitor", response_class=HTMLResponse)
|
|
async def monitor_page():
|
|
return HTMLResponse(read_html(os.path.join(TEMPLATES_DIR, "views", "monitor.html")))
|
|
|
|
|
|
@app.get("/logs", response_class=HTMLResponse)
|
|
async def logs_page():
|
|
return HTMLResponse(read_html(os.path.join(TEMPLATES_DIR, "views", "logs.html")))
|