All files / src/configuration caller.ts

100% Statements 17/17
100% Branches 4/4
100% Functions 3/3
100% Lines 17/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66            272x 272x 272x                             272x               272x 341x 341x 341x 48x 48x               293x 293x                 272x     272x 299x       272x 1519x    
/**
 * Who a request comes from, derived from the authenticated request only: the GitLab
 * account of the OAuth token, or the operator's token in static-token mode. A client
 * never names the account it acts for.
 */
 
import { AsyncLocalStorage } from 'node:async_hooks';
import { getTokenContext } from '../oauth/token-context';
import { normalizeInstanceUrl } from '../utils/url';
 
export interface Caller {
  /** Account whose settings apply; shared by all its sessions. */
  accountKey: string;
  /** MCP session of the request; session overrides apply to it only. */
  sessionKey: string;
  /** Display name of the account, never a credential. */
  accountLabel: string;
  instanceUrl: string;
  /** Whether the account is a GitLab user signed in through OAuth. */
  oauth: boolean;
}
 
/** Session key of a request that carries no MCP session id (the stdio transport). */
const SESSIONLESS = 'stdio';
 
/**
 * The caller of the current request. In OAuth mode the account is the GitLab user the
 * token was issued for on its instance; otherwise every request uses the operator's token,
 * so the account is that token's instance. A static-token server belongs to its operator:
 * the operator's servers on one instance share these settings, whichever token each uses.
 */
export function resolveCaller(sessionId: string | undefined, instanceUrl: string): Caller {
  const token = getTokenContext();
  const sessionKey = sessionId ?? SESSIONLESS;
  if (token) {
    const instance = normalizeInstanceUrl(token.apiUrl);
    return {
      accountKey: `gitlab:${instance}#${token.gitlabUserId}`,
      sessionKey,
      accountLabel: token.gitlabUsername,
      instanceUrl: instance,
      oauth: true,
    };
  }
  const instance = normalizeInstanceUrl(instanceUrl);
  return {
    accountKey: `token:${instance}`,
    sessionKey,
    accountLabel: 'Configured access token',
    instanceUrl: instance,
    oauth: false,
  };
}
 
const callerStorage = new AsyncLocalStorage<Caller>();
 
/** Run `fn` with `caller` as the caller of everything it does. */
export function runWithCaller<T>(caller: Caller, fn: () => T): T {
  return callerStorage.run(caller, fn);
}
 
/** The caller of the running tool call; undefined outside one. */
export function currentCaller(): Caller | undefined {
  return callerStorage.getStore();
}