GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。 NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは 別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
71 lines
2.7 KiB
JavaScript
71 lines
2.7 KiB
JavaScript
const { test } = require('node:test');
|
|
const assert = require('node:assert');
|
|
const {
|
|
SESSION_COOKIE_NAME,
|
|
verifyMasterKey,
|
|
createSessionToken,
|
|
verifySessionToken,
|
|
parseCookies,
|
|
buildSessionCookieHeader,
|
|
buildLogoutCookieHeader,
|
|
} = require('../src/adminAuth');
|
|
|
|
test('verifyMasterKey returns true only for an exact match', () => {
|
|
assert.strictEqual(verifyMasterKey('secret123', 'secret123'), true);
|
|
assert.strictEqual(verifyMasterKey('wrong', 'secret123'), false);
|
|
assert.strictEqual(verifyMasterKey('', 'secret123'), false);
|
|
assert.strictEqual(verifyMasterKey('secret123', ''), false);
|
|
assert.strictEqual(verifyMasterKey('secret123', undefined), false);
|
|
});
|
|
|
|
test('createSessionToken/verifySessionToken round-trip successfully within TTL', () => {
|
|
const secret = 'test-secret';
|
|
const now = 1700000000000;
|
|
const token = createSessionToken(secret, now);
|
|
assert.strictEqual(verifySessionToken(token, secret, now + 1000), true);
|
|
});
|
|
|
|
test('verifySessionToken rejects a token signed with a different secret', () => {
|
|
const now = 1700000000000;
|
|
const token = createSessionToken('secret-a', now);
|
|
assert.strictEqual(verifySessionToken(token, 'secret-b', now + 1000), false);
|
|
});
|
|
|
|
test('verifySessionToken rejects an expired token', () => {
|
|
const secret = 'test-secret';
|
|
const now = 1700000000000;
|
|
const token = createSessionToken(secret, now);
|
|
const oneDayAndOneMs = 24 * 60 * 60 * 1000 + 1;
|
|
assert.strictEqual(verifySessionToken(token, secret, now + oneDayAndOneMs), false);
|
|
});
|
|
|
|
test('verifySessionToken rejects malformed tokens', () => {
|
|
assert.strictEqual(verifySessionToken('', 'secret'), false);
|
|
assert.strictEqual(verifySessionToken(undefined, 'secret'), false);
|
|
assert.strictEqual(verifySessionToken('no-dot-here', 'secret'), false);
|
|
assert.strictEqual(verifySessionToken('123.abc.extra', 'secret'), false);
|
|
});
|
|
|
|
test('parseCookies parses a Cookie header into a key-value map', () => {
|
|
const result = parseCookies('foo=bar; portal_admin_session=abc123');
|
|
assert.deepStrictEqual(result, { foo: 'bar', portal_admin_session: 'abc123' });
|
|
});
|
|
|
|
test('parseCookies returns {} for an empty or missing header', () => {
|
|
assert.deepStrictEqual(parseCookies(undefined), {});
|
|
assert.deepStrictEqual(parseCookies(''), {});
|
|
});
|
|
|
|
test('buildSessionCookieHeader includes the cookie name, HttpOnly and Path=/admin', () => {
|
|
const header = buildSessionCookieHeader('sometoken');
|
|
assert.ok(header.startsWith(`${SESSION_COOKIE_NAME}=sometoken`));
|
|
assert.ok(header.includes('HttpOnly'));
|
|
assert.ok(header.includes('Path=/admin'));
|
|
});
|
|
|
|
test('buildLogoutCookieHeader clears the cookie with Max-Age=0', () => {
|
|
const header = buildLogoutCookieHeader();
|
|
assert.ok(header.startsWith(`${SESSION_COOKIE_NAME}=`));
|
|
assert.ok(header.includes('Max-Age=0'));
|
|
});
|