This commit is contained in:
Fred KISSIE
2026-03-11 00:27:27 +01:00
parent 8a39b3fd45
commit f80e212b07
13 changed files with 156 additions and 618 deletions

View File

@@ -73,7 +73,11 @@ const setHeaderAuthSchema = z.object({
extendedCompatibility: z.boolean()
});
export function EditPolicyAuthMethodsSectionForm() {
export function EditPolicyAuthMethodsSectionForm({
readonly
}: {
readonly?: boolean;
}) {
const { policy } = useResourcePolicyContext();
const router = useRouter();
@@ -132,6 +136,7 @@ export function EditPolicyAuthMethodsSectionForm() {
const [, formAction, isSubmitting] = useActionState(onSubmit, null);
async function onSubmit() {
if (readonly) return;
const isValid = await form.trigger();
if (!isValid) return;
@@ -237,14 +242,16 @@ export function EditPolicyAuthMethodsSectionForm() {
</SettingsSectionDescription>
</SettingsSectionHeader>
<SettingsSectionBody>
<Button
type="button"
variant="outline"
onClick={() => setIsExpanded(true)}
>
<Plus className="mr-2 h-4 w-4" />
{t("resourcePolicyAuthMethodAdd")}
</Button>
{!readonly && (
<Button
type="button"
variant="outline"
onClick={() => setIsExpanded(true)}
>
<Plus className="mr-2 h-4 w-4" />
{t("resourcePolicyAuthMethodAdd")}
</Button>
)}
</SettingsSectionBody>
</SettingsSection>
);
@@ -541,6 +548,7 @@ export function EditPolicyAuthMethodsSectionForm() {
type="button"
variant="secondary"
size="sm"
disabled={readonly}
onClick={
hasPassword
? () =>
@@ -579,6 +587,7 @@ export function EditPolicyAuthMethodsSectionForm() {
type="button"
variant="secondary"
size="sm"
disabled={readonly}
onClick={
hasPincode
? () =>
@@ -619,6 +628,7 @@ export function EditPolicyAuthMethodsSectionForm() {
type="button"
variant="secondary"
size="sm"
disabled={readonly}
onClick={
hasHeaderAuth
? () =>
@@ -644,7 +654,7 @@ export function EditPolicyAuthMethodsSectionForm() {
<Button
type="submit"
loading={isSubmitting}
disabled={isSubmitting}
disabled={readonly || isSubmitting}
>
{t("authMethodsSave")}
</Button>

View File

@@ -28,9 +28,13 @@ import { EditPolicyRulesSectionForm } from "./EditPolicyRulesSectionForm";
export type EditPolicyFormProps = {
hidePolicyNameForm?: boolean;
readonly?: boolean;
};
export function EditPolicyForm({ hidePolicyNameForm }: EditPolicyFormProps) {
export function EditPolicyForm({
hidePolicyNameForm,
readonly
}: EditPolicyFormProps) {
const { org } = useOrgContext();
const t = useTranslations();
const { env } = useEnvContext();
@@ -100,23 +104,26 @@ export function EditPolicyForm({ hidePolicyNameForm }: EditPolicyFormProps) {
return (
<SettingsContainer>
{!hidePolicyNameForm && <EditPolicyNameSectionForm />}
{!hidePolicyNameForm && <EditPolicyNameSectionForm readonly={readonly} />}
<EditPolicyUsersRolesSectionForm
allRoles={allRoles}
allUsers={allUsers}
allIdps={allIdps}
readonly={readonly}
/>
<EditPolicyAuthMethodsSectionForm />
<EditPolicyAuthMethodsSectionForm readonly={readonly} />
<EditPolicyOtpEmailSectionForm
emailEnabled={env.email.emailEnabled}
readonly={readonly}
/>
<EditPolicyRulesSectionForm
isMaxmindAvailable={isMaxmindAvailable}
isMaxmindAsnAvailable={isMaxmindASNAvailable}
readonly={readonly}
/>
</SettingsContainer>
);

View File

@@ -40,7 +40,7 @@ import { useForm } from "react-hook-form";
// ─── PolicyNameSection ──────────────────────────────────────────────────
export function EditPolicyNameSectionForm() {
export function EditPolicyNameSectionForm({ readonly }: { readonly?: boolean }) {
const t = useTranslations();
const api = createApiClient(useEnvContext());
const router = useRouter();
@@ -61,6 +61,7 @@ export function EditPolicyNameSectionForm() {
const [, formAction, isSubmitting] = useActionState(onSubmit, null);
async function onSubmit() {
if (readonly) return;
const isValid = await form.trigger();
if (!isValid) return;
@@ -125,6 +126,7 @@ export function EditPolicyNameSectionForm() {
<FormControl>
<Input
{...field}
disabled={readonly}
placeholder={t(
"resourcePolicyNamePlaceholder"
)}
@@ -141,7 +143,7 @@ export function EditPolicyNameSectionForm() {
<Button
type="submit"
loading={isSubmitting}
disabled={isSubmitting}
disabled={readonly || isSubmitting}
>
{t("saveSettings")}
</Button>

View File

@@ -46,10 +46,12 @@ import { useResourcePolicyContext } from "@app/providers/ResourcePolicyProvider"
type PolicyOtpEmailSectionProps = {
emailEnabled: boolean;
readonly?: boolean;
};
export function EditPolicyOtpEmailSectionForm({
emailEnabled
emailEnabled,
readonly
}: PolicyOtpEmailSectionProps) {
const t = useTranslations();
@@ -87,6 +89,7 @@ export function EditPolicyOtpEmailSectionForm({
const [, formAction, isSubmitting] = useActionState(onSubmit, null);
async function onSubmit() {
if (readonly) return;
const isValid = await form.trigger();
if (!isValid) return;
@@ -141,14 +144,16 @@ export function EditPolicyOtpEmailSectionForm({
</SettingsSectionDescription>
</SettingsSectionHeader>
<SettingsSectionBody>
<Button
type="button"
variant="outline"
onClick={() => setIsExpanded(true)}
>
<Plus className="mr-2 h-4 w-4" />
{t("resourcePolicyOtpEmailAdd")}
</Button>
{!readonly && (
<Button
type="button"
variant="outline"
onClick={() => setIsExpanded(true)}
>
<Plus className="mr-2 h-4 w-4" />
{t("resourcePolicyOtpEmailAdd")}
</Button>
)}
</SettingsSectionBody>
</SettingsSection>
);
@@ -186,7 +191,7 @@ export function EditPolicyOtpEmailSectionForm({
onCheckedChange={(val) => {
form.setValue("emailWhitelistEnabled", val);
}}
disabled={!emailEnabled}
disabled={readonly || !emailEnabled}
/>
{whitelistEnabled && emailEnabled && (
@@ -268,7 +273,9 @@ export function EditPolicyOtpEmailSectionForm({
<Button
type="submit"
loading={isSubmitting}
disabled={isSubmitting || !emailEnabled}
disabled={
readonly || isSubmitting || !emailEnabled
}
>
{t("otpEmailWhitelistSave")}
</Button>

View File

@@ -108,11 +108,13 @@ type LocalRule = {
type PolicyRulesSectionProps = {
isMaxmindAvailable: boolean;
isMaxmindAsnAvailable: boolean;
readonly?: boolean;
};
export function EditPolicyRulesSectionForm({
isMaxmindAvailable,
isMaxmindAsnAvailable
isMaxmindAsnAvailable,
readonly
}: PolicyRulesSectionProps) {
const t = useTranslations();
@@ -331,6 +333,7 @@ export function EditPolicyRulesSectionForm({
defaultValue={row.original.priority}
className="w-[75px]"
type="number"
disabled={readonly}
onClick={(e) => e.currentTarget.focus()}
onBlur={(e) => {
const parsed = z.coerce
@@ -361,6 +364,7 @@ export function EditPolicyRulesSectionForm({
cell: ({ row }) => (
<Select
defaultValue={row.original.action}
disabled={readonly}
onValueChange={(value: "ACCEPT" | "DROP" | "PASS") =>
updateRule(row.original.ruleId, { action: value })
}
@@ -390,6 +394,7 @@ export function EditPolicyRulesSectionForm({
cell: ({ row }) => (
<Select
defaultValue={row.original.match}
disabled={readonly}
onValueChange={(
value: "CIDR" | "IP" | "PATH" | "COUNTRY" | "ASN"
) =>
@@ -439,6 +444,7 @@ export function EditPolicyRulesSectionForm({
<Button
variant="outline"
role="combobox"
disabled={readonly}
className="min-w-50 justify-between"
>
{row.original.value
@@ -494,6 +500,7 @@ export function EditPolicyRulesSectionForm({
<Button
variant="outline"
role="combobox"
disabled={readonly}
className="min-w-50 justify-between"
>
{row.original.value
@@ -579,6 +586,7 @@ export function EditPolicyRulesSectionForm({
<Input
defaultValue={row.original.value}
className="min-w-50"
disabled={readonly}
onBlur={(e) =>
updateRule(row.original.ruleId, {
value: e.target.value
@@ -593,6 +601,7 @@ export function EditPolicyRulesSectionForm({
cell: ({ row }) => (
<Switch
defaultChecked={row.original.enabled}
disabled={readonly}
onCheckedChange={(val) =>
updateRule(row.original.ruleId, { enabled: val })
}
@@ -606,6 +615,7 @@ export function EditPolicyRulesSectionForm({
<div className="flex items-center space-x-2">
<Button
variant="outline"
disabled={readonly}
onClick={() => removeRule(row.original.ruleId)}
>
{t("delete")}
@@ -621,7 +631,8 @@ export function EditPolicyRulesSectionForm({
isMaxmindAvailable,
isMaxmindAsnAvailable,
updateRule,
removeRule
removeRule,
readonly
]
);
@@ -638,6 +649,8 @@ export function EditPolicyRulesSectionForm({
const [isPending, startTransition] = useTransition();
async function saveRules() {
if (readonly) return;
const isValid = form.trigger();
if (!isValid) return;
@@ -688,14 +701,16 @@ export function EditPolicyRulesSectionForm({
</SettingsSectionDescription>
</SettingsSectionHeader>
<SettingsSectionBody>
<Button
type="button"
variant="outline"
onClick={() => setIsExpanded(true)}
>
<Plus className="mr-2 h-4 w-4" />
{t("resourcePolicyRulesAdd")}
</Button>
{!readonly && (
<Button
type="button"
variant="outline"
onClick={() => setIsExpanded(true)}
>
<Plus className="mr-2 h-4 w-4" />
{t("resourcePolicyRulesAdd")}
</Button>
)}
</SettingsSectionBody>
</SettingsSection>
);
@@ -721,6 +736,7 @@ export function EditPolicyRulesSectionForm({
onCheckedChange={(val) => {
form.setValue("applyRules", val);
}}
disabled={readonly}
/>
</div>
@@ -741,6 +757,7 @@ export function EditPolicyRulesSectionForm({
<FormControl>
<Select
value={field.value}
disabled={readonly || !rulesEnabled}
onValueChange={
field.onChange
}
@@ -776,6 +793,7 @@ export function EditPolicyRulesSectionForm({
<FormControl>
<Select
value={field.value}
disabled={readonly || !rulesEnabled}
onValueChange={
field.onChange
}
@@ -842,6 +860,7 @@ export function EditPolicyRulesSectionForm({
<Button
variant="outline"
role="combobox"
disabled={readonly || !rulesEnabled}
aria-expanded={
openAddRuleCountrySelect
}
@@ -931,6 +950,7 @@ export function EditPolicyRulesSectionForm({
<Button
variant="outline"
role="combobox"
disabled={readonly || !rulesEnabled}
aria-expanded={
openAddRuleAsnSelect
}
@@ -1043,7 +1063,7 @@ export function EditPolicyRulesSectionForm({
</PopoverContent>
</Popover>
) : (
<Input {...field} />
<Input {...field} disabled={readonly || !rulesEnabled} />
)}
</FormControl>
<FormMessage />
@@ -1053,7 +1073,7 @@ export function EditPolicyRulesSectionForm({
<Button
type="submit"
variant="outline"
disabled={!rulesEnabled}
disabled={readonly || !rulesEnabled}
>
{t("ruleSubmit")}
</Button>
@@ -1134,7 +1154,7 @@ export function EditPolicyRulesSectionForm({
<Button
onClick={() => startTransition(() => saveRules())}
loading={isPending}
disabled={isPending}
disabled={readonly || isPending}
>
{t("rulesSave")}
</Button>

View File

@@ -53,12 +53,14 @@ type PolicyUsersRolesSectionProps = {
allRoles: { id: string; text: string }[];
allUsers: { id: string; text: string }[];
allIdps: { id: number; text: string }[];
readonly?: boolean;
};
export function EditPolicyUsersRolesSectionForm({
allRoles,
allUsers,
allIdps
allIdps,
readonly
}: PolicyUsersRolesSectionProps) {
const t = useTranslations();
@@ -106,6 +108,8 @@ export function EditPolicyUsersRolesSectionForm({
const [, formAction, isSubmitting] = useActionState(onSubmit, null);
async function onSubmit() {
if (readonly) return;
const isValid = await form.trigger();
if (!isValid) return;
@@ -172,6 +176,7 @@ export function EditPolicyUsersRolesSectionForm({
console.log(`form.setValue("sso", ${val})`);
form.setValue("sso", val);
}}
disabled={readonly}
/>
{ssoEnabled && (
@@ -221,6 +226,7 @@ export function EditPolicyUsersRolesSectionForm({
true
}
sortTags={true}
disabled={readonly}
/>
</FormControl>
<FormMessage />
@@ -277,6 +283,7 @@ export function EditPolicyUsersRolesSectionForm({
true
}
sortTags={true}
disabled={readonly}
/>
</FormControl>
<FormMessage />
@@ -292,6 +299,7 @@ export function EditPolicyUsersRolesSectionForm({
{t("defaultIdentityProvider")}
</label>
<Select
disabled={readonly}
onValueChange={(value) => {
if (value === "none") {
form.setValue(
@@ -347,7 +355,7 @@ export function EditPolicyUsersRolesSectionForm({
<Button
type="submit"
loading={isSubmitting}
disabled={isSubmitting}
disabled={readonly || isSubmitting}
>
{t("resourceUsersRolesSubmit")}
</Button>