init: 数字员工平台初始代码

包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。
- 工作台画布:节点拖放、连线模式、右键菜单、AI 助手
- 后端:连接器 API、专员种子数据
- 导航:左侧导航、工坊、市场、控制台
This commit is contained in:
eaiadmin
2026-08-18 20:19:58 +08:00
commit 4e8817d768
239 changed files with 48631 additions and 0 deletions
+155
View File
@@ -0,0 +1,155 @@
# BE01 — 认证模块设计
> **版本:V1.1 | 技术:JWT(python-jose)+ bcrypt | 参考:pj006-zhilianyuan2 auth/security.py + dependencies.py**
---
## 1. 模块职责
- 用户注册(仅管理员可创建账号)
- 密码登录 → JWT 签发
- Token 校验 + 用户状态检查
- 角色守卫(普通用户 / 管理员)
## 2. 核心流程
```
POST /api/auth/login
→ 校验 username + password
→ bcrypt verify
→ 签发 JWT(含 sub=username, role, exp)
→ 返回 { token, expires_in, user }
GET /api/auth/me
→ Authorization: Bearer <token>
→ 解码 JWT → 校验用户状态
→ 返回用户信息
```
## 3. 密码哈希(参考 zhilianyuan2 模式)
```python
# core/security.py
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(password: str, hashed: str) -> bool:
return pwd_context.verify(password, hashed)
```
## 4. JWT 签发与校验
```python
# core/security.py
from jose import jwt, JWTError
from datetime import datetime, timedelta, timezone
def create_access_token(
*, subject: str, role: str, settings: Settings
) -> str:
issued_at = datetime.now(timezone.utc)
payload = {
"sub": subject,
"role": role,
"iat": issued_at,
"exp": issued_at + timedelta(minutes=settings.jwt_expire_minutes),
}
return jwt.encode(payload, settings.jwt_secret, algorithm="HS256")
def decode_access_token(token: str, settings: Settings) -> dict:
try:
return jwt.decode(token, settings.jwt_secret, algorithms=["HS256"])
except JWTError as e:
raise AuthError(f"令牌无效或已过期:{e}")
```
## 5. 依赖注入(参考 zhilianyuan2 dependencies.py)
```python
# core/deps.py
from fastapi import Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
async def get_current_user(
credentials: HTTPAuthorizationCredentials | None = Depends(
HTTPBearer(auto_error=False)
),
db: Session = Depends(get_db),
settings: Settings = Depends(get_settings),
) -> User:
"""解析 JWT + 校验用户状态"""
if credentials is None:
raise AuthError("缺少 Authorization Bearer 令牌")
payload = decode_access_token(credentials.credentials, settings)
username = payload.get("sub")
user = db.query(User).filter(User.username == username).first()
if user is None:
raise AuthError("用户不存在")
if user.status != "active":
raise AuthError("账号已禁用")
return user
def require_admin(current_user: User = Depends(get_current_user)) -> User:
"""管理员角色守卫"""
if current_user.role != "admin":
raise ForbiddenError("需要管理员权限")
return current_user
```
## 6. API 路由
```python
# api/auth.py
from fastapi import APIRouter, Depends
from pydantic import BaseModel
router = APIRouter(prefix="/api/auth", tags=["auth"])
class LoginRequest(BaseModel):
username: str
password: str
class TokenResponse(BaseModel):
token: str
expires_in: int
user: UserPublic
@router.post("/login")
def login(request: LoginRequest, settings: SettingsDep):
user = authenticate(request.username, request.password)
token = create_access_token(subject=user.username, role=user.role, settings=settings)
return {"data": {
"token": token,
"expires_in": settings.jwt_expire_minutes * 60,
"user": UserPublic.from_orm(user),
}}
@router.get("/me")
def me(current_user: CurrentUser):
return {"data": UserPublic.from_orm(current_user)}
```
## 7. 数据表
```sql
CREATE TABLE user (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
password_hash VARCHAR(256) NOT NULL,
full_name VARCHAR(64) NOT NULL,
role ENUM('employee','admin') NOT NULL DEFAULT 'employee',
status ENUM('active','disabled') NOT NULL DEFAULT 'active',
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
);
```
## 8. 安全约束
- 禁用账号即时失效:token 校验时检查 status
- 前端路由守卫仅作 UX 隐藏,不以之为安全边界
- 所有权限以后端鉴权为准