Files
chocoadmin/auth.ts
T

116 lines
2.7 KiB
TypeScript

import NextAuth, { type DefaultSession } from "next-auth";
import Credentials from "next-auth/providers/credentials";
import { z } from "zod";
import { ACTIVATE_STATUSES } from "@/lib/constants";
const credentialsSchema = z.object({
adminName: z.string().trim().min(1),
password: z.string().min(1),
});
type AdminAuthRow = {
AdminID: bigint | number;
Name: string;
Email: string;
AccountType: bigint | number;
ActivateStatus: bigint | number;
};
declare module "next-auth" {
interface Session {
user: {
adminID: number;
accountType: number;
activateStatus: number;
} & DefaultSession["user"];
}
interface User {
accountType: number;
activateStatus: number;
}
}
declare module "next-auth/jwt" {
interface JWT {
accountType?: number;
activateStatus?: number;
}
}
export const {
handlers: { GET, POST },
auth,
signIn,
signOut,
} = NextAuth({
pages: {
signIn: "/login",
},
session: {
strategy: "jwt",
},
providers: [
Credentials({
credentials: {
adminName: { label: "관리자 아이디", type: "text" },
password: { label: "암호", type: "password" },
},
async authorize(credentials) {
const parsedCredentials = credentialsSchema.safeParse(credentials);
if (!parsedCredentials.success) {
return null;
}
const { db } = await import("@/lib/db");
const { adminName, password } = parsedCredentials.data;
const admins = await db.$queryRaw<AdminAuthRow[]>`
SELECT AdminID, Name, Email, AccountType, ActivateStatus
FROM admin
WHERE Name = ${adminName} AND Password = PASSWORD(${password})
LIMIT 1
`;
const admin = admins[0];
const adminID = Number(admin?.AdminID);
const accountType = Number(admin?.AccountType);
const activateStatus = Number(admin?.ActivateStatus);
if (!admin || activateStatus === ACTIVATE_STATUSES.PENDING) {
return null;
}
return {
id: String(adminID),
name: admin.Name,
email: admin.Email,
accountType,
activateStatus,
};
},
}),
],
callbacks: {
jwt({ token, user }) {
if (user) {
token.accountType = user.accountType;
token.activateStatus = user.activateStatus;
}
return token;
},
session({ session, token }) {
return {
...session,
user: {
...session.user,
adminID: Number(token.sub),
accountType: Number(token.accountType),
activateStatus: Number(token.activateStatus),
},
};
},
},
});