Files
server-core/app/api/routers/rbac_org.py
T
Pine cb1492f2d6 fix: 完整审查修复 - 5个问题
1. _resolve_identity: permissions_for 未归一化 role → 使用 account_type+permission_role
2. rbac_org.py: 用 user.role 判断 operator → 改用 capabilities
3. membership_service: sync_user_affiliation 不同步 organization_members → 新增 _sync_org_members
4. repositories.to_profile: capabilities 只查旧表 → 增加 organization_members 查询
5. Header.RoleBadge: account_type_label 被 t() 重复翻译 → 优先直接显示中文
2026-09-03 09:43:34 +08:00

90 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
"""组织/租户端点:企业 / 载体 / 服务商(按角色 + 组织作用域)。"""
from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from ..dependencies import get_db, get_user_organizations, get_user_primary_org
from ..schemas.org import OrgMemberAdd
from ...rbac import require_roles
from ...infrastructure.repositories import Database
router = APIRouter(tags=["org"])
@router.get("/org/me", summary="当前组织信息")
async def org_me(
db: Database = Depends(get_db),
user: dict = Depends(require_roles("opc_member", "carrier", "operator")),
):
"""返回用户绑定的所有组织(优先 organization_members,回退 users.org_id)。"""
orgs = await get_user_organizations(db, user["id"])
region = await db.regions.get(user["region_id"]) if user.get("region_id") else None
primary_org = orgs[0] if orgs else None
return {
"user_id": user["id"],
"role": user["role"],
"sub_role": user["sub_role"],
"org": primary_org,
"organizations": orgs,
"region": region,
}
@router.get("/carrier/enterprises", summary="载体下辖企业")
async def carrier_enterprises(
db: Database = Depends(get_db),
user: dict = Depends(require_roles("carrier")),
):
"""返回绑定到当前载体(parent_id == 载体 org_id)的企业。"""
carrier_org = await get_user_primary_org(db, user, org_type="carrier")
if not carrier_org:
return []
return await db.orgs.list_by_parent(carrier_org["org_id"])
# ── 机构成员(机构主账号 + 机构内子账号,账号可挂多机构)────────────────────
@router.get("/org/{org_id}/members", summary="机构成员列表")
async def org_members(
org_id: str,
db: Database = Depends(get_db),
user: dict = Depends(require_roles("carrier", "operator")),
):
# 机构管理员本人 或 平台运营 可查看
if "operator" not in (user.get("capabilities") or []) and not await db.org_members.is_admin(org_id, user["id"]):
raise HTTPException(status_code=403, detail="Forbidden: not org admin")
return {"items": await db.org_members.list_for_org(org_id)}
@router.post("/org/{org_id}/members", summary="添加机构成员(子账号)")
async def org_add_member(
org_id: str,
req: OrgMemberAdd,
db: Database = Depends(get_db),
user: dict = Depends(require_roles("carrier", "operator")),
):
if "operator" not in (user.get("capabilities") or []) and not await db.org_members.is_admin(org_id, user["id"]):
raise HTTPException(status_code=403, detail="Forbidden: not org admin")
target_id = req.user_id
if not target_id and req.username:
found = await db.users.get_by_username(req.username)
if found is None:
raise HTTPException(status_code=404, detail="账号不存在")
target_id = found["id"]
if not target_id:
raise HTTPException(status_code=400, detail="缺少 user_id 或 username")
return await db.org_members.add_member(org_id, target_id, req.role, req.is_admin)
@router.get("/me/orgs", summary="我加入的机构")
async def my_orgs(
db: Database = Depends(get_db),
user: dict = Depends(require_roles("opc_member", "carrier", "operator")),
):
"""返回当前账号挂靠的所有机构及成员角色(支持一账号多机构)。"""
from ...services.org_service import OrgService
return await OrgService(db).my_orgs(user["id"])