|
|
@ -1,18 +1,30 @@ |
|
|
|
|
|
import { getRequestIP } from "h3"; |
|
|
import { loginUser } from "#server/service/auth"; |
|
|
import { loginUser } from "#server/service/auth"; |
|
|
import { toPublicAuthError } from "#server/service/auth/errors"; |
|
|
import { toPublicAuthError } from "#server/service/auth/errors"; |
|
|
import { setSessionCookie } from "#server/service/auth/cookie"; |
|
|
import { setSessionCookie } from "#server/service/auth/cookie"; |
|
|
|
|
|
import { captchaConsume } from "#server/service/captcha/store"; |
|
|
type LoginBody = { |
|
|
import { assertLoginRegisterCaptchaFieldsPresent } from "#server/service/captcha/validate-body"; |
|
|
username: string; |
|
|
import { assertUnderRateLimit } from "#server/utils/simple-rate-limit"; |
|
|
password: string; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export default defineWrappedResponseHandler(async (event) => { |
|
|
export default defineWrappedResponseHandler(async (event) => { |
|
|
|
|
|
const ip = getRequestIP(event, { xForwardedFor: true }) ?? "unknown"; |
|
|
|
|
|
assertUnderRateLimit(`auth-login:${ip}`, 30, 60_000); |
|
|
|
|
|
|
|
|
|
|
|
const body = await readBody(event); |
|
|
|
|
|
assertLoginRegisterCaptchaFieldsPresent(body); |
|
|
|
|
|
if (!captchaConsume(body.captchaId, body.captchaAnswer)) { |
|
|
|
|
|
throw createError({ |
|
|
|
|
|
statusCode: 400, |
|
|
|
|
|
statusMessage: "验证码错误或已过期,请重试", |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
const body = await readBody<LoginBody>(event); |
|
|
const result = await loginUser({ |
|
|
const result = await loginUser(body); |
|
|
username: body.username, |
|
|
|
|
|
password: body.password, |
|
|
|
|
|
}); |
|
|
setSessionCookie(event, result.sessionId); |
|
|
setSessionCookie(event, result.sessionId); |
|
|
|
|
|
|
|
|
return R.success({ |
|
|
return R.success({ |
|
|
user: result.user, |
|
|
user: result.user, |
|
|
}); |
|
|
}); |
|
|
|