register.js
1.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 注册流程:密码经 hasher 哈希落库 + 首次签发会话。
*
* 产品决策(§3 留口):本实现采用「注册即激活并签发会话」路径(欧美刷剧 MVP 追求转化、
* 降低试看→注册摩擦)。验证码确认走独立 sendCode/verifyCode(用于敏感操作 / reset),
* 不阻塞注册主路径。库内 grep 不到明文密码持久化、不到自写哈希循环(全走 hasher)。
*/
import { AuthError } from './errors.js'
import { issueSession } from './session.js'
/**
* @param {Object} deps
* @param {import('./index.js').UserRepo} deps.userRepo
* @param {import('./index.js').TokenSigner} deps.tokenSigner
* @param {import('./index.js').Hasher} deps.hasher
* @param {number} [deps.accessTtlMs]
* @param {number} [deps.refreshTtlMs]
* @returns {(args: { email: string, password: string, locale?: string, email_verified_at?: Date }) => Promise<import('./index.js').AuthTokens>}
*/
export function makeRegister(deps) {
const { userRepo, hasher } = deps
return async function register({ email, password, locale, email_verified_at }) {
const normalized = String(email ?? '').trim().toLowerCase()
if (!normalized || !password) {
throw new AuthError({ code: 'INVALID_CREDENTIALS', message: 'email and password required' })
}
const existing = await userRepo.findByEmail(normalized)
if (existing) {
throw new AuthError({ code: 'EMAIL_TAKEN' })
}
const password_hash = await hasher.hash(password)
const user = await userRepo.create({ email: normalized, password_hash, locale, email_verified_at })
const issued = await issueSession(deps, { user_id: user.id })
return { user, access_token: issued.access_token, refresh_token: issued.refresh_token }
}
}