feat(auth): 统一鉴权收口,账号单一角色+权限码,去多身份
- dependencies._resolve_identity 收敛为单角色(users.role),不再读身份分支 - auth.login/select_identity 单角色发token、identities 恒空,Pine=operator(运营方) - repositories.to_profile 按 role 计算 account_type(修复身份标签显示"服务方") - seed 重构 PERMISSIONS/ROLE_PERMISSIONS:operator 平台全 menu、carrier 园区 menu:park_*,删多端口冗余 - account_types 归一 operator/carrier/opc_member/service Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+4
-19
@@ -27,25 +27,10 @@ def get_db(request: Request) -> Database:
|
||||
return request.app.state.db
|
||||
|
||||
|
||||
async def _resolve_identity(user: dict, identity_id: str | None, db: Database) -> dict:
|
||||
"""按令牌携带的 identity_id 装配当前身份;缺失则回退到 users.role 单角色。
|
||||
|
||||
身份即权限来源:从 user_identities 取 role/sub_role/org/region,
|
||||
并据此计算 permissions 与数据范围(全异步,角色变更即时生效)。
|
||||
"""
|
||||
if identity_id:
|
||||
ident = await db.identities.get_for_user(identity_id, user["id"])
|
||||
if ident and ident.get("status") == "active":
|
||||
user["identity_id"] = ident["id"]
|
||||
user["port"] = ident["port"]
|
||||
user["role"] = ident["role"]
|
||||
user["sub_role"] = ident.get("sub_role")
|
||||
user["org_id"] = ident.get("org_id")
|
||||
user["region_id"] = ident.get("region_id")
|
||||
user["identity_name"] = ident.get("name", "")
|
||||
|
||||
async def _resolve_identity(user: dict, db: Database) -> dict:
|
||||
"""单账号角色(多身份已收敛):role 由 users.role 提供,仅计算权限与数据范围。"""
|
||||
user["permissions"] = await db.roles.permissions_for(
|
||||
user.get("role", "opc_member"), user.get("sub_role"),
|
||||
user.get("role", "opc_member"), None,
|
||||
)
|
||||
user["scope_region_ids"] = await db.regions.visible_region_ids(user.get("region_id"))
|
||||
user["scope_level"] = await db.regions.level(user.get("region_id"))
|
||||
@@ -77,7 +62,7 @@ async def get_current_user(
|
||||
if user is None or user.get("status") != "active":
|
||||
raise HTTPException(status_code=401, detail="Invalid or expired token")
|
||||
|
||||
return await _resolve_identity(user, payload.get("identity_id"), db)
|
||||
return await _resolve_identity(user, db)
|
||||
|
||||
|
||||
async def optional_current_user(
|
||||
|
||||
+10
-15
@@ -219,19 +219,19 @@ async def login(req: LoginRequest, db: Database = Depends(get_db)):
|
||||
if user.get("status") != "active":
|
||||
raise HTTPException(status_code=403, detail="Account is disabled")
|
||||
|
||||
identities = await db.identities.list_for_user(user["id"], active_only=True)
|
||||
identity = identities[0] if len(identities) == 1 else None
|
||||
token_record = await _issue_token(db, user, req.expires_in, identity=identity)
|
||||
profile = await _profile_for(user, identity, db)
|
||||
# 账号单一角色(去多身份):不再按 user_identities 选身份,按 users.role 解析账号类型。
|
||||
identity = None
|
||||
token_record = await _issue_token(db, user, req.expires_in, identity=None)
|
||||
profile = await _profile_for(user, None, db)
|
||||
|
||||
await db.audit.add(
|
||||
action="login", resource="auth", resource_id=user["id"],
|
||||
detail=f"login {user['username']} ({len(identities)} identities)",
|
||||
detail=f"login {user['username']} (account_type={profile.get('account_type', '')})",
|
||||
user_id=user["id"],
|
||||
)
|
||||
return LoginResponse(
|
||||
token=token_record["token"],
|
||||
identities=_identity_summaries(identities),
|
||||
identities=[],
|
||||
**profile,
|
||||
)
|
||||
|
||||
@@ -242,17 +242,12 @@ async def select_identity(
|
||||
user: dict = Depends(get_current_user),
|
||||
db: Database = Depends(get_db),
|
||||
):
|
||||
"""把当前令牌切换到指定端口身份(该身份须属于当前账号且为启用状态)。"""
|
||||
ident = await db.identities.get_for_user(req.identity_id, user["id"])
|
||||
if ident is None or ident.get("status") != "active":
|
||||
raise HTTPException(status_code=404, detail="Identity not found or disabled")
|
||||
|
||||
token_record = await _issue_token(db, user, None, identity=ident)
|
||||
profile = await _profile_for(user, ident, db)
|
||||
identities = await db.identities.list_for_user(user["id"], active_only=True)
|
||||
"""切换身份(多身份已收敛)——恒按账号单一角色(users.role)签发,忽略 identity_id。"""
|
||||
token_record = await _issue_token(db, user, None, identity=None)
|
||||
profile = await _profile_for(user, None, db)
|
||||
return LoginResponse(
|
||||
token=token_record["token"],
|
||||
identities=_identity_summaries(identities),
|
||||
identities=[],
|
||||
**profile,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user