ci/woodpecker/push/woodpecker Pipeline was successful
Co-authored-by: HiFox Agent <agents-noreply@hifox.com>
60 lines
3.2 KiB
TypeScript
60 lines
3.2 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { Hono } from 'hono';
|
|
import jwt from 'jsonwebtoken';
|
|
import { passwordRouter } from './password.js';
|
|
import { authMiddleware } from './middleware.js';
|
|
import { readOnlyMiddleware } from '../read-only-middleware.js';
|
|
import { verifyAuthToken } from './config.js';
|
|
|
|
test('固定密码模式默认关闭、失败限流、只读权限及换密失效', async () => {
|
|
const previous = { ...process.env };
|
|
try {
|
|
delete process.env.BI_AUTH_MODE;
|
|
process.env.JWT_SECRET = 'test-signing-secret-with-at-least-32-characters';
|
|
process.env.BI_AUTH_PASSWORD = 'test-password-only-123456';
|
|
process.env.DEV_BYPASS_AUTH = '0';
|
|
const app = new Hono();
|
|
app.use('/api/*', readOnlyMiddleware);
|
|
app.route('/api/auth', passwordRouter());
|
|
app.use('/api/*', authMiddleware);
|
|
app.get('/api/data', c => c.json({ ok: true }));
|
|
app.post('/api/data', c => c.json({ ok: true }));
|
|
const login = (password: unknown) => app.request('/api/auth/password', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ password }) });
|
|
assert.deepEqual(await (await app.request('/api/auth/config')).json(), { mode: 'sso' });
|
|
assert.equal((await login(process.env.BI_AUTH_PASSWORD)).status, 403);
|
|
const ssoToken = jwt.sign({ userId: 'sso-user', roles: [] }, process.env.JWT_SECRET);
|
|
assert.equal(verifyAuthToken(ssoToken).userId, 'sso-user');
|
|
process.env.BI_AUTH_MODE = 'password';
|
|
assert.throws(() => verifyAuthToken(ssoToken));
|
|
assert.equal((await login('wrong')).status, 401);
|
|
process.env.DB_READ_ONLY = '1';
|
|
const response = await login(process.env.BI_AUTH_PASSWORD);
|
|
assert.equal(response.status, 200);
|
|
const { token, user } = await response.json();
|
|
assert.deepEqual(user.roles, ['BI-LEADER-ENERGY']);
|
|
const headers = { Authorization: `Bearer ${token}` };
|
|
assert.equal((await app.request('/api/data', { headers })).status, 200);
|
|
const payload = verifyAuthToken(token);
|
|
assert.equal(Number(payload.exp) - Number(payload.iat), 8 * 60 * 60);
|
|
process.env.DB_READ_ONLY = '0';
|
|
assert.equal((await app.request('/api/data', { method: 'POST', headers })).status, 403);
|
|
assert.equal((await app.request('/api/data')).status, 401);
|
|
assert.throws(() => verifyAuthToken(jwt.sign({ authMethod: 'password' }, 'wrong-key')));
|
|
process.env.BI_AUTH_PASSWORD = 'a-different-password-123456';
|
|
assert.equal((await app.request('/api/data', { headers })).status, 401);
|
|
process.env.BI_AUTH_MODE = 'sso';
|
|
assert.equal((await app.request('/api/data', { headers })).status, 401);
|
|
process.env.BI_AUTH_MODE = 'password';
|
|
delete process.env.BI_AUTH_PASSWORD;
|
|
assert.equal((await login('')).status, 503);
|
|
process.env.BI_AUTH_PASSWORD = 'a-different-password-123456';
|
|
for (let i = 0; i < 20; i++) await login('wrong');
|
|
assert.equal((await login(process.env.BI_AUTH_PASSWORD)).status, 429);
|
|
} finally {
|
|
for (const key of ['BI_AUTH_MODE', 'BI_AUTH_PASSWORD', 'JWT_SECRET', 'DEV_BYPASS_AUTH', 'DB_READ_ONLY']) {
|
|
if (previous[key] === undefined) delete process.env[key]; else process.env[key] = previous[key];
|
|
}
|
|
}
|
|
});
|