1

我开始使用带有apollo-server-expressand的 graphql 开发一个 express API graphql-tools。我的注册用户流程步骤是:

  1. 用户提交用户名、电子邮件和密码。

  2. 服务器通过 Mailgun 向用户发送一封电子邮件,其中包含由 . 生成的唯一链接uuid

  3. 用户点击链接以验证注册。

但我正在努力解决如何在解析器中绑定突变。见片段:

服务器.js

  const buildOptions = async (req, res, done) => {
    const user = await authenticate(req, mongo.Users)
    return {
      schema,
      context: {
        dataloaders: buildDataloaders(mongo),
        mongo,
        user
      },
    }
    done()
  }
  // JWT setting
  app.use('/graphAPI',
    jwt({
      secret: JWT_SECRET,
      credentialsRequired: false,
    }),
    graphqlExpress(buildOptions),
    res => data => res.send(JSON.stringify(data))
  )

解析器上的突变

 signupUser: async (root, data, {mongo: { Users }}) => {
      // Check existed accounts,
      // if account is not exist, assign new account
      const existed = await Users.findOne({email: data.email})
      if (!existed) {
        // create a token for sending email
        const registrationToken = {
          token: uuid.v4(),
          created_at: new Date(),
          expireAfterSeconds: 3600000 * 6 // half day
        }
        const newUser = {
          name: data.name,
          email: data.email,
          password: await bcrypt.hash(data.password, 10),
          created_at: new Date(),
          verification_token: registrationToken,
          is_verified: false,
        }
        const response = await Users.insert(newUser)
        // send and email to user
        await verifyEmail(newUser)
        return Object.assign({id: response.insertedIds[0]}, newUser)
      }
      // Throw error when account existed
      const error = new Error('Email existed')
      error.status = 409
      throw error
    },

    // VERIFY USER
    // Set verify to true (after user click on the link)
    // Add user to mailist
    verifiedUser: async (root, data, {mongo: { Users }}) => {
      await Users.updateOne(
        { email: data.email },
        {
          set: {is_verified: true},
          unset: {verification_token: {token: ''}}
        }
      )
    },

路由配置

routes.get('/verify?:token', (req, res, next) => {
  res.render('verified', {title: 'Success'})
}) 

路由配置是我卡住的地方,因为对象通过内部的上下文传递给所有解析器graphqlExpress

任何人都可以帮助我或为我推荐任何相关的文章。非常感谢。

4

2 回答 2

1

似乎与其利用verifiedUser端点,不如将该逻辑保留在控制器中以进行/verify路由会更简单。就像是:

routes.get('/verify?:token', (req, res) => {
  Users.updateOne(
    { verification_token: { token } },
    {
      $set: {is_verified: true},
      $unset: {verification_token: {token: ''}}
    },
    (err, data) => {
      const status = err ? 'Failure' : 'Success'
      res.render('verified', {title: status})
    }    
  )
})
于 2017-08-08T23:45:48.850 回答
1

您将需要 3 个 graphql 端点和 1 个 apollo http 端点来实现正确的工作流程。

或者,您可以将 3 个 graphql 端点合二为一,但这将是一个具有许多不同职责的大功能。

1# graphql 端点:changepass-request

  • 期望电子邮件参数
  1. 检查是否在 db 中找到了具有此类电子邮件的用户:
  2. 生成代码
  3. 保存在本地账户节点
  4. 使用 http 链接将代码发送到用户电子邮件以确认代码:http: //yoursite.com/auth/verify ?code=1234
  5. 返回 redirect_uri: http://yoursite.com/auth/confirm-code 用于 UI 页面,提示输入确认码

2# graphql 端点:changepass-confirm

  • 期望代码参数:
  • 如果在 db 中找到具有此类代码的用户,则将 redirect_uri 返回到 UI 页面,并提示新通行证,并在参数中使用确认码:http: //yoursite.com/auth/change-pass ?code=1234

3# graphql 端点:changepass-complete

  • 期望代码和新通行证:
  1. 哈希新密码
  2. 在 db 中搜索具有此类代码 3a 的本地帐户。如果未找到:使用 redirect_uri 向登录页面返回错误:http: //yoursite.com/auth ?success=false&message="确认代码不正确,重试。" 3b。如果找到:更改新密码,使用 redirect_uri 将成功状态返回到登录页面:http: //yoursite.com/auth?success=true&message="ok"

4# apollo HTTP 端点:http: //yoursite.com/auth/verify ?code=1234

  • 如果没有提供代码:重定向到 UI 注册页面,参数中有错误消息:http: //yoursite.com/auth ?success=false&message="确认代码不正确,重试。"

  • 如果提供了代码:在 db 中搜索具有此类代码 1a 的本地帐户。如果找不到用户:重定向到 reg ui,参数中出现错误混乱:http: //yoursite.com/auth ?success=false&message="确认代码不正确,再试一次。" 1.b 如果用户找到:重定向到带有新密码提示的 ui 页面并将新代码附加到参数

我没有在上面放任何代码,因此您可以在其他身份验证场景中使用此工作流程。

于 2021-01-26T06:46:50.763 回答