@accounts/graphql-api 中文文档教程

发布于 3年前 浏览 20 项目主页 更新于 3年前

@accounts/graphql-api

带有 JSAccounts 的 GraphQL 服务器的架构、解析器和实用程序

npmMIT License

这个包不需要任何网络接口/express 来与你的 GraphQL 结合 -它只是 GraphQL 模式、解析器和实用程序的集合!

How to use this package?

此包导出 GraphQL 架构和 GraphQL 解析器,您可以使用现有的 GraphQL 架构服务器对其进行扩展。

首先从 NPM / Yarn 安装它:

// Npm
npm install --save @accounts/server @accounts/graphql-api @graphql-modules/core

// Yarn
yarn add @accounts/server @accounts/graphql-api @graphql-modules/core

这个包不会创建传输或其他任何东西,只会创建模式和字符串以及作为对象的解析器。

首先根据需要配置您的 AccountsServer。 例如,使用 MongoDB:

import mongoose from 'mongoose'
import AccountsServer from '@accounts/server'
import AccountsPassword from '@accounts/password'
import MongoDBInterface from '@accounts/mongo'

const db = mongoose.connection

const password = new AccountsPassword()

const accountsServer = new AccountsServer({
  {
    db: new MongoDBInterface(db),
    tokenSecret: 'SECRET',
  },
  {
    password,
  }
});

接下来,从此包中导入 AccountsModule,并使用您的 AccountsServer 运行它:

import { AccountsModule } from '@accounts/graphql-api';

const accountsGraphQL = AccountsModule.forRoot({
  accountsServer,
});

现在,将 accountsGraphQL.typeDefs 添加到您的模式定义(就在将其与 makeExecutableSchema 一起使用之前),并使用 @graphql-tools/epoxy 将您的解析器对象与 accountsGraphQL.resolvers 合并,例如:

import { makeExecutableSchema } from '@graphql-tools/schema';
import { mergeGraphQLSchemas, mergeResolvers } from '@graphql-tools/epoxy';

const typeDefs = [
  `
  type Query {
    myQuery: String
  }

  type Mutation {
    myMutation: String
  }

  schema {
      query: Query,
      mutation: Mutation
  }
  `,
  accountsGraphQL.typeDefs,
];

let myResolvers = {
  Query: {
    myQuery: () => 'Hello',
  },
  Mutation: {
    myMutation: () => 'Hello',
  },
};

const schema = makeExecutableSchema({
  resolvers: mergeResolvers([accountsGraphQL.resolvers, myResolvers]),
  typeDefs: mergeGraphQLSchemas([typeDefs]),
});

最后一步是使用上下文中间件扩展您的 graphqlExpress,它从 HTTP 请求中提取身份验证令牌,因此 AccountsServer 将自动验证它:

app.use(
  GRAPHQL_ROUTE,
  bodyParser.json(),
  graphqlExpress((request) => {
    return {
      context: {
        ...accountsGraphQL(request),
        // your context
      },
      schema,
    };
  })
);

Authenticating Resolvers

您可以使用 验证您自己的解析器JSAccounts 身份验证流程,使用此包中的 authenticated 方法。

此方法作曲家还使用当前经过身份验证的用户扩展了 context

这是受保护突变的示例:

import AccountsServer from '@accounts/server';
import { authenticated } from '@accounts/graphql-api';

export const resolver = {
  Mutation: {
    updateUserProfile: authenticated((rootValue, args, context) => {
      // Write your resolver here
      // context.user - the current authenticated user!
    }),
  },
};

Customization

此包允许您自定义 GraphQL 架构及其解析器。

例如,某些应用程序主查询称为 MyQueryRootQuery 而不是查询,因此您可以自定义名称,而无需修改应用程序的架构。

这些是可用的自定义:

  • rootQueryName (string) - The name of the root query, default: Query.
  • rootMutationName (string) - The name of the root mutation, default: Mutation.
  • extend (boolean) - whether to add extend before the root type declaration, default: true.
  • withSchemaDefinition (boolean): whether to add schema { ... } declaration to the generation schema, default: false.

将第二个对象传递给 createAccountsGraphQL,例如:

另一种可能的自定义是修改身份验证标头的名称,将其与 accountsContext(默认is Authorization):

const myCustomGraphQLAccounts = AccountsModule.forRoot({
  accountsServer,
  rootQueryName: 'RootQuery',
  rootMutationName: 'RootMutation',
  headerName: 'MyCustomHeader',
});

Extending User

要使用自定义字段和逻辑扩展 User 对象,请添加您自己的 User GraphQL 类型定义,前缀为 扩展,并添加您的字段:

extend type User {
  firstName: String
  lastName: String
}

同时为您添加的字段实现一个常规解析器:

const UserResolver = {
  firstName: () => 'Dotan',
  lastName: () => 'Simha',
};

Extending User during password creation

要在用户创建期间扩展用户对象,您需要扩展CreateUserInput 类型并添加您的字段:

extend input CreateUserInput {
  profile: CreateUserProfileInput!
}

input CreateUserProfileInput {
  firstName: String!
  lastName: String!
}

用户将保存在数据库中,并设置了配置文件键。

Example: Authenticate with a Service

mutation Authenticate {
  authenticate(serviceName: "password", params: { password: "<pw>", user: { email: "<email>" } })
}
  1. serviceName - corresponds to the package you are using to authenticate (e.g. oauth, password, twitter, instagram, two factor, token, etc).
  2. params - These will be different depending on the service you are using.
  • Twitter/Instagram
mutation Authenticate {
  authenticate(
    serviceName: "twitter"
    params: { access_token: "<access-token>", access_token_secret: "<access-token-secret>" }
  )
}
  • OAuth
mutation Authenticate {
  authenticate(serviceName: "oauth", params: { provider: "<your-provider>" })
}
  • Password: Below the user contains email but can contain one or more of id, email or username too.
mutation Authenticate {
  authenticate(serviceName: "password", params: { password: "<pw>", user: { email: "<email>" } })
}
  • Two Factor
mutation Authenticate {
  authenticate(serviceName: "two-factor", params: { code: "<two-factor-code>" })
}
  • Token
mutation Authenticate {
  authenticate(serviceName: "token", params: { token: "<token>" })
}

Verify Authentication

检查用户是否已成功通过身份验证的方法是相同的,除了 verifyAuthentication 返回一个 boolean 而不是 LoginResult

mutation Verify {
  verifyAuthentication(
    serviceName: "password"
    params: { password: "<pw>", user: { email: "<email>" } }
  )
}

这将如果您的用户已成功通过身份验证,则返回类似于此的结果:

{
  "data": {
    "verifyAuthentication": true
  }
}

@accounts/graphql-api

Schema, Resolvers and Utils for GraphQL server with JSAccounts

npmMIT License

This package does not requires any network interface / express in order to combine with your GraphQL - it's just a collection of GraphQL schema, resolvers and utils!

How to use this package?

This package exports GraphQL schema and GraphQL resolvers, which you can extend with your existing GraphQL schema server.

Start by installing it from NPM / Yarn:

// Npm
npm install --save @accounts/server @accounts/graphql-api @graphql-modules/core

// Yarn
yarn add @accounts/server @accounts/graphql-api @graphql-modules/core

This package does not create a transport or anything else, only schema and string and resolvers as object.

Start by configuring your AccountsServer as you wish. For example, using MongoDB:

import mongoose from 'mongoose'
import AccountsServer from '@accounts/server'
import AccountsPassword from '@accounts/password'
import MongoDBInterface from '@accounts/mongo'

const db = mongoose.connection

const password = new AccountsPassword()

const accountsServer = new AccountsServer({
  {
    db: new MongoDBInterface(db),
    tokenSecret: 'SECRET',
  },
  {
    password,
  }
});

Next, import AccountsModule from this package, and run it with your AccountsServer:

import { AccountsModule } from '@accounts/graphql-api';

const accountsGraphQL = AccountsModule.forRoot({
  accountsServer,
});

Now, add accountsGraphQL.typeDefs to your schema definition (just before using it with makeExecutableSchema), and merge your resolvers object with accountsGraphQL.resolvers by using @graphql-tools/epoxy, for example:

import { makeExecutableSchema } from '@graphql-tools/schema';
import { mergeGraphQLSchemas, mergeResolvers } from '@graphql-tools/epoxy';

const typeDefs = [
  `
  type Query {
    myQuery: String
  }

  type Mutation {
    myMutation: String
  }

  schema {
      query: Query,
      mutation: Mutation
  }
  `,
  accountsGraphQL.typeDefs,
];

let myResolvers = {
  Query: {
    myQuery: () => 'Hello',
  },
  Mutation: {
    myMutation: () => 'Hello',
  },
};

const schema = makeExecutableSchema({
  resolvers: mergeResolvers([accountsGraphQL.resolvers, myResolvers]),
  typeDefs: mergeGraphQLSchemas([typeDefs]),
});

The last step is to extend your graphqlExpress with a context middleware, that extracts the authentication token from the HTTP request, so AccountsServer will automatically validate it:

app.use(
  GRAPHQL_ROUTE,
  bodyParser.json(),
  graphqlExpress((request) => {
    return {
      context: {
        ...accountsGraphQL(request),
        // your context
      },
      schema,
    };
  })
);

Authenticating Resolvers

You can authenticate your own resolvers with JSAccounts authentication flow, by using authenticated method from this package.

This method composer also extends context with the current authenticated user!

This is an example for a protected mutation:

import AccountsServer from '@accounts/server';
import { authenticated } from '@accounts/graphql-api';

export const resolver = {
  Mutation: {
    updateUserProfile: authenticated((rootValue, args, context) => {
      // Write your resolver here
      // context.user - the current authenticated user!
    }),
  },
};

Customization

This package allow you to customize the GraphQL schema and it's resolvers.

For example, some application main query called MyQuery or RootQuery instead of query, so you can customize the name, without modifying you application's schema.

These are the available customizations:

  • rootQueryName (string) - The name of the root query, default: Query.
  • rootMutationName (string) - The name of the root mutation, default: Mutation.
  • extend (boolean) - whether to add extend before the root type declaration, default: true.
  • withSchemaDefinition (boolean): whether to add schema { ... } declaration to the generation schema, default: false.

Pass a second object to createAccountsGraphQL, for example:

Another possible customization is to modify the name of the authentication header, use it with accountsContext (the default is Authorization):

const myCustomGraphQLAccounts = AccountsModule.forRoot({
  accountsServer,
  rootQueryName: 'RootQuery',
  rootMutationName: 'RootMutation',
  headerName: 'MyCustomHeader',
});

Extending User

To extend User object with custom fields and logic, add your own GraphQL type definition of User with the prefix of extend, and add your fields:

extend type User {
  firstName: String
  lastName: String
}

And also implement a regular resolver, for the fields you added:

const UserResolver = {
  firstName: () => 'Dotan',
  lastName: () => 'Simha',
};

Extending User during password creation

To extend the user object during the user creation you need to extend the CreateUserInput type and add your fields:

extend input CreateUserInput {
  profile: CreateUserProfileInput!
}

input CreateUserProfileInput {
  firstName: String!
  lastName: String!
}

The user will be saved in the db with the profile key set.

Example: Authenticate with a Service

mutation Authenticate {
  authenticate(serviceName: "password", params: { password: "<pw>", user: { email: "<email>" } })
}
  1. serviceName - corresponds to the package you are using to authenticate (e.g. oauth, password, twitter, instagram, two factor, token, etc).
  2. params - These will be different depending on the service you are using.
  • Twitter/Instagram
mutation Authenticate {
  authenticate(
    serviceName: "twitter"
    params: { access_token: "<access-token>", access_token_secret: "<access-token-secret>" }
  )
}
  • OAuth
mutation Authenticate {
  authenticate(serviceName: "oauth", params: { provider: "<your-provider>" })
}
  • Password: Below the user contains email but can contain one or more of id, email or username too.
mutation Authenticate {
  authenticate(serviceName: "password", params: { password: "<pw>", user: { email: "<email>" } })
}
  • Two Factor
mutation Authenticate {
  authenticate(serviceName: "two-factor", params: { code: "<two-factor-code>" })
}
  • Token
mutation Authenticate {
  authenticate(serviceName: "token", params: { token: "<token>" })
}

Verify Authentication

The way to check if a user has been successfully authenticated is identical, with the exception that verifyAuthentication returns a boolean instead of a LoginResult:

mutation Verify {
  verifyAuthentication(
    serviceName: "password"
    params: { password: "<pw>", user: { email: "<email>" } }
  )
}

This will return a result similar to this, if your user has been successfully authenticated:

{
  "data": {
    "verifyAuthentication": true
  }
}
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文