Validates session on app mount by calling GET /api/auth/session instead of relying solely on cached sessionStorage. This ensures the UI state always reflects server reality — expired or revoked sessions are detected immediately. Changes: - Backend: Add GET /api/auth/session endpoint (requires valid session, returns 200/401) - Frontend: Add useSessionValidation hook for mount-time validation - Frontend: Add SessionValidationLoading component for validation spinner - Frontend: Update AuthProvider to call validation on mount with loading state - Frontend: Add validateSession API function - Docs: Update Features.md with session validation behavior - Docs: Update Web-Development.md with session validation pattern Handles three outcomes: 1. Valid session (200): Proceed with cached state 2. Invalid session (401): Clear sessionStorage and redirect to login 3. Network error: Don't logout (backend may be temporarily unreachable) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
138 lines
6.4 KiB
TypeScript
138 lines
6.4 KiB
TypeScript
/**
|
|
* API endpoint path constants.
|
|
*
|
|
* Every backend path used by the frontend is defined here.
|
|
* Components and API modules import from this file rather than
|
|
* hard-coding URL strings, so renaming an endpoint requires only one change.
|
|
*/
|
|
|
|
export const ENDPOINTS = {
|
|
// -------------------------------------------------------------------------
|
|
// Health
|
|
// -------------------------------------------------------------------------
|
|
health: "/health",
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Setup wizard
|
|
// -------------------------------------------------------------------------
|
|
setup: "/setup",
|
|
setupTimezone: "/setup/timezone",
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Authentication
|
|
// -------------------------------------------------------------------------
|
|
authLogin: "/auth/login",
|
|
authLogout: "/auth/logout",
|
|
authSession: "/auth/session",
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Dashboard
|
|
// -------------------------------------------------------------------------
|
|
dashboardStatus: "/dashboard/status",
|
|
dashboardBans: "/dashboard/bans",
|
|
dashboardBansByCountry: "/dashboard/bans/by-country",
|
|
dashboardBansTrend: "/dashboard/bans/trend",
|
|
dashboardBansByJail: "/dashboard/bans/by-jail",
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Jails
|
|
// -------------------------------------------------------------------------
|
|
jails: "/jails",
|
|
jail: (name: string): string => `/jails/${encodeURIComponent(name)}`,
|
|
jailBanned: (name: string): string => `/jails/${encodeURIComponent(name)}/banned`,
|
|
jailStart: (name: string): string => `/jails/${encodeURIComponent(name)}/start`,
|
|
jailStop: (name: string): string => `/jails/${encodeURIComponent(name)}/stop`,
|
|
jailIdle: (name: string): string => `/jails/${encodeURIComponent(name)}/idle`,
|
|
jailReload: (name: string): string => `/jails/${encodeURIComponent(name)}/reload`,
|
|
jailsReloadAll: "/jails/reload-all",
|
|
jailIgnoreIp: (name: string): string => `/jails/${encodeURIComponent(name)}/ignoreip`,
|
|
jailIgnoreSelf: (name: string): string => `/jails/${encodeURIComponent(name)}/ignoreself`,
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Bans
|
|
// -------------------------------------------------------------------------
|
|
bans: "/bans",
|
|
bansActive: "/bans/active",
|
|
bansAll: "/bans/all",
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Geo / IP lookup
|
|
// -------------------------------------------------------------------------
|
|
geoLookup: (ip: string): string => `/geo/lookup/${encodeURIComponent(ip)}`,
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Configuration
|
|
// -------------------------------------------------------------------------
|
|
configJails: "/config/jails",
|
|
configJailsInactive: "/config/jails/inactive",
|
|
configJail: (name: string): string => `/config/jails/${encodeURIComponent(name)}`,
|
|
configJailLogPath: (name: string): string =>
|
|
`/config/jails/${encodeURIComponent(name)}/logpath`,
|
|
configJailActivate: (name: string): string =>
|
|
`/config/jails/${encodeURIComponent(name)}/activate`,
|
|
configJailDeactivate: (name: string): string =>
|
|
`/config/jails/${encodeURIComponent(name)}/deactivate`,
|
|
configJailLocalOverride: (name: string): string =>
|
|
`/config/jails/${encodeURIComponent(name)}/local`,
|
|
configJailValidate: (name: string): string =>
|
|
`/config/jails/${encodeURIComponent(name)}/validate`,
|
|
configGlobal: "/config/global",
|
|
configReload: "/config/reload",
|
|
configRestart: "/config/restart",
|
|
configRegexTest: "/config/regex-test",
|
|
configPreviewLog: "/config/preview-log",
|
|
configMapColorThresholds: "/config/map-color-thresholds",
|
|
|
|
// File-based config (jail.d, filter.d, action.d)
|
|
configJailFiles: "/config/jail-files",
|
|
configJailFile: (filename: string): string =>
|
|
`/config/jail-files/${encodeURIComponent(filename)}`,
|
|
configJailFileEnabled: (filename: string): string =>
|
|
`/config/jail-files/${encodeURIComponent(filename)}/enabled`,
|
|
configJailFileParsed: (filename: string): string =>
|
|
`/config/jail-files/${encodeURIComponent(filename)}/parsed`,
|
|
configFilters: "/config/filters",
|
|
configFiltersRaw: "/config/filters/raw",
|
|
configFilter: (name: string): string => `/config/filters/${encodeURIComponent(name)}`,
|
|
configFilterRaw: (name: string): string => `/config/filters/${encodeURIComponent(name)}/raw`,
|
|
configFilterParsed: (name: string): string =>
|
|
`/config/filters/${encodeURIComponent(name)}/parsed`,
|
|
configJailFilter: (name: string): string =>
|
|
`/config/jails/${encodeURIComponent(name)}/filter`,
|
|
configJailAction: (name: string): string =>
|
|
`/config/jails/${encodeURIComponent(name)}/action`,
|
|
configJailActionName: (jailName: string, actionName: string): string =>
|
|
`/config/jails/${encodeURIComponent(jailName)}/action/${encodeURIComponent(actionName)}`,
|
|
configActions: "/config/actions",
|
|
configAction: (name: string): string => `/config/actions/${encodeURIComponent(name)}`,
|
|
configActionRaw: (name: string): string => `/config/actions/${encodeURIComponent(name)}/raw`,
|
|
configActionParsed: (name: string): string =>
|
|
`/config/actions/${encodeURIComponent(name)}/parsed`,
|
|
|
|
// fail2ban log viewer (Task 2)
|
|
configFail2BanLog: "/config/fail2ban-log",
|
|
configServiceStatus: "/config/service-status",
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Server settings
|
|
// -------------------------------------------------------------------------
|
|
serverSettings: "/server/settings",
|
|
serverFlushLogs: "/server/flush-logs",
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Ban history
|
|
// -------------------------------------------------------------------------
|
|
history: "/history",
|
|
historyIp: (ip: string): string => `/history/${encodeURIComponent(ip)}`,
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Blocklists
|
|
// -------------------------------------------------------------------------
|
|
blocklists: "/blocklists",
|
|
blocklist: (id: number): string => `/blocklists/${String(id)}`,
|
|
blocklistPreview: (id: number): string => `/blocklists/${String(id)}/preview`,
|
|
blocklistsImport: "/blocklists/import",
|
|
blocklistsSchedule: "/blocklists/schedule",
|
|
blocklistsLog: "/blocklists/log",
|
|
} as const;
|