From 00f43976b3419e7e8197b01253f618cd0b42cb60 Mon Sep 17 00:00:00 2001 From: Pine Date: Wed, 26 Aug 2026 13:09:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(auth):=20=E8=B4=A6=E5=8F=B7=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=94=B6=E6=95=9B=E4=B8=BA=E5=9B=9B=E7=A7=8D=20+=20?= =?UTF-8?q?=E5=AF=B9=E5=A4=96=E4=B8=8B=E5=8F=91=E4=B8=AD=E6=96=87=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(=E6=96=87=E6=9C=AC)=20-=20account=5Ftype(role)?= =?UTF-8?q?=E2=86=92operator/carrier/opc=5Fmember/service;=20=E9=9D=9E?= =?UTF-8?q?=E8=BF=90=E8=90=A5=E9=9D=9EOPC=E4=B8=80=E5=BE=8Bservice;=20sub?= =?UTF-8?q?=5Frole=E7=BD=AENone=20-=20=E7=99=BB=E5=BD=95/me/=E8=B5=84?= =?UTF-8?q?=E6=96=99=E7=BB=9F=E4=B8=80=E8=BF=94=E5=9B=9E=20account=5Ftype?= =?UTF-8?q?=20+=20account=5Ftype=5Flabel(=E8=BF=90=E8=90=A5=E6=96=B9/?= =?UTF-8?q?=E8=BD=BD=E4=BD=93=E6=96=B9/OPC/=E6=9C=8D=E5=8A=A1=E6=96=B9);?= =?UTF-8?q?=20=E5=89=8D=E7=AB=AF=E7=9B=B4=E6=8E=A5=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E6=96=87=E6=9C=AC=20-=20=E6=9D=83=E9=99=90=E6=8C=89=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E7=B1=BB=E5=9E=8B=E8=A7=A3=E6=9E=90(service=E2=86=92p?= =?UTF-8?q?rovider=E5=9F=BA=E5=BA=A7),=20=E9=80=BB=E8=BE=91=E9=9B=86?= =?UTF-8?q?=E4=B8=AD=E5=9C=A8=20app/domain/account=5Ftypes.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/schemas/auth.py | 3 +++ app/domain/account_types.py | 17 +++++++++++------ app/infrastructure/repositories.py | 6 +++++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/app/api/schemas/auth.py b/app/api/schemas/auth.py index aac23bc..b411ab9 100644 --- a/app/api/schemas/auth.py +++ b/app/api/schemas/auth.py @@ -84,6 +84,9 @@ class UserProfile(BaseModel): # RBAC(登录/me 返回;update-profile 不重签时不返回权限明细) role: str = "opc_member" sub_role: str | None = None + # 账号类型(四种)与中文标签 —— 前端直接渲染文本,不做代码映射 + account_type: str = "service" + account_type_label: str = "服务方" org_id: str | None = None region_id: str | None = None permissions: list[str] = Field(default_factory=list) diff --git a/app/domain/account_types.py b/app/domain/account_types.py index 6d9c9d8..1eb78bd 100644 --- a/app/domain/account_types.py +++ b/app/domain/account_types.py @@ -14,7 +14,7 @@ """ from __future__ import annotations -ACCOUNT_TYPES = ("operator", "carrier", "opc", "service") +ACCOUNT_TYPES = ("operator", "carrier", "opc_member", "service") def account_type(role: str | None) -> str: @@ -25,17 +25,22 @@ def account_type(role: str | None) -> str: if r in ("carrier", "park", "park_staff", "carrier_staff"): return "carrier" if r in ("opc_member", "opc", "opc_certified", "opc_independent"): - return "opc" - # provider / enterprise / government / investor / ... 全部归 服务方 + return "opc_member" + # provider / enterprise / government / investor / developer / ... 全部归 服务方 return "service" def permission_role(atype: str) -> str: - """账号类型 → 用于查权限表( roles/ )的角色码。service 用 provider 基座。""" + """账号类型 → 用于查权限表( roles/ )的角色码。 + + 四种类型各自对应一个已种子的权限角色: + operator→operator, carrier→carrier, opc_member→opc_member, + service→provider(服务方基座权限, 后期扩 服务商/甲方企业 可在其上叠加)。 + """ return { "operator": "operator", "carrier": "carrier", - "opc": "opc_member", + "opc_member": "opc_member", "service": "provider", }.get(atype, "provider") @@ -45,6 +50,6 @@ def label(atype: str) -> str: return { "operator": "运营方", "carrier": "载体方", - "opc": "OPC", + "opc_member": "OPC", "service": "服务方", }.get(atype, "服务方") diff --git a/app/infrastructure/repositories.py b/app/infrastructure/repositories.py index 6432ceb..e9eb308 100644 --- a/app/infrastructure/repositories.py +++ b/app/infrastructure/repositories.py @@ -14,6 +14,7 @@ from sqlalchemy import delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession from .. import config +from ..domain.account_types import account_type as _acct_type, label as _acct_label from .models import ( Agent, AuditLog, @@ -583,7 +584,10 @@ class UserRepository: profile["status"] = user.get("opc_status", "") profile["topics"] = _parse_topics(user.get("topics", "")) profile["role"] = user.get("role", "opc_member") - profile["sub_role"] = user.get("sub_role") + profile["sub_role"] = None # 子角色已停用 + atype = user.get("account_type") or _acct_type(user.get("role")) + profile["account_type"] = atype + profile["account_type_label"] = user.get("account_type_label") or _acct_label(atype) profile["org_id"] = user.get("org_id") profile["region_id"] = user.get("region_id") profile["permissions"] = user.get("permissions", [])