+
@@ -915,19 +238,180 @@ function GeneralSectionForm() {
);
}
-function LogRetentionSectionForm() {
- const { org } = useOrgContext();
+function GeneralSectionForm({ org }: SectionFormProps) {
const form = useForm({
- resolver: zodResolver(GeneralFormSchema),
+ resolver: zodResolver(
+ GeneralFormSchema.pick({
+ name: true,
+ subnet: true
+ })
+ ),
defaultValues: {
- name: org?.org.name
+ name: org.name,
+ subnet: org.subnet || "" // Add default value for subnet
},
mode: "onChange"
});
const t = useTranslations();
- const subscription = useSubscriptionStatusContext();
- const { isUnlocked } = useLicenseStatusContext();
- const { isPaidUser } = usePaidStatus();
+ const router = useRouter();
+
+ const [, formAction, loadingSave] = useActionState(performSave, null);
+ const api = createApiClient(useEnvContext());
+
+ async function performSave() {
+ const isValid = await form.trigger();
+ if (!isValid) return;
+
+ const data = form.getValues();
+
+ try {
+ const reqData = {
+ name: data.name
+ } as any;
+
+ // Update organization
+ await api.post(`/org/${org.orgId}`, reqData);
+
+ toast({
+ title: t("orgUpdated"),
+ description: t("orgUpdatedDescription")
+ });
+ router.refresh();
+ } catch (e) {
+ toast({
+ variant: "destructive",
+ title: t("orgErrorUpdate"),
+ description: formatAxiosError(e, t("orgErrorUpdateMessage"))
+ });
+ }
+ }
+
+ return (
+
+
+ {t("general")}
+
+ {t("orgGeneralSettingsDescription")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function LogRetentionSectionForm({ org }: SectionFormProps) {
+ const form = useForm({
+ resolver: zodResolver(
+ GeneralFormSchema.pick({
+ settingsLogRetentionDaysRequest: true,
+ settingsLogRetentionDaysAccess: true,
+ settingsLogRetentionDaysAction: true
+ })
+ ),
+ defaultValues: {
+ settingsLogRetentionDaysRequest:
+ org.settingsLogRetentionDaysRequest ?? 15,
+ settingsLogRetentionDaysAccess:
+ org.settingsLogRetentionDaysAccess ?? 15,
+ settingsLogRetentionDaysAction:
+ org.settingsLogRetentionDaysAction ?? 15
+ },
+ mode: "onChange"
+ });
+
+ const router = useRouter();
+ const t = useTranslations();
+ const { isPaidUser, hasSaasSubscription } = usePaidStatus();
+
+ const [, formAction, loadingSave] = useActionState(performSave, null);
+ const api = createApiClient(useEnvContext());
+
+ async function performSave() {
+ const isValid = await form.trigger();
+ if (!isValid) return;
+
+ const data = form.getValues();
+
+ try {
+ const reqData = {
+ settingsLogRetentionDaysRequest:
+ data.settingsLogRetentionDaysRequest,
+ settingsLogRetentionDaysAccess:
+ data.settingsLogRetentionDaysAccess,
+ settingsLogRetentionDaysAction:
+ data.settingsLogRetentionDaysAction
+ } as any;
+
+ // Update organization
+ await api.post(`/org/${org.orgId}`, reqData);
+
+ toast({
+ title: t("orgUpdated"),
+ description: t("orgUpdatedDescription")
+ });
+ router.refresh();
+ } catch (e) {
+ toast({
+ variant: "destructive",
+ title: t("orgErrorUpdate"),
+ description: formatAxiosError(e, t("orgErrorUpdateMessage"))
+ });
+ }
+ }
return (
@@ -939,421 +423,566 @@ function LogRetentionSectionForm() {
- (
-
-
- {t("logRetentionRequestLabel")}
-
-
-
-
-
-
- )}
- />
-
- {build != "oss" && (
- <>
-
-
- {
- const isDisabled =
- (build == "saas" &&
- !subscription?.subscribed) ||
- (build == "enterprise" &&
- !isUnlocked());
-
- return (
-
-
- {t("logRetentionAccessLabel")}
-
-
-
-
-
-
- );
- }}
- />
- {
- const isDisabled =
- (build == "saas" &&
- !subscription?.subscribed) ||
- (build == "enterprise" &&
- !isUnlocked());
-
- return (
-
-
- {t("logRetentionActionLabel")}
-
-
-
-
-
-
- );
- }}
+ ).map((option) => (
+
+ {t(option.label)}
+
+ ))}
+
+
+
+
+
+ )}
/>
- >
- )}
+
+ {build !== "oss" && (
+ <>
+
+
+ {
+ const isDisabled = !isPaidUser;
+
+ return (
+
+
+ {t(
+ "logRetentionAccessLabel"
+ )}
+
+
+
+
+
+
+ );
+ }}
+ />
+ {
+ const isDisabled = !isPaidUser;
+
+ return (
+
+
+ {t(
+ "logRetentionActionLabel"
+ )}
+
+
+
+
+
+
+ );
+ }}
+ />
+ >
+ )}
+
+
+
+
+
+
);
}
-function SectionForm() {
- const { org } = useOrgContext();
+function SecuritySettingsSectionForm({ org }: SectionFormProps) {
+ const router = useRouter();
const form = useForm({
- resolver: zodResolver(GeneralFormSchema),
+ resolver: zodResolver(
+ GeneralFormSchema.pick({
+ requireTwoFactor: true,
+ maxSessionLengthHours: true,
+ passwordExpiryDays: true
+ })
+ ),
defaultValues: {
- name: org?.org.name
+ requireTwoFactor: org.requireTwoFactor || false,
+ maxSessionLengthHours: org.maxSessionLengthHours || null,
+ passwordExpiryDays: org.passwordExpiryDays || null
},
mode: "onChange"
});
const t = useTranslations();
- const subscription = useSubscriptionStatusContext();
- const { isUnlocked } = useLicenseStatusContext();
const { isPaidUser } = usePaidStatus();
- return (
-
- {build !== "oss" && (
- <>
-
-
-
- {t("securitySettings")}
-
-
- {t("securitySettingsDescription")}
-
-
-
-
-
- {
- const isDisabled =
- isSecurityFeatureDisabled();
+ // Track initial security policy values
+ const initialSecurityValues = {
+ requireTwoFactor: org.requireTwoFactor || false,
+ maxSessionLengthHours: org.maxSessionLengthHours || null,
+ passwordExpiryDays: org.passwordExpiryDays || null
+ };
- return (
-
-
+ const [isSecurityPolicyConfirmOpen, setIsSecurityPolicyConfirmOpen] =
+ useState(false);
+
+ // 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
+ );
+ };
+
+ const [, formAction, loadingSave] = useActionState(onSubmit, null);
+ const api = createApiClient(useEnvContext());
+
+ const formRef = useRef
>(null);
+
+ async function onSubmit() {
+ // Check if security policies have changed
+ if (hasSecurityPolicyChanged()) {
+ setIsSecurityPolicyConfirmOpen(true);
+ return;
+ }
+
+ await performSave();
+ }
+
+ async function performSave() {
+ const isValid = await form.trigger();
+ if (!isValid) return;
+
+ const data = form.getValues();
+
+ try {
+ const reqData = {
+ requireTwoFactor: data.requireTwoFactor || false,
+ maxSessionLengthHours: data.maxSessionLengthHours,
+ passwordExpiryDays: data.passwordExpiryDays
+ } as any;
+
+ // Update organization
+ await api.post(`/org/${org.orgId}`, reqData);
+
+ toast({
+ title: t("orgUpdated"),
+ description: t("orgUpdatedDescription")
+ });
+ router.refresh();
+ } catch (e) {
+ toast({
+ variant: "destructive",
+ title: t("orgErrorUpdate"),
+ description: formatAxiosError(e, t("orgErrorUpdateMessage"))
+ });
+ }
+ }
+
+ return (
+ <>
+
+ {t("securityPolicyChangeDescription")}
+
+ }
+ buttonText={t("saveSettings")}
+ onConfirm={performSave}
+ string={t("securityPolicyChangeConfirmMessage")}
+ title={t("securityPolicyChangeWarning")}
+ warningText={t("securityPolicyChangeWarningText")}
+ />
+
+
+
+ {t("securitySettings")}
+
+
+ {t("securitySettingsDescription")}
+
+
+
+
+
-