mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
The socket the app's pages call over (/zap) opened only for a session, so a recipient signing by their link, who has no account, could not reach the routes that sign a field or complete a document: every field they clicked failed with "An error occurred while signing the field". tRPC had served those as public procedures; the port to ZAP kept their bodies and lost the door. A connection from the app's own pages with no session now opens as anonymous and reaches only the routes tRPC served publicly, each authorised by the token it carries; every other route answers it 401 before its handler runs. The operation API still refuses a request without a token.
95 lines
3.0 KiB
TypeScript
95 lines
3.0 KiB
TypeScript
/**
|
|
* A connection without a session — a recipient signing by their link, a visitor
|
|
* on a direct template link — reaches the public routes and nothing else.
|
|
*
|
|
* Run: npx tsx --test packages/trpc/__tests__/anonymous.test.ts
|
|
*/
|
|
import assert from 'node:assert/strict';
|
|
import { describe, test } from 'node:test';
|
|
|
|
import type { Logger } from 'pino';
|
|
|
|
import { newZapRequest } from '../zap/gen/transport_zap';
|
|
import type { AnonymousZapContext, ZapContext } from '../zap/server/context';
|
|
import { makeDispatcher, readReply } from '../zap/server/dispatch';
|
|
import { publicRoutes } from '../zap/server/public-routes';
|
|
|
|
const logger = { info: () => {}, error: () => {}, child: () => logger } as unknown as Logger;
|
|
|
|
const metadata = {
|
|
requestMetadata: {},
|
|
source: 'app' as const,
|
|
auth: null,
|
|
};
|
|
|
|
const anonymous: AnonymousZapContext = { user: null, session: null, teamId: -1, metadata, logger };
|
|
|
|
const signedIn: ZapContext = {
|
|
user: { id: 7, name: 'Signed In', email: '[email protected]' },
|
|
session: null,
|
|
teamId: 3,
|
|
metadata: { ...metadata, auth: 'session' },
|
|
logger,
|
|
};
|
|
|
|
const seen: Array<{ route: string; user: unknown }> = [];
|
|
|
|
const routes = {
|
|
'field.signFieldWithToken': (ctx: { user: unknown }) => {
|
|
seen.push({ route: 'field.signFieldWithToken', user: ctx.user });
|
|
return 'signed';
|
|
},
|
|
'envelope.recipient.set': (ctx: { user: unknown }) => {
|
|
seen.push({ route: 'envelope.recipient.set', user: ctx.user });
|
|
return 'set';
|
|
},
|
|
};
|
|
|
|
const call = async (ctx: AnonymousZapContext | ZapContext, method: string) => {
|
|
const handler = makeDispatcher(routes, publicRoutes)(ctx);
|
|
const response = await handler({
|
|
promiseID: 1,
|
|
payload: newZapRequest({ method, payload: '', teamId: '' }),
|
|
} as Parameters<typeof handler>[0]);
|
|
|
|
return readReply(response.body);
|
|
};
|
|
|
|
describe('an anonymous connection', () => {
|
|
test('calls a public route, with no user', async () => {
|
|
seen.length = 0;
|
|
const reply = await call(anonymous, 'field.signFieldWithToken');
|
|
|
|
assert.equal(reply.ok, true);
|
|
assert.deepEqual(seen, [{ route: 'field.signFieldWithToken', user: null }]);
|
|
});
|
|
|
|
test('is refused every other route before its handler runs', async () => {
|
|
seen.length = 0;
|
|
const reply = await call(anonymous, 'envelope.recipient.set');
|
|
|
|
assert.equal(reply.ok, false);
|
|
assert.equal(reply.status, 401);
|
|
assert.deepEqual(seen, []);
|
|
});
|
|
});
|
|
|
|
describe('a signed-in connection', () => {
|
|
test('calls any route as its user', async () => {
|
|
seen.length = 0;
|
|
const reply = await call(signedIn, 'envelope.recipient.set');
|
|
|
|
assert.equal(reply.ok, true);
|
|
assert.equal((seen[0].user as { id: number }).id, 7);
|
|
});
|
|
});
|
|
|
|
describe('the public routes', () => {
|
|
test('are the token flows a recipient or a direct-link visitor needs, and no editor route', () => {
|
|
for (const route of publicRoutes) {
|
|
assert.doesNotMatch(route, /^(admin|apiToken|team|organisation|folder|webhook|profile)\./);
|
|
assert.doesNotMatch(route, /\.(set|update|delete|create)$/);
|
|
}
|
|
});
|
|
});
|