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
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,
|
|
},
|
|
});
|
|
}
|