GraphQl突变:addUser未创建用户



我正在将Google Books应用程序从Restful API重构为GraphQL,并且我被卡住了一个突变,而不是按照我期望的方式行事。

当用户填写在sign .js上找到的表单时,突变ADD_USER应该在Mongoose中创建一个用户,该用户应该有一个分配给他们的JWT令牌,并且用户应该在成功执行突变后登录。

行动观察:•突变是从前端发射的。当我在浏览器中打开开发人员工具时,我可以看到用户名,电子邮件和密码作为变量传递。•我已经尝试控制台记录令牌,并不断得到一个未定义的返回•当我尝试在GraphQL沙箱中运行突变时,我得到一个空值返回。•当我在控制台记录resolvers.js中的参数时,控制台没有出现值,这告诉我请求没有到达解析器。

SignupForm.js (React FE Page)

import React, { useState } from "react";
import { Form, Button, Alert } from "react-bootstrap";
import { useMutation } from "@apollo/client";
import { ADD_USER } from "../utils/mutations";
import Auth from "../utils/auth";
const SignupForm = () => {
// set initial form state
const [userFormData, setUserFormData] = useState({
username: "",
email: "",
password: "",
});
// set state for form validation
const [validated] = useState(false);
// set state for alert
const [showAlert, setShowAlert] = useState(false);
const [addUser] = useMutation(ADD_USER);
const handleInputChange = (event) => {
const { name, value } = event.target;
setUserFormData({ ...userFormData, [name]: value });
};
const handleFormSubmit = async (event) => {
event.preventDefault();
// check if form has everything (as per react-bootstrap docs)
const form = event.currentTarget;
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
try {
///Add user is not returning data. payload is being passed as an object
const response = await addUser({
variables: { ...userFormData },
});
if (!response.ok) {
throw new Error("OH NO!SOMETHING WENT WRONG!");
}
const { token, user } = await response.json();
console.log(user);
Auth.login(token);
} catch (err) {
console.error(err);
setShowAlert(true);
}
setUserFormData({
username: "",
email: "",
password: "",
});
};

Mutation.js

export const ADD_USER = gql`
mutation addUser($username: String!, $email: String!, $password: String!) {
addUser(username: $username, email: $email, password: $password) {
token
user {
username
email
}
}
}
`;

typeDefs.js

const { gql } = require("apollo-server-express");
const typeDefs = gql`
input SavedBooks {
authors: [String]
description: String
bookId: String
image: String
link: String
title: String
}
type Books {
authors: [String]
description: String
bookId: ID
image: String
link: String
title: String
}
type User {
_id: ID
username: String
email: String
password: String
savedBooks: [Books]
}
type Auth {
token: ID!
user: User
}
type Query {
me: User
}
type Mutation {
##creates a user profile through the Auth type, that way we can pass a token upon creation
addUser(username: String!, email: String!, password: String!): Auth
login(email: String!, password: String!): Auth
saveBook(bookData: SavedBooks): User
deleteBook(bookId: ID!): User
}
`;
module.exports = typeDefs;

resolvers.js

const { User, Book } = require("../models");
const { AuthenticationError } = require("apollo-server-express");
const { signToken } = require("../utils/auth");

const resolvers = {
Query: {
me: async (parent, args, context) => {
if (context.user) {
return User.findOne({ _id: context.user._id }).populate("books");
}
throw new AuthenticationError("You need to log in");
},
},
};
Mutation: {
//try refactoring as a .then
addUser: async (parent, args) => {
//create user profile
await console.log("resolver test");
console.log(args);
const user = await User.create({ username, email, password });
//assign token to user
const token = signToken(user);
return { token, user };
};
login: async (parent, { email, password }) => {
const user = User.findOne({ email });
if (!user) {
throw new AuthenticationError("Invalid Login Credentials");
}
const correctPw = await profile.isCorrectPassword(password);
if (!correctPw) {
throw new AuthenticationError("Invalid Login Credentials");
}
const token = signToken(user);
return { token, user };
};
saveBook: async (parent, { bookData }, context) => {
if (context.user) {
return User.findOneAndUpdate(
{ _id: context.user._id },
{ $addToSet: { savedBooks: bookData } },
{ new: true }
);
}
throw new AuthenticationError("You need to log in");
};
deleteBook: async (parent, { bookId }, context) => {
if (context.user) {
return User.findOneAndUpdate(
{ _id: contex.user._id },
//remove selected books from the savedBooks Array
{ $pull: { savedBooks: context.bookId } },
{ new: true }
);
}
throw new AuthenticationError("You need to log in");
};
}
module.exports = resolvers;

auth.js

const jwt = require("jsonwebtoken");
// set token secret and expiration date
const secret = "mysecretsshhhhh";
const expiration = "2h";
module.exports = {
// function for our authenticated routes
authMiddleware: function ({ req }) {
// allows token to be sent via  req.query or headers
let token = req.query.token || req.headers.authorization || req.body.token;
// ["Bearer", "<tokenvalue>"]
if (req.headers.authorization) {
token = token.split(" ").pop().trim();
}
if (!token) {
return req;
}
// verify token and get user data out of it
try {
const { data } = jwt.verify(token, secret, { maxAge: expiration });
req.user = data;
} catch {
console.log("Invalid token");
return res.status(400).json({ message: "invalid token!" });
}
// send to next endpoint
return req;
},
signToken: function ({ username, email, _id }) {
const payload = { username, email, _id };
return jwt.sign({ data: payload }, secret, { expiresIn: expiration });
},
};

基本上,我已经从前端梳理到后端寻找我引入这个bug的地方,并且被卡住了。任何建议或反馈都是非常感谢的。

我能找出问题所在。首先,resolver.js上的一个语法错误阻止了我的突变被读取。

接下来,我对SignupForm.js中的handleFormSubmit做了如下调整

try {
///Add user is not returning data. payload is being passed as an object
const {data} = await addUser({
variables: { ...userFormData },
});
console.log(data)
console.log(userFormData)

**Auth.login(data.addUser.token);**
} catch (err) {
console.error(err);
setShowAlert(true);
}

这样,我的FE就可以正确地解释在成功创建用户后我的Auth中间件传递回来的内容。谢谢你的帮助,xadm,能够说出这个问题让我思考在其他地方攻击这个bug。

最新更新