首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GraphQl突变: addUser未创建用户

GraphQl突变: addUser未创建用户
EN

Stack Overflow用户
提问于 2021-10-04 03:23:08
回答 1查看 478关注 0票数 1

我正在将一个Google应用程序从一个Restful重构到GraphQL,我被困在了一个不像我所期望的那样的变异中。

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

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

SignupForm.js (React Page)

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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的地方,并且被困住了。如有任何建议或反馈,敬请见谅。

EN

回答 1

Stack Overflow用户

发布于 2021-10-05 00:43:04

我解决了这个问题。首先,resolver.js上的一个语法错误阻止了我的突变被读取。

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

代码语言:javascript
复制
  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的其他地方。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69430592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档