mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 02:49:33 +01:00
fix(auth): require the request on findSessionOrFail
findSessionOrFail took `req` as optional, so the quiet default was the unscoped lookup: a route that forgot to pass it compiled cleanly and, in multi-user mode, returned another user's session. `req` is now required, and a caller with no request in flight must use the explicit, greppable findSessionUnscopedOrFail instead. Every current caller in src/ already passes req (verified by grep and tsc), so behaviour is unchanged; the new helper has no production callers and exists so the next request-less caller does not make `req` optional again. Tests pin the unscoped helper's behaviour and assert, from the source AST, that `req` is a required parameter (tsc does not typecheck test/).
This commit is contained in:
1 parent
002de32a08
commit
4f9274af3a
2 files changed
+53
-5
No files matched your search
@@ -10,10 +10,16 @@ import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
|
||||
import fs from 'node:fs/promises';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import ts from 'typescript';
|
||||
import { WebServer } from '../src/web/server.js';
|
||||
import { TmuxManager } from '../src/tmux-manager.js';
|
||||
import { createUser, invalidateUsersCache } from '../src/user-store.js';
|
||||
import { canAccessOwned, findSessionOrFail, sessionCapacityState } from '../src/web/route-helpers.js';
|
||||
import {
|
||||
canAccessOwned,
|
||||
findSessionOrFail,
|
||||
findSessionUnscopedOrFail,
|
||||
sessionCapacityState,
|
||||
} from '../src/web/route-helpers.js';
|
||||
|
||||
vi.spyOn(TmuxManager, 'isTmuxAvailable').mockReturnValue(true);
|
||||
|
||||
@@ -154,6 +160,26 @@ describe('session-scoping helpers (multi-user)', () => {
|
||||
expect(findSessionOrFail(ctxWith(map), 's1', reqAs('root', 'admin'))).toBeDefined();
|
||||
});
|
||||
|
||||
it('findSessionUnscopedOrFail is the explicit unscoped lookup: returns a foreign session, 404s an unknown id', () => {
|
||||
const map = new Map<string, unknown>([['s1', fakeSession('alice')]]);
|
||||
expect(findSessionUnscopedOrFail(ctxWith(map), 's1')).toBeDefined();
|
||||
expect(() => findSessionUnscopedOrFail(ctxWith(map), 'missing')).toThrow();
|
||||
});
|
||||
|
||||
it('findSessionOrFail declares req as REQUIRED, so an unscoped call must use the explicit helper', async () => {
|
||||
// tsc does not typecheck test/, so pin the signature from the source AST: an
|
||||
// optional `req` would make forgetting it compile into an UNSCOPED lookup.
|
||||
const file = path.join(import.meta.dirname, '../src/web/route-helpers.ts');
|
||||
const src = ts.createSourceFile(file, await fs.readFile(file, 'utf8'), ts.ScriptTarget.Latest, true);
|
||||
const decl = src.statements.find(
|
||||
(s): s is ts.FunctionDeclaration => ts.isFunctionDeclaration(s) && s.name?.text === 'findSessionOrFail'
|
||||
);
|
||||
const req = decl?.parameters.find((p) => p.name.getText(src) === 'req');
|
||||
expect(req).toBeDefined();
|
||||
expect(req?.questionToken).toBeUndefined();
|
||||
expect(req?.initializer).toBeUndefined();
|
||||
});
|
||||
|
||||
it('per-user session cap counts only the owner sessions', () => {
|
||||
const map = new Map<string, unknown>([
|
||||
['a', fakeSession('alice')],
|
||||
|
||||
Reference in new issue
Block a user