GraphQl 프로젝트 - 3

원종서·2021년 9월 30일
0

graphql

목록 보기
3/5

SeePrfile

// in seeProfile.typedefs.js

type seeProfileResult {
        ok: Boolean!
        error: String
        user: User
    }

    type Query {
        seeProfile(username: String!): seeProfileResult!
    }
    

in seeProfile.resolvers.js
Query: {
        seeProfile: async (_, {username}) => {
            const user = await client.user.findUnique({where: {username}});

            if (!user) {
                return {
                    ok: false,
                    error: "유저의 아이디를 찾을 수 없습니다.",
                };
            }

            return {
                ok: true,
                user,
            };
        },
    },

Login

// in login.typedefs.js

export default gql`
    type loginResult {
        ok: Boolean!
        error: String
        token: String
    }

    type Mutation {
        login(username: String!, password: String!): loginResult!
    }
`;
// in login.resolvers.js
   Mutation: {
        login: async (_, {username, password}) => {
            const user = await client.user.findUnique({where: {username}});

            if (!user) {
                return {
                    error: "유저를 찾을 수 없습니다.",
                    ok: false,
                };
            }
            const match = await bcrypt.compare(password, user.password);

            if (!match) {
                return {
                    error: "비밀번호가 틀립니다.",
                    ok: false,
                };
            }
            const token = await jwt.sign({id: user.id}, process.env.SECRET_KEY);

            return {
                ok: true,
                token,
            };
        },
    },

bcrypt 패키지를 사용해서 비밀번호 채크를 하고
session 대신 jwt토큰을 사용하겠다.


Edit Profile

// in editProfile.typedefs.js

export default gql`
    type editProfileResult {
        ok: Boolean!
        error: String
    }

    type Mutation {
        editProfile(
            password: String
            name: String
            avatarURL: String
        ): editProfileResult!
    }
`;


// in editProfile.resolvers.js

const resolverFn = async (_, {password, name, avatarURL}, {loggedInUser}) => {
    let hashedPassword = null;

    if (password) {
        hashedPassword = await bcrypt.hash(password, 10);
    }

    const updatedUser = await client.user.update({
        where: {id: loggedInUser.id},
        data: {
            // password : hashedPassword,
            ...(hashedPassword && {password: hashedPassword}),
            avatarURL,
            name,
        },
    });
    if (updatedUser.id) {
        return {
            ok: true,
        };
    } else {
        return {
            ok: false,
            error: "업데이트 실패",
        };
    }
};

export default {
    Mutation: {
        editProfile: protectedResolver(resolverFn),
    },
};

protectedResolver라는 함수를 반환하는 함수를 이용해서
로그인되지 않은 사용자에게 에러를 발생시킬 수 있다.

export function protectedResolver(resolver) {
    return function (root, args, context, info) {
        if (!context.loggedInUser) {
            return {
                ok: false,
                error: "먼저 로그인을 해주세요",
            };
        }
        return resolver(root, args, context, info);
    };
}

매 함수마다 jwt를 검증하는 것이 불필요해
resolver 의 세번째 매개변수 Context를 사용해보저ㅏ


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

Context에는 오브젝트와 함수를 지정할 수 있는데
cotext에 지정된 값들은 프로젝트 내 모든 resover에서 상용 할 수 있다.

또 context에는 매개변수로 req,res를 받을 수 있다.

헤더 안에 token 을 넣어주고 req를 보내면 context에서 받을 수 있다.

export const getUser = async (token) => {
    try {
        if (!token) {
            return null;
        }
        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 (error) {
        console.error(error);
        return null;
    }
};

매번 토큰을 verify하고 client 를 통해 유저를 찾는 것보다
context를 이용해 user 정보를 통채로 보내주는게 소스코드의 량을 줄 일 수 있다

0개의 댓글