@555platform/protektor 中文文档教程
Protektor
Protektor 是一个基于同构角色的权限库,可同时保护 UI 资源和数据模型。
Install
来自 npm
npm install @555platform/protektor
Defining Resource Data Model Mappings
的 Protektor 的主要特点是对 UI 资源以及相关数据模型执行权限,因此,定义资源数据模型映射是初始化 Proteckor 的第一步。 此步骤还为 Protektor 提供了所有要保护的资源的列表。
要将资源定义为数据模型名称调用:
import Protektor from 'protektor';
Protektor.resourceModels(resourceName, dataModel)
resourceName 是一个字符串,用于标识您要保护的任何资源,通常这是一些 UI 组件或视图。 dataModel 是一个字符串或字符串列表,标识访问资源信息所需的数据模型。
要检索资源的数据模型,请调用相同的函数,但仅使用 resourceName:
Protektor.resourceModels(resourceName)
这将返回与给定资源关联的数据模型。
Define Role Identifier
角色标识符是唯一标识角色的对象。 该对象应包含所有 唯一标识角色的相关信息。 最简单的例子是角色标识符 仅名称:
{
name: 'admin'
}
更复杂的角色标识符还可以存储有关角色组的信息。 例如,也许你 需要为您的管理员团队设置角色,并为添加的其他团队设置默认角色 团队创建时自动。 您可以通过创建 group
字段来区分 在两个 admin
角色之间:
admin role for administrator team:
{
name: 'admin',
group: 'system_administrators`
}
对于其他团队:
Upon creation of each team the default admin role could be assigned:
{
name: 'admin',
group: 'default_team_roles'
}
Protektor 需要能够搜索角色标识符,但它不知道哪些字段 或角色标识符中字段的组合使其成为唯一的搜索条件。 为了 要向 Protektor 提供此信息,您必须注册返回唯一的谓词 角色的身份。 谓词是一个具有角色标识符对象的函数 并根据您选择的任何算法返回唯一 ID。
使用上面的最后一个例子,我们可以编写我们的谓词来返回名称和组的 slug fields:
function roleId(roleIdentifier) {
return slug(roleIdentifier.name + ' ' + roleIdentifier.group);
}
Protektor.registerRoleIdentifierPredicate(roleId)
注意,如果你没有注册角色标识符谓词,Protektor 将扫描角色标识符 对象的所有顶级键的对象和连接值。 取决于您的应用 这可能足以满足您的需求。
Define Permissions
要在 role
中定义访问权限,请指定允许对资源执行的操作:
Protektor.allow({ action, resource, roleIdentifier })
or to disallow action explicitly:
Protektor.forbid({ action, resource, roleIdentifier })
您还可以通过以下方式删除特定权限:
Protektor.removePermission({ action, resource, roleIdentifier })
可以调用 allow 然后禁止相同的资源、操作和角色。 最后一次调用将覆盖权限。
Remove Role
要删除整个角色,请使用 removeRole
API:
Protektor.removeRole(roleIdentifier)
Checking Permissions On The Server
Protektor 库支持通过 hasPermission
API 在服务器端检查给定角色的权限:
Protektor.hasPermission({ action, resource, roleIdentifier })
Returns true if permitted, otherwise false
在服务器端,您还可以调用 hasModel
用于验证给定角色是否可以访问您尝试使用的数据模型的 API:
Protektor.hasModel({ modelName, roleIdentifier })
Returns true if the specified model is accessible by the role, otherwise false
如果角色允许访问,有时获取实际模型对象很有用。 这可以通过 getModel
API 来完成:
Protektor.getModel({ modelName, roleIdentifier, modelTransformCallback })
modelTransformCallback 是一个函数,如果允许访问模型,则使用 modelName 作为参数调用,如果不允许,则使用 undefined 调用。
Searching For Roles On The Server
Protektor 提供了两个 API 来搜索角色。 一个用于查找特定角色,第二个用于过滤 根据某些标准排除角色。
要查找特定角色调用 Protektor.roleToJSON(RoleIdentifier)
。 这将以 JSON 对象的形式返回角色 已准备好编组给客户端。
要根据某些条件查找角色,请使用 Protektor.filterRoles(filterComparator, roleIdentifier)
。 此函数将根据 filterComparator
和值返回符合条件的所有角色 在 roleIdentifier
对象中提供。
例如,假设您的角色定义如下:
[
{
name: 'role1'
},
{
name: 'role2'
},
{
name: 'role1',
group: 'global'
},
{
name: 'role2',
group: 'global'
}
]
并且您只想获取属于全局组的角色。 您将按如下方式调用 filterRoles
:
const globalRoles = await Protektor.filterRoles(
roleIdentifier => roleIdentifier.group,
{
group: 'global'
}
);
这将仅返回具有全局组
[
{
name: 'role1',
group: 'global'
},
{
name: 'role2',
group: 'global'
}
]
Marshalling Role To The Client
的角色:将具有其权限的角色发送到客户端调用服务器端 API:Protektor.roleToJSON(roleIdentifier)
。
Checking Permissions - ReactJS Client
Protektor 提供了 hasPermission
render prop 组件,它将检查角色的权限。 如果角色被允许访问资源,子组件将被渲染。
import { hasPermission, RoleBuilder } from 'protektor';
const currentRole = RoleBuilder.fromJSON(roleData);
.
.
.
<HasPermission to="read" access="Home" forRole={currentRole}>
<SideNavSection
to="/home"
label="Home"
/>
</HasPermission>
这里 RoleBuilder
从 JSON 创建当前用户角色。 您需要先将角色从服务器编组到客户端。
RoleBuilder
RoleBuilder 对象是客户端帮助程序,用于解组出现的 Role 的 JSON 表示 从服务器。 RoleBuilder 返回由 Role
对象描述的角色的客户端表示。
Client Role object
客户端角色对象是在服务器上定义的角色的表示,它与所有客户端 API 一起使用。 它具有以下 API:
* roleIdentifier() - returns RoleIdentifier object as defined by developer
* hasPermission = ({ action, resource }) - returns true if action is allowed on resource, otherwise false
Protektor Storage
默认情况下,Protektor 使用默认内存存储。 Protektor 存储可以将角色和权限数据持久保存到您想要的任何位置。 protektor-data-adapter
包提供了可用于扩展的基本适配器类。
import Protektor from 'protektor';
import { Adapter } from 'protektor-data-adapter';
class SomeNewAdapter extends Adapter {}
const someNewAdapter = new SomeNewAdapter();
.
.
.
Protektor.registerAdapter(someNewAdapter);
Protektor
Protektor is an isomorphic role based permission library that protects both UI resources and data models.
Install
From npm
npm install @555platform/protektor
Defining Resource Data Model Mappings
The main feature of Protektor is enforcing permissions for both UI resources as well as related data models, therefore, defining resource data model mapping is the first step to initialize Proteckor. This step also gives Protektor list of all the resources to protect.
To define resource to data model name call:
import Protektor from 'protektor';
Protektor.resourceModels(resourceName, dataModel)
resourceName is a string identifying any resource you want to protect and typically this is some UI component or view. dataModel is a string or list of strings identifying data models needed to access information for the resource.
To retrieve data models for the resource call the same function but only with resourceName:
Protektor.resourceModels(resourceName)
This will return data model(s) associated with the given resource.
Define Role Identifier
Role identifier is an object that uniquely identifies the role. This object should contain all the relevant information to uniquely identify the role. Simplest example would be Role Identifier with just name:
{
name: 'admin'
}
More complex Role Identifier could also store information about role groups. For example, maybe you need to have roles for your administrator team and default roles for other teams that are added automatically upon team creation. You could handle this by creating group
field to differentiate between two admin
roles:
admin role for administrator team:
{
name: 'admin',
group: 'system_administrators`
}
And for other teams:
Upon creation of each team the default admin role could be assigned:
{
name: 'admin',
group: 'default_team_roles'
}
Protektor needs to be able to search for the role identifier but it does not know what fields or combination of fields within role identifier makes it unique search criteria. In order to provide Protektor with this information you must register predicate that returns unique identity for the role. The predicate is a function with that takes role identifier object and returns unique id based on whatever algorithm you choose.
Using the last example above we could write our predicate to return the slug of name and group fields:
function roleId(roleIdentifier) {
return slug(roleIdentifier.name + ' ' + roleIdentifier.group);
}
Protektor.registerRoleIdentifierPredicate(roleId)
Note that if you do not register role identifier predicate Protektor will scan role identifier object and concatinate values of object's all top level keys. Depending on your application this may be sufficient for you needs.
Define Permissions
To define access permissions within a role
specify allowed action on the resource:
Protektor.allow({ action, resource, roleIdentifier })
or to disallow action explicitly:
Protektor.forbid({ action, resource, roleIdentifier })
You can also remove specific permission with:
Protektor.removePermission({ action, resource, roleIdentifier })
It is possible to call allow and then forbid on the same resource, action, role. The last call will overwrite permissions.
Remove Role
To remove entire role use removeRole
API:
Protektor.removeRole(roleIdentifier)
Checking Permissions On The Server
Protektor library supports checking permissions for the given role on the server side via hasPermission
API:
Protektor.hasPermission({ action, resource, roleIdentifier })
Returns true if permitted, otherwise false
On the server side you can also call hasModel
API to verify that the given role has access to the data model you are trying to use:
Protektor.hasModel({ modelName, roleIdentifier })
Returns true if the specified model is accessible by the role, otherwise false
Sometimes it is useful to get the actual model object if the role permits the access. This can be accomplished with getModel
API:
Protektor.getModel({ modelName, roleIdentifier, modelTransformCallback })
modelTransformCallback is a function that is called with modelName as parameter if the access to model is permitted or undefined if not permitted.
Searching For Roles On The Server
Protektor provides two APIs to search for roles. One to find a specific Role and second one to filter out roles based on some criteria.
To find specific role call Protektor.roleToJSON(RoleIdentifier)
. This will return role as JSON object that is ready to be marshalled to the client.
To find roles based on some criteria use Protektor.filterRoles(filterComparator, roleIdentifier)
. This function will return all roles that match criteria based on the filterComparator
and value provided in roleIdentifier
object.
For example let's assume you have roles defined like this:
[
{
name: 'role1'
},
{
name: 'role2'
},
{
name: 'role1',
group: 'global'
},
{
name: 'role2',
group: 'global'
}
]
and you want to just get the roles that belong to global group. You would call filterRoles
as follows:
const globalRoles = await Protektor.filterRoles(
roleIdentifier => roleIdentifier.group,
{
group: 'global'
}
);
This would return only roles with group global:
[
{
name: 'role1',
group: 'global'
},
{
name: 'role2',
group: 'global'
}
]
Marshalling Role To The Client
To send a role with its permissions to the client call server side API: Protektor.roleToJSON(roleIdentifier)
.
Checking Permissions - ReactJS Client
Protektor provides hasPermission
render prop component that will check permissions for the role. If the role is allowed to access to the resource children components will be rendered.
import { hasPermission, RoleBuilder } from 'protektor';
const currentRole = RoleBuilder.fromJSON(roleData);
.
.
.
<HasPermission to="read" access="Home" forRole={currentRole}>
<SideNavSection
to="/home"
label="Home"
/>
</HasPermission>
Here RoleBuilder
creates current user role from JSON. You will need to marshal the role from the server to client first.
RoleBuilder
RoleBuilder object is client side helper for unmarshalling JSON representation of Role that comes from the server. RoleBuilder returns client side representation of role described by Role
object.
Client Role object
Client Role object is representation of the role defined on the server and it is used with all client APIs. It has the following APIs:
* roleIdentifier() - returns RoleIdentifier object as defined by developer
* hasPermission = ({ action, resource }) - returns true if action is allowed on resource, otherwise false
Protektor Storage
By default Protektor uses default memory store. Protektor storage can persist role and permission data to anywhere you want. protektor-data-adapter
package provides base adapter class that you can use to extend.
import Protektor from 'protektor';
import { Adapter } from 'protektor-data-adapter';
class SomeNewAdapter extends Adapter {}
const someNewAdapter = new SomeNewAdapter();
.
.
.
Protektor.registerAdapter(someNewAdapter);