feat: 完成分类、worksheet 接口开发,资源迁移到七牛

This commit is contained in:
R524809
2026-10-16 17:32:23 +08:00
parent e6ded00a4c
commit 8827110f2f
107 changed files with 12775 additions and 125 deletions
@@ -0,0 +1,34 @@
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { LoginRateLimiter } from '../src/auth/login-rate-limiter';
import { ApiException } from '../src/common/api-exception';
test('登录分别限制 IP 与可信身份,窗口过期后恢复且返回重试期限', (context) => {
context.mock.method(Date, 'now', () => 1000);
const limiter = new LoginRateLimiter();
for (let i = 0; i < 30; i++) limiter.checkIp('127.0.0.1');
assert.throws(
() => limiter.checkIp('127.0.0.1'),
(error: unknown) =>
error instanceof ApiException &&
error.reason === 'RATE_LIMITED' &&
error.retryAfterSeconds === 60,
);
limiter.checkIp('127.0.0.2');
for (let i = 0; i < 10; i++) limiter.checkIdentity('openid-a');
assert.throws(() => limiter.checkIdentity('openid-a'), ApiException);
limiter.checkIdentity('openid-b');
context.mock.method(Date, 'now', () => 61_000);
limiter.checkIp('127.0.0.1');
limiter.checkIdentity('openid-a');
});
test('大量来源不会无限增长内存,过期后可以回收容量', (context) => {
context.mock.method(Date, 'now', () => 0);
const limiter = new LoginRateLimiter();
for (let i = 0; i < 10_000; i++) limiter.checkIp(`ip-${i}`);
assert.throws(() => limiter.checkIp('new-ip'), ApiException);
limiter.checkIp('ip-0');
context.mock.method(Date, 'now', () => 60_000);
limiter.checkIp('new-ip');
});