Skip to main content

v4 代码迁移:更新政策

¥v4 code migration: Updating policies

本指南是 v4 代码迁移指南 的一部分,旨在帮助你将 Strapi 应用的代码从 v3.6.x 迁移到 v4.0.x

¥This guide is part of the v4 code migration guide designed to help you migrate the code of a Strapi application from v3.6.x to v4.0.x

🤓 v3/v4 比较

在 Strapi v3 和 v4 中,策略都处理授权。策略可以全局存储或限定范围(即使用特定的 API 或插件),并且可以应用于 REST 控制器的操作或 GraphQL 解析器。

¥In both Strapi v3 and v4, policies handle authorization. Policies can be stored globally or scoped (i.e. with a specific API or plugin) and can be applied to REST controller's actions or to GraphQL resolvers.

在 Strapi v3 中,策略是 Koa 中间件,根据 REST 上下文接受或拒绝请求。作为中间件,v3 策略始终接收 Koa 上下文,要么来自 REST 请求,要么从 GraphQL 解析器参数构建。

¥In Strapi v3, policies are Koa middlewares accepting or rejecting requests based on the REST context. As middlewares, v3 policies always receive a Koa context, either coming from the REST request or built from the GraphQL resolver arguments.

在 Strapi v4 中,policies 是应该返回 trueundefined 才能接受请求的函数。v4 策略接收一个自定义上下文,该上下文无法根据调用策略的位置(例如 REST 控制器的操作或 GraphQL 解析器)进行修改。

¥In Strapi v4, policies are functions that should return true or undefined for the request to be accepted. v4 policies receive a custom context, that cannot be modified, based on where the policy has been called from (e.g. a REST controller’s action or a GraphQL resolver).

充当路由中间件的 Strapi v3 策略应转换为正确的 v4 路由中间件

¥Strapi v3 policies acting as route middlewares should be converted to proper v4 route middlewares.

要将策略迁移到 Strapi v4:

¥To migrate a policy to Strapi v4:

  1. 根据策略范围,将策略文件移动到适当的文件夹中:

    ¥Move the policy file in the appropriate folder, depending on the policy scope:

    政策范围文件夹
    全局的./src/policies
    特定的 API./src/api/<api-name>/policies
    特定插件./src/plugins/<plugin-name>/policies

    (参见 插件策略迁移 文档)
  2. (可选)更新策略代码。Strapi v4 策略是返回 trueundefined 以授权请求的函数。

    ¥(optional) Update the policy code. Strapi v4 policies are functions returning true or undefined to authorize the request.

迁移策略代码取决于代码本身,本迁移指南无法涵盖所有现有用例。以下示例涵盖了 v4 策略与 REST 和 GraphQL API 配合使用或特别与这些 API 之一配合使用的一些常见用例。这些示例可用于全局、API 相关或插件相关的策略。

¥Migrating a policy code depends on the code itself and this migration guide can't cover every existing use case. The following examples cover some common use cases of v4 policies working with both REST and GraphQL APIs or specifically with one of these APIs. These examples can be used for global, API-related, or plugin-related policies.

Example: Authorize only logged in users (REST and GraphQL)

以下 v3 策略仅授权登录用户:

¥The following v3 policy authorizes only logged in users:

module.exports = async (ctx, next) => {
if (ctx.state.user) {
// Go to next policy or will reach the controller's action.
return await next();
}

ctx.unauthorized(`You're not logged in!`);
};

要将此策略更新为 v4,请将其替换为以下代码:

¥To update this policy to v4, replace it with the following code:

module.exports = (policyContext, config, { strapi }) => {
if (policyContext.state.user) { // if a session is open
// go to next policy or reach the controller's action
return true;
}

return false; // If you return nothing, Strapi considers you didn't want to block the request and will let it pass
};

v4 策略使用 policyContext.state 变量,REST 和 GraphQL 均可访问。

¥The v4 policy uses the policyContext.state variable, accessible to both REST and GraphQL.

Example: Shared policy with alternate logic for REST and GraphQL

以下 v4 策略检查当前请求是否来自通过 policyContext.type 的 REST 或 GraphQL,并允许为每个请求运行替代验证规则。

¥The following v4 policy checks if the current request is coming from REST or GraphQL via the policyContext.type and allows running alternative validation rules for each.

path: ./src/policies or ./src/api/api-name/policies/ depending on where you want to apply the policy

module.exports = (policyContext, config, { strapi }) => {
// handle Koa
if (policyContext.type === 'koa') {
// Do REST validation
return true
}

// handle GraphQL
else if (policyContext.type === 'graphql') {
// Do GraphQL validation
return true
}

// handle other cases
return false;
};
Example: Authorize only for a specific entity (REST)

以下策略代码可用于授权仅针对特定实体:

¥The following policy code can be used to authorize only targeting a specific entity:

module.exports = (policyContext, config, { strapi }) => {
return policyContext.params.id === 5;
};
Example: Authorize field resolvers only for a specific entity (GraphQL)

以下策略代码可用于授权仅针对特定实体的字段解析器:

¥The following policy code can be used to authorize field resolvers only targeting a specific entity:

module.exports = (policyContext, config, { strapi }) => {
return typeof policyContext.parent === 'object' && policyContext.parent.id === 5;
};
💡 定制技巧

在 Strapi v4 中,根据策略是否应用于 REST 还是 GraphQL(使用 policyContext.type 是 REST 的 koagraphql ),该函数可以访问不同的上下文:

¥In Strapi v4, depending on whether the policy is applied to REST or GraphQL (use policyContext.type is either koa for REST or graphql ), the function has access to different contexts:

  • REST 和 GraphQL 上下文都可以访问 istypestate

    ¥Both REST and GraphQL contexts have access to the is, type, and state.

  • REST 上下文可以访问被破坏的 Koa 上下文。

    ¥The REST context have access to the destructed Koa context.

  • GraphQL 上下文可以访问 parentargscontext(这是 GraphQL 上下文)、infohttp(其中包含 Koa 上下文)(请参阅 GraphQL 定制 文档)。

    ¥The GraphQL context has access to parent, args, context (which is the GraphQL Context), info & http (which contains the Koa context) (see GraphQL customization documentation).

你可以使用 policyContext.type(对于 REST,该值是 koa;对于 GraphQL 插件,该值是 graphql)来确定策略使用的上下文类型。

¥You can use policyContext.type, which value is either koa for REST or graphql for the GraphQL plugin, to determine the type of context the policy uses.