feat: access-control seam exposes prepended policies + create default
The OSS access-control form currently lets a plugin replace the
`allowed_users` policy entry. Multi-tenancy also wants:
- an extra radio option for "Org-scoped" sitting in front of the
built-ins, and
- a context-sensitive create-time default (routes inside a non-
platform Org should land on the Org-scoped policy rather than
`authed`).
Extend the `accessControl` slot with two more hooks:
- `prependedPolicies?: { policyValue, labelId, tipsId?, Field? }[]`
— entries prepended to the radio group; each may carry an
optional content `Field` rendered when selected.
- `resolveCreateDefault?: () => string | undefined` — overrides the
initial `access_policy` for the create flow; the OSS fallback is
still `authed`.
The host's tooltip list mirrors the same order. Existing behaviour
without a plugin is unchanged.
This commit is contained in:
@@ -34,7 +34,14 @@ import { AccessControlFormData } from '../../config/types';
|
|||||||
|
|
||||||
type TransferKey = string | number | bigint;
|
type TransferKey = string | number | bigint;
|
||||||
|
|
||||||
const buildAccessScopeTips = (override?: AllowedUsersOverride) => [
|
const buildAccessScopeTips = (
|
||||||
|
override?: AllowedUsersOverride,
|
||||||
|
prepended: PrependedPolicy[] = []
|
||||||
|
) => [
|
||||||
|
...prepended.map((p) => ({
|
||||||
|
title: { text: p.labelId, locale: true },
|
||||||
|
tips: p.tipsId ?? p.labelId
|
||||||
|
})),
|
||||||
{
|
{
|
||||||
title: {
|
title: {
|
||||||
text: 'models.accessSettings.authed',
|
text: 'models.accessSettings.authed',
|
||||||
@@ -92,14 +99,37 @@ type AllowedUsersOverride = {
|
|||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Extra policy entries prepended to the radio list (rendered before
|
||||||
|
// `authed`). Each entry can optionally bring a `Field` that renders
|
||||||
|
// when its policy is selected — leave it out for plain "scope"
|
||||||
|
// policies that need no extra config (e.g. ORG).
|
||||||
|
type PrependedPolicy = {
|
||||||
|
policyValue: string;
|
||||||
|
labelId: string;
|
||||||
|
tipsId?: string;
|
||||||
|
Field?: React.ComponentType<{
|
||||||
|
form: any;
|
||||||
|
routeId?: number;
|
||||||
|
action: PageActionType;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
||||||
const { action, currentData, onFinish, onValuesChange } = props;
|
const { action, currentData, onFinish, onValuesChange } = props;
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const accessPolicy = Form.useWatch('access_policy', form);
|
const accessPolicy = Form.useWatch('access_policy', form);
|
||||||
|
const pluginAccessControl = getGPUStackPlugin()?.accessControl;
|
||||||
const allowedUsersOverride: AllowedUsersOverride | undefined =
|
const allowedUsersOverride: AllowedUsersOverride | undefined =
|
||||||
getGPUStackPlugin()?.accessControl?.allowedUsersOverride;
|
pluginAccessControl?.allowedUsersOverride;
|
||||||
const overridePolicyValue = allowedUsersOverride?.policyValue;
|
const overridePolicyValue = allowedUsersOverride?.policyValue;
|
||||||
|
const prependedPolicies: PrependedPolicy[] =
|
||||||
|
pluginAccessControl?.prependedPolicies ?? [];
|
||||||
|
const resolveCreateDefault: (() => string | undefined) | undefined =
|
||||||
|
pluginAccessControl?.resolveCreateDefault;
|
||||||
|
const activePrependedPolicy = prependedPolicies.find(
|
||||||
|
(p) => p.policyValue === accessPolicy
|
||||||
|
);
|
||||||
const [targetKeys, setTargetKeys] = useState<TransferKey[]>([]);
|
const [targetKeys, setTargetKeys] = useState<TransferKey[]>([]);
|
||||||
const [totalPages, setTotalPages] = useState(0);
|
const [totalPages, setTotalPages] = useState(0);
|
||||||
const [userList, setUserList] = useState<
|
const [userList, setUserList] = useState<
|
||||||
@@ -316,7 +346,14 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
scrollToFirstError={true}
|
scrollToFirstError={true}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
users: [],
|
users: [],
|
||||||
access_policy: action === PageAction.CREATE ? 'authed' : undefined
|
// For create the plugin (if registered) may supply a context-
|
||||||
|
// sensitive default — e.g. routes in a non-platform Org
|
||||||
|
// default to the Org-scoped policy. Fall back to `authed`
|
||||||
|
// (the OSS default) if the plugin doesn't return a value.
|
||||||
|
access_policy:
|
||||||
|
action === PageAction.CREATE
|
||||||
|
? (resolveCreateDefault?.() ?? 'authed')
|
||||||
|
: undefined
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Label>
|
<Label>
|
||||||
@@ -324,7 +361,10 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
<TooltipList
|
<TooltipList
|
||||||
list={buildAccessScopeTips(allowedUsersOverride)}
|
list={buildAccessScopeTips(
|
||||||
|
allowedUsersOverride,
|
||||||
|
prependedPolicies
|
||||||
|
)}
|
||||||
></TooltipList>
|
></TooltipList>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -337,6 +377,10 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
onChange={handleOnPolicyChange}
|
onChange={handleOnPolicyChange}
|
||||||
style={{ marginBottom: 12 }}
|
style={{ marginBottom: 12 }}
|
||||||
options={[
|
options={[
|
||||||
|
...prependedPolicies.map((p) => ({
|
||||||
|
label: intl.formatMessage({ id: p.labelId }),
|
||||||
|
value: p.policyValue
|
||||||
|
})),
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({ id: 'models.accessSettings.authed' }),
|
label: intl.formatMessage({ id: 'models.accessSettings.authed' }),
|
||||||
value: 'authed'
|
value: 'authed'
|
||||||
@@ -373,6 +417,13 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
></AlertBlockInfo>
|
></AlertBlockInfo>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{activePrependedPolicy?.Field && (
|
||||||
|
<activePrependedPolicy.Field
|
||||||
|
form={form}
|
||||||
|
routeId={currentData?.id}
|
||||||
|
action={action}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{allowedUsersOverride &&
|
{allowedUsersOverride &&
|
||||||
accessPolicy === overridePolicyValue && (
|
accessPolicy === overridePolicyValue && (
|
||||||
<allowedUsersOverride.Field
|
<allowedUsersOverride.Field
|
||||||
|
|||||||
Reference in New Issue
Block a user