如何为基于角色的访问控制 (RBAC) 创建自定义条件
🌐 How to create custom conditions for Role-Based Access Control (RBAC)
Page summary:使用
conditionProviderAPI 在 Strapi 中创建自定义基于角色的访问控制 (RBAC) 条件,以根据用户属性、实体查询或外部条件限制管理面板访问。🌐 Create custom Role-Based Access Control (RBAC) conditions in Strapi using the
conditionProviderAPI to restrict admin panel access based on user properties, entity queries, or external conditions.
基于角色的访问控制(RBAC)是一种限制某些用户访问的 方法。在 Strapi 应用中,管理员面板的用户是管理员。他们的角色和权限可以在管理员面板中配置。
🌐 Role-Based Access Control (RBAC) is an approach to restricting access to some users. In a Strapi application, users of the admin panel are administrators. Their roles and permissions are configured in the admin panel.
声明新条件
🌐 Declaring new conditions
将单个条件声明为对象,将多个条件声明为对象数组。每个条件对象可以有5个可能的属性:
🌐 Declare a single condition as an object, and multiple conditions as an array of objects. Each condition object can have 5 possible properties:
displayName(字符串):在管理面板中显示的条件名称,name(字符串):条件名称,使用连字符 ,category(字符串,可选):条件可以分组到管理面板中提供的类别;如果未定义,条件将出现在“默认”类别下,plugin(字符串,可选):如果条件是由插件创建的,应为插件的名称,使用kebab-case(例如content-manager),handler:用于验证条件的函数(参见 使用条件处理程序)
在 /src/index.js 中找到的全局 bootstrap 函数 中声明并注册条件(参见 注册条件)。
🌐 Declare and register conditions in the global bootstrap function found in /src/index.js (see Registering conditions).
条件 name 属性在其命名空间内充当唯一 ID,如果定义了 plugin 属性,则该命名空间是插件,否则就是根命名空间。
🌐 The condition name property acts as a unique id within its namespace, that is either the plugin if the plugin property is defined, or the root namespace.
使用条件处理器
🌐 Using the condition handler
条件可以应用于任何权限,条件 handler 用于验证该条件。handler 是一个返回查询对象或布尔值的函数。
🌐 A condition can be applied to any permission, and the condition handler is used to verify the condition. The handler is a function returning a query object or a boolean value.
查询对象用于验证你读取、创建、更新、删除或发布的实体的条件。它们使用 sift.js 库,但仅支持以下操作符:
$or$and$eq$ne$in$nin$lt$lte$gt$gte$exists$elemMatch
这个列表是详尽的。条件查询对象在管理员创建、更新、删除或发布实体时,会在内存中使用 sift.js 进行评估,而且只有上面列出的运算符被注册。其他运算符,包括在 REST API 和 查询引擎 API 中可用的过滤运算符,比如 $eqi、$contains、$startsWith 或 $null,在这里不支持 ,评估条件时会抛出 Unsupported operation 错误。
🌐 This list is exhaustive. Condition query objects are evaluated in-memory with sift.js whenever an administrator creates, updates, deletes, or publishes an entity, and only the operators listed above are registered. Other operators, including filter operators available in the REST API and Query Engine API such as $eqi, $contains, $startsWith, or $null, are not supported here and throw an Unsupported operation error when the condition is evaluated.
条件 handler 可以是一个同步或异步函数,该函数:
🌐 The condition handler can be a synchronous or asynchronous function that:
- 接收发出请求的经过身份验证的用户,
- 并返回
true、false或一个查询对象。
返回 true 或 false 对于验证外部条件或经过身份验证的用户的条件是有用的。例如,一个允许仅在服务器时间为下午5点时访问管理面板页面的条件可以使用此处理程序:
🌐 Returning true or false is useful to verify an external condition or a condition on the authenticated user.
For instance, a condition that allows access to a page in the admin panel only if server time is 5pm could use this handler:
handler: () => new Date().getHours() === 17;
handler 函数接收已认证的用户,因此它可以对用户进行条件验证:
🌐 The handler function receives the authenticated user, so it can verify conditions on the user:
const condition = {
displayName: 'Email address from strapi.io',
name: 'email-strapi-dot-io',
async handler(user) {
return user.email.includes('@strapi.io');
},
};
为了获得更细粒度的控制,handler 函数也可以返回一个查询对象:
🌐 For more granular control, the handler function can also return a query object:
const condition = {
displayName: 'price greater than 50',
name: 'price-gt-50',
async handler(user) {
return { price: { $gt: 50 } };
},
};
登记条件
🌐 Registering conditions
要在管理面板中可用,条件应在 /src/index 中找到的全局 bootstrap 函数 中声明并注册。使用 conditionProvider.register() 方法注册单个条件:
🌐 To be available in the admin panel, conditions should be declared and registered in the global bootstrap function found in /src/index. Register a single condition with the conditionProvider.register() method:
- JavaScript
- TypeScript
module.exports = async () => {
await strapi.admin.services.permission.conditionProvider.register({
displayName: 'Billing amount under 10K',
name: 'billing-amount-under-10k',
plugin: 'admin',
handler: { amount: { $lt: 10000 } },
});
};
export default async () => {
await strapi.admin.services.permission.conditionProvider.register({
displayName: 'Billing amount under 10K',
name: 'billing-amount-under-10k',
plugin: 'admin',
handler: { amount: { $lt: 10000 } },
});
};
要注册多个条件,将其定义为一个 条件对象数组,使用 conditionProvider.registerMany():
🌐 To register multiple conditions, defined as an array of condition objects, use conditionProvider.registerMany():
- JavaScript
- TypeScript
const conditions = [
{
displayName: "Entity has same name as user",
name: "same-name-as-user",
plugin: "name of a plugin if created in a plugin",
handler: (user) => {
return { name: user.name };
},
},
{
displayName: "Email address from strapi.io",
name: "email-strapi-dot-io",
async handler(user) {
return user.email.includes('@strapi.io');
},
}
];
module.exports = {
async bootstrap(/*{ strapi }*/) {
// do your boostrap
await strapi.admin.services.permission.conditionProvider.registerMany(conditions);
},
};
const conditions = [
{
displayName: "Entity has same name as user",
name: "same-name-as-user",
plugin: "name of a plugin if created in a plugin"
handler: (user) => {
return { name: user.name };
},
},
{
displayName: "Email address from strapi.io",
name: "email-strapi-dot-io",
async handler(user) {
return user.email.includes('@strapi.io');
},
}
];
export default async () => {
// do your boostrap
await strapi.admin.services.permission.conditionProvider.registerMany(conditions);
};