import * as plugins from '../../plugins.js'; import type { OpsServer } from '../classes.opsserver.js'; import * as interfaces from '../../../ts_interfaces/index.js'; export interface IAuthRequest { identity?: interfaces.data.IIdentity; apiToken?: string; } export interface IAuthRequirement { scope?: interfaces.data.TApiTokenScope; requireAdminIdentity?: boolean; requireAdminToken?: boolean; } export interface IAuthContext { type: 'identity' | 'apiToken'; userId: string; role?: string; isAdmin: boolean; scopes: interfaces.data.TApiTokenScope[]; identity?: interfaces.data.IIdentity; token?: interfaces.data.IStoredApiToken; } const typedAuthError = (messageArg: string) => { return new plugins.typedrequest.TypedResponseError(messageArg); }; export async function requireOpsAuth( opsServerRefArg: OpsServer, requestArg: IAuthRequest, requirementArg: IAuthRequirement = {}, ): Promise { let identityNeedsAdmin = false; let tokenNeedsAdmin = false; let tokenNeedsScope = false; if (requestArg.identity?.jwt) { const identity = await opsServerRefArg.adminHandler.validateIdentity(requestArg.identity); if (identity) { const isAdmin = identity.role === 'admin'; if (!requirementArg.requireAdminIdentity || isAdmin) { return { type: 'identity', userId: identity.userId, role: identity.role, isAdmin, scopes: [], identity, }; } identityNeedsAdmin = true; } } if (requestArg.apiToken) { const tokenManager = opsServerRefArg.dcRouterRef.apiTokenManager; const token = tokenManager ? await tokenManager.validateToken(requestArg.apiToken) : null; if (token) { if (requirementArg.requireAdminToken && token.policy?.role !== 'admin') { tokenNeedsAdmin = true; } else if (requirementArg.scope && !tokenManager!.hasScope(token, requirementArg.scope)) { tokenNeedsScope = true; } else { const scopes = token.policy?.role === 'admin' ? ['*' as interfaces.data.TApiTokenScope] : Array.from(new Set([...(token.scopes || []), ...(token.policy?.scopes || [])])); return { type: 'apiToken', userId: token.createdBy, role: token.policy?.role || 'operator', isAdmin: token.policy?.role === 'admin', scopes, token, }; } } } if (tokenNeedsScope) { throw typedAuthError('insufficient scope'); } if (tokenNeedsAdmin) { throw typedAuthError('admin API token required'); } if (identityNeedsAdmin) { throw typedAuthError('admin identity required'); } throw typedAuthError('unauthorized'); }