@via-profit/ability 2.0.0-rc.7 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +328 -156
- package/build/playground.js +59 -416
- package/build/playground.js.map +1 -1
- package/dist/AbilityCode.d.ts +6 -6
- package/dist/AbilityCompare.d.ts +2 -2
- package/dist/AbilityCondition.d.ts +13 -10
- package/dist/AbilityError.d.ts +0 -3
- package/dist/AbilityMatch.d.ts +2 -2
- package/dist/AbilityPolicy.d.ts +12 -11
- package/dist/AbilityPolicyEffect.d.ts +2 -2
- package/dist/AbilityResolver.d.ts +1 -1
- package/dist/AbilityRule.d.ts +18 -3
- package/dist/AbilityRuleSet.d.ts +11 -6
- package/dist/index.js +79 -68
- package/package.json +1 -2
- package/dist/AbilityPolicyResult.d.ts +0 -6
- package/dist/playground.d.ts +0 -26
package/README.md
CHANGED
|
@@ -3,109 +3,92 @@
|
|
|
3
3
|
> Набор сервисов, частично реализующих
|
|
4
4
|
> принцип [Attribute Based Access Control](https://en.wikipedia.org/wiki/Attribute-based_access_control)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
чтобы проверить наличие доступа к этим данным.
|
|
8
|
-
|
|
9
|
-
# Draft
|
|
6
|
+
Этот сервис позволяет создавать правила и политики, применять их к данным и проверять доступ на их основе.
|
|
10
7
|
|
|
11
8
|
## Содержание
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
## Оглавление
|
|
11
|
+
- [Обзор](#overview)
|
|
12
|
+
- [Состав пакета](#structure)
|
|
13
|
+
- [Основные принципы](#principles)
|
|
14
|
+
- [Правила](#rules)
|
|
15
|
+
- [Создание правила](#rule-creation)
|
|
16
|
+
- [Проверка правила](#rule-check)
|
|
17
|
+
- [Группы правил](#rule-sets)
|
|
18
|
+
- [Создание группы правил](#ruleset-creation)
|
|
19
|
+
- [Проверка группы правил](#ruleset-check)
|
|
20
|
+
- [Политики](#policies)
|
|
21
|
+
- [Создание политики](#policy-creattion)
|
|
22
|
+
- [Проверка политики](#policy-check)
|
|
23
|
+
- [Управление политиками](#policy-management)
|
|
24
24
|
|
|
25
|
-
2.3 [Класс AbilityRule](#ability-rule-class)
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
---
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
3.2 [Примеры](#policy-recipes)
|
|
32
|
-
|
|
33
|
-
3.3 [Класс AbilityPolicy](#ability-policy-class)
|
|
34
|
-
|
|
35
|
-
4. [Создание политики из конфига](#policy-config)
|
|
36
|
-
|
|
37
|
-
## Описание и общие принципы <a name="overview"></a>
|
|
28
|
+
## Обзор <a name="overview"></a>
|
|
38
29
|
|
|
39
30
|
### Состав пакета <a name="structure"></a>
|
|
40
31
|
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
32
|
+
- **`AbilityRule`** — класс отдельного правила
|
|
33
|
+
- **`AbilityRuleSet`** — класс группы правил
|
|
34
|
+
- **`AbilityPolicy`** — класс политики
|
|
35
|
+
- **`AbilityResolver`** — управление политиками
|
|
36
|
+
- **`AbilityMatch`** — константы состояния правил (`pending`, `match`, `mismatch`)
|
|
37
|
+
- **`AbilityCompare`** — способы сравнения (`or`, `and`)
|
|
38
|
+
- **`AbilityCondition`** — методы вычисления (`equal`, `not_equal`, `more_than`, `less_than`, `in`, `not_in` и др.)
|
|
39
|
+
- **`AbilityPolicyEffect`** — эффекты политики (`deny`, `permit`)
|
|
40
|
+
- **`AbilityParser`** — парсер конфигурационных правил (JSON)
|
|
41
|
+
- **`AbilityError`** — инстанс ошибок
|
|
42
|
+
|
|
43
|
+
### Основные принципы <a name="principles"></a>
|
|
53
44
|
|
|
54
|
-
|
|
45
|
+
Работа сервиса основана на формировании **правил**, объединении их в **политики** и проверке доступа с их помощью.
|
|
55
46
|
|
|
56
|
-
|
|
47
|
+
Пример: необходимо **запретить доступ** пользователям, связанным с отделом менеджеров, **за исключением администраторов**.
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
пользователи являются те пользователи, среди ролей которых имеется роль `manager`. Администраторы - пользователи имеющие
|
|
61
|
-
соответствующую роль (`administrator`).
|
|
49
|
+
- Менеджеры — если их отдел `managers` или есть роль `manager`
|
|
50
|
+
- Администраторы — пользователи с ролью `administrator`
|
|
62
51
|
|
|
63
|
-
|
|
52
|
+
Структура политики:
|
|
64
53
|
|
|
65
54
|

|
|
66
55
|
|
|
67
|
-
JSON
|
|
56
|
+
JSON-конфигурация:
|
|
68
57
|
|
|
69
58
|
```json
|
|
70
59
|
{
|
|
71
|
-
"name": "
|
|
72
|
-
"compareMethod":
|
|
60
|
+
"name": "Запрет доступа для менеджеров (исключение: администраторы)",
|
|
61
|
+
"compareMethod": "and",
|
|
73
62
|
"action": "order.update",
|
|
74
|
-
"effect":
|
|
63
|
+
"effect": "deny",
|
|
75
64
|
"ruleSet": [
|
|
76
65
|
{
|
|
77
66
|
"name": "Менеджеры",
|
|
78
|
-
"compareMethod":
|
|
67
|
+
"compareMethod": "or",
|
|
79
68
|
"rules": [
|
|
80
69
|
{
|
|
81
|
-
"name": "
|
|
82
|
-
"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"managers"
|
|
86
|
-
]
|
|
70
|
+
"name": "Отдел managers",
|
|
71
|
+
"subject": "user.department",
|
|
72
|
+
"resource": "managers",
|
|
73
|
+
"condition": "in"
|
|
87
74
|
},
|
|
88
75
|
{
|
|
89
|
-
"name": "
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"manager"
|
|
94
|
-
]
|
|
76
|
+
"name": "Роль manager",
|
|
77
|
+
"subject": "user.roles",
|
|
78
|
+
"resource": "manager",
|
|
79
|
+
"condition": "in"
|
|
95
80
|
}
|
|
96
81
|
]
|
|
97
82
|
},
|
|
98
83
|
{
|
|
99
84
|
"name": "Не администраторы",
|
|
100
|
-
"compareMethod":
|
|
85
|
+
"compareMethod": "and",
|
|
101
86
|
"rules": [
|
|
102
87
|
{
|
|
103
|
-
"name": "
|
|
104
|
-
"
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"administrator"
|
|
108
|
-
]
|
|
88
|
+
"name": "Нет роли administrator",
|
|
89
|
+
"subject": "user.roles",
|
|
90
|
+
"resource": "administrator",
|
|
91
|
+
"condition": "not in"
|
|
109
92
|
}
|
|
110
93
|
]
|
|
111
94
|
}
|
|
@@ -113,154 +96,343 @@ JSON представление такой политики будет имет
|
|
|
113
96
|
}
|
|
114
97
|
```
|
|
115
98
|
|
|
116
|
-
|
|
117
|
-
проверку (метод `check`):
|
|
99
|
+
Применение политики:
|
|
118
100
|
|
|
119
101
|
```ts
|
|
120
|
-
const jsonConfig = { ... }
|
|
121
|
-
|
|
122
|
-
const result = AbilityPolicy.parse(jsonConfig).check({
|
|
102
|
+
const jsonConfig = { ... };
|
|
103
|
+
AbilityPolicy.parse(jsonConfig).check({
|
|
123
104
|
user: {
|
|
124
105
|
department: 'managers',
|
|
125
|
-
roles: ['manager', '
|
|
106
|
+
roles: ['manager', 'coach'],
|
|
126
107
|
}
|
|
127
108
|
});
|
|
128
|
-
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
129
112
|
|
|
130
113
|
## Правила <a name="rules"></a>
|
|
131
114
|
|
|
132
|
-
|
|
133
|
-
|
|
115
|
+
**Правила** выполняют условие проверки и возвращают результат. **Основная цель** - выполнить сравнение переданных
|
|
116
|
+
значений субъекта и ресурса, а затем вернуть результат такого сравнения.
|
|
117
|
+
|
|
118
|
+
### Создание правила <a name="rule-creation"></a>
|
|
134
119
|
|
|
135
|
-
|
|
120
|
+
Создать правило можно двумя способами: создание через конструктор класса и парсинг JSON-конфига правила.
|
|
136
121
|
|
|
137
|
-
|
|
138
|
-
данном модуле.
|
|
122
|
+
При создании необходимо указать следующие параметры:
|
|
139
123
|
|
|
140
|
-
|
|
124
|
+
- **id** - `string` Уникальный идентификатор.
|
|
125
|
+
- **name** - `string` Название правила.
|
|
126
|
+
- **condition** - `AbilityCondition` Определяет условия сравнения переданных данных
|
|
127
|
+
- **subject** - `string` Dot notation путь в проверяемом субъекте, например: `user.name`.
|
|
128
|
+
- **resource** - `string | number | boolean | (string | number)[]` Dot notation путь в проверяемом ресурсе, например:
|
|
129
|
+
`user.name` или значение, которое может быть строкой, числом, булеан значением или массивом строк или чисел.
|
|
130
|
+
|
|
131
|
+
_Создание правила через конструктор класса:_
|
|
141
132
|
|
|
142
133
|
```ts
|
|
143
134
|
import { AbilityRule, AbilityCondition } from '@via-profit/ability';
|
|
144
135
|
|
|
145
136
|
const rule = new AbilityRule({
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
],
|
|
137
|
+
id: '<rule-id>',
|
|
138
|
+
name: 'Пользователь из отдела managers',
|
|
139
|
+
subject: 'user.department',
|
|
140
|
+
resource: 'managers',
|
|
141
|
+
condition: AbilityCondition.equal
|
|
152
142
|
});
|
|
153
143
|
|
|
154
144
|
```
|
|
155
145
|
|
|
156
|
-
|
|
157
|
-
значение которого будет равно (`=`) `managers`
|
|
146
|
+
_Создание правила через парсинг JSON-конфигурации:_
|
|
158
147
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
148
|
+
```ts
|
|
149
|
+
import { AbilityRule } from '@via-profit/ability';
|
|
150
|
+
|
|
151
|
+
const rule = AbilityRule.parse({
|
|
152
|
+
"id": "<rule-id>",
|
|
153
|
+
"name": "Пользователь из отдела managers",
|
|
154
|
+
"subject": "user.department",
|
|
155
|
+
"resource": "managers",
|
|
156
|
+
"condition": "="
|
|
157
|
+
});
|
|
163
158
|
|
|
164
|
-
|
|
159
|
+
```
|
|
165
160
|
|
|
166
|
-
|
|
167
|
-
import { AbilityRule, AbilityCondition } from '@via-profit/ability';
|
|
161
|
+
### Проверка правила <a name="rule-check"></a>
|
|
168
162
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
163
|
+
Для проверки правила следует вызвать метод `check` класса `AbilityRule` передав объект проверяемого ресурса. Этот метод
|
|
164
|
+
вернёт экземпляр класса
|
|
165
|
+
`AbilityMatch`, при помощи методов которого можно определить имеется ли совпадение правила и переданных значений.
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
import { AbilityRule } from '@via-profit/ability';
|
|
169
|
+
|
|
170
|
+
const rule = AbilityRule.parse({
|
|
171
|
+
"id": "<rule-id>",
|
|
172
|
+
"name": "Пользователь из отдела managers",
|
|
173
|
+
"subject": "user.department",
|
|
174
|
+
"resource": "managers",
|
|
175
|
+
"condition": "="
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
-
const
|
|
178
|
+
const match = rule.check({
|
|
179
179
|
user: {
|
|
180
180
|
department: 'managers',
|
|
181
|
-
}
|
|
181
|
+
},
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
+
const is = match.isEqual(AbilityMatch.match); // true
|
|
185
|
+
|
|
184
186
|
```
|
|
185
187
|
|
|
186
|
-
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Группы правил <a name="rule-sets"></a>
|
|
191
|
+
|
|
192
|
+
**Группы правил** необходимы для объединения нескольких правил в группу. **Основная цель** - выполнить проверку каждого
|
|
193
|
+
правила в группе и вернуть лишь один результат.
|
|
194
|
+
|
|
195
|
+
Создавая группу следует указывать метод сравнения (`compareMethod`), который необходим для вычисления значения всей
|
|
196
|
+
группы при проверке правил.
|
|
197
|
+
|
|
198
|
+
При создании необходимо указать следующие параметры:
|
|
199
|
+
|
|
200
|
+
- **id** - `string` Уникальный идентификатор.
|
|
201
|
+
- **name** - `string` Название группы.
|
|
202
|
+
- **compareMethod** - `AbilityCompare` Способ сравнения правил в группе (`or` или `and`).
|
|
203
|
+
|
|
204
|
+
_Влияние **compareMethod** на результат вычисления группы:_
|
|
205
|
+
|
|
206
|
+
- **`or`** - Результат всей группы примет значение `match`, если хотя бы одно из правил вернуло `match`.
|
|
207
|
+
- **`and`** - Результат всей группы примет значение `match`, если все правила вернули `match`.
|
|
208
|
+
|
|
209
|
+
### Создание группы правил <a name="ruleset-creation"></a>
|
|
187
210
|
|
|
188
|
-
|
|
211
|
+
Создать группу правил можно двумя способами: создание через конструктор класса и парсинг JSON-конфига группы.
|
|
212
|
+
|
|
213
|
+
_Создание группы через конструктор класса_:
|
|
189
214
|
|
|
190
215
|
```ts
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
216
|
+
import { AbilityRuleSet, AbilityCompare } from '@via-profit/ability';
|
|
217
|
+
|
|
218
|
+
const ruleSet = new AbilityRuleSet({
|
|
219
|
+
id: '<set-id>',
|
|
220
|
+
name: 'Название группы',
|
|
221
|
+
compareMethod: AbilityCompare.and,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// Добавление правил в группу
|
|
225
|
+
ruleSet.addRules([
|
|
226
|
+
new AbilityRule(...),
|
|
227
|
+
new AbilityRule(...),
|
|
228
|
+
]);
|
|
229
|
+
|
|
196
230
|
```
|
|
197
231
|
|
|
198
|
-
|
|
232
|
+
_Создание группы через парсинг JSON-конфига группы_:
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import { AbilityRuleSet } from '@via-profit/ability';
|
|
236
|
+
|
|
237
|
+
const ruleSet = AbilityRuleSet.parse({
|
|
238
|
+
'id': '<set-id>',
|
|
239
|
+
'name': 'Название группы',
|
|
240
|
+
'compareMethod': 'and',
|
|
241
|
+
'rules': [
|
|
242
|
+
{
|
|
243
|
+
'id': '<rule-id>',
|
|
244
|
+
'name': 'Пользователь из отдела managers',
|
|
245
|
+
'subject': 'user.department',
|
|
246
|
+
'resource': 'managers',
|
|
247
|
+
'condition': '=',
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
});
|
|
199
251
|
|
|
200
|
-
|
|
201
|
-
- `AbilityCondition.NOT_EQUAL` (`<>`) Не равно
|
|
202
|
-
- `AbilityCondition.MORE_THAN` (`>`) Больше
|
|
203
|
-
- `AbilityCondition.LESS_THAN` (`<`) Меньше
|
|
204
|
-
- `AbilityCondition.LESS_OR_EQUAL` (`<=`) Меньше или равно
|
|
205
|
-
- `AbilityCondition.MORE_OR_EQUAL` (`>=`) Больше или равно
|
|
206
|
-
- `AbilityCondition.IN` (`in` Вхождение в массив. Позволяет проверять вхождение значения в массив
|
|
207
|
-
- `AbilityCondition.NOT_IN` (`not in` Нет вхождения в массив. Позволяет проверять отсутствие значения в массив
|
|
252
|
+
```
|
|
208
253
|
|
|
209
|
-
###
|
|
254
|
+
### Проверка группы правил <a name="ruleset-check"></a>
|
|
210
255
|
|
|
211
|
-
|
|
212
|
-
|
|
256
|
+
Для проверки группы правил следует вызвать метод `check` класса `AbilityRuleSet` передав объект проверяемого ресурса.
|
|
257
|
+
Этот метод вернёт экземпляр класса `AbilityMatch`, при помощи методов которого можно определить имеется ли совпадение
|
|
258
|
+
для группы и переданных значений.
|
|
213
259
|
|
|
214
260
|
```ts
|
|
215
|
-
|
|
216
|
-
age: 18,
|
|
217
|
-
};
|
|
261
|
+
import { AbilityRuleSet, AbilityCompare } from '@via-profit/ability';
|
|
218
262
|
|
|
219
|
-
const
|
|
263
|
+
const ruleSet = new AbilityRuleSet({
|
|
264
|
+
id: '<set-id>',
|
|
265
|
+
name: 'Название группы',
|
|
266
|
+
compareMethod: AbilityCompare.and,
|
|
267
|
+
}).addRules([
|
|
268
|
+
new AbilityRule(...),
|
|
269
|
+
new AbilityRule(...),
|
|
270
|
+
]);
|
|
271
|
+
|
|
272
|
+
const match = rule.check({ ... });
|
|
273
|
+
|
|
274
|
+
const is = match.isEqual(AbilityMatch.match);
|
|
220
275
|
```
|
|
221
276
|
|
|
222
|
-
|
|
277
|
+
___
|
|
278
|
+
|
|
279
|
+
## Политики <a name="policies"></a>
|
|
280
|
+
|
|
281
|
+
**Политики** включают в себя группы правил. Основная цель - выполнить проверку всех вложенных групп, сравнить результат
|
|
282
|
+
выполнения групп и вернуть один единственный результат.
|
|
283
|
+
|
|
284
|
+
### Создание политики <a name="policy-creattion"></a>
|
|
285
|
+
|
|
286
|
+
Создать политику можно двумя способами: создание через конструктор класса и парсинг JSON-конфига политики.
|
|
287
|
+
|
|
288
|
+
При создании политики необходимо указать следующие параметры:
|
|
289
|
+
|
|
290
|
+
- **id** - `string` Уникальный идентификатор.
|
|
291
|
+
- **name** - `string` Название политики.
|
|
292
|
+
- **action** - `string` Ключ политики, в формате Dot notation, определяющий схожесть политик. В названии может
|
|
293
|
+
применяться символ звездочки (`*`). Политики с одинаковым экшеном обрабатываются вместе как группа политик. Экшен
|
|
294
|
+
`users.account` не считается похожим с экшеном `users.account.login`, но в это же время `users.account.*` равен экшену
|
|
295
|
+
`users.account.login` (из-за использования звездочки).
|
|
296
|
+
- **compareMethod** - `AbilityCompare` Метод сравнения групп правил, входящих в политику (`or` или `and`)
|
|
297
|
+
- **effect** - `AbilityPolicyEffect` Определяет итоговый результат всех вычислений (`permit` или `deny`). В слчае
|
|
298
|
+
использования класса `AbilityResolver` (метод `enforce`) последний выкинет исключение `AbilityError`, если политика
|
|
299
|
+
вернёт `deny`. Текст сообщения `AbilityError` будет соответствовать названию сработавшей политики. В остальных случаях
|
|
300
|
+
ничего не произойдет.
|
|
301
|
+
- **ruleSet** - `AbilityRuleSet[]` Массив групп (см. [Группы правил](#rule-sets))
|
|
223
302
|
|
|
224
|
-
|
|
225
|
-
|
|
303
|
+
**Замечание** - Политика может быть запрещающей (`effect` = `deny`) и разрешающей (`effect` = `permit`). Если вам
|
|
304
|
+
необходимо ограничить какой-либо доступ, например, пользователю с недостаточными правами, то следует создавать политику
|
|
305
|
+
с эффектом `deny`.
|
|
306
|
+
|
|
307
|
+
_Создание политики через конструктор класса_:
|
|
226
308
|
|
|
227
309
|
```ts
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
310
|
+
import { AbilityPolicy, AbilityCondition } from '@via-profit/ability';
|
|
311
|
+
|
|
312
|
+
const policy = new AbilityPolicy({
|
|
313
|
+
id: '<policy-id>',
|
|
314
|
+
name: 'Пример политики',
|
|
315
|
+
effect: 'deny',
|
|
316
|
+
action: 'users.update',
|
|
317
|
+
compareMethod: 'and',
|
|
318
|
+
ruleSet: [
|
|
319
|
+
new AbilityRule({
|
|
320
|
+
id: '<rule-id>',
|
|
321
|
+
name: 'Пользователь является владельцем заказа',
|
|
322
|
+
subject: 'user.id',
|
|
323
|
+
resource: 'order.owner',
|
|
324
|
+
condition: AbilityCondition.equal
|
|
325
|
+
})
|
|
326
|
+
]
|
|
327
|
+
});
|
|
231
328
|
|
|
232
|
-
const isPermit = new AbilityRule('has role', ['subject.roles', 'in', 'administrator']).isPermit(
|
|
233
|
-
user,
|
|
234
|
-
); // true
|
|
235
329
|
```
|
|
236
330
|
|
|
237
|
-
|
|
331
|
+
_Создание политики через парсинг JSON-конфига_:
|
|
238
332
|
|
|
239
|
-
|
|
240
|
-
|
|
333
|
+
```ts
|
|
334
|
+
import { AbilityPolicy } from '@via-profit/ability';
|
|
335
|
+
|
|
336
|
+
const policy = AbilityPolicy.parse({
|
|
337
|
+
"id": "bb758c1b-1015-4894-ba25-d23156e063cf",
|
|
338
|
+
"name": "Status hui",
|
|
339
|
+
"action": "order.status",
|
|
340
|
+
"effect": "deny",
|
|
341
|
+
"compareMethod": "and",
|
|
342
|
+
"ruleSet": [
|
|
343
|
+
{
|
|
344
|
+
"id": "9cc009e5-0aa9-453a-a668-cb3f418ced92",
|
|
345
|
+
"name": "Не администратор",
|
|
346
|
+
"compareMethod": "and",
|
|
347
|
+
"rules": [
|
|
348
|
+
{
|
|
349
|
+
"id": "4093cd50-e54f-4062-8053-2d3b5966fad3",
|
|
350
|
+
"name": "Нет роли администраторв",
|
|
351
|
+
"subject": "account.roles",
|
|
352
|
+
"resource": "administrator",
|
|
353
|
+
"condition": "<>"
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Проверка политики <a name="policy-check"></a>
|
|
363
|
+
|
|
364
|
+
Для проверки политики правил следует вызвать метод `check` класса `AbilityPolicy` передав объект проверяемого ресурса.
|
|
365
|
+
Этот метод вернёт экземпляр класса `AbilityMatch`, при помощи методов которого можно определить имеется ли совпадение
|
|
366
|
+
для группы и переданных значений.
|
|
241
367
|
|
|
242
368
|
```ts
|
|
243
|
-
|
|
244
|
-
id: '1',
|
|
245
|
-
};
|
|
369
|
+
import { AbilityPolicy } from '@via-profit/ability';
|
|
246
370
|
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
};
|
|
371
|
+
const policy = AbilityPolicy.parse({ ... });
|
|
372
|
+
|
|
373
|
+
const match = policy.check({ ... });
|
|
250
374
|
|
|
251
|
-
const
|
|
252
|
-
user,
|
|
253
|
-
order,
|
|
254
|
-
); // true
|
|
375
|
+
const is = match.isEqual(AbilityMatch.match);
|
|
255
376
|
```
|
|
256
377
|
|
|
257
|
-
|
|
378
|
+
___
|
|
258
379
|
|
|
259
|
-
##
|
|
380
|
+
## Управление политиками <a name="policy-management"></a>
|
|
381
|
+
|
|
382
|
+
Для управления политиками реализован специальный класс `AbilityResolver`.
|
|
383
|
+
|
|
384
|
+
В случае, если вам необходимо запустить лишь разовую проверку данных, то данный раздел можно опустить.
|
|
260
385
|
|
|
261
|
-
|
|
386
|
+
**AbilityResolver** необходим для возможности запуска проверки разных политик в разный период времени.
|
|
262
387
|
|
|
388
|
+
Политики содержат название экшена (поле `action`) определяемого разработчиком. Запуск метода `enforce` или `resolve`
|
|
389
|
+
отберет из всех переданных политик только те, которые попадают под указанный экшен.
|
|
390
|
+
|
|
391
|
+
```ts
|
|
392
|
+
import { AbilityPolicy, AbilityPolicyConfig, AbilityResolver } from './AbilityPolicy';
|
|
393
|
+
|
|
394
|
+
const config: AbilityPolicyConfig[] = [...]; // массив различных политик (JSON)
|
|
395
|
+
const policies: AbilityPolicy<Resources>[] = config.map(cfg => AbilityPolicy.parse(cfg)); // массив уже созданных политик
|
|
396
|
+
|
|
397
|
+
// Проверка политик с экшеном `order.create`
|
|
398
|
+
// Варинат 1. Будет выброшено исключение AbilityError
|
|
399
|
+
// c название политики, которая вернула deny,
|
|
400
|
+
// либо ничего не произойдет, если ни одна из политик
|
|
401
|
+
// не вернет deny
|
|
402
|
+
new AbilityResolver(policies).enforce('order.create', {
|
|
403
|
+
user: { department: 'managers' },
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// Вариант 2.
|
|
407
|
+
const isDeny = new AbilityResolver(policies)
|
|
408
|
+
.resolve('order.create', {
|
|
409
|
+
user: { department: 'managers' },
|
|
410
|
+
})
|
|
411
|
+
.isDeny();
|
|
412
|
+
|
|
413
|
+
if (isDeny) {
|
|
414
|
+
throw new AbilityError('Permission denied');
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
// Типы ресурсов, где каждый ключ будет являться название экшена
|
|
419
|
+
type Resources = {
|
|
420
|
+
['order.status']: { // <-- название экшена
|
|
421
|
+
readonly account: { // <-- данные ресурса
|
|
422
|
+
readonly roles: readonly string[];
|
|
423
|
+
};
|
|
424
|
+
};
|
|
425
|
+
['order.create']: {
|
|
426
|
+
readonly user: {
|
|
427
|
+
readonly department: string;
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
...
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
```
|
|
263
434
|
|
|
264
|
-
|
|
435
|
+
_Пояснение примера выше. В данном примере создается массив всех политик, а затем запускается проверка политик подходящих
|
|
436
|
+
по указанному экшену, а самое главное, что при помощи типа `Resources`, который необходимо формировать
|
|
437
|
+
вручную, **TypeScript** подскажет какие именно данные следует передать вторым аргументом (ресурс)._
|
|
265
438
|
|
|
266
|
-
Политику и правила можно создавать не только по средствам классов, но и при помощи конфигураций.
|