mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 09:41:59 +00:00
277982ead3
- 蓝图:bp_* 操作和逐卡白名单、蓝图检查、留痕、按蓝图判权限;五个场景模板加自由形(骨架、关节、应用骨架、定时任务),实例化与骨架比对;BlueprintApplier / TemplateApplier(只收模板声明过的关节)与自查;look 新类别口径卡;蓝图对话和填关节两个流式接口,不同组的关节并行填、出错的组串行重试;模板列表 - 试运行与发布单:四种起点(对话、模板、问数据的一轮、已发布版本);试运行是探索运行,草稿应用按这次运行解析、印章写试运行,流程类派给自己、不触发升级;发布单九步、预检只读、每步留痕、停下后接着做、核对卡片指纹和应用管理权、启动时整理中断的单;白话层覆盖全部问题编号 - 记录表与文件:平台托管只追加的记录表、按高水位固定数据、连接上的临时视图做行级可见、写入走动作(records_append)、表版本在发布时切换、草稿不影响线上、记录列表遮敏感列;文件按哈希存、两步上传、提交时绑定运行、下载按读权限、清理、file_text、按配方导入一期(table_import_period) - 个人应用:存成个人应用(问数据的约束)、刷新(遮罩、只读、每日上限)、只有拥有者看得见、提交审核与共享副本、开关下发到认人接口;页面编辑的候选;隐藏组件不下发;三条新检查
73 lines
3.2 KiB
Python
73 lines
3.2 KiB
Python
"""记录表的行级可见(docs/design/normal-user-apps.md N8、§3.7、§3.12)。
|
||
|
||
谁看得到哪些行,只有三种:all(全部)、mine(只看自己提交的,_submitted_by = 看的人)、none(一行都不给)。
|
||
- 正式运行以服务身份跑,看全部:看板读的是正式运行的封存结果,汇总是全量的(作者的选择,发布摘要里写明);
|
||
- 别的运行(问数据、试运行、个人应用的刷新)按发起人和这张表所属应用的授权:use 只看自己的,observe、manage 看全部;
|
||
- 记录列表(records_list、GET /api/apps/{id}/records)按看的人,同一套规则;
|
||
- 关登录时所有人等同管理员,看全部;管理员看全部。
|
||
过滤在查询连接的临时视图上做(records/store.view_prelude),模型和 SQL 都绕不过去。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from sqlalchemy import select
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
SCOPES = ("all", "mine", "none")
|
||
|
||
|
||
def scope_of_role(principal: Any, role: str | None) -> str:
|
||
"""看的人在应用上拿到的那一档 → 看哪些行。"""
|
||
from app.apps.access import at_least
|
||
|
||
if principal.mode == "off" or principal.role == "admin":
|
||
return "all"
|
||
if at_least(role, "observe"):
|
||
return "all"
|
||
return "mine" if role == "use" else "none"
|
||
|
||
|
||
async def scope_of(session: AsyncSession, principal: Any, app_id: str | None) -> str:
|
||
"""看的人对这张表(所属应用 app_id)看哪些行。还没归到应用的(试运行时按蓝图建的):搭建者看全部,使用者看自己的。"""
|
||
from app.apps.access import app_role
|
||
from app.db.models_apps import App
|
||
|
||
if principal.mode == "off" or principal.role == "admin":
|
||
return "all"
|
||
if not app_id:
|
||
return "all" if principal.at_least("builder") else "mine"
|
||
app = await session.get(App, app_id)
|
||
if app is None:
|
||
return "all" if principal.at_least("builder") else "none"
|
||
return scope_of_role(principal, await app_role(session, principal, app))
|
||
|
||
|
||
async def scope_of_run(session: AsyncSession, app_id: str | None, *, run_class: str | None,
|
||
started_by: str | None) -> dict[str, Any]:
|
||
"""一次运行看哪些行,记进 data_versions:{"rows": all|mine|none, "viewer"?: 发起人}。发起时定下,续跑、恢复沿用。"""
|
||
from app.api.deps import auth_mode
|
||
|
||
if run_class == "formal":
|
||
return {"rows": "all"}
|
||
mode = auth_mode()
|
||
if mode == "off":
|
||
return {"rows": "all"}
|
||
principal = await _principal(session, started_by, mode)
|
||
if principal is None:
|
||
return {"rows": "none"}
|
||
scope = await scope_of(session, principal, app_id)
|
||
return {"rows": scope, **({"viewer": principal.username} if scope == "mine" else {})}
|
||
|
||
|
||
async def _principal(session: AsyncSession, username: str | None, mode: str) -> Any | None:
|
||
from app.auth.sessions import principal_of
|
||
from app.db.models import User
|
||
|
||
if not username:
|
||
return None
|
||
user = (await session.execute(select(User).where(User.username == username))).scalar_one_or_none()
|
||
if user is None or user.disabled:
|
||
return None
|
||
return await principal_of(session, user, mode)
|