// @vitest-environment node import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import path from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import * as Y from 'yjs' import { LoginLimiter, SessionManager, isSameOrigin, readCookie } from '../auth.ts' import { Storage } from '../db.ts' import { detectImageType } from '../images.ts' describe('SessionManager', () => { const sessions = new SessionManager('secret', 'password', 30) it('签发的令牌可以通过校验', () => { expect(sessions.verify(sessions.issue())).not.toBeNull() }) it('拒绝被篡改或过期的令牌', () => { const token = sessions.issue() const [body, signature] = token.split('.') expect(sessions.verify(`${body}x.${signature}`)).toBeNull() expect(sessions.verify(`${body}.${signature}x`)).toBeNull() expect(sessions.verify('garbage')).toBeNull() expect(sessions.verify(sessions.issue(Date.now() - 31 * 86_400_000))).toBeNull() }) it('修改口令后旧令牌失效', () => { const token = sessions.issue() expect(new SessionManager('secret', 'new-password', 30).verify(token)).toBeNull() }) it('校验口令', () => { expect(sessions.checkPassword('password')).toBe(true) expect(sessions.checkPassword('Password')).toBe(false) expect(sessions.checkPassword(undefined)).toBe(false) }) it('有效期过半时提示续期', () => { const now = Date.now() expect(sessions.shouldRenew(sessions.verify(sessions.issue(now))!, now)).toBe(false) const old = sessions.verify(sessions.issue(now - 20 * 86_400_000), now)! expect(sessions.shouldRenew(old, now)).toBe(true) }) }) describe('请求辅助函数', () => { it('解析 Cookie', () => { expect(readCookie('a=1; boundless_session=abc%3D; b=2', 'boundless_session')).toBe('abc=') expect(readCookie(undefined, 'x')).toBeUndefined() }) it('只接受同源请求,并识别反向代理转发的 Host', () => { expect(isSameOrigin(undefined, ['example.com'])).toBe(true) expect(isSameOrigin('https://example.com', ['example.com'])).toBe(true) expect(isSameOrigin('https://evil.com', ['example.com'])).toBe(false) expect(isSameOrigin('https://board.me', ['board.me', 'localhost:3000'])).toBe(true) }) it('登录失败过多时暂时锁定', () => { const limiter = new LoginLimiter(3, 1000) limiter.fail('ip', 0) limiter.fail('ip', 10) expect(limiter.isBlocked('ip', 20)).toBe(false) limiter.fail('ip', 30) expect(limiter.isBlocked('ip', 40)).toBe(true) expect(limiter.isBlocked('ip', 2000)).toBe(false) }) }) describe('detectImageType', () => { const bytes = (...values: Array) => new Uint8Array( values.flatMap((value) => typeof value === 'string' ? [...value].map((char) => char.charCodeAt(0)) : [value], ), ) it('根据文件头识别格式', () => { expect(detectImageType(bytes(0x89, 'PNG\r\n', 0x1a, '\n', 0, 0, 0, 0))).toBe('png') expect(detectImageType(bytes(0xff, 0xd8, 0xff, 0xe0, 0, 0, 0, 0, 0, 0, 0, 0))).toBe('jpg') expect(detectImageType(bytes('RIFF', 0, 0, 0, 0, 'WEBP'))).toBe('webp') expect(detectImageType(bytes(''))).toBe('svg') }) it('拒绝非图片文件', () => { expect(detectImageType(bytes('