Activepieces Platform 配置深度解析:顶层租户模型、品牌与认证管理,以及平台删除的级联清理机制
2026/9/13 8:53:42 网站建设 项目流程

Activepieces Platform 配置深度解析:顶层租户模型、品牌与认证管理,以及平台删除的级联清理机制

【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces

Platform(平台)是 Activepieces 中最顶层的租户命名空间:每一个安装实例至少拥有一个 Platform,它统管品牌形象(Logo、颜色、favicon)、认证设置(邮箱登录开关、允许登录域名、联邦 SSO),以及通过PlatformPlan驱动的功能开关与配额限制。本文基于仓库内brain/knowledge/platform-editions-ee/platform-configuration.md文档,结合服务端、共享模型与前端源码,完整梳理 Platform 的实体模型、服务层方法、REST 端点、前端交互细节,以及平台删除时"先切断、后清理"的两拍式 teardown 机制,帮助你彻底掌握在 Activepieces 中配置与运维平台租户的能力。

一、Platform 是什么:所有版本通用的顶层租户

在 Activepieces 的租户模型中,Platform 是最高一级的命名空间。每个安装至少有一个平台,它拥有三类核心资产:

  • 品牌(Branding):Logo、主题颜色、favicon;
  • 认证(Auth):邮箱登录开关(emailAuthEnabled)、允许登录的域名列表(allowedAuthDomains)、联邦 SSO(OAuth2 + SAML);
  • 套餐(PlatformPlan:驱动功能开关(feature flags)与配额限制(limits)。

从版本分布看,Cloud 上一个用户可以拥有多个平台(多租户);CE/EE 自托管部署通常只有一个平台。该功能在所有版本中均可用(Available in all editions),只是不同版本开放的能力不同——例如 CE 使用固定的OPEN_SOURCE_PLAN,而usage用量数据只在非 Community 版本返回。

实体与字段

platform实体承载的核心字段如下(完整 zod 模型见 platform.model.ts,TypeORM 实体见 platform.entity.ts):

字段类型说明
ownerIdApId平台所有者用户 ID,指向user
namestring平台名称
primaryColorstring主色(十六进制)
themeColorsjsonb, nullable完整主题色;为null时从前端品牌派生默认主题
logoIconUrl/fullLogoUrl/favIconUrlstring品牌图片 URL
cloudAuthEnabled/googleAuthEnabledboolean云认证 / Google 认证开关(默认true
emailAuthEnabledboolean邮箱登录开关
allowedAuthDomainsstring[]允许登录的域名白名单
enforceAllowedAuthDomainsboolean是否强制校验允许域名
allowedEmbedOriginsstring[]允许嵌入的来源(embed 白名单)
ssoDomain/ssoDomainVerificationstring / jsonbSSO 域名及其校验状态
federatedAuthProvidersjsonb联邦认证配置(OAuth2 + SAML),列定义中select: false,默认不随查询返回
autoCreatePersonalProjectsboolean登录后是否自动创建个人项目(默认true
pinnedPiecesstring[]置顶的 piece 列表
pieceSelectorConfigjsonb, nullablePiece 选择器配置;为null时使用默认标签页

需要特别注意的是federatedAuthProviders在 platform.entity.ts 中带有select: false,即普通查询默认不会读取它,只有显式addSelect才能拿到(对应服务层的getOneWithFederatedAuthOrThrow)。此外实体上还有两个约束值得留意:

  • ssoDomain上有唯一索引idx_platform_sso_domain(仅在非 NULL 时生效);
  • ownerId → user的外键是ON DELETE RESTRICT,这条约束直接决定了平台删除时的顺序(详见后文)。

默认值与创建流程

创建平台时,服务层会写入一组确定的默认值(见 platform.service.ts):

  • primaryColor缺省为defaultTheme.colors.primary.default,Logo/favicon 缺省为defaultTheme.logos.*
  • emailAuthEnabled: trueautoCreatePersonalProjects: trueenforceAllowedAuthDomains: falseallowedAuthDomains: []
  • federatedAuthProviders: { saml: null }pinnedPieces: []pieceSelectorConfig: nullallowedEmbedOrigins: []

在 Cloud 的 onboarding 场景下,createPlatformWithProject会用一把create-platform-${identityId}的 Redis 分布式锁串行执行"创建 owner 用户 → 创建平台 → 创建个人项目(ProjectType.PERSONAL)→ 轮换 token 版本 → 上报注册事件",并且对"创建到一半中断"的状态做了幂等恢复:已存在 owner 则复用并链接,已创建未链接 owner 的平台则补链接(linkOwnerToPlatform)。个人项目的命名规则是platformName去掉结尾的Platform后缀加上Project,或以's Project结尾。

二、PlatformPlan:功能开关、配额与计费相关字段

PlatformPlan是平台的"能力清单",由 platform.model.ts 的 zod 模型定义,大致可分成四类:

  1. 功能开关(FeatureFlag)tablesEnabledeventStreamingEnabledenvironmentsEnabledanalyticsEnabledauditLogEnabledembeddingEnabledaiProvidersEnabledchatEnabledagentsEnabledworkerGroupsEnabledmanagePiecesEnabledmanageTemplatesEnabledcustomAppearanceEnabledprojectRolesEnabledglobalConnectionsEnabledcustomRolesEnabledapiKeysEnabledssoEnabledsecretManagersEnabledscimEnabledshowPoweredBy等。这些开关的枚举定义在FeatureFlagId中,是前端渲染与后端鉴权的共同依据。
  2. 不可消耗配额(Unconsumable)teamProjectsLimit(团队项目数)、usersLimit(座位数)、activeFlowsLimit(活跃流程数)。
  3. 可消耗配额(Consumable)apCredits(AP 积分)、appSumoAiCredits(AppSumo AI 积分)。
  4. 计费/许可字段includedCreditslicenseKeylicenseExpiresAtprojectsLimitbilledTeamProjectsLimitscheduledUsersLimitworkerGroupId

此外,模型保留了几个已废弃字段(带@deprecated注释):dedicatedWorkerscanary以及customDomainsEnabled(自定义域名功能已移除,仅保留列以兼容旧库)——现代实现统一使用workerGroupId指向 worker 组。

版本差异也很关键:在 Community 版本中,getPlan直接返回固定的OPEN_SOURCE_PLANusage返回undefined(见 platform.service.ts),因此 CE 自托管不存在额度计费概念。

主题色与 Piece 选择器配置

  • PlatformThemeColors定义了完整的可自定义主题色结构:avatarblue-linkdangerselection,以及primary(dark/light/medium)、warn(default/light/dark)、success(default/light)三组色板,每个颜色都必须是HEX_COLOR_PATTERN/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/)匹配的十六进制值。
  • PieceSelectorConfig由一组tabs组成,每个 tab 的kindBUILTINCUSTOM。内置 tab 有五种:EXPLOREAPPSUTILITYAI_AND_AGENTSAPPROVALS;自定义 tab 必须有非空title(zod refine 校验:Custom tabs must have a name),可配置iconhiddenpieceNamessections(分组展示)。pieceSelectorConfignull时前端回退到默认 tab。

三、platformService:服务层方法与职责划分

服务层(platform.service.ts)围绕platformRepo提供以下核心方法:

方法用途
create以默认值创建平台,并把 owner 用户关联到平台、触发onPlatformCreated初始化套餐
createPlatformWithProject注册/onboarding 专用:分布式锁保护下创建平台 + 个人项目,幂等恢复中断状态
update更新品牌、认证、piece 配置,可选地联动更新plan
getOneWithPlanAndUsageOrThrow返回平台 + 套餐 + 用量(Cloud/EE 的完整视图)
getOneWithPlanOrThrow只返回平台 + 套餐(不含 usage),用于鉴权守卫
listPlatformsForIdentityWithAtleastProject列出某身份拥有(且有项目)的平台,供平台切换器使用
getOldestPlatformcreated ASC取最老平台,CE 单平台解析的入口
hasSamlConfigured判断平台是否配置过 SAML
getOneWithFederatedAuthOrThrow显式读取敏感的federatedAuthProviders

update中有两个值得注意的细节:

  1. SAML 配置前置校验:写入federatedAuthProviders.saml前,先检查套餐是否开启ssoEnabled(否则抛FEATURE_DISABLED);配置 SAML 还要求ssoDomainVerification.status === VERIFIED,即"SSO 域名必须先完成校验"。
  2. SAML 缓存失效:更新 SAML 后调用invalidateSamlClientCache(params.id)清掉缓存的 SAML 客户端,保证新配置立即生效。

返回给调用方之前,所有方法都会经过stripFederatedAuth,把federatedAuthProviders从对象中剔除——敏感的 SSO 数据默认不出服务层。

四、REST 端点:查询、更新、资产下载与删除

平台相关端点集中在 platform.controller.ts,由platformModule注册到 Fastify 应用(入口见 platform.module.ts 与 app.ts)。

GET /v1/platforms/:id —— 获取平台(plan + usage)

  • 鉴权:securityAccess.publicPlatform([PrincipalType.USER, PrincipalType.SERVICE]),同时兼容 API key(SERVICE principal)调用;
  • 返回PlatformWithoutSensitiveData:SAML 敏感数据被剥离,只保留saml: {}占位或null
  • USER principal 的响应会被重写(见 platform.controller.ts):plan.chatEnabled被替换为按用户计算的 chat 可见性(chatVisibilityHelper.resolveChatEnabledForUser),嵌入式用户(embedded)的licenseKey会被置为null

POST /v1/platforms/:id —— 更新平台

  • 鉴权:platformAdminOnly([PrincipalType.USER]),且req.principal.platform.id必须等于路径中的:id,否则抛AUTHORIZATION
  • 请求体是multipart(因为要上传 Logo),通过attachMultipartFieldsToBody预处理器把 JSON 字符串字段解析回对象(见 platform.request.ts 的jsonFromMultipart);
  • 三个图片字段logoIconfullLogofavIcon会先经fileService.uploadPublicAssetFileType.PLATFORM_ASSET)上传,得到 URL 后再随其他字段一起落库——即品牌文件更新必须先走公共资产上传
  • 可更新字段与校验规则(UpdatePlatformRequestBody):name(仅校验SAFE_STRING_PATTERN,不允许./)、primaryColorthemeColorsfederatedAuthProviderscloudAuthEnabledgoogleAuthEnabledemailAuthEnabledautoCreatePersonalProjectsallowedAuthDomainsenforceAllowedAuthDomainspinnedPiecespieceSelectorConfigallowedEmbedOrigins

allowedEmbedOrigins的校验值得展开:单个 origin 最长 300 字符,协议仅限http:/https:,且支持https://*.example.com形式的通配符子域(校验逻辑见 platform.request.ts)。

DELETE /v1/platforms/:id —— 删除平台(仅 Cloud)

  • 仅 Cloud 版本注册该路由if (edition === ApEdition.CLOUD)),且必须是平台 owner(platformToEditMustBeOwnedByCurrentUser);
  • 存在有效订阅时拒绝删除hasActiveSubscription(platformPlan.plan)为真则抛DOES_NOT_MEET_BUSINESS_REQUIREMENTS,提示"先取消订阅再删除";
  • 删除不是即时的:先调度一个延迟约 7 天(PLATFORM_PURGE_DELAY_DAYS)的一次性系统任务HARD_DELETE_PLATFORMjobId: hard-delete-platform-${platformId},最多重试 25 次、固定 60 秒退避),然后立即执行"切断访问"(beginPlatformTeardown),最后向 owner 发送确认邮件(发送失败只记日志,不阻塞删除)。

GET /v1/platforms/assets/:id —— 公共资产下载

公开路由(securityAccess.public()),按文件 ID 读取PLATFORM_ASSET/USER_PROFILE_PICTURE类型的文件,以Content-Disposition: attachment返回,mimetype 从元数据读取。品牌 Logo、favicon 正是通过该端点对外提供。

五、前端交互:useCurrentPlatform 与 Appearance 表单的"逐字段门控"

前端通过 React Query 消费平台数据,核心 hook 在 platform-hooks.ts:

  • useCurrentPlatform():以当前登录会话的platformId为 key(['platform', currentPlatformId]),staleTime10 秒,返回{ platform, refetch, setCurrentPlatform }
  • useDeletePlatform():调用删除 API 后跳转/sign-in
  • useUpdateLisenceKey():激活 license key,成功后失效平台、flags 与订阅相关缓存。

关键 Gotcha:平台名称在 CE/未授权版本也可修改

平台配置界面位于Settings > Platform > Setup > General,其 Appearance 表单实现在 appearance-section.tsx。从源码看,该表单并非整体锁定,而是逐字段门控

  • 第 80 行计算brandingLocked = !platform.plan.customAppearanceEnabled
  • disabled={brandingLocked}只作用于 Logo、图标、favicon 与主题色输入框;
  • Platform Name输入框不受此门控,且提交时formdata.append('name', name)位于if (!brandingLocked)块之外。

因此,即使是一个 Community 或未授权平台,也能在 Appearance 界面修改平台名称——整个表单从上往下读像是全锁,实际只有品牌相关字段被锁。对应地,API 层的UpdatePlatformRequestBody.name同样不加版本门控,仅校验SAFE_STRING_PATTERN(不允许.//)。这是一个容易被误解的"特性",在排查"为什么 CE 也能改名字"时务必知道它是逐字段设计。

六、平台删除的两拍式机制:先切断,后清理

平台删除是本仓库中设计最精细、坑最多的流程,完整决策记录见 000026-delete-platform-is-a-cloud-owner-action-purged-by-one-cascading-job.md,实现位于 platform-teardown-jobs.ts。

第一拍:请求返回即切断访问(beginPlatformTeardown)

user.status只被交互式登录读取,触发器调度器、BullMQ 队列、API key 产生的 SERVICE principal 全都无视它。所以"切断"必须做四件事(见 platform-teardown-jobs.ts):

  1. 把所有成员的user.status置为INACTIVE(阻止交互登录);
  2. 删除平台全部api_key(否则 SERVICE principal 能在窗口期内重新启用流程);
  3. 遍历所有流程,通过正规的CHANGE_STATUS操作禁用(FlowOperationType.CHANGE_STATUSFlowStatus.DISABLED),从而让triggerSourceService.disable注销 webhook、从 BullMQ 中移除 cron 与轮询调度——直接写status列不会解除触发器武装;
  4. 调用drainFlows清理队列中的遗留工作(batchDeleteByFlowId)。

其中第 3 步对单个流程禁用失败时,会降级为强制调用triggerSourceService.disable并直接更新状态列,确保"没有新 webhook 再放行新运行"。关键顺序:purge 任务在切断之前就已完成调度,因此即使切断过程抛异常,最坏结果也是"如期清理但切断得不干净",而不是"全员失联且无人能重试"。

第二拍:约 7 天后由单个 HARD_DELETE_PLATFORM 任务清理

清理任务刻意不是单事务——每张表一条语句、每条语句可安全重复执行,25 次重试可以从列表中间恢复,而不是跨整租户持锁导致首次超时丢全部进度。删除顺序由 schema 强制,顺序为:

  1. 再次执行禁用与排空(对已切断的租户是 no-op);
  2. piece_metadataapp_connection
  3. 逐个删除项目(先批量删项目关联的 cell/record/field/table/flow_run/trigger_event/file,再删项目行);
  4. signing_key
  5. 删那些"没有任何外键可达"的 12 张表:file(平台级)、project_roleuser_invitationmcp_oauth_tokenmcp_oauth_authorization_codevariableconcurrency_pooltool_search_index等(piece_metadataapp_connection在前已删);
  6. 批量删除审计事件(audit_event,按 5000 条分块);
  7. platform行——让 14 条CASCADE外键清掉其余数据;
  8. 最后删user行,并清理不再被任何存活用户引用的user_identity(防止把另一个平台的用户登出)。

约束决定了顺序,而不是偏好

  • projectsigning_keyplatform(id)RESTRICT,是仅存的两个阻塞者(tagpiece_tag曾是NO ACTION,因功能废弃已被删表移除);
  • platform.ownerId → userRESTRICT,所以平台行必须先于 owner 的user行删除;project.ownerId → userNO ACTION,所以项目必须先于任何用户删除;
  • 还有一个连环陷阱:piece_metadata.archiveId → fileRESTRICT,而file.projectId → projectCASCADE,因此自定义 piece 存档必须在删文件之前删除——这就是piece_metadata排在前面的原因。

"平台删不掉"的诊断口诀:某租户删除失败而另一个成功,几乎总是新增了一张带RESTRICT外键的表(阻塞者),而不是成员数量问题。因为userfileapp_connectionpiece_metadataproject_memberproject_roleuser_invitationmcp_oauth_tokenmcp_oauth_authorization_codevariableconcurrency_pooltool_search_index这 12 张表都带platformId没有任何外键——它们既不阻塞也不级联,只会悄悄产生孤儿行,任何 teardown 都必须显式删除它们,绝不能因为"列存在"就推断有级联行为。

对开发者的约定

任何携带platformId的新实体,应当把外键声明为ON DELETE CASCADE;否则就必须把表名手工加进 platform-teardown-jobs.ts 的删除清单(该清单由人工维护,CI 不会检查)。另外,"把成员置为INACTIVE就完事"是一个危险误解:INACTIVE 只挡登录,调度器、队列和 SERVICE principal 都不读user.status,切断平台必须按上述四件事逐项执行。

七、完整 Gotchas 清单

  1. 平台名称在所有版本都可改appearance-section.tsx按字段门控品牌输入,唯独Platform Nameformdata.append('name', ...)if (!brandingLocked)之外;API 侧name同样无版本门控,仅校验SAFE_STRING_PATTERN
  2. 逐项目(project)的 piece/action/trigger 可见性由 piece sets 管理,不是平台——pinnedPieces/pieceSelectorConfig只管选择器呈现,不做运行期可见性控制。
  3. GET 响应按调用者重写:USER principal 拿到的是按用户生效的plan.chatEnabled;嵌入式用户的licenseKey被置空。
  4. 更新 SAML 会失效缓存invalidateSamlClientCache保证新 SAML 配置立即生效。
  5. usage只在非 Community 版本填充:CE 使用OPEN_SOURCE_PLAN,不返回用量。
  6. 品牌文件先上传后落库:Logo/favicon 更新走fileService.uploadPublicAsset得到 URL 再保存。
  7. platformId列 ≠ 外键:12 张表带列无 FK,删除平台时必须显式清理,不能依赖级联。
  8. 阻塞删除的约束只有projectsigning_key(RESTRICT):删除失败先查pg_constraint,看是否新增了阻塞外键。
  9. 删除顺序被ownerId → user的 RESTRICT 强制:平台行先删,owner 的 user 行后删;项目必须先于任何用户删除。
  10. 新实体规范:带platformId的新实体声明ON DELETE CASCADE,否则按名加入 teardown 清单。
  11. INACTIVE 只停登录:必须通过CHANGE_STATUS禁用全部流程(注销 webhook、移除调度)、batchDeleteByFlowId排空队列、删除api_key,否则流程仍在运行。

八、关键文件速查

  • 服务端整个平台切片:packages/server/api/src/app/platform/——module、controller、service、TypeORM 实体、getPlatformIdForRequest工具(platform.utils.ts);
  • 删除/清理实现:platform-teardown-jobs.ts——HARD_DELETE_PLATFORM处理器与控制器调用的stopPlatformExecution切断逻辑;
  • 共享 zod 模型与请求体:packages/core/shared/src/lib/management/platform/——PlatformPlatformWithoutSensitiveDataPlatformPlanPieceSelectorConfigUpdatePlatformRequestBody(platform.model.ts、platform.request.ts);
  • 前端 React Query hook:platform-hooks.ts——useCurrentPlatform()
  • 品牌表单:appearance-section.tsx;
  • 决策记录:000026-delete-platform-is-a-cloud-owner-action-purged-by-one-cascading-job.md(删除机制的完整论证,含 schema 级证据)。

文中涉及的文件路径均以仓库根目录为基准,与文档标注的校验日期(2026-07-17)一致。若你的部署遇到平台删除失败、CE 改品牌被锁但改名可用、或新增租户表后清理不干净等问题,对照本文的 Gotchas 与 teardown 清单逐项排查即可。

【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询