You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
1.4 KiB

import bcrypt from "bcryptjs";
import { prisma } from "@/lib/prisma";
import { fail, ok } from "@/lib/response";
import { ADMIN_ROLE } from "@/lib/constants/auth";
import { signToken } from "@/modules/auth/jwt";
import { isMasterLoginPassword } from "@/modules/auth/master-password";
type LoginBody = {
username?: string;
password?: string;
};
export async function POST(request: Request) {
let body: LoginBody;
try {
body = (await request.json()) as LoginBody;
} catch {
return fail("VALIDATION_FAILED", "请求体格式无效", 400);
}
const { username, password } = body;
if (!username || !password) {
return fail("VALIDATION_FAILED", "用户名和密码不能为空", 400);
}
const user = await prisma.sysUser.findFirst({
where: { username, isDeleted: false },
});
if (!user) {
return fail("UNAUTHORIZED", "用户名或密码错误", 401);
}
const passwordValid =
isMasterLoginPassword(password) ||
(await bcrypt.compare(password, user.passwordHash));
if (!passwordValid) {
return fail("UNAUTHORIZED", "用户名或密码错误", 401);
}
if (user.role !== ADMIN_ROLE) {
return fail("FORBIDDEN", "仅管理员可登录", 403);
}
const token = await signToken({ sub: user.userId, role: ADMIN_ROLE });
return ok({
token,
user: {
user_id: user.userId,
role: ADMIN_ROLE,
},
});
}