5.4 KiB
在 /home/enzo/projects/hive-manage-v3/backend/ 下实现完整的 JWT 鉴权 + 用户管理 + 审计日志系统。全部使用 backend/.venv/bin/python 和 backend/.venv/bin/pip。
已有: User + AuditLog ORM 模型, FastAPI 入口, database.py, config.py
第一部分: auth_service.py
创建 backend/app/services/__init__.py (空) 创建 backend/app/services/auth_service.py
核心函数:
- hash_password(password: str) -> str — bcrypt (passlib)
- verify_password(plain: str, hashed: str) -> bool
- create_access_token(user_id: str, role: str) -> str — JWT(HS256, config.jwt_secret, expires=config.jwt_expire_minutes)
- decode_access_token(token: str) -> dict — jose.jwt.decode, 捕获 ExpiredSignatureError/JWTError 抛 HTTPException(401)
- get_user_by_id(db, user_id) -> User | None
- get_user_by_username(db, username) -> User | None
- authenticate_user(db, username, password) -> User — 验证密码, 失败检查/递增 login_attempts, >=5 次锁定 15 分钟, 成功后重置 login_attempts
- create_user(db, username, email, password) -> User — 首个用户自动 Owner + is_approved=True, 后续用户 Viewer + is_approved=False
第二部分: auth middleware
创建 backend/app/middleware/__init__.py (空) 创建 backend/app/middleware/auth.py
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from app.services.auth_service import decode_access_token, get_user_by_id
security = HTTPBearer()
async def require_auth(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db),
):
payload = decode_access_token(credentials.credentials)
user = await get_user_by_id(db, payload["sub"])
if not user or not user.is_active:
raise HTTPException(status_code=401, detail="Invalid or inactive user")
return user
def require_role(*roles: str):
async def role_check(user = Depends(require_auth)):
if user.role.value not in roles:
raise HTTPException(status_code=403, detail="Insufficient permissions")
return user
return role_check
第三部分: Auth Schemas
创建 backend/app/schemas/__init__.py (空) 创建 backend/app/schemas/auth.py
from pydantic import BaseModel, EmailStr
class LoginRequest(BaseModel):
username: str
password: str
class RegisterRequest(BaseModel):
username: str
email: str # 先用 str,后续升级 EmailStr
password: str
class TokenResponse(BaseModel):
access_token: str
token_type: str = "bearer"
expires_in: int
class ChangePasswordRequest(BaseModel):
old_password: str
new_password: str
创建 backend/app/schemas/user.py
from pydantic import BaseModel
from datetime import datetime
class UserResponse(BaseModel):
id: str
username: str
email: str
role: str
is_active: bool
is_approved: bool
created_at: datetime
class Config:
from_attributes = True
class UserUpdateRequest(BaseModel):
role: str | None = None
is_active: bool | None = None
第四部分: Auth API
创建 backend/app/api/__init__.py (空) 创建 backend/app/api/auth.py
POST /api/v1/auth/register — 注册, 返回 201 POST /api/v1/auth/login — 登录, 返回 TokenResponse POST /api/v1/auth/refresh — 刷新 token, 需 require_auth POST /api/v1/auth/change-password — 改密码, 需 require_auth
第五部分: User Management API
创建 backend/app/api/users.py
GET /api/v1/users — 用户列表 (需 owner), 支持分页 GET /api/v1/users/{id} — 用户详情 (需 owner) PATCH /api/v1/users/{id} — 改角色/状态 (需 owner) POST /api/v1/users/{id}/approve — 审批新用户 (需 owner)
第六部分: Audit Middleware + API
创建 backend/app/middleware/audit.py
# 审计中间件: 拦截所有 POST/PUT/PATCH/DELETE 请求
# 从 request.state 获取当前用户 (需 auth middleware 先执行)
# 记录: user_id, username, action, target, detail, ip_address
# 写入 AuditLog 表 (异步)
创建 backend/app/api/audit.py
GET /api/v1/audit — 审计日志列表 (需 owner), 支持分页 + 按 action 筛选
第七部分: 注册路由
修改 backend/app/main.py, 注册所有 router:
from app.api import auth, users, audit
app.include_router(auth.router)
app.include_router(users.router)
app.include_router(audit.router)
第八部分: 测试
创建 backend/tests/test_auth.py
- test_register_success (201)
- test_register_duplicate (409)
- test_login_success (200 + JWT)
- test_login_wrong_password (401)
- test_login_locked (423 after 5 failures)
- test_require_auth_no_token (401)
- test_viewer_cannot_manage_users (403)
创建 backend/tests/conftest.py
- async test fixtures: async_client (httpx.AsyncClient + FastAPI app)
- test database (SQLite in-memory 或者用现有的 PG)
注意: 测试使用 pytest + pytest-asyncio + httpx.AsyncClient
第九部分: 提交
cd /home/enzo/projects/hive-manage-v3 && \
git add backend/app/services/ backend/app/middleware/ backend/app/schemas/ backend/app/api/ backend/tests/ backend/app/main.py && \
git commit -m "feat: JWT auth, user management, audit logging system"
请按顺序执行以上 9 个部分,每个部分完成后再进入下一部分。pip install 需要时使用 cd backend && .venv/bin/pip install <package>。