instaclone - user token

wj·2023년 6월 14일
0

token을 argument 대신 http headers에 작성하게 되면

개발자 도구 네트워크 탭에서 jwt-token을 확인할 수 있다.
유저가 http header를 통해 토큰을 자동적으로 보내게 됨.

  • resolver에는 root, args, context, info 4가지의 arguments가 있음. context는 모든 resolver에서 접근 가능한 내용이 담기는 object.

//server.js

const server = new ApolloServer({
    schema,
    context: {
        token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNjg2NzIyNjgxfQ.aCmbecZ5WgsuBIM_FOQ0vvNxmA1wgMQLHAdp9lfxWIQ"
    },

});

//editProfile.resolvers.js

import bcript from "bcrypt"; //항상 맨 위에 불러오기
import Jwt from "jsonwebtoken";
//{ Jwt } 작성 시, value값 안 읽히므로 주의
import client from "../../client";

export default {
    Mutation: {
        //root, args, context, info 총 4개의 arguments가 있다
        //context는 모든 resolver에서 접근 가능한 정보를 넣을 수 있는 object
        //context에 작성하게 되면 모든 resolver에서 접근이 가능!(login, createAccount 등)
        //gql을 생성하는 아폴로 서버의 context에 token을 넣으면 모든 resolver에서 접근이 가능하다.
        editProfile: async (_, {
            firstName,
            lastName,
            userName,
            email,
            password: newPassword,
        }, { token }) => {
            //id라는 object를 open하는 것
            const { id } = await Jwt.verify(token, process.env.SECRET_KEY);
            
            let uglyPassword = null;
            if (newPassword) {
                uglyPassword = await bcript.hash(newPassword, 10);
            }
            const updatedUser = await client.user.update({
                where: {
                    //id를 입력한 token에서 가져온다. 
                    id,
                },
                data: {
                    firstName,
                    lastName,
                    userName,
                    email,
                    ...(uglyPassword && {
                        password: uglyPassword
                    }),
                },
            });
            if (updatedUser.id) {
                return {
                    ok: true,
                }
            } else {
                return {
                    ok: false,
                    error: "Could not update profile",
                }
            }
        },
    },
};
  • token값을 resolver마다 불러오는 대신 token값을 불러오는 getUser함수를 만들어서 request 받을 때마다 함수가 실행되도록 만드는 것이 효율적

//users.utills.js

import Jwt from "jsonwebtoken";
import client from "../client";

export const getUser = async (token) => {
    try {
        if (!token) {
            return null;
        }
        //id라는 object를 open하는 것
        const {
            id
        } = await Jwt.verify(token, process.env.SECRET_KEY);
        const user = await client.user.findUnique({
            where: {
                id
            }
        });
        if (user) {
            return user;
        } else {
            return null;
        }
    } catch {
        return null;
    }
};

//server.js

require('dotenv').config();
import { ApolloServer } from "apollo-server";
import schema from "./schema";
import { getUser } from "./users/users.utills";

const server = new ApolloServer({
    schema,
    context: async({ req }) => {
        return {
            loggedInUser: await getUser(req.headers.token),
        };
    },

});

const PORT = process.env.PORT

server
    .listen(PORT)
    .then(() => console.log(`🎈 Server is running on http://localhost:${PORT}/ ✅`));
  • user의 id가 ull일 경우, 아래의 코드가 실행되지 않도록 protectResolver 함수를 만든다.
    각 resolver에 추가하는 대신, context에 넣어서 모든 resolver에서 접근이 가능하도록 작성
//user id가 null일 경우 resolver의 실행을 중단시킴
export const protectResolver = (user) => {
    if (!user) {
        throw new Error("You need to login.");

    }
}
profile
tistory로 옮겼습니다

0개의 댓글