import { validateSessionById, isAuthEnabled, SESSION_COOKIE, getUserPermissionsForEnvironment } from './auth'; import { validateApiToken } from './api-tokens'; import { isEnterprise } from './license'; import { userHasAdminRole, userCanAccessEnvironment } from './db'; import { parseCookieHeader } from '$lib/utils/cookie-parse'; import { canExecDecision } from './ws-exec-core'; export interface WsUpgradeAuth { userId: number; username: string; isAdmin: boolean; authDisabled: boolean; } type LowercasedHeaders = Record; function pickHeader(headers: LowercasedHeaders, name: string): string | undefined { const v = headers[name]; if (Array.isArray(v)) return v[0]; return v; } export async function authenticateWsUpgrade( headers: LowercasedHeaders ): Promise { const authEnabled = await isAuthEnabled(); if (!authEnabled) { return { userId: -1, username: '__bootstrap__', isAdmin: true, authDisabled: true }; } const cookieHeader = pickHeader(headers, 'cookie'); const cookies = parseCookieHeader(cookieHeader); const sessionId = cookies[SESSION_COOKIE]; if (sessionId) { const user = await validateSessionById(sessionId); if (user) { const enterprise = await isEnterprise(); const isAdmin = enterprise ? await userHasAdminRole(user.id) : true; return { userId: user.id, username: user.username, isAdmin, authDisabled: false }; } } const authHeader = pickHeader(headers, 'authorization'); if (authHeader && authHeader.startsWith('Bearer ')) { const token = authHeader.slice(7).trim(); const user = await validateApiToken(token); if (user) { const enterprise = await isEnterprise(); const isAdmin = enterprise ? await userHasAdminRole(user.id) : true; return { userId: user.id, username: user.username, isAdmin, authDisabled: false }; } } return null; } export async function canAccessEnvForUser( auth: WsUpgradeAuth, environmentId: number | undefined | null ): Promise { if (auth.authDisabled) return true; if (auth.isAdmin) return true; const enterprise = await isEnterprise(); if (!enterprise) return true; if (environmentId == null) { return false; } return userCanAccessEnvironment(auth.userId, environmentId); } /** * Whether the WS user may open a container exec/terminal session. Mirrors the * REST gate `auth.can('containers','exec',envId)`. Pure logic lives in * ws-exec-core; this binds the real enterprise + permission deps. */ export async function canExecForUser( auth: WsUpgradeAuth, environmentId: number | undefined | null ): Promise { return canExecDecision(auth, environmentId, { isEnterprise, getPerms: getUserPermissionsForEnvironment }); } declare global { // eslint-disable-next-line no-var var __authenticateWsUpgrade: | ((headers: LowercasedHeaders) => Promise) | undefined; // eslint-disable-next-line no-var var __canAccessEnvForUser: | ((auth: WsUpgradeAuth, envId: number | undefined | null) => Promise) | undefined; // eslint-disable-next-line no-var var __canExecForUser: | ((auth: WsUpgradeAuth, envId: number | undefined | null) => Promise) | undefined; } globalThis.__authenticateWsUpgrade = authenticateWsUpgrade; globalThis.__canAccessEnvForUser = canAccessEnvForUser; globalThis.__canExecForUser = canExecForUser;