Written by
Lee Jongseo
on
on
TypeGraphQL[6] - Forgot Password
해당 포스트는 Ben Awad의 TypeGraphQL Tutorial을 기반으로 작성하였습니다.
ForgotPassword resolver
다음 형태의 mutation
type을 작성하고자 한다.
type Mutation {
forgotPassword(email: String!): Boolean!
}
이메일을 인자로 전달하면 해당 유저에게 토큰과 함꼐 change-password
URL로 이동할 수 있는 링크를 전달한다.
// ForgotPassword.ts
@Resolver()
export class ForgotPasswordResolver {
@Mutation(() => Boolean)
async forgotPassword(@Arg("email") email: string): Promise<boolean> {
// 이메일에 해당하는 유저를 찾는다.
const user = await User.findOne({where: {email}})
if (!user) {
return false
}
// 토큰을 생성한다
const token = v4()
// redis store에 토큰-userId 쌍을 저장한다.
// 토큰을 구별하기 위해 prefix을 설정한다.
await redis.set(forgotPasswordPrefix + token, user.id, "ex", 60 * 60 * 24)
// 이메일을 전송한다.
await sendEmail(email, `http://localhost:3000/user/change-password/${token}`)
return true
}
}
mutation {
forgotPassword(email: "lee@lee.com")
}
토큰과 함꼐 링크가 전송된다. 링크를 클릭하면 유저가 토큰과 함께 changePassword를 요청하게 된다.
ChangePassword Resolver
비밀번호를 잊어버리면 새롭게 비밀번호를 설정하도록 한다.
다음의 Mutation Schema를 작성하고자한다.
type Mutation {
changePassword(data: ChangePasswordInput!): User
}
먼저 InputType을 설정한다
// ChangePasswordInput.ts
@InputType()
export class ChangePasswordInput {
@Field()
token: string;
@Field()
password: string;
}
@Resolver()
export class ChangePasswordResolver {
@Mutation(()=> User)
async changePassword(@Arg("data") {token, password}: ChangePasswordInput): Promise<User | null> {
// redis store에서 userId를 가져온다.
const userId = await redis.get(forgotPasswordPrefix + token)
if (!userId) {
return null
}
// fetch user
const user = await User.findOne(userId)
if (!user) {
return null
}
// redis store의 데이터를 삭제한다.
await redis.del(forgotPasswordPrefix + token)
// password를 새로 설정한 후 데이터베이스에 반영한다.
user.password = await bcrpytjs.hash(passoword, 12)
await user.save()
return user
}
}
graphql 쿼리를 작성하여 테스트 해본다.
mutation {
changePassword(token: "forgot password로부터 전달받은 토큰", password: "새롭게 설정할 패스워드") "{
name
email
}
}