Atom Authorization
Atom authorization
mainly solves such problems: who
can perform which actions
of atom data within which data scope
Authorization Record
Authorization of atom action
for atomClass
, such as the following authorization record:
Role | AtomClass | Atom Action |
---|---|---|
system | party | create |
Data Scope of Authorization
When authorizing, you can specify the data scope of the permission, such as the following authorization record:
Role | AtomClass | Atom Action | Data Scope |
---|---|---|---|
system | party | read | finance department |
The role
system
can only readparty
data offinance department
Authorization Ways
There are three ways of authorization: Artificial Authorization
, Initial Authorization
, Test Authorization
The API methods for initial authorization
and test authorization
are as follows:
addRoleRight
a-base/backend/src/config/middleware/adapter/role.js
- 1async addRoleRight({ roleId, atomClassId, action, scope })
Name | Description |
---|---|
roleId | RoleId to be authorized |
atomClassId | Atom Class Id |
action | Atom Action Code |
scope | Data Scope |
scope supports the following values:
0
: Can operate the atom data created by selfroleId
: Can operate the atom data created by users belonged to roleId and roleId’s child rolesroleIds
: Array of roleId
addRoleRightBatch
a-base/backend/src/config/middleware/adapter/role.js
- 1// const roleRights = [
- 2// { roleName: 'cms-writer', action: 'create' },
- 3// { roleName: 'cms-writer', action: 'write', scopeNames: 0 },
- 4// { roleName: 'cms-writer', action: 'delete', scopeNames: 0 },
- 5// { roleName: 'cms-writer', action: 'read', scopeNames: 'authenticated' },
- 6// { roleName: 'cms-publisher', action: 'read', scopeNames: 'authenticated' },
- 7// { roleName: 'cms-publisher', action: 'write', scopeNames: 'authenticated' },
- 8// { roleName: 'cms-publisher', action: 'publish', scopeNames: 'authenticated' },
- 9// { roleName: 'root', action: 'read', scopeNames: 'authenticated' },
- 10// ];
- 11async addRoleRightBatch({ module, atomClassName, roleRights })
Name | Description |
---|---|
module | module name. If it is empty, the current module name will be used |
atomClassName | atom class name |
roleRights | array of authorization records |
For Example
src/suite-vendor/test-party/modules/test-party/backend/src/service/version.js
- 1// add role rights
- 2const roleRights = [
- 3 { roleName: 'system', action: 'create' },
- 4 { roleName: 'system', action: 'write', scopeNames: 0 },
- 5 { roleName: 'system', action: 'delete', scopeNames: 0 },
- 6 { roleName: 'system', action: 'read', scopeNames: 'authenticated' },
- 7 { roleName: 'system', action: 'review', scopeNames: 'authenticated' },
- 8];
- 9await this.ctx.meta.role.addRoleRightBatch({ atomClassName: 'party', roleRights });
Rules of Authorization Checking
Because atoms provide many features and states such as draft
, simple workflow
and public access
will affect the checking rules of atom authorizations
Rules of Authorization Checking corresponding to different states of atoms is as follows:
Atom Action | Draft | Simple Workflow | Public Access | Normal |
---|---|---|---|---|
create | - | - | - | - |
read | only the creator has permission | determine whether there is authorization for other actions. For example, if there is write permission, there must be read permission |
no need to check | need to check |
write、delete | only the creator has permission | need to check | - | need to check |
custom actions | - | need to check | - | need to check |
-
: not supportcreate
: only need to authorize on atom class, regardless of the atom data
Draft
Atom have two states: draft
and normal
In the draft
state, only the creator can perform the actions of write
and delete
In the normal
state, only authorized users can perform the corresponding authorized actions
Public Access
By default, atoms can only be queried if they are granted permission. CabloyJS also supports direct public access
without permission. Just set the public
of the atom class to 1
Simple Workflow
At present, CabloyJS implements the simple workflow
mechanism
For example, we can design such a workflow:
1、The user creates a new article, which is in draft
state, and can be read by self
2、The article submitted by the user cannot be accessed publicly at this time, but can be read by the users who have review
permission
3、The article can only be accessed publicly after reviewed
by users who have review
permission
Authorization Checking
Authorization can be checked by middleware
or API
Check by Middleware
CabloyJS uses the global middleware right
to encapsulate the logic of authorization checking. It only needs to configure the corresponding middleware parameters on the API route
src/suite-vendor/test-party/modules/test-party/backend/src/routes.js
- 1{ method: 'post', path: 'test/atom/checkRightCreate', controller: testAtomRight, middlewares: 'test',
- 2 meta: { right: { type: 'atom', action: 1 } },
- 3},
- 4{ method: 'post', path: 'test/atom/checkRightRead', controller: testAtomRight, middlewares: 'test',
- 5 meta: { right: { type: 'atom', action: 2 } },
- 6},
- 7{ method: 'post', path: 'test/atom/checkRightWrite', controller: testAtomRight, middlewares: 'test',
- 8 meta: { right: { type: 'atom', action: 3 } },
- 9},
- 10{ method: 'post', path: 'test/atom/checkRightAction', controller: testAtomRight, middlewares: 'test',
- 11 meta: { right: { type: 'atom', action: 101 } },
- 12},
Name | Description |
---|---|
right | the global middleware right , which is enabled by default, only needs to configure parameters |
type | authorization type. here is atom authorization |
action | atom action code |
Check by API
src/suite-vendor/test-party/modules/test-party/backend/src/controller/test/atom/all.js
- 1// atomClass
- 2const atomClass = await this.ctx.meta.atomClass.get({ atomClassName: 'party' });
- 3// userIds
- 4const userIds = this.ctx.cache.mem.get('userIds');
action: create
- 1const checkRightCreates = [[ 'Tom', true ], [ 'Jimmy', true ], [ 'Smith', false ]];
- 2for (const [ userName, right ] of checkRightCreates) {
- 3 const res = await this.ctx.meta.atom.checkRightCreate({
- 4 atomClass,
- 5 user: { id: userIds[userName] },
- 6 });
- 7 assert.equal(!!res, right, userName);
- 8}
action: read
- 1const checkRightReads = [[ 'Tom', partyKey.atomId, true ]];
- 2for (const [ userName, atomId, right ] of checkRightReads) {
- 3 const res = await this.ctx.meta.atom.checkRightRead({
- 4 atom: { id: atomId },
- 5 user: { id: userIds[userName] },
- 6 });
- 7 assert.equal(!!res, right, userName);
- 8}
action: write
- 1const checkRightWrites = [[ 'Tom', partyKey.atomId, true ], [ 'Tomson', partyKey.atomId, false ]];
- 2for (const [ userName, atomId, right ] of checkRightWrites) {
- 3 const res = await this.ctx.meta.atom.checkRightUpdate({
- 4 atom: { id: atomId, action: this.ctx.constant.module('a-base').atom.action.write },
- 5 user: { id: userIds[userName] },
- 6 });
- 7 assert.equal(!!res, right, userName);
- 8}
action: delete
- 1const checkRightDeletes = [[ 'Tom', partyKey.atomId, true ], [ 'Tomson', partyKey.atomId, false ]];
- 2for (const [ userName, atomId, right ] of checkRightDeletes) {
- 3 const res = await this.ctx.meta.atom.checkRightUpdate({
- 4 atom: { id: atomId, action: this.ctx.constant.module('a-base').atom.action.delete },
- 5 user: { id: userIds[userName] },
- 6 });
- 7 assert.equal(!!res, right, userName);
- 8}
custom actions
- 1// action: review(101)
- 2const checkRightActions_1 = [[ 'Tom', partyKey.atomId, false ], [ 'Jane', partyKey.atomId, true ]];
- 3for (const [ userName, atomId, right ] of checkRightActions_1) {
- 4 const res = await this.ctx.meta.atom.checkRightAction({
- 5 atom: { id: atomId, action: 101 },
- 6 user: { id: userIds[userName] },
- 7 });
- 8 assert.equal(!!res, right, userName);
- 9}
Comments: