Files
memind/server/portal-auth-session-helpers.test.mjs
T

143 lines
3.8 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { createPortalAuthSessionHelpers } from './portal-auth-session-helpers.mjs';
function createRequest(cookie = '', overrides = {}) {
return {
headers: {},
hostname: 'm.example.com',
protocol: 'https',
get(name) {
if (String(name).toLowerCase() === 'cookie') return cookie;
if (String(name).toLowerCase() === 'host') {
return this.headers.host ?? this.hostname;
}
return this.headers[String(name).toLowerCase()];
},
...overrides,
};
}
function createResponse() {
return {
headers: {},
set(name, value) {
this.headers[name] = value;
return this;
},
};
}
test('auth session helpers parse legacy and user cookies', () => {
const helpers = createPortalAuthSessionHelpers({
isSecureRequest: () => false,
});
const req = createRequest(
'tkmind_h5_session=legacy-token; tkmind_user_session=user-token',
);
assert.equal(helpers.legacySessionToken(req), 'legacy-token');
assert.equal(helpers.userToken(req), 'user-token');
});
test('auth session helpers set and clear user login cookies', () => {
const helpers = createPortalAuthSessionHelpers({
isSecureRequest: () => true,
getLegacyAuth: () => ({}),
});
const req = createRequest('', {
headers: { host: 'm.tkmind.cn' },
});
const loginRes = createResponse();
helpers.setUserLoginCookies(loginRes, req, 'user-token');
const loginCookies = loginRes.headers['Set-Cookie'];
assert.ok(Array.isArray(loginCookies));
assert.ok(
loginCookies.some((cookie) =>
cookie.includes('tkmind_user_session=user-token'),
),
);
assert.ok(
loginCookies.every((cookie) => cookie.includes('Secure')),
);
const logoutRes = createResponse();
helpers.clearUserLoginCookies(logoutRes, req);
const logoutCookies = logoutRes.headers['Set-Cookie'];
assert.ok(
logoutCookies.some((cookie) =>
cookie.includes('tkmind_user_session='),
),
);
assert.ok(
logoutCookies.some((cookie) =>
cookie.includes('tkmind_h5_session='),
),
);
});
test('attachUserSession verifies the user token and populates request state', async () => {
const calls = [];
const helpers = createPortalAuthSessionHelpers({
isSecureRequest: () => false,
getUserAuth: () => ({
async verify(token) {
calls.push(token);
return { userId: 'user-1' };
},
}),
});
const req = createRequest(
'tkmind_user_session=user-token',
);
let nextCalls = 0;
await helpers.attachUserSession(req, {}, () => {
nextCalls += 1;
});
assert.deepEqual(calls, ['user-token']);
assert.deepEqual(req.userSession, { userId: 'user-1' });
assert.equal(req.userSessionError, null);
assert.equal(nextCalls, 1);
});
test('attachUserSession records verification failure and always continues', async () => {
const logs = [];
const failure = new Error('database unavailable');
const helpers = createPortalAuthSessionHelpers({
isSecureRequest: () => false,
getUserAuth: () => ({
async verify() {
throw failure;
},
}),
logger: {
error(...args) {
logs.push(args);
},
},
});
const req = createRequest(
'tkmind_user_session=user-token',
);
let nextCalls = 0;
await helpers.attachUserSession(req, {}, () => {
nextCalls += 1;
});
assert.equal(req.userSession, null);
assert.equal(req.userSessionError, failure);
assert.equal(nextCalls, 1);
assert.deepEqual(logs[0], [
'[Auth] session verify failed:',
'database unavailable',
]);
const noAuthHelpers = createPortalAuthSessionHelpers({
isSecureRequest: () => false,
});
const noAuthReq = createRequest();
await noAuthHelpers.attachUserSession(noAuthReq, {}, () => {
nextCalls += 1;
});
assert.equal(nextCalls, 2);
assert.equal(noAuthReq.userToken, undefined);
});