mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-28 22:00:51 +00:00
add confirm dialog to update security settings
This commit is contained in:
@@ -1774,6 +1774,10 @@
|
||||
"180Days": "180 days",
|
||||
"1Year": "1 year",
|
||||
"subscriptionBadge": "Subscription Required",
|
||||
"securityPolicyChangeWarning": "Security Policy Change Warning",
|
||||
"securityPolicyChangeDescription": "You are about to change security policy settings. After saving, you may need to reauthenticate to comply with these policy updates. All users who are not compliant will also need to reauthenticate.",
|
||||
"securityPolicyChangeConfirmMessage": "I confirm",
|
||||
"securityPolicyChangeWarningText": "This will affect all users in the organization",
|
||||
"authPageErrorUpdateMessage": "An error occurred while updating the auth page settings",
|
||||
"authPageUpdated": "Auth page updated successfully",
|
||||
"healthCheckNotAvailable": "Local",
|
||||
|
||||
@@ -86,20 +86,6 @@ export async function updateOrg(
|
||||
parsedBody.data.passwordExpiryDays = undefined;
|
||||
}
|
||||
|
||||
if (
|
||||
req.user &&
|
||||
req.user.type === UserType.Internal &&
|
||||
parsedBody.data.requireTwoFactor === true &&
|
||||
!req.user.twoFactorEnabled
|
||||
) {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.FORBIDDEN,
|
||||
"You must enable two-factor authentication for your account before enforcing it for all users"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const updatedOrg = await db
|
||||
.update(orgs)
|
||||
.set({
|
||||
|
||||
@@ -108,6 +108,7 @@ export default function GeneralPage() {
|
||||
|
||||
const [loadingDelete, setLoadingDelete] = useState(false);
|
||||
const [loadingSave, setLoadingSave] = useState(false);
|
||||
const [isSecurityPolicyConfirmOpen, setIsSecurityPolicyConfirmOpen] = useState(false);
|
||||
const authPageSettingsRef = useRef<AuthPageSettingsRef>(null);
|
||||
|
||||
const form = useForm({
|
||||
@@ -122,6 +123,23 @@ export default function GeneralPage() {
|
||||
mode: "onChange"
|
||||
});
|
||||
|
||||
// Track initial security policy values
|
||||
const initialSecurityValues = {
|
||||
requireTwoFactor: org?.org.requireTwoFactor || false,
|
||||
maxSessionLengthHours: org?.org.maxSessionLengthHours || null,
|
||||
passwordExpiryDays: org?.org.passwordExpiryDays || null
|
||||
};
|
||||
|
||||
// Check if security policies have changed
|
||||
const hasSecurityPolicyChanged = () => {
|
||||
const currentValues = form.getValues();
|
||||
return (
|
||||
currentValues.requireTwoFactor !== initialSecurityValues.requireTwoFactor ||
|
||||
currentValues.maxSessionLengthHours !== initialSecurityValues.maxSessionLengthHours ||
|
||||
currentValues.passwordExpiryDays !== initialSecurityValues.passwordExpiryDays
|
||||
);
|
||||
};
|
||||
|
||||
async function deleteOrg() {
|
||||
setLoadingDelete(true);
|
||||
try {
|
||||
@@ -174,6 +192,16 @@ export default function GeneralPage() {
|
||||
}
|
||||
|
||||
async function onSubmit(data: GeneralFormValues) {
|
||||
// Check if security policies have changed
|
||||
if (hasSecurityPolicyChanged()) {
|
||||
setIsSecurityPolicyConfirmOpen(true);
|
||||
return;
|
||||
}
|
||||
|
||||
await performSave(data);
|
||||
}
|
||||
|
||||
async function performSave(data: GeneralFormValues) {
|
||||
setLoadingSave(true);
|
||||
|
||||
try {
|
||||
@@ -231,6 +259,20 @@ export default function GeneralPage() {
|
||||
string={org?.org.name || ""}
|
||||
title={t("orgDelete")}
|
||||
/>
|
||||
<ConfirmDeleteDialog
|
||||
open={isSecurityPolicyConfirmOpen}
|
||||
setOpen={setIsSecurityPolicyConfirmOpen}
|
||||
dialog={
|
||||
<div>
|
||||
<p>{t("securityPolicyChangeDescription")}</p>
|
||||
</div>
|
||||
}
|
||||
buttonText={t("saveSettings")}
|
||||
onConfirm={() => performSave(form.getValues())}
|
||||
string={t("securityPolicyChangeConfirmMessage")}
|
||||
title={t("securityPolicyChangeWarning")}
|
||||
warningText={t("securityPolicyChangeWarningText")}
|
||||
/>
|
||||
<SettingsSection>
|
||||
<SettingsSectionHeader>
|
||||
<SettingsSectionTitle>
|
||||
|
||||
@@ -54,6 +54,7 @@ type InviteUserFormProps = {
|
||||
dialog: React.ReactNode;
|
||||
buttonText: string;
|
||||
onConfirm: () => Promise<void>;
|
||||
warningText?: string;
|
||||
};
|
||||
|
||||
export default function InviteUserForm({
|
||||
@@ -63,7 +64,8 @@ export default function InviteUserForm({
|
||||
title,
|
||||
onConfirm,
|
||||
buttonText,
|
||||
dialog
|
||||
dialog,
|
||||
warningText
|
||||
}: InviteUserFormProps) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
@@ -86,13 +88,20 @@ export default function InviteUserForm({
|
||||
|
||||
function reset() {
|
||||
form.reset();
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
async function onSubmit(values: z.infer<typeof formSchema>) {
|
||||
setLoading(true);
|
||||
await onConfirm();
|
||||
reset();
|
||||
try {
|
||||
await onConfirm();
|
||||
setOpen(false);
|
||||
reset();
|
||||
} catch (error) {
|
||||
// Handle error if needed
|
||||
console.error("Confirmation failed:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -111,8 +120,8 @@ export default function InviteUserForm({
|
||||
<CredenzaBody>
|
||||
<div className="mb-4 break-all overflow-hidden">
|
||||
{dialog}
|
||||
<div className="mt-2 mb-6 font-bold text-red-700">
|
||||
{t("cannotbeUndone")}
|
||||
<div className="mt-2 mb-6 font-bold text-destructive">
|
||||
{warningText || t("cannotbeUndone")}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user