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:
+20
-4
@@ -1,5 +1,7 @@
|
||||
import { applyAccessExtensions } from './access.extensions';
|
||||
|
||||
export default (initialState: { currentUser?: Global.UserInfo }) => {
|
||||
const canSeeAdmin = !!(
|
||||
const isPlatformAdmin = !!(
|
||||
initialState &&
|
||||
initialState.currentUser &&
|
||||
initialState.currentUser.is_admin
|
||||
@@ -10,10 +12,24 @@ export default (initialState: { currentUser?: Global.UserInfo }) => {
|
||||
!initialState.currentUser.is_admin
|
||||
);
|
||||
|
||||
return {
|
||||
canSeeAdmin,
|
||||
// Predicate roles, top-down by strictness:
|
||||
// * `canSeeAdmin` — strictly platform admin (`users.is_admin`).
|
||||
// Gates Users, Dashboard.
|
||||
// * `canSeeOrgAdmin` — admin-style menus that work cross-org
|
||||
// (Resources, Models, Cluster Management). Defaults to platform
|
||||
// admin; extensions widen to include org admins.
|
||||
// * `canManageCurrentOrg` — pages that only make sense inside a
|
||||
// specific org context (member / group management). Defaults to
|
||||
// `false`; extensions widen when both an org is selected AND
|
||||
// the caller is admin of it.
|
||||
// Pass through `applyAccessExtensions` so build-time tooling can
|
||||
// widen these without editing this file. Default is a no-op.
|
||||
return applyAccessExtensions({
|
||||
canSeeAdmin: isPlatformAdmin,
|
||||
canSeeOrgAdmin: isPlatformAdmin,
|
||||
canManageCurrentOrg: false,
|
||||
canSeeUser,
|
||||
canDelete: true,
|
||||
canLogin: true
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user