ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

在 Backstage 中查看我拥有的实体(Viewing What You Own):归属关系与过滤机制完全指南

2026/9/11 21:54:44 拓冰建站 浏览量
在 Backstage 中查看我拥有的实体(Viewing What You Own):归属关系与过滤机制完全指南 在 Backstage 中查看我拥有的实体Viewing What You Own归属关系与过滤机制完全指南【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstageBackstage 的软件目录Software Catalog是团队管理组件、API、网站、系统等软件实体的统一入口而我拥有什么则是每位开发者登录后最常关心的视图。本文基于官方入门文档 docs/getting-started/view-what-you-own.md讲解如何通过目录页面查看当前用户直接拥有或通过所在分组间接拥有的实体并结合仓库源码深入剖析ownedBy归属关系在前端过滤与后端查询中的实现原理。读完本文你将掌握在 Backstage 门户中定位我的资产的标准操作流程并能从代码层面理解归属过滤的完整调用链。前置概念什么是拥有实体在 Backstage 的实体模型Entity Model中一个实体如Component、API、System可以通过关系Relations指向它的所有者。所有者通常是用户User或分组Group这一关系在 catalog-model 中被定义为RELATION_OWNED_BY即ownedBy反向关系对应的正向关系为ownerOf。因此你可以通过两种途径拥有实体直接拥有实体的spec.owner指向你本人当前登录用户间接拥有实体的spec.owner指向你所在的分组Group而你是该分组的成员。这两种归属在目录页面中被分别称为Direct Relations直接关系与Aggregated Relations聚合关系下文会详细说明。操作步骤三步查看你所拥有的实体根据官方入门文档查看你拥有实体只需三步进入主页在左侧边栏Sidebar中选择Home进入软件目录的默认主页选择类型在Kind下拉列表中选择User选择用户在All Users列表中选择你的用户名。页面随即展示你拥有直接或通过所在分组间接拥有的实体列表。你可以在两个视图之间切换Direct Relations直接归你所有的实体Aggregated Relations通过你所在分组拥有的实体。官方文档为此提供了截图见下展示的是以guest用户登录时目录页面呈现的归属实体结果说明上述All Users下拉与Kind筛选属于目录页左侧过滤面板的一部分。它们与我拥有的实体owned筛选共同构成了目录页的完整过滤体验具体实现见下文源码分析。源码级剖析归属关系如何被计算与过滤要理解上述交互背后的原理需要从前端 Hook、筛选器、后端查询三个层面来看。1. 身份与归属引用ownershipEntityRefs归属判断的第一步是拿到当前登录用户的所有权引用列表。在 plugins/catalog-react/src/hooks/useEntityOwnership.ts 中useEntityOwnership通过identityApi.getBackstageIdentity()获取ownershipEntityRefs一个实体引用字符串数组包含用户自身的引用以及其所属分组的引用然后将其与实体上的ownedBy关系逐一比对const { ownershipEntityRefs } await identityApi.getBackstageIdentity(); ... const isOwnedEntity useMemo(() { const myOwnerRefs new Set(refs ?? []); return (entity: Entity) { const entityOwnerRefs getEntityRelations(entity, RELATION_OWNED_BY).map( stringifyEntityRef, ); for (const ref of entityOwnerRefs) { if (myOwnerRefs.has(ref)) { return true; } } return false; }; }, [refs]);从源码可以看到isOwnedEntity采用集合交集的方式判断只要实体的任意一个ownedBy引用落在当前用户的ownershipEntityRefs集合中即判定为我拥有。由于ownershipEntityRefs天然包含用户本身 用户所属分组因此该逻辑同时覆盖了直接拥有与聚合拥有两种情形。值得注意的是该 Hook 仅在挂载时加载一次useAsync依赖为空数组[]加载期间isOwnedEntity恒返回false这是它文档注释中特别声明的行为。2. 前端筛选器EntityUserFilter目录页左侧的过滤面板由 UserListPicker 组件实现。它渲染两组过滤项个人过滤Personal Filtersowned我拥有的与starred我收藏的组织过滤Organizationall全部实体分组名取自配置organization.name默认回退为Backstage。每个过滤项右侧还会显示对应的实体计数例如我拥有的右侧的数字即当前登录用户拥有的实体数量。当某个过滤项计数为 0 时该菜单项会被禁用disabled{filterCounts[item.id] 0}当用户选择owned且计数为 0 时组件会自动回退到all过滤见 UserListPicker.tsx。选择owned后组件通过updateFilters({ user: EntityUserFilter.owned(ownershipEntityRefs) })应用筛选。EntityUserFilter定义于 plugins/catalog-react/src/filters.ts它把当前用户的归属引用集合包装成目录查询可识别的过滤条件。在计数实现 useOwnedEntitiesCount.ts 中可以看到最终它会调用catalogApi.queryEntities并携带relations.ownedBy: ownedClaims这样的过滤键——这正是把归属语义映射为目录 API 查询参数的落点const { totalItems } await catalogApi.queryEntities({ ...req.filter, filter: { ...filter, relations.ownedBy: ownedClaims, }, limit: 0, }); return totalItems;若当前用户与所选的owners过滤没有公共引用getOwnedCountClaims返回undefined代码会直接返回计数 0 而跳过网络请求这是一种针对空结果的短路优化见 useOwnedEntitiesCount.ts。3. 页面默认行为DefaultCatalogPage与initiallySelectedFilter官方入门文档描述的操作是在目录主页完成的该页面对应插件包中的DefaultCatalogPageplugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx。它的initiallySelectedFilter属性默认值为owned意味着目录页在首次打开时默认就选中我拥有的过滤视图这与文档中打开 Home 即可查看归属实体的体验一致export function DefaultCatalogPage(props: DefaultCatalogPageProps) { const { ... initiallySelectedFilter owned, initialKind component, ... } props;开发者也可以通过向DefaultCatalogPage传入initiallySelectedFilter可选值包括owned、starred、all或filters属性来定制页面的初始过滤状态与过滤面板。Direct Relations 与 Aggregated Relations两种视图的含义当你按文档步骤打开我拥有的实体页面时可以切换两种视图视图含义判定依据Direct Relations实体直接归你所有实体的ownedBy关系直接指向你的用户实体Aggregated Relations通过你所在分组拥有的实体实体的ownedBy关系指向你的某个所属分组这两种视图本质上是ownershipEntityRefs集合中用户自身引用与所属分组引用的两种呈现方式。无论切换哪种视图底层使用的都是同一套ownedBy关系查询见上文EntityUserFilter与queryEntities的relations.ownedBy过滤参数区别仅在于结果集展示维度与聚合粒度的不同。如何让实体归属到你spec.owner配置要让某类实体出现在我拥有的实体视图中需要在实体的catalog-info.yaml描述文件中正确声明所有者。以最常见的Component为例apiVersion: backstage.io/v1alpha1 kind: Component metadata: name: my-service description: An example service spec: type: service owner: group:team-a若spec.owner写为user:alice则只有用户alice能通过我拥有的视图看到它Direct Relations若spec.owner写为group:team-a推荐做法则team-a的所有成员都能通过聚合视图看到它Aggregated Relations。spec.owner使用实体引用Entity Reference语法通常写作kind:namespace/name的形式其中namespace缺省时为default。关于实体引用格式的细节可参考仓库中的架构决策文档 docs/architecture-decisions/adr009-entity-references.md。常见问题与排查思路为什么我拥有的视图是空的先确认当前登录用户身份是否正确再检查目标实体catalog-info.yaml中spec.owner是否指向你本人或你所属的分组且用户/分组实体确实存在于目录中。为什么我拥有的计数为 0 且被禁用当useOwnedEntitiesCount计算得到 0 时UserListPicker会禁用该菜单项并自动回退到all这是预期行为见 UserListPicker.tsx。如何让目录页默认打开我拥有的视图默认即为owned如需修改可向DefaultCatalogPage传入initiallySelectedFilterstarred或all。延伸阅读入门指南在目录中查看实体的一般流程见 docs/getting-started/viewing-catalog.md筛选目录见 docs/getting-started/filter-catalog.md实体模型与关系软件目录的核心实体与关系定义见 docs/features/software-catalog源码参考归属判断 Hook 见 plugins/catalog-react/src/hooks/useEntityOwnership.ts计数逻辑见 plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts过滤面板见 plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx。【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考