mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-07 03:06:40 +00:00
🚧 org settings form
This commit is contained in:
@@ -1853,6 +1853,8 @@
|
|||||||
"enableTwoFactorAuthentication": "Enable two-factor authentication",
|
"enableTwoFactorAuthentication": "Enable two-factor authentication",
|
||||||
"completeSecuritySteps": "Complete Security Steps",
|
"completeSecuritySteps": "Complete Security Steps",
|
||||||
"securitySettings": "Security Settings",
|
"securitySettings": "Security Settings",
|
||||||
|
"dangerSection": "Danger section",
|
||||||
|
"dangerSectionDescription": "Delete organization alongside all its sites, clients, resources, etc...",
|
||||||
"securitySettingsDescription": "Configure security policies for the organization",
|
"securitySettingsDescription": "Configure security policies for the organization",
|
||||||
"requireTwoFactorForAllUsers": "Require Two-Factor Authentication for All Users",
|
"requireTwoFactorForAllUsers": "Require Two-Factor Authentication for All Users",
|
||||||
"requireTwoFactorDescription": "When enabled, all internal users in this organization must have two-factor authentication enabled to access the organization.",
|
"requireTwoFactorDescription": "When enabled, all internal users in this organization must have two-factor authentication enabled to access the organization.",
|
||||||
@@ -2063,7 +2065,7 @@
|
|||||||
"request": "Request",
|
"request": "Request",
|
||||||
"requests": "Requests",
|
"requests": "Requests",
|
||||||
"logs": "Logs",
|
"logs": "Logs",
|
||||||
"logsSettingsDescription": "Monitor logs collected from this orginization",
|
"logsSettingsDescription": "Monitor logs collected from this organization",
|
||||||
"searchLogs": "Search logs...",
|
"searchLogs": "Search logs...",
|
||||||
"action": "Action",
|
"action": "Action",
|
||||||
"actor": "Actor",
|
"actor": "Actor",
|
||||||
|
|||||||
@@ -368,9 +368,9 @@ export default function GeneralPage() {
|
|||||||
/>
|
/>
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
</SettingsSection>
|
|
||||||
|
|
||||||
<SettingsSection>
|
<hr className="my-12 max-w-xl" />
|
||||||
|
|
||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
{t("logRetention")}
|
{t("logRetention")}
|
||||||
@@ -587,266 +587,258 @@ export default function GeneralPage() {
|
|||||||
)}
|
)}
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
</SettingsSection>
|
|
||||||
|
|
||||||
{build !== "oss" && (
|
{build !== "oss" && (
|
||||||
<SettingsSection>
|
<>
|
||||||
<SettingsSectionHeader>
|
<hr className="my-12 max-w-xl" />
|
||||||
<SettingsSectionTitle>
|
<SettingsSectionHeader>
|
||||||
{t("securitySettings")}
|
<SettingsSectionTitle>
|
||||||
</SettingsSectionTitle>
|
{t("securitySettings")}
|
||||||
<SettingsSectionDescription>
|
</SettingsSectionTitle>
|
||||||
{t("securitySettingsDescription")}
|
<SettingsSectionDescription>
|
||||||
</SettingsSectionDescription>
|
{t("securitySettingsDescription")}
|
||||||
</SettingsSectionHeader>
|
</SettingsSectionDescription>
|
||||||
<SettingsSectionBody>
|
</SettingsSectionHeader>
|
||||||
<SettingsSectionForm>
|
<SettingsSectionBody>
|
||||||
<SecurityFeaturesAlert />
|
<SettingsSectionForm className="mb-4">
|
||||||
<FormField
|
<SecurityFeaturesAlert />
|
||||||
control={form.control}
|
<FormField
|
||||||
name="requireTwoFactor"
|
control={form.control}
|
||||||
render={({ field }) => {
|
name="requireTwoFactor"
|
||||||
const isDisabled =
|
render={({ field }) => {
|
||||||
isSecurityFeatureDisabled();
|
const isDisabled =
|
||||||
|
isSecurityFeatureDisabled();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormItem className="col-span-2">
|
<FormItem className="col-span-2">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
<FormControl>
|
||||||
|
<SwitchInput
|
||||||
|
id="require-two-factor"
|
||||||
|
defaultChecked={
|
||||||
|
field.value ||
|
||||||
|
false
|
||||||
|
}
|
||||||
|
label={t(
|
||||||
|
"requireTwoFactorForAllUsers"
|
||||||
|
)}
|
||||||
|
disabled={
|
||||||
|
isDisabled
|
||||||
|
}
|
||||||
|
onCheckedChange={(
|
||||||
|
val
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
!isDisabled
|
||||||
|
) {
|
||||||
|
form.setValue(
|
||||||
|
"requireTwoFactor",
|
||||||
|
val
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
<FormMessage />
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"requireTwoFactorDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="maxSessionLengthHours"
|
||||||
|
render={({ field }) => {
|
||||||
|
const isDisabled =
|
||||||
|
isSecurityFeatureDisabled();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormItem className="col-span-2">
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"maxSessionLength"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<SwitchInput
|
<Select
|
||||||
id="require-two-factor"
|
value={
|
||||||
defaultChecked={
|
field.value?.toString() ||
|
||||||
field.value ||
|
"null"
|
||||||
false
|
|
||||||
}
|
}
|
||||||
label={t(
|
onValueChange={(
|
||||||
"requireTwoFactorForAllUsers"
|
value
|
||||||
)}
|
|
||||||
disabled={
|
|
||||||
isDisabled
|
|
||||||
}
|
|
||||||
onCheckedChange={(
|
|
||||||
val
|
|
||||||
) => {
|
) => {
|
||||||
if (
|
if (
|
||||||
!isDisabled
|
!isDisabled
|
||||||
) {
|
) {
|
||||||
|
const numValue =
|
||||||
|
value ===
|
||||||
|
"null"
|
||||||
|
? null
|
||||||
|
: parseInt(
|
||||||
|
value,
|
||||||
|
10
|
||||||
|
);
|
||||||
form.setValue(
|
form.setValue(
|
||||||
"requireTwoFactor",
|
"maxSessionLengthHours",
|
||||||
val
|
numValue
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
disabled={
|
||||||
|
isDisabled
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={t(
|
||||||
|
"selectSessionLength"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{SESSION_LENGTH_OPTIONS.map(
|
||||||
|
(
|
||||||
|
option
|
||||||
|
) => (
|
||||||
|
<SelectItem
|
||||||
|
key={
|
||||||
|
option.value ===
|
||||||
|
null
|
||||||
|
? "null"
|
||||||
|
: option.value.toString()
|
||||||
|
}
|
||||||
|
value={
|
||||||
|
option.value ===
|
||||||
|
null
|
||||||
|
? "null"
|
||||||
|
: option.value.toString()
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t(
|
||||||
|
option.labelKey
|
||||||
|
)}
|
||||||
|
</SelectItem>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
|
||||||
<FormMessage />
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"requireTwoFactorDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="maxSessionLengthHours"
|
|
||||||
render={({ field }) => {
|
|
||||||
const isDisabled =
|
|
||||||
isSecurityFeatureDisabled();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormItem className="col-span-2">
|
|
||||||
<FormLabel>
|
|
||||||
{t("maxSessionLength")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Select
|
|
||||||
value={
|
|
||||||
field.value?.toString() ||
|
|
||||||
"null"
|
|
||||||
}
|
|
||||||
onValueChange={(
|
|
||||||
value
|
|
||||||
) => {
|
|
||||||
if (
|
|
||||||
!isDisabled
|
|
||||||
) {
|
|
||||||
const numValue =
|
|
||||||
value ===
|
|
||||||
"null"
|
|
||||||
? null
|
|
||||||
: parseInt(
|
|
||||||
value,
|
|
||||||
10
|
|
||||||
);
|
|
||||||
form.setValue(
|
|
||||||
"maxSessionLengthHours",
|
|
||||||
numValue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disabled={
|
|
||||||
isDisabled
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue
|
|
||||||
placeholder={t(
|
|
||||||
"selectSessionLength"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{SESSION_LENGTH_OPTIONS.map(
|
|
||||||
(
|
|
||||||
option
|
|
||||||
) => (
|
|
||||||
<SelectItem
|
|
||||||
key={
|
|
||||||
option.value ===
|
|
||||||
null
|
|
||||||
? "null"
|
|
||||||
: option.value.toString()
|
|
||||||
}
|
|
||||||
value={
|
|
||||||
option.value ===
|
|
||||||
null
|
|
||||||
? "null"
|
|
||||||
: option.value.toString()
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{t(
|
|
||||||
option.labelKey
|
|
||||||
)}
|
|
||||||
</SelectItem>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"maxSessionLengthDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="passwordExpiryDays"
|
|
||||||
render={({ field }) => {
|
|
||||||
const isDisabled =
|
|
||||||
isSecurityFeatureDisabled();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormItem className="col-span-2">
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"passwordExpiryDays"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Select
|
|
||||||
value={
|
|
||||||
field.value?.toString() ||
|
|
||||||
"null"
|
|
||||||
}
|
|
||||||
onValueChange={(
|
|
||||||
value
|
|
||||||
) => {
|
|
||||||
if (
|
|
||||||
!isDisabled
|
|
||||||
) {
|
|
||||||
const numValue =
|
|
||||||
value ===
|
|
||||||
"null"
|
|
||||||
? null
|
|
||||||
: parseInt(
|
|
||||||
value,
|
|
||||||
10
|
|
||||||
);
|
|
||||||
form.setValue(
|
|
||||||
"passwordExpiryDays",
|
|
||||||
numValue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disabled={
|
|
||||||
isDisabled
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue
|
|
||||||
placeholder={t(
|
|
||||||
"selectPasswordExpiry"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{PASSWORD_EXPIRY_OPTIONS.map(
|
|
||||||
(
|
|
||||||
option
|
|
||||||
) => (
|
|
||||||
<SelectItem
|
|
||||||
key={
|
|
||||||
option.value ===
|
|
||||||
null
|
|
||||||
? "null"
|
|
||||||
: option.value.toString()
|
|
||||||
}
|
|
||||||
value={
|
|
||||||
option.value ===
|
|
||||||
null
|
|
||||||
? "null"
|
|
||||||
: option.value.toString()
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{t(
|
|
||||||
option.labelKey
|
|
||||||
)}
|
|
||||||
</SelectItem>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
{t(
|
<FormDescription>
|
||||||
"editPasswordExpiryDescription"
|
{t(
|
||||||
)}
|
"maxSessionLengthDescription"
|
||||||
</FormDescription>
|
)}
|
||||||
</FormItem>
|
</FormDescription>
|
||||||
);
|
</FormItem>
|
||||||
}}
|
);
|
||||||
/>
|
}}
|
||||||
</SettingsSectionForm>
|
/>
|
||||||
</SettingsSectionBody>
|
<FormField
|
||||||
</SettingsSection>
|
control={form.control}
|
||||||
)}
|
name="passwordExpiryDays"
|
||||||
|
render={({ field }) => {
|
||||||
|
const isDisabled =
|
||||||
|
isSecurityFeatureDisabled();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormItem className="col-span-2">
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"passwordExpiryDays"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Select
|
||||||
|
value={
|
||||||
|
field.value?.toString() ||
|
||||||
|
"null"
|
||||||
|
}
|
||||||
|
onValueChange={(
|
||||||
|
value
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
!isDisabled
|
||||||
|
) {
|
||||||
|
const numValue =
|
||||||
|
value ===
|
||||||
|
"null"
|
||||||
|
? null
|
||||||
|
: parseInt(
|
||||||
|
value,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
form.setValue(
|
||||||
|
"passwordExpiryDays",
|
||||||
|
numValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={
|
||||||
|
isDisabled
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={t(
|
||||||
|
"selectPasswordExpiry"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{PASSWORD_EXPIRY_OPTIONS.map(
|
||||||
|
(
|
||||||
|
option
|
||||||
|
) => (
|
||||||
|
<SelectItem
|
||||||
|
key={
|
||||||
|
option.value ===
|
||||||
|
null
|
||||||
|
? "null"
|
||||||
|
: option.value.toString()
|
||||||
|
}
|
||||||
|
value={
|
||||||
|
option.value ===
|
||||||
|
null
|
||||||
|
? "null"
|
||||||
|
: option.value.toString()
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t(
|
||||||
|
option.labelKey
|
||||||
|
)}
|
||||||
|
</SelectItem>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
{t(
|
||||||
|
"editPasswordExpiryDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SettingsSectionForm>
|
||||||
|
</SettingsSectionBody>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</SettingsSection>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
{build === "saas" && <AuthPageSettings ref={authPageSettingsRef} />}
|
{build === "saas" && <AuthPageSettings ref={authPageSettingsRef} />}
|
||||||
|
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
{build !== "saas" && (
|
|
||||||
<Button
|
|
||||||
variant="destructive"
|
|
||||||
onClick={() => setIsDeleteModalOpen(true)}
|
|
||||||
className="flex items-center gap-2"
|
|
||||||
loading={loadingDelete}
|
|
||||||
disabled={loadingDelete}
|
|
||||||
>
|
|
||||||
{t("orgDelete")}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
form="org-settings-form"
|
form="org-settings-form"
|
||||||
@@ -856,6 +848,30 @@ export default function GeneralPage() {
|
|||||||
{t("saveSettings")}
|
{t("saveSettings")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{build !== "saas" && (
|
||||||
|
<SettingsSection>
|
||||||
|
<SettingsSectionHeader>
|
||||||
|
<SettingsSectionTitle>
|
||||||
|
{t("dangerSection")}
|
||||||
|
</SettingsSectionTitle>
|
||||||
|
<SettingsSectionDescription>
|
||||||
|
{t("dangerSectionDescription")}
|
||||||
|
</SettingsSectionDescription>
|
||||||
|
</SettingsSectionHeader>
|
||||||
|
<div className="flex justify-start gap-2">
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
onClick={() => setIsDeleteModalOpen(true)}
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
loading={loadingDelete}
|
||||||
|
disabled={loadingDelete}
|
||||||
|
>
|
||||||
|
{t("orgDelete")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</SettingsSection>
|
||||||
|
)}
|
||||||
</SettingsContainer>
|
</SettingsContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user