우선 나는 MySQL을 사용하였고 Prisma를 같이 사용하였다.
AuthJS에서도 공식적으로 Prisma를 지원하니 자세한 내용은 공식 홈페이지를 참고하자.
내가 고민했던 문제는 축구팀을 관리하는 웹사이트이기 때문에 관리자와 일반 유저를 구분하는 것이 필수적인데 이걸 어떻게 구현할 수 있을까였다.
우선 특정 유저에게 관리자를 부여하는 방법은 여러가지가 있겠지만 우선 나는 팀메이트에 가장 먼저 가입한 유저에게 관리자를 부여하고 이후 새로 가입하는 유저들은 일반 유저로 취급하는 것을 생각했다.
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
role String? @default("user") // 추가한 부분
resultcode String?
accounts Account[]
sessions Session[]
message String?
createdAt DateTime @default(now())
}
우선 AuthJS의 공식 홈페이지를 따라 로그인을 구현해보면 User 모델을 작성했을 텐데, 여기에 role 속성을 추가하였다.
default 값은 user이고, 처음으로 가입하는 사용자에게만 admin 값을 부여할 것이다.
auth.ts 파일로 가면
import { PrismaAdapter } from "@auth/prisma-adapter";
import NextAuth from "next-auth";
import Naver from "next-auth/providers/naver";
import prisma from "./lib/prisma";
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [Naver],
pages: {
signIn: "/auth/signin",
},
callbacks: {
},
});
이렇게 로그인 로직이 작성되어 있을 것이다.
여기서 callbacks 부분에 관리자를 부여하는 로직을 작성해주었다.
const existingUser = await prisma.user.findUnique({
where: { email: user.email as string },
});
우선 먼저 로그인한 회원의 이메일을 이용해 findUnique 메소드로 해당 회원이 DB에 등록된 회원인지 아닌지 확인한다.
findUnique는 고유한 값을 이용해 해당 값이 일치하는 하나의 요소를 반환하는 메소드이다.
const firstUser = await prisma.user.findFirst({
orderBy: {
createdAt: 'asc',
},
});
그리고 해당 회원이 DB에 등록된 회원이 아니라면 DB 내에 이미 등록된 다른 회원이 있는지 확인한다.
findFirst는 가장 먼저 저장된 값을 반환하므로 이 값이 있다면 DB에는 이미 다른 사람이 저장되어 있을 것이다.
그렇게 해서 찾은 firstUser가 존재하지 않는다면, 로그인을 시도한 이 유저는 팀메이트에 최초로 로그인을 시도한 회원이므로 이 유저에게 admin 역할을 부여한다.
const newUser = await prisma.user.create({
data: {
email: user.email as string,
name: user.name,
image: user.image,
role: 'admin', // 처음 등록된 유저는 admin
},
});
firstUser가 아닌 다른 회원에게는
const newUser = await prisma.user.create({
data: {
email: user.email,
name: user.name,
image: user.image,
role: 'user', // 기본값 'user'
},
});
user 역할을 부여한다.