1.0.34
This commit is contained in:
56 files changed
+9101
-117
No files matched your search
@@ -0,0 +1,96 @@
|
||||
import { validateSessionById, isAuthEnabled, SESSION_COOKIE } from './auth';
|
||||
import { validateApiToken } from './api-tokens';
|
||||
import { isEnterprise } from './license';
|
||||
import { userHasAdminRole, userCanAccessEnvironment } from './db';
|
||||
|
||||
export interface WsUpgradeAuth {
|
||||
userId: number;
|
||||
username: string;
|
||||
isAdmin: boolean;
|
||||
authDisabled: boolean;
|
||||
}
|
||||
|
||||
function parseCookieHeader(header: string | undefined): Record<string, string> {
|
||||
if (!header) return {};
|
||||
const out: Record<string, string> = {};
|
||||
for (const part of header.split(';')) {
|
||||
const eq = part.indexOf('=');
|
||||
if (eq < 0) continue;
|
||||
const k = part.slice(0, eq).trim();
|
||||
let v = part.slice(eq + 1).trim();
|
||||
if (v.startsWith('"') && v.endsWith('"')) v = v.slice(1, -1);
|
||||
if (k) out[k] = decodeURIComponent(v);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
type LowercasedHeaders = Record<string, string | string[] | undefined>;
|
||||
|
||||
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<WsUpgradeAuth | null> {
|
||||
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<boolean> {
|
||||
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);
|
||||
}
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var
|
||||
var __authenticateWsUpgrade:
|
||||
| ((headers: LowercasedHeaders) => Promise<WsUpgradeAuth | null>)
|
||||
| undefined;
|
||||
// eslint-disable-next-line no-var
|
||||
var __canAccessEnvForUser:
|
||||
| ((auth: WsUpgradeAuth, envId: number | undefined | null) => Promise<boolean>)
|
||||
| undefined;
|
||||
}
|
||||
|
||||
globalThis.__authenticateWsUpgrade = authenticateWsUpgrade;
|
||||
globalThis.__canAccessEnvForUser = canAccessEnvForUser;
|
||||
Reference in new issue
Block a user