v0.2.0: CRM/ERP 系统升级 - 清理 .gitignore 并移除误提交的 venv/env/db 文件
- 更新 .gitignore:全面覆盖环境变量、数据库、日志、缓存、上传文件 - 移除误跟踪的 server/venv/、crm_data.db、.env 文件 - 新增 server/.env.example 模板 - 新增合同管理、利润核算、AI教练等功能模块 - 新增 Playwright e2e 测试套件 - 前后端多项功能升级和 bug 修复
This commit is contained in:
+47
-2
@@ -1,18 +1,21 @@
|
||||
"""
|
||||
FastAPI 依赖注入 —— 权限拦截核心
|
||||
get_current_user: 解析 JWT → 查表获取完整权限上下文
|
||||
get_current_company_id: 从 X-Company-Id Header 提取公司 ID + IDOR 校验
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
from fastapi import Depends, Header
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.exceptions import UnauthorizedException
|
||||
from app.core.exceptions import ForbiddenException, UnauthorizedException
|
||||
from app.core.security import decode_access_token
|
||||
from app.db.database import get_db
|
||||
from app.models.sys import SysUser
|
||||
from app.models.sys import SysCompany, SysUser, SysUserCompany
|
||||
from app.schemas.auth import CurrentUserPayload
|
||||
|
||||
|
||||
@@ -65,3 +68,45 @@ async def get_current_user(
|
||||
data_scope=user.role.data_scope if user.role else "self",
|
||||
menu_keys=user.role.menu_keys if user.role else [],
|
||||
)
|
||||
|
||||
|
||||
async def get_current_company_id(
|
||||
x_company_id: str = Header(..., alias="X-Company-Id", description="当前工作台的公司 ID"),
|
||||
current_user: CurrentUserPayload = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> uuid.UUID:
|
||||
"""
|
||||
公司视角依赖(IDOR 防护核心):
|
||||
1. 从 X-Company-Id Header 提取公司 UUID
|
||||
2. 校验当前用户是否归属于该公司(查 sys_user_companies)
|
||||
3. 校验公司是否启用
|
||||
"""
|
||||
# ── 解析 company_id ──
|
||||
try:
|
||||
company_uuid = uuid.UUID(x_company_id)
|
||||
except ValueError:
|
||||
raise UnauthorizedException("X-Company-Id 格式错误,需为合法 UUID")
|
||||
|
||||
# ── IDOR 防护:校验用户-公司归属 ──
|
||||
assoc = (await db.execute(
|
||||
select(SysUserCompany).where(
|
||||
SysUserCompany.user_id == current_user.user_id,
|
||||
SysUserCompany.company_id == company_uuid,
|
||||
)
|
||||
)).scalar_one_or_none()
|
||||
|
||||
if assoc is None:
|
||||
raise ForbiddenException("您无权访问该公司数据")
|
||||
|
||||
# ── 校验公司是否启用 ──
|
||||
company = (await db.execute(
|
||||
select(SysCompany).where(
|
||||
SysCompany.id == company_uuid,
|
||||
SysCompany.is_active.is_(True),
|
||||
)
|
||||
)).scalar_one_or_none()
|
||||
|
||||
if company is None:
|
||||
raise ForbiddenException("公司不存在或已停用")
|
||||
|
||||
return company_uuid
|
||||
|
||||
Reference in New Issue
Block a user