mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 14:21:58 +00:00
59 lines
2.6 KiB
Python
59 lines
2.6 KiB
Python
"""应用级权限(§3.12):use 能用(入口、视图、自己的实例);observe 另能看全部实例;manage 能搭建、发布、授权、管钩子。
|
||
|
||
- 关登录:全部放行,等同 manage(界面上挂横幅说明,签批人是自报的署名);
|
||
- admin:所有应用 manage;
|
||
- builder:所有应用至少 observe(能用、能看全部实例);自己建的、或者有 manage 授权的才 manage;
|
||
- user:按授权(给本人、给所在的组、给所有人)取最高的那一档,最高到 observe:搭建、发布、绑定岗位、授权、钩子、按草稿
|
||
预览、改派催办都不给 user 角色(§3.12),授给它的 manage 按 observe 算。没有授权就看不到这个应用。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from sqlalchemy import select
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from app.api.deps import Principal
|
||
from app.db.models_apps import AppGrant
|
||
|
||
RANK = {"use": 1, "observe": 2, "manage": 3}
|
||
|
||
|
||
def at_least(role: str | None, need: str) -> bool:
|
||
return RANK.get(role or "", 0) >= RANK[need]
|
||
|
||
|
||
def granted_role(principal: Principal, grants: list[Any]) -> str | None:
|
||
"""授权里这个人能拿到的最高一档。"""
|
||
best: str | None = None
|
||
groups = set(principal.groups)
|
||
for g in grants:
|
||
hit = (g.principal_kind == "everyone"
|
||
or (g.principal_kind == "user" and principal.username and g.principal == principal.username)
|
||
or (g.principal_kind == "group" and g.principal in groups))
|
||
if hit and RANK.get(g.role, 0) > RANK.get(best or "", 0):
|
||
best = g.role
|
||
return best
|
||
|
||
|
||
def role_of(principal: Principal, app: Any, grants: list[Any]) -> str | None:
|
||
if principal.mode == "off" or principal.role == "admin":
|
||
return "manage"
|
||
granted = granted_role(principal, grants)
|
||
if principal.role == "builder":
|
||
if app.created_by and principal.username and app.created_by == principal.username:
|
||
return "manage"
|
||
return granted if at_least(granted, "manage") else "observe"
|
||
return "observe" if at_least(granted, "manage") else granted
|
||
|
||
|
||
async def grants_of(session: AsyncSession, app_id: str) -> list[AppGrant]:
|
||
return list((await session.execute(select(AppGrant).where(AppGrant.app_id == app_id)
|
||
.order_by(AppGrant.created_at))).scalars())
|
||
|
||
|
||
async def app_role(session: AsyncSession, principal: Principal, app: Any) -> str | None:
|
||
if principal.mode == "off" or principal.role == "admin":
|
||
return "manage"
|
||
return role_of(principal, app, await grants_of(session, app.id))
|