Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 90 additions & 4 deletions src/modules/settings/AuthenticationTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ export default function AuthenticationTab({ account }: Readonly<Props>) {
peerInactivityExpirationEnabled,
setPeerInactivityExpirationEnabled,
peerInactivityExpiresIn,
setPeerInactivityExpiresIn,
peerInactivityExpireInterval,
setPeerInactivityExpireInterval,
] = useExpirationState({
enabled: account.settings.peer_inactivity_expiration_enabled,
expirationInSeconds: account.settings.peer_inactivity_expiration || 600,
expirationInSeconds: account.settings.peer_inactivity_expiration ?? 600,
timeRange: ["minutes", "hours", "days"],
});

Expand All @@ -129,6 +131,18 @@ export default function AuthenticationTab({ account }: Readonly<Props>) {
isLocalMFAEnabled,
]);

// An empty/cleared input converts to NaN; block saving until it's a
// positive number so the API never receives an invalid duration.
const inactivityExpirationSeconds = convertToSeconds(
peerInactivityExpiresIn,
peerInactivityExpireInterval,
);
const isInactivityExpirationInvalid =
loginExpiration &&
peerInactivityExpirationEnabled &&
(!Number.isFinite(inactivityExpirationSeconds) ||
inactivityExpirationSeconds <= 0);

const saveChanges = async () => {
const expiration = convertToSeconds(expiresIn, expireInterval);

Expand All @@ -145,7 +159,9 @@ export default function AuthenticationTab({ account }: Readonly<Props>) {
peer_inactivity_expiration_enabled: loginExpiration
? peerInactivityExpirationEnabled
: false,
peer_inactivity_expiration: 600,
peer_inactivity_expiration: peerInactivityExpirationEnabled
? inactivityExpirationSeconds
: account.settings.peer_inactivity_expiration ?? 600,
extra: {
...account.settings?.extra,
peer_approval_enabled: isAnyIntegrationEnabled
Expand Down Expand Up @@ -219,7 +235,11 @@ export default function AuthenticationTab({ account }: Readonly<Props>) {

<Button
variant={"primary"}
disabled={!hasChanges || !permission.settings.update}
disabled={
!hasChanges ||
!permission.settings.update ||
isInactivityExpirationInvalid
}
onClick={saveChanges}
data-testid={"save-authentication-settings"}
>
Expand Down Expand Up @@ -412,10 +432,76 @@ export default function AuthenticationTab({ account }: Readonly<Props>) {
helpText={
<>
Enable to require authentication after users disconnect from
management for 10 minutes.
management for the configured period of time.
</>
}
/>
<div
className={cn(
"flex justify-between gap-10",
!peerInactivityExpirationEnabled &&
"opacity-50 pointer-events-none",
)}
>
<div className={"w-full"}>
<Label>Inactivity Expiration</Label>
<HelpText>
Time a peer can stay disconnected from management before
re-authentication is required.
</HelpText>
</div>
<div className={"w-full flex gap-3"}>
<Input
placeholder={"10"}
maxWidthClass={"min-w-[100px]"}
min={1}
disabled={
!loginExpiration ||
!peerInactivityExpirationEnabled ||
!permission.settings.update
}
data-testid={"peer-inactivity-expiration-input"}
className={"w-full"}
value={peerInactivityExpiresIn}
type={"number"}
onChange={(e) => setPeerInactivityExpiresIn(e.target.value)}
/>
<Select
disabled={
!loginExpiration ||
!peerInactivityExpirationEnabled ||
!permission.settings.update
}
value={peerInactivityExpireInterval}
onValueChange={(v) => setPeerInactivityExpireInterval(v)}
>
<SelectTrigger
className="w-full"
data-testid={"peer-inactivity-expiration-select"}
>
<div className={"flex items-center gap-3"}>
<CalendarClock
size={15}
className={"text-nb-gray-300"}
/>
<SelectValue
placeholder="Select interval..."
data-testid={
"peer-inactivity-expiration-select-value"
}
/>
</div>
</SelectTrigger>
<SelectContent
data-testid={"peer-inactivity-expiration-select-content"}
>
<SelectItem value="days">Days</SelectItem>
<SelectItem value="hours">Hours</SelectItem>
<SelectItem value="minutes">Minutes</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
</div>
</div>
Expand Down
Loading