mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-11 10:03:35 +00:00
first pass restyle of auth methods and rules
This commit is contained in:
310
src/components/resource-policy/PolicyAuthStackSectionCreate.tsx
Normal file
310
src/components/resource-policy/PolicyAuthStackSectionCreate.tsx
Normal file
@@ -0,0 +1,310 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
SettingsSection,
|
||||
SettingsSectionBody,
|
||||
SettingsSectionDescription,
|
||||
SettingsSectionHeader,
|
||||
SettingsSubsectionDescription,
|
||||
SettingsSubsectionHeader,
|
||||
SettingsSubsectionTitle,
|
||||
SettingsSectionTitle
|
||||
} from "@app/components/Settings";
|
||||
import { TagInput } from "@app/components/tags/tag-input";
|
||||
import { FormField } from "@app/components/ui/form";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useState } from "react";
|
||||
import { type UseFormReturn, useWatch } from "react-hook-form";
|
||||
import type { PolicyFormValues } from ".";
|
||||
import {
|
||||
EmailCredenza,
|
||||
HeaderAuthCredenza,
|
||||
PasscodeCredenza,
|
||||
PincodeCredenza
|
||||
} from "./PolicyAuthMethodCredenzas";
|
||||
import { PolicyAuthMethodRow } from "./PolicyAuthMethodRow";
|
||||
import { PolicyAuthSsoSection } from "./PolicyAuthSsoSection";
|
||||
import type { PolicyAuthMethodId } from "./policy-auth-method-id";
|
||||
import {
|
||||
getEmailWhitelistSummary,
|
||||
getHeaderAuthSummary,
|
||||
getPasscodeSummary,
|
||||
getPincodeSummary
|
||||
} from "./policy-auth-summaries";
|
||||
|
||||
export type PolicyAuthStackSectionCreateProps = {
|
||||
form: UseFormReturn<PolicyFormValues, any, any>;
|
||||
orgId: string;
|
||||
allIdps: { id: number; text: string }[];
|
||||
allRoles: { id: string; text: string }[];
|
||||
allUsers: { id: string; text: string }[];
|
||||
emailEnabled: boolean;
|
||||
};
|
||||
|
||||
export function PolicyAuthStackSectionCreate({
|
||||
form: parentForm,
|
||||
allIdps,
|
||||
allRoles,
|
||||
allUsers,
|
||||
emailEnabled
|
||||
}: PolicyAuthStackSectionCreateProps) {
|
||||
const t = useTranslations();
|
||||
const [editingMethod, setEditingMethod] =
|
||||
useState<PolicyAuthMethodId | null>(null);
|
||||
const [activeRolesTagIndex, setActiveRolesTagIndex] = useState<
|
||||
number | null
|
||||
>(null);
|
||||
const [activeUsersTagIndex, setActiveUsersTagIndex] = useState<
|
||||
number | null
|
||||
>(null);
|
||||
|
||||
const sso = useWatch({ control: parentForm.control, name: "sso" });
|
||||
const skipToIdpId = useWatch({
|
||||
control: parentForm.control,
|
||||
name: "skipToIdpId"
|
||||
});
|
||||
const password = useWatch({
|
||||
control: parentForm.control,
|
||||
name: "password"
|
||||
});
|
||||
const pincode = useWatch({ control: parentForm.control, name: "pincode" });
|
||||
const headerAuth = useWatch({
|
||||
control: parentForm.control,
|
||||
name: "headerAuth"
|
||||
});
|
||||
const emailWhitelistEnabled = useWatch({
|
||||
control: parentForm.control,
|
||||
name: "emailWhitelistEnabled"
|
||||
});
|
||||
const emails =
|
||||
useWatch({ control: parentForm.control, name: "emails" }) ?? [];
|
||||
|
||||
const passcodeActive = Boolean(password);
|
||||
const pinActive = Boolean(pincode);
|
||||
const headerAuthActive = Boolean(headerAuth);
|
||||
|
||||
const closeCredenza = () => setEditingMethod(null);
|
||||
|
||||
const handleToggle = (
|
||||
method: PolicyAuthMethodId,
|
||||
active: boolean,
|
||||
onDisable: () => void,
|
||||
onEnable?: () => void
|
||||
) => {
|
||||
if (active) {
|
||||
onEnable?.();
|
||||
setEditingMethod(method);
|
||||
return;
|
||||
}
|
||||
onDisable();
|
||||
setEditingMethod((current) => (current === method ? null : current));
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
{t("policyAuthStackTitle")}
|
||||
</SettingsSectionTitle>
|
||||
<SettingsSectionDescription>
|
||||
{t("policyAuthStackDescription")}
|
||||
</SettingsSectionDescription>
|
||||
</SettingsSectionHeader>
|
||||
<SettingsSectionBody>
|
||||
<div className="w-full md:w-1/2">
|
||||
<PolicyAuthSsoSection
|
||||
sso={Boolean(sso)}
|
||||
onSsoChange={(active) =>
|
||||
parentForm.setValue("sso", active)
|
||||
}
|
||||
skipToIdpId={skipToIdpId}
|
||||
onSkipToIdpChange={(id) =>
|
||||
parentForm.setValue("skipToIdpId", id)
|
||||
}
|
||||
allIdps={allIdps}
|
||||
rolesEditor={
|
||||
<FormField
|
||||
control={parentForm.control}
|
||||
name="roles"
|
||||
render={({ field }) => (
|
||||
<TagInput
|
||||
{...field}
|
||||
activeTagIndex={activeRolesTagIndex}
|
||||
setActiveTagIndex={
|
||||
setActiveRolesTagIndex
|
||||
}
|
||||
placeholder={t("accessRoleSelect2")}
|
||||
tags={field.value ?? []}
|
||||
setTags={(newRoles) =>
|
||||
field.onChange(newRoles)
|
||||
}
|
||||
autocompleteOptions={allRoles}
|
||||
allowDuplicates={false}
|
||||
size="sm"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
usersEditor={
|
||||
<FormField
|
||||
control={parentForm.control}
|
||||
name="users"
|
||||
render={({ field }) => (
|
||||
<TagInput
|
||||
{...field}
|
||||
activeTagIndex={activeUsersTagIndex}
|
||||
setActiveTagIndex={
|
||||
setActiveUsersTagIndex
|
||||
}
|
||||
placeholder={t("accessUserSelect")}
|
||||
tags={field.value ?? []}
|
||||
setTags={(newUsers) =>
|
||||
field.onChange(newUsers)
|
||||
}
|
||||
autocompleteOptions={allUsers}
|
||||
allowDuplicates={false}
|
||||
size="sm"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<SettingsSubsectionHeader>
|
||||
<SettingsSubsectionTitle>
|
||||
{t("policyAuthOtherMethodsTitle")}
|
||||
</SettingsSubsectionTitle>
|
||||
<SettingsSubsectionDescription>
|
||||
{t("policyAuthOtherMethodsDescription")}
|
||||
</SettingsSubsectionDescription>
|
||||
</SettingsSubsectionHeader>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
<PolicyAuthMethodRow
|
||||
id="pincode"
|
||||
title={t("policyAuthPincodeTitle")}
|
||||
description={t("policyAuthPincodeDescription")}
|
||||
summary={getPincodeSummary({ t })}
|
||||
active={pinActive}
|
||||
onConfigure={() => setEditingMethod("pincode")}
|
||||
onToggle={(active) =>
|
||||
handleToggle("pincode", active, () =>
|
||||
parentForm.setValue("pincode", null)
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<PolicyAuthMethodRow
|
||||
id="passcode"
|
||||
title={t("policyAuthPasscodeTitle")}
|
||||
description={t("policyAuthPasscodeDescription")}
|
||||
summary={getPasscodeSummary({ t })}
|
||||
active={passcodeActive}
|
||||
onConfigure={() => setEditingMethod("passcode")}
|
||||
onToggle={(active) =>
|
||||
handleToggle("passcode", active, () =>
|
||||
parentForm.setValue("password", null)
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<PolicyAuthMethodRow
|
||||
id="email"
|
||||
title={t("policyAuthEmailTitle")}
|
||||
description={t("policyAuthEmailDescription")}
|
||||
summary={getEmailWhitelistSummary({
|
||||
t,
|
||||
count: emails.length
|
||||
})}
|
||||
active={Boolean(emailWhitelistEnabled)}
|
||||
onConfigure={() => setEditingMethod("email")}
|
||||
onToggle={(active) =>
|
||||
handleToggle(
|
||||
"email",
|
||||
active,
|
||||
() =>
|
||||
parentForm.setValue(
|
||||
"emailWhitelistEnabled",
|
||||
false
|
||||
),
|
||||
() =>
|
||||
parentForm.setValue(
|
||||
"emailWhitelistEnabled",
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
disabled={!emailEnabled}
|
||||
/>
|
||||
|
||||
<PolicyAuthMethodRow
|
||||
id="header-auth"
|
||||
title={t("policyAuthHeaderAuthTitle")}
|
||||
description={t("policyAuthHeaderAuthDescription")}
|
||||
summary={getHeaderAuthSummary({
|
||||
t,
|
||||
headerName: headerAuth?.user ?? ""
|
||||
})}
|
||||
active={headerAuthActive}
|
||||
onConfigure={() => setEditingMethod("headerAuth")}
|
||||
onToggle={(active) =>
|
||||
handleToggle("headerAuth", active, () =>
|
||||
parentForm.setValue("headerAuth", null)
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<PincodeCredenza
|
||||
open={editingMethod === "pincode"}
|
||||
onOpenChange={(open) => !open && closeCredenza()}
|
||||
defaultPincode={pincode?.pincode ?? ""}
|
||||
onSave={(value) => {
|
||||
parentForm.setValue("pincode", { pincode: value });
|
||||
}}
|
||||
/>
|
||||
|
||||
<PasscodeCredenza
|
||||
open={editingMethod === "passcode"}
|
||||
onOpenChange={(open) => !open && closeCredenza()}
|
||||
defaultPassword={password?.password ?? ""}
|
||||
onSave={(value) => {
|
||||
parentForm.setValue("password", { password: value });
|
||||
}}
|
||||
/>
|
||||
|
||||
<EmailCredenza
|
||||
open={editingMethod === "email"}
|
||||
onOpenChange={(open) => !open && closeCredenza()}
|
||||
emailEnabled={emailEnabled}
|
||||
emails={emails}
|
||||
onEmailsChange={(value) =>
|
||||
parentForm.setValue(
|
||||
"emails",
|
||||
value as PolicyFormValues["emails"]
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<HeaderAuthCredenza
|
||||
open={editingMethod === "headerAuth"}
|
||||
onOpenChange={(open) => !open && closeCredenza()}
|
||||
defaultValues={
|
||||
headerAuth
|
||||
? {
|
||||
user: headerAuth.user,
|
||||
password: headerAuth.password,
|
||||
extendedCompatibility:
|
||||
headerAuth.extendedCompatibility
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onSave={(value) => {
|
||||
parentForm.setValue("headerAuth", value);
|
||||
}}
|
||||
/>
|
||||
</SettingsSectionBody>
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user