feat: plugin extension slots for access, request interceptors, Users actions, and form fields

Four purely-additive seams that let build-time tooling extend host
behaviour without forking files:

* `src/access.extensions.ts` — identity `applyAccessExtensions`
  (mirrors `config/routes.extensions.ts`). `src/access.ts` runs the
  resolved predicate object through it. Adds two new predicates,
  `canSeeOrgAdmin` and `canManageCurrentOrg`, alongside the existing
  `canSeeAdmin`. Resources, Models children, Cluster Management, and
  Resources/Backends are retagged from `canSeeAdmin` to
  `canSeeOrgAdmin`. Users and Dashboard stay strict.
* `src/request.extensions.ts` — identity-empty
  `extraRequestInterceptors`. `src/request-config.tsx` spreads it
  into the existing `requestInterceptors` list so extensions can
  inject context-aware headers without forking the request config.
* Users page action column — renders
  `getGPUStackPlugin()?.components?.UserRowActions` next to the
  existing DropdownButtons inside a Space when a plugin component
  is registered. If absent, the cell renders exactly as before.
* `src/components/plugin-extra-fields.tsx` — generic component-slot
  helper. Renders `pluginManager.components.<name>` if registered,
  forwarding a `context` payload. Used by create/edit forms to let
  plugins inject extra `Form.Item` fields. Mounted in the relevant
  create forms — API Keys, Cloud Credentials, Clusters, Model
  Routes, Model Providers, and Inference Backends — under the slot
  name `CreateOrgScopeField`. Resources whose org is implicit from a
  parent (Models / Workers / Benchmarks / Worker Pools / Model Files
  inherit from the chosen Cluster) deliberately don't mount the slot.
This commit is contained in:
gitlawr
2026-05-08 18:29:52 +08:00
committed by jialin
parent 896b8ef326
commit 2889ba7c78
18 changed files with 211 additions and 67 deletions
+15 -5
View File
@@ -1,4 +1,5 @@
// columns.ts
import PluginExtraFields from '@/components/plugin-extra-fields';
import { tableSorter } from '@/config/settings';
import {
AutoTooltip,
@@ -8,7 +9,7 @@ import {
} from '@gpustack/core-ui';
import { useIntl, useModel } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Tag } from 'antd';
import { Space, Tag } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import dayjs from 'dayjs';
import { useMemo } from 'react';
@@ -197,10 +198,19 @@ const useUsersColumns = ({
dataIndex: 'operation',
span: 3,
render: (text, record) => (
<DropdownButtons
items={setActions(record)}
onSelect={(val) => handleSelect(val, record)}
/>
// Plugin slot for per-row user actions. If no plugin is
// registered, `PluginExtraFields` renders nothing and the
// cell looks exactly as before.
<Space size={4}>
<DropdownButtons
items={setActions(record)}
onSelect={(val) => handleSelect(val, record)}
/>
<PluginExtraFields
name="UserRowActions"
context={{ user: record }}
/>
</Space>
)
}
];