Sign in verified accounts automatically and require eight-character passwords

This commit is contained in:
2026-10-13 16:33:52 +09:00
parent 9e0f493228
commit d6e60ecb3b
18 changed files with 538 additions and 63 deletions

View File

@@ -7,16 +7,17 @@ import type { Mail } from '../src/auth.js';
import { normalizeEmail } from '../src/auth.js';
import * as s from '../src/db/schema.js';
const password = 'correct horse battery staple';
test('개발은 1자 비밀번호를 허용하고 운영은 12자 규칙을 유지', async () => {
test('새 비밀번호는 개발·운영 모두 최소 8자이며 API 안내와 일치', async () => {
const f = await fixture();
try {
assert.equal((await f.call(null, '/auth/me')).json().passwordMinLength, 1);
assert.match(await f.service.auth.password('1'), /^\$argon2id\$/);
assert.equal((await f.call(null, '/auth/me')).json().passwordMinLength, 8);
await assert.rejects(() => f.service.auth.password('1234567'), /8~1024/);
assert.match(await f.service.auth.password('12345678'), /^\$argon2id\$/);
await assert.rejects(() => f.service.auth.password(''));
f.cfg.production = true;
assert.equal((await f.call(null, '/auth/me')).json().passwordMinLength, 12);
await assert.rejects(() => f.service.auth.password('1234'), /12~1024/);
assert.match(await f.service.auth.password('123412341234'), /^\$argon2id\$/);
assert.equal((await f.call(null, '/auth/me')).json().passwordMinLength, 8);
await assert.rejects(() => f.service.auth.password('1234567'), /8~1024/);
assert.match(await f.service.auth.password('12345678'), /^\$argon2id\$/);
} finally {
await f.close();
}
@@ -44,9 +45,9 @@ async function register(
assert.equal(result.statusCode, 200, result.body);
const mail = f.mails.find((m) => m.to === email)!;
const token = mail.text.match(/#verify=([A-Za-z0-9_-]+)/)![1]!;
if (verify)
assert.equal((await f.call(c, '/auth/verify-email', 'POST', { token })).statusCode, 200);
const login = await f.call(c, '/auth/login', 'POST', { email, password });
const login = verify
? await f.call(c, '/auth/verify-email', 'POST', { token })
: await f.call(c, '/auth/login', 'POST', { email, password });
assert.equal(login.statusCode, 200, login.body);
c.cookie += '; ' + String(login.headers['set-cookie']).split(';')[0];
c.socket?.disconnect();
@@ -89,10 +90,13 @@ test('가입은 메일 게이트웨이로 인증 토큰을 보내고 해시만
assert.match(user.passwordHash!, /^\$argon2id\$/);
assert.equal(f.service.db.select().from(s.accountTokens).get()!.tokenHash === a.token, false);
assert.equal((await request(f, a, 'alice@example.com')).statusCode, 403);
assert.equal(
(await f.call(a, '/auth/verify-email', 'POST', { token: a.token })).statusCode,
200,
);
const verified = await f.call(a, '/auth/verify-email', 'POST', { token: a.token });
assert.equal(verified.statusCode, 200, verified.body);
a.cookie =
a.cookie.replace(/;\s*hop_account=[^;]*/g, '') +
'; ' +
String(verified.headers['set-cookie']).split(';')[0];
assert.equal((await f.call(a, '/auth/me')).json().account.verified, true);
assert.equal(
(await f.call(a, '/auth/verify-email', 'POST', { token: a.token })).statusCode,
400,