mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-13 16:00:02 +02:00
Merge branch 'aig' of github.com:fosrl/pangolin into aig
This commit is contained in:
@@ -855,12 +855,16 @@
|
|||||||
"authMethodsSave": "Save Settings",
|
"authMethodsSave": "Save Settings",
|
||||||
"policyAuthStackTitle": "Authentication",
|
"policyAuthStackTitle": "Authentication",
|
||||||
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
|
"policyAuthStackDescription": "Control which authentication methods are required to access this resource",
|
||||||
|
"policyAuthInferenceStackDescription": "Choose which users and roles can authenticate to this AI gateway",
|
||||||
"policyAuthOrLogicTitle": "Multiple authentication methods active",
|
"policyAuthOrLogicTitle": "Multiple authentication methods active",
|
||||||
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
|
"policyAuthOrLogicBanner": "Visitors may authenticate using any one of the active methods below. They do not need to complete all of them.",
|
||||||
"policyAuthMethodActive": "Active",
|
"policyAuthMethodActive": "Active",
|
||||||
"policyAuthMethodOff": "Off",
|
"policyAuthMethodOff": "Off",
|
||||||
"policyAuthSsoTitle": "Platform SSO",
|
"policyAuthSsoTitle": "Platform SSO",
|
||||||
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
|
"policyAuthSsoDescription": "Require sign-in through your organization's identity provider",
|
||||||
|
"policyAuthInferenceSsoDescription": "Selected users and roles can authenticate to the gateway using their identity API key",
|
||||||
|
"policyAuthInferenceIdentityKeyHelp": "Every user already has an identity API key, so you only need to create virtual API keys for non-user clients or shared access. Users can retrieve their key by signing in with their identity provider at <resourceLink></resourceLink>, where it will be shown after login.",
|
||||||
|
"policyAuthInferenceIdentityKeyHelpNoUrl": "Every user already has an identity API key, so you only need to create virtual API keys for non-user clients or shared access. Users can retrieve their key by signing in with their identity provider at this resource's URL, where it will be shown after login.",
|
||||||
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
|
"policyAuthSsoSummary": "{idp} · {users} users, {roles} roles",
|
||||||
"policyAuthSsoDefaultIdp": "Default provider",
|
"policyAuthSsoDefaultIdp": "Default provider",
|
||||||
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
|
"policyAuthAddDefaultIdentityProvider": "Add Default Identity Provider",
|
||||||
|
|||||||
@@ -372,30 +372,6 @@ export default function VirtualApiKeysTable({
|
|||||||
},
|
},
|
||||||
cell: ({ row }) => moment(row.original.createdAt).format("lll")
|
cell: ({ row }) => moment(row.original.createdAt).format("lll")
|
||||||
},
|
},
|
||||||
{
|
|
||||||
accessorKey: "expiresAt",
|
|
||||||
friendlyName: t("expires"),
|
|
||||||
header: ({ column }) => {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() =>
|
|
||||||
column.toggleSorting(column.getIsSorted() === "asc")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{t("expires")}
|
|
||||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
cell: ({ row }) => {
|
|
||||||
const expiresAt = row.original.expiresAt;
|
|
||||||
if (expiresAt) {
|
|
||||||
return moment(expiresAt).format("lll");
|
|
||||||
}
|
|
||||||
return t("never");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ export type PolicyAuthSsoSectionProps = {
|
|||||||
usersEditor: React.ReactNode;
|
usersEditor: React.ReactNode;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
idpDisabled?: boolean;
|
idpDisabled?: boolean;
|
||||||
|
ssoLocked?: boolean;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function PolicyAuthSsoSection({
|
export function PolicyAuthSsoSection({
|
||||||
@@ -40,7 +43,10 @@ export function PolicyAuthSsoSection({
|
|||||||
rolesEditor,
|
rolesEditor,
|
||||||
usersEditor,
|
usersEditor,
|
||||||
disabled,
|
disabled,
|
||||||
idpDisabled
|
idpDisabled,
|
||||||
|
ssoLocked,
|
||||||
|
title,
|
||||||
|
description
|
||||||
}: PolicyAuthSsoSectionProps) {
|
}: PolicyAuthSsoSectionProps) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const [showIdpSelect, setShowIdpSelect] = useState(skipToIdpId != null);
|
const [showIdpSelect, setShowIdpSelect] = useState(skipToIdpId != null);
|
||||||
@@ -52,22 +58,34 @@ export function PolicyAuthSsoSection({
|
|||||||
}, [skipToIdpId]);
|
}, [skipToIdpId]);
|
||||||
|
|
||||||
const idpSelectDisabled = idpDisabled ?? disabled;
|
const idpSelectDisabled = idpDisabled ?? disabled;
|
||||||
|
const ssoActive = ssoLocked || sso;
|
||||||
|
const ssoTitle = title ?? t("policyAuthSsoTitle");
|
||||||
|
const ssoDescription = description ?? t("policyAuthSsoDescription");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsFormGrid>
|
<SettingsFormGrid>
|
||||||
<SettingsFormCell span="full">
|
{!ssoLocked && (
|
||||||
<SwitchInput
|
<SettingsFormCell span="full">
|
||||||
id="policy-auth-sso"
|
<SwitchInput
|
||||||
label={t("policyAuthSsoTitle")}
|
id="policy-auth-sso"
|
||||||
description={t("policyAuthSsoDescription")}
|
label={ssoTitle}
|
||||||
checked={sso}
|
description={ssoDescription}
|
||||||
disabled={disabled}
|
checked={ssoActive}
|
||||||
onCheckedChange={onSsoChange}
|
disabled={disabled}
|
||||||
/>
|
onCheckedChange={onSsoChange}
|
||||||
</SettingsFormCell>
|
/>
|
||||||
|
</SettingsFormCell>
|
||||||
|
)}
|
||||||
|
|
||||||
{sso && (
|
{ssoActive && (
|
||||||
<>
|
<>
|
||||||
|
{ssoLocked && ssoDescription && (
|
||||||
|
<SettingsFormCell span="full">
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{ssoDescription}
|
||||||
|
</p>
|
||||||
|
</SettingsFormCell>
|
||||||
|
)}
|
||||||
<SettingsFormCell span="full">
|
<SettingsFormCell span="full">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("roles")}</FormLabel>
|
<FormLabel>{t("roles")}</FormLabel>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from "@app/components/roles-selector";
|
} from "@app/components/roles-selector";
|
||||||
import { UsersSelector } from "@app/components/users-selector";
|
import { UsersSelector } from "@app/components/users-selector";
|
||||||
import { Button } from "@app/components/ui/button";
|
import { Button } from "@app/components/ui/button";
|
||||||
|
import { Alert, AlertDescription } from "@app/components/ui/alert";
|
||||||
import { Form, FormField } from "@app/components/ui/form";
|
import { Form, FormField } from "@app/components/ui/form";
|
||||||
import { toast } from "@app/hooks/useToast";
|
import { toast } from "@app/hooks/useToast";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
@@ -28,8 +29,10 @@ import type { GetResourcePolicyResponse } from "@server/routers/policy";
|
|||||||
import { UserType } from "@server/types/UserTypes";
|
import { UserType } from "@server/types/UserTypes";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import type { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
|
import { ExternalLink, InfoIcon } from "lucide-react";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { toUnicode } from "punycode";
|
||||||
import {
|
import {
|
||||||
useActionState,
|
useActionState,
|
||||||
useContext,
|
useContext,
|
||||||
@@ -108,9 +111,21 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
const resourceContext = useContext(ResourceContext);
|
const resourceContext = useContext(ResourceContext);
|
||||||
const api = createApiClient(useEnvContext());
|
const api = createApiClient(useEnvContext());
|
||||||
|
|
||||||
|
const isInferenceResource = resourceContext?.resource.mode === "inference";
|
||||||
const isResourceOverlay = resourceId !== undefined;
|
const isResourceOverlay = resourceId !== undefined;
|
||||||
const authReadonly = readonly || isResourceOverlay;
|
const authReadonly = readonly || isResourceOverlay;
|
||||||
|
|
||||||
|
const inferenceResourceUrl = useMemo(() => {
|
||||||
|
if (!isInferenceResource || !resourceContext?.resource) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { ssl, fullDomain } = resourceContext.resource;
|
||||||
|
if (!fullDomain) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return `${ssl ? "https" : "http"}://${toUnicode(fullDomain)}`;
|
||||||
|
}, [isInferenceResource, resourceContext?.resource]);
|
||||||
|
|
||||||
const policyRoleItems = useMemo<OverlaySelectedRole[]>(
|
const policyRoleItems = useMemo<OverlaySelectedRole[]>(
|
||||||
() =>
|
() =>
|
||||||
policy.roles.map((r) => ({
|
policy.roles.map((r) => ({
|
||||||
@@ -264,6 +279,12 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
const overlayRoles = combinedRoles.filter((r) => !r.isAdmin);
|
const overlayRoles = combinedRoles.filter((r) => !r.isAdmin);
|
||||||
const overlayUsers = combinedUsers;
|
const overlayUsers = combinedUsers;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isInferenceResource && !form.getValues("sso")) {
|
||||||
|
form.setValue("sso", true);
|
||||||
|
}
|
||||||
|
}, [isInferenceResource, form]);
|
||||||
|
|
||||||
const [, formAction, isSubmitting] = useActionState(onSubmit, null);
|
const [, formAction, isSubmitting] = useActionState(onSubmit, null);
|
||||||
const [isSavingOverlay, setIsSavingOverlay] = useState(false);
|
const [isSavingOverlay, setIsSavingOverlay] = useState(false);
|
||||||
|
|
||||||
@@ -294,7 +315,7 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
.put(
|
.put(
|
||||||
`/resource-policy/${policy.resourcePolicyId}/access-control`,
|
`/resource-policy/${policy.resourcePolicyId}/access-control`,
|
||||||
{
|
{
|
||||||
sso: payload.sso,
|
sso: isInferenceResource ? true : payload.sso,
|
||||||
userIds: payload.users.map((user) => user.id),
|
userIds: payload.users.map((user) => user.id),
|
||||||
roleIds: payload.roles.map((role) => Number(role.id)),
|
roleIds: payload.roles.map((role) => Number(role.id)),
|
||||||
skipToIdpId: payload.skipToIdpId
|
skipToIdpId: payload.skipToIdpId
|
||||||
@@ -302,94 +323,101 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
)
|
)
|
||||||
.catch(handleError)
|
.catch(handleError)
|
||||||
);
|
);
|
||||||
|
policyUpdates.sso = isInferenceResource ? true : payload.sso;
|
||||||
|
|
||||||
|
if (!isInferenceResource) {
|
||||||
|
if (passcodeActive && payload.password?.password) {
|
||||||
|
requests.push(
|
||||||
|
api
|
||||||
|
.put(
|
||||||
|
`/resource-policy/${policy.resourcePolicyId}/password`,
|
||||||
|
{ password: payload.password.password }
|
||||||
|
)
|
||||||
|
.catch(handleError)
|
||||||
|
);
|
||||||
|
policyUpdates.passwordId = policy.passwordId ?? -1;
|
||||||
|
} else if (!passcodeActive && passcodeOnServerRef.current) {
|
||||||
|
requests.push(
|
||||||
|
api
|
||||||
|
.put(
|
||||||
|
`/resource-policy/${policy.resourcePolicyId}/password`,
|
||||||
|
{ password: null }
|
||||||
|
)
|
||||||
|
.catch(handleError)
|
||||||
|
);
|
||||||
|
policyUpdates.passwordId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinActive && payload.pincode?.pincode?.length === 6) {
|
||||||
|
requests.push(
|
||||||
|
api
|
||||||
|
.put(
|
||||||
|
`/resource-policy/${policy.resourcePolicyId}/pincode`,
|
||||||
|
{ pincode: payload.pincode.pincode }
|
||||||
|
)
|
||||||
|
.catch(handleError)
|
||||||
|
);
|
||||||
|
policyUpdates.pincodeId = policy.pincodeId ?? -1;
|
||||||
|
} else if (!pinActive && pincodeOnServerRef.current) {
|
||||||
|
requests.push(
|
||||||
|
api
|
||||||
|
.put(
|
||||||
|
`/resource-policy/${policy.resourcePolicyId}/pincode`,
|
||||||
|
{ pincode: null }
|
||||||
|
)
|
||||||
|
.catch(handleError)
|
||||||
|
);
|
||||||
|
policyUpdates.pincodeId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
headerAuthActive &&
|
||||||
|
payload.headerAuth?.user &&
|
||||||
|
payload.headerAuth?.password
|
||||||
|
) {
|
||||||
|
requests.push(
|
||||||
|
api
|
||||||
|
.put(
|
||||||
|
`/resource-policy/${policy.resourcePolicyId}/header-auth`,
|
||||||
|
{ headerAuth: payload.headerAuth }
|
||||||
|
)
|
||||||
|
.catch(handleError)
|
||||||
|
);
|
||||||
|
policyUpdates.headerAuth = {
|
||||||
|
id: policy.headerAuth?.id ?? -1,
|
||||||
|
extendedCompability:
|
||||||
|
payload.headerAuth.extendedCompatibility ?? true
|
||||||
|
};
|
||||||
|
} else if (!headerAuthActive && headerAuthOnServerRef.current) {
|
||||||
|
requests.push(
|
||||||
|
api
|
||||||
|
.put(
|
||||||
|
`/resource-policy/${policy.resourcePolicyId}/header-auth`,
|
||||||
|
{ headerAuth: null }
|
||||||
|
)
|
||||||
|
.catch(handleError)
|
||||||
|
);
|
||||||
|
policyUpdates.headerAuth = {
|
||||||
|
id: null,
|
||||||
|
extendedCompability: null
|
||||||
|
} as unknown as GetResourcePolicyResponse["headerAuth"];
|
||||||
|
}
|
||||||
|
|
||||||
if (passcodeActive && payload.password?.password) {
|
|
||||||
requests.push(
|
requests.push(
|
||||||
api
|
api
|
||||||
.put(
|
.put(
|
||||||
`/resource-policy/${policy.resourcePolicyId}/password`,
|
`/resource-policy/${policy.resourcePolicyId}/whitelist`,
|
||||||
{ password: payload.password.password }
|
{
|
||||||
|
emailWhitelistEnabled:
|
||||||
|
payload.emailWhitelistEnabled,
|
||||||
|
emails: payload.emails?.map((e) => e.text) ?? []
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.catch(handleError)
|
.catch(handleError)
|
||||||
);
|
);
|
||||||
policyUpdates.passwordId = policy.passwordId ?? -1;
|
policyUpdates.emailWhitelistEnabled = payload.emailWhitelistEnabled;
|
||||||
} else if (!passcodeActive && passcodeOnServerRef.current) {
|
|
||||||
requests.push(
|
|
||||||
api
|
|
||||||
.put(
|
|
||||||
`/resource-policy/${policy.resourcePolicyId}/password`,
|
|
||||||
{ password: null }
|
|
||||||
)
|
|
||||||
.catch(handleError)
|
|
||||||
);
|
|
||||||
policyUpdates.passwordId = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pinActive && payload.pincode?.pincode?.length === 6) {
|
|
||||||
requests.push(
|
|
||||||
api
|
|
||||||
.put(
|
|
||||||
`/resource-policy/${policy.resourcePolicyId}/pincode`,
|
|
||||||
{ pincode: payload.pincode.pincode }
|
|
||||||
)
|
|
||||||
.catch(handleError)
|
|
||||||
);
|
|
||||||
policyUpdates.pincodeId = policy.pincodeId ?? -1;
|
|
||||||
} else if (!pinActive && pincodeOnServerRef.current) {
|
|
||||||
requests.push(
|
|
||||||
api
|
|
||||||
.put(
|
|
||||||
`/resource-policy/${policy.resourcePolicyId}/pincode`,
|
|
||||||
{ pincode: null }
|
|
||||||
)
|
|
||||||
.catch(handleError)
|
|
||||||
);
|
|
||||||
policyUpdates.pincodeId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
headerAuthActive &&
|
|
||||||
payload.headerAuth?.user &&
|
|
||||||
payload.headerAuth?.password
|
|
||||||
) {
|
|
||||||
requests.push(
|
|
||||||
api
|
|
||||||
.put(
|
|
||||||
`/resource-policy/${policy.resourcePolicyId}/header-auth`,
|
|
||||||
{ headerAuth: payload.headerAuth }
|
|
||||||
)
|
|
||||||
.catch(handleError)
|
|
||||||
);
|
|
||||||
policyUpdates.headerAuth = {
|
|
||||||
id: policy.headerAuth?.id ?? -1,
|
|
||||||
extendedCompability:
|
|
||||||
payload.headerAuth.extendedCompatibility ?? true
|
|
||||||
};
|
|
||||||
} else if (!headerAuthActive && headerAuthOnServerRef.current) {
|
|
||||||
requests.push(
|
|
||||||
api
|
|
||||||
.put(
|
|
||||||
`/resource-policy/${policy.resourcePolicyId}/header-auth`,
|
|
||||||
{ headerAuth: null }
|
|
||||||
)
|
|
||||||
.catch(handleError)
|
|
||||||
);
|
|
||||||
policyUpdates.headerAuth = {
|
|
||||||
id: null,
|
|
||||||
extendedCompability: null
|
|
||||||
} as unknown as GetResourcePolicyResponse["headerAuth"];
|
|
||||||
}
|
|
||||||
|
|
||||||
requests.push(
|
|
||||||
api
|
|
||||||
.put(`/resource-policy/${policy.resourcePolicyId}/whitelist`, {
|
|
||||||
emailWhitelistEnabled: payload.emailWhitelistEnabled,
|
|
||||||
emails: payload.emails?.map((e) => e.text) ?? []
|
|
||||||
})
|
|
||||||
.catch(handleError)
|
|
||||||
);
|
|
||||||
policyUpdates.emailWhitelistEnabled = payload.emailWhitelistEnabled;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const results = await Promise.all(requests);
|
const results = await Promise.all(requests);
|
||||||
if (results.every((res) => res && res.status === 200)) {
|
if (results.every((res) => res && res.status === 200)) {
|
||||||
@@ -411,13 +439,17 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
|
|
||||||
updatePolicy(policyUpdates);
|
updatePolicy(policyUpdates);
|
||||||
|
|
||||||
resourceContext?.updateAuthInfo({
|
resourceContext?.updateAuthInfo(
|
||||||
sso: payload.sso,
|
isInferenceResource
|
||||||
whitelist: payload.emailWhitelistEnabled,
|
? { sso: true }
|
||||||
password: passcodeOnServerRef.current,
|
: {
|
||||||
pincode: pincodeOnServerRef.current,
|
sso: payload.sso,
|
||||||
headerAuth: headerAuthOnServerRef.current
|
whitelist: payload.emailWhitelistEnabled,
|
||||||
});
|
password: passcodeOnServerRef.current,
|
||||||
|
pincode: pincodeOnServerRef.current,
|
||||||
|
headerAuth: headerAuthOnServerRef.current
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t("success"),
|
title: t("success"),
|
||||||
@@ -514,19 +546,53 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
{t("policyAuthStackTitle")}
|
{t("policyAuthStackTitle")}
|
||||||
</SettingsSectionTitle>
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
{t("policyAuthStackDescription")}
|
{isInferenceResource
|
||||||
|
? t("policyAuthInferenceStackDescription")
|
||||||
|
: t("policyAuthStackDescription")}
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
{isResourceOverlay && (
|
{isResourceOverlay && (
|
||||||
<SharedPolicyResourceNotice section="authentication" />
|
<SharedPolicyResourceNotice section="authentication" />
|
||||||
)}
|
)}
|
||||||
|
{isInferenceResource && (
|
||||||
|
<Alert variant="neutral">
|
||||||
|
<InfoIcon className="h-4 w-4" />
|
||||||
|
<AlertDescription>
|
||||||
|
{inferenceResourceUrl
|
||||||
|
? t.rich(
|
||||||
|
"policyAuthInferenceIdentityKeyHelp",
|
||||||
|
{
|
||||||
|
resourceLink: () => (
|
||||||
|
<a
|
||||||
|
href={
|
||||||
|
inferenceResourceUrl
|
||||||
|
}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-primary hover:underline"
|
||||||
|
>
|
||||||
|
{inferenceResourceUrl}
|
||||||
|
<ExternalLink className="ml-1 inline size-3.5 shrink-0 align-text-bottom" />
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
: t(
|
||||||
|
"policyAuthInferenceIdentityKeyHelpNoUrl"
|
||||||
|
)}
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
<SettingsSectionForm variant="half">
|
<SettingsSectionForm variant="half">
|
||||||
<PolicyAuthSsoSection
|
<PolicyAuthSsoSection
|
||||||
sso={Boolean(sso)}
|
sso={Boolean(sso) || isInferenceResource}
|
||||||
onSsoChange={(active) =>
|
onSsoChange={(active) => {
|
||||||
form.setValue("sso", active)
|
if (isInferenceResource) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
form.setValue("sso", active);
|
||||||
|
}}
|
||||||
skipToIdpId={skipToIdpId}
|
skipToIdpId={skipToIdpId}
|
||||||
onSkipToIdpChange={(id) =>
|
onSkipToIdpChange={(id) =>
|
||||||
form.setValue("skipToIdpId", id)
|
form.setValue("skipToIdpId", id)
|
||||||
@@ -534,6 +600,12 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
allIdps={allIdps}
|
allIdps={allIdps}
|
||||||
disabled={authReadonly}
|
disabled={authReadonly}
|
||||||
idpDisabled={authReadonly}
|
idpDisabled={authReadonly}
|
||||||
|
ssoLocked={isInferenceResource}
|
||||||
|
description={
|
||||||
|
isInferenceResource
|
||||||
|
? t("policyAuthInferenceSsoDescription")
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
rolesEditor={
|
rolesEditor={
|
||||||
isResourceOverlay ? (
|
isResourceOverlay ? (
|
||||||
<RolesSelector
|
<RolesSelector
|
||||||
@@ -605,100 +677,132 @@ export function PolicyAuthStackSectionEdit({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PolicyAuthOtherMethodsSection
|
{!isInferenceResource && (
|
||||||
pinActive={pinActive}
|
<PolicyAuthOtherMethodsSection
|
||||||
passcodeActive={passcodeActive}
|
pinActive={pinActive}
|
||||||
emailWhitelistEnabled={Boolean(
|
passcodeActive={passcodeActive}
|
||||||
emailWhitelistEnabled
|
emailWhitelistEnabled={Boolean(
|
||||||
)}
|
emailWhitelistEnabled
|
||||||
headerAuthActive={headerAuthActive}
|
)}
|
||||||
headerAuthUser={headerAuth?.user ?? ""}
|
headerAuthActive={headerAuthActive}
|
||||||
emailCount={emails.length}
|
headerAuthUser={headerAuth?.user ?? ""}
|
||||||
emailEnabled={emailEnabled}
|
emailCount={emails.length}
|
||||||
disabled={authReadonly}
|
emailEnabled={emailEnabled}
|
||||||
onConfigure={openMethodEditor}
|
disabled={authReadonly}
|
||||||
onTogglePincode={(active) =>
|
onConfigure={openMethodEditor}
|
||||||
handleToggle("pincode", active, () => {
|
onTogglePincode={(active) =>
|
||||||
setPinActive(false);
|
handleToggle("pincode", active, () => {
|
||||||
form.setValue("pincode", null);
|
setPinActive(false);
|
||||||
})
|
form.setValue("pincode", null);
|
||||||
}
|
})
|
||||||
onTogglePasscode={(active) =>
|
}
|
||||||
handleToggle("passcode", active, () => {
|
onTogglePasscode={(active) =>
|
||||||
setPasscodeActive(false);
|
handleToggle("passcode", active, () => {
|
||||||
form.setValue("password", null);
|
setPasscodeActive(false);
|
||||||
})
|
form.setValue("password", null);
|
||||||
}
|
})
|
||||||
onToggleEmail={(active) =>
|
}
|
||||||
handleToggle("email", active, () =>
|
onToggleEmail={(active) =>
|
||||||
form.setValue(
|
handleToggle("email", active, () =>
|
||||||
"emailWhitelistEnabled",
|
form.setValue(
|
||||||
false
|
"emailWhitelistEnabled",
|
||||||
|
false
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
onToggleHeaderAuth={(active) =>
|
||||||
onToggleHeaderAuth={(active) =>
|
handleToggle(
|
||||||
handleToggle("headerAuth", active, () => {
|
"headerAuth",
|
||||||
setHeaderAuthActive(false);
|
active,
|
||||||
form.setValue("headerAuth", null);
|
() => {
|
||||||
})
|
setHeaderAuthActive(false);
|
||||||
}
|
form.setValue(
|
||||||
/>
|
"headerAuth",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
|
|
||||||
<PincodeCredenza
|
{!isInferenceResource && (
|
||||||
open={editingMethod === "pincode"}
|
<>
|
||||||
onOpenChange={(open) => !open && closeCredenza()}
|
<PincodeCredenza
|
||||||
defaultPincode={pincode?.pincode ?? ""}
|
open={editingMethod === "pincode"}
|
||||||
onSave={(value) => {
|
onOpenChange={(open) =>
|
||||||
form.setValue("pincode", { pincode: value });
|
!open && closeCredenza()
|
||||||
setPinActive(true);
|
}
|
||||||
}}
|
defaultPincode={pincode?.pincode ?? ""}
|
||||||
/>
|
onSave={(value) => {
|
||||||
|
form.setValue("pincode", {
|
||||||
|
pincode: value
|
||||||
|
});
|
||||||
|
setPinActive(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<PasscodeCredenza
|
<PasscodeCredenza
|
||||||
open={editingMethod === "passcode"}
|
open={editingMethod === "passcode"}
|
||||||
onOpenChange={(open) => !open && closeCredenza()}
|
onOpenChange={(open) =>
|
||||||
defaultPassword={password?.password ?? ""}
|
!open && closeCredenza()
|
||||||
existingConfigured={Boolean(policy.passwordId)}
|
}
|
||||||
onSave={(value) => {
|
defaultPassword={password?.password ?? ""}
|
||||||
form.setValue("password", { password: value });
|
existingConfigured={Boolean(
|
||||||
setPasscodeActive(true);
|
policy.passwordId
|
||||||
}}
|
)}
|
||||||
/>
|
onSave={(value) => {
|
||||||
|
form.setValue("password", {
|
||||||
|
password: value
|
||||||
|
});
|
||||||
|
setPasscodeActive(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<EmailCredenza
|
<EmailCredenza
|
||||||
open={editingMethod === "email"}
|
open={editingMethod === "email"}
|
||||||
onOpenChange={(open) => !open && closeCredenza()}
|
onOpenChange={(open) =>
|
||||||
emailEnabled={emailEnabled}
|
!open && closeCredenza()
|
||||||
disabled={authReadonly}
|
}
|
||||||
emails={emails}
|
emailEnabled={emailEnabled}
|
||||||
onSave={(value) => {
|
disabled={authReadonly}
|
||||||
form.setValue("emails", value);
|
emails={emails}
|
||||||
form.setValue("emailWhitelistEnabled", true);
|
onSave={(value) => {
|
||||||
}}
|
form.setValue("emails", value);
|
||||||
/>
|
form.setValue(
|
||||||
|
"emailWhitelistEnabled",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<HeaderAuthCredenza
|
<HeaderAuthCredenza
|
||||||
open={editingMethod === "headerAuth"}
|
open={editingMethod === "headerAuth"}
|
||||||
onOpenChange={(open) => !open && closeCredenza()}
|
onOpenChange={(open) =>
|
||||||
defaultValues={
|
!open && closeCredenza()
|
||||||
headerAuth
|
}
|
||||||
? {
|
defaultValues={
|
||||||
user: headerAuth.user,
|
headerAuth
|
||||||
password: headerAuth.password,
|
? {
|
||||||
extendedCompatibility:
|
user: headerAuth.user,
|
||||||
headerAuth.extendedCompatibility ??
|
password: headerAuth.password,
|
||||||
true
|
extendedCompatibility:
|
||||||
}
|
headerAuth.extendedCompatibility ??
|
||||||
: undefined
|
true
|
||||||
}
|
}
|
||||||
existingConfigured={Boolean(policy.headerAuth?.id)}
|
: undefined
|
||||||
onSave={(value) => {
|
}
|
||||||
form.setValue("headerAuth", value);
|
existingConfigured={Boolean(
|
||||||
setHeaderAuthActive(true);
|
policy.headerAuth?.id
|
||||||
}}
|
)}
|
||||||
/>
|
onSave={(value) => {
|
||||||
|
form.setValue("headerAuth", value);
|
||||||
|
setHeaderAuthActive(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
<SettingsSectionFooter>
|
<SettingsSectionFooter>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
Reference in New Issue
Block a user