option to disable the session timeout

This commit is contained in:
Jarek Krochmalski committed 2026-08-27 07:34:37 +02:00
1 parent ef390e94ec
commit b04bc504f9
5 files changed
+109 -17

No files matched your search

+8 -4
View File
@@ -42,8 +42,9 @@ export const GET: RequestHandler = async ({ cookies }) => {
/**
* @openapi
* summary: Update the global authentication settings (enabling auth requires at least one admin/user to exist)
* body: {authEnabled:boolean, defaultProvider:string}
* body-example: {"authEnabled":true,"defaultProvider":"local"}
* description: sessionTimeout is in seconds (clamped 3600..604800); 0 disables expiry so sessions never time out.
* body: {authEnabled:boolean, defaultProvider:string, sessionTimeout:integer}
* body-example: {"authEnabled":true,"defaultProvider":"local","sessionTimeout":86400}
* resp-200: {authEnabled:boolean!, defaultProvider:string}
* resp-400: Cannot enable authentication without an existing user/admin (response includes requiresUser:true)
* resp-401: Authentication required (auth is enabled and the caller is not authenticated)
@@ -82,9 +83,12 @@ export const PUT: RequestHandler = async ({ request, cookies }) => {
}
}
// Enforce minimum session timeout of 1 hour
// 0 means "never expire" (#1302); otherwise enforce 1 hour .. 7 days.
if (data.sessionTimeout !== undefined) {
data.sessionTimeout = Math.max(3600, Math.min(604800, parseInt(data.sessionTimeout) || 86400));
const parsed = parseInt(data.sessionTimeout);
data.sessionTimeout = parsed === 0
? 0
: Math.max(3600, Math.min(604800, parsed || 86400));
}
const settings = await updateAuthSettings(data);
+18 -4
View File
@@ -16,7 +16,7 @@
RefreshCw,
Save
} from 'lucide-svelte';
import { TogglePill } from '$lib/components/ui/toggle-pill';
import { TogglePill, ToggleGroup } from '$lib/components/ui/toggle-pill';
import { canAccess, authStore } from '$lib/stores/auth';
import { licenseStore } from '$lib/stores/license';
@@ -48,6 +48,7 @@
let authEnabled = $state(false);
let authLoading = $state(true);
let sessionTimeout = $state(86400);
let neverExpire = $state(false);
let authSaving = $state(false);
// Roles state (shared with sub-tabs that need it)
@@ -61,6 +62,8 @@
if (response.ok) {
const data = await response.json();
authEnabled = data.authEnabled;
// 0 is the "never expire" sentinel; keep the last real timeout for the input.
neverExpire = data.sessionTimeout === 0;
sessionTimeout = data.sessionTimeout || 86400;
}
} catch (error) {
@@ -116,7 +119,7 @@
const response = await fetch('/api/auth/settings', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionTimeout: sessionTimeout })
body: JSON.stringify({ sessionTimeout: neverExpire ? 0 : sessionTimeout })
});
if (response.ok) {
toast.success('Settings saved');
@@ -256,8 +259,19 @@
<div class="space-y-1.5">
<Label class="text-sm">Session timeout</Label>
<p class="text-xs text-muted-foreground mb-2">
How long until inactive sessions expire
How long a session stays valid after sign-in
</p>
<div class="flex items-center gap-2 mb-2">
<ToggleGroup
value={neverExpire ? 'never' : 'timed'}
options={[{ value: 'timed', label: 'Timed' }, { value: 'never', label: 'Never expire' }]}
onchange={(v) => neverExpire = v === 'never'}
disabled={!$canAccess('settings', 'edit')}
/>
<span class="text-xs text-muted-foreground">
{neverExpire ? 'Sessions stay signed in until logout' : 'Sessions expire after the timeout below'}
</span>
</div>
<div class="flex items-center gap-2">
<Input
type="number"
@@ -270,7 +284,7 @@
e.currentTarget.value = String(sessionTimeout);
}}
class="w-32"
disabled={!$canAccess('settings', 'edit')}
disabled={neverExpire || !$canAccess('settings', 'edit')}
/>
<span class="text-sm text-muted-foreground">seconds</span>
<span class="text-xs text-muted-foreground">