chyz 1.0.13-rc.8 → 1.1.0-rc.1

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.
Files changed (80) hide show
  1. package/BaseChyz.ts +79 -20
  2. package/Doc/Moel kullanma.md +13 -0
  3. package/Examples/Controllers/ApiController.ts +22 -22
  4. package/Examples/Controllers/BasicApiController.ts +121 -0
  5. package/Examples/Controllers/SiteController.ts +18 -8
  6. package/Examples/Models/AuthAssignment.ts +50 -0
  7. package/Examples/Models/AuthItem.ts +59 -0
  8. package/Examples/Models/AuthItemChild.ts +49 -0
  9. package/Examples/Models/Categories.ts +4 -0
  10. package/Examples/Models/KeycloakUser.ts +4 -0
  11. package/Examples/Models/User.ts +8 -1
  12. package/Examples/index.ts +22 -2
  13. package/Examples/log/app.log +14466 -0
  14. package/Examples/log/errors.log +594 -0
  15. package/Examples/package.json +5 -2
  16. package/README.md +265 -12
  17. package/base/ActionFilter.ts +1 -1
  18. package/base/BaseError.ts +4 -2
  19. package/base/DbConnection.ts +9 -5
  20. package/base/InvalidArgumentException.ts +16 -0
  21. package/base/Model.ts +231 -34
  22. package/base/ModelManager.ts +6 -1
  23. package/base/RestClient.ts +4 -4
  24. package/base/ValidationHttpException.ts +1 -1
  25. package/base/index.ts +1 -0
  26. package/dist/BaseChyz.js +67 -15
  27. package/dist/BaseChyz.js.map +1 -1
  28. package/dist/base/ActionFilter.js +1 -1
  29. package/dist/base/ActionFilter.js.map +1 -1
  30. package/dist/base/BaseError.js +6 -2
  31. package/dist/base/BaseError.js.map +1 -1
  32. package/dist/base/DbConnection.js +1 -0
  33. package/dist/base/DbConnection.js.map +1 -1
  34. package/dist/base/InvalidArgumentException.js +18 -0
  35. package/dist/base/InvalidArgumentException.js.map +1 -0
  36. package/dist/base/Model.js +192 -4
  37. package/dist/base/Model.js.map +1 -1
  38. package/dist/base/ModelManager.js +0 -8
  39. package/dist/base/ModelManager.js.map +1 -1
  40. package/dist/base/RestClient.js +4 -4
  41. package/dist/base/RestClient.js.map +1 -1
  42. package/dist/base/ValidationHttpException.js +1 -1
  43. package/dist/base/index.js +1 -0
  44. package/dist/base/index.js.map +1 -1
  45. package/dist/filters/AccessControl.js +15 -3
  46. package/dist/filters/AccessControl.js.map +1 -1
  47. package/dist/filters/AccessRule.js +99 -38
  48. package/dist/filters/AccessRule.js.map +1 -1
  49. package/dist/filters/auth/HttpBasicAuth.js +65 -0
  50. package/dist/filters/auth/HttpBasicAuth.js.map +1 -1
  51. package/dist/filters/auth/JwtHttpBearerAuth.js +1 -1
  52. package/dist/filters/auth/JwtHttpBearerAuth.js.map +1 -1
  53. package/dist/filters/auth/index.js +1 -0
  54. package/dist/filters/auth/index.js.map +1 -1
  55. package/dist/package.json +7 -5
  56. package/dist/rbac/AuthAssignment.js +45 -0
  57. package/dist/rbac/AuthAssignment.js.map +1 -0
  58. package/dist/rbac/AuthItem.js +52 -0
  59. package/dist/rbac/AuthItem.js.map +1 -0
  60. package/dist/rbac/AuthItemChild.js +44 -0
  61. package/dist/rbac/AuthItemChild.js.map +1 -0
  62. package/dist/rbac/AuthManager.js +359 -0
  63. package/dist/rbac/AuthManager.js.map +1 -0
  64. package/dist/requiments/Utils.js +5 -1
  65. package/dist/requiments/Utils.js.map +1 -1
  66. package/dist/web/WebUser.js +78 -0
  67. package/dist/web/WebUser.js.map +1 -1
  68. package/filters/AccessControl.ts +19 -6
  69. package/filters/AccessRule.ts +61 -16
  70. package/filters/auth/HttpBasicAuth.ts +68 -0
  71. package/filters/auth/JwtHttpBearerAuth.ts +1 -1
  72. package/filters/auth/index.ts +1 -0
  73. package/package.json +7 -5
  74. package/rbac/AuthAssignment.ts +50 -0
  75. package/rbac/AuthItem.ts +57 -0
  76. package/rbac/AuthItemChild.ts +50 -0
  77. package/rbac/AuthManager.ts +398 -0
  78. package/requiments/Utils.ts +6 -0
  79. package/web/IdentityInterface.ts +6 -0
  80. package/web/WebUser.ts +88 -1
@@ -0,0 +1,398 @@
1
+ import {Component, DataErrorDbException, InvalidConfigException, ModelManager, UnauthorizedHttpException} from "../base";
2
+ import {BaseChyz, InvalidArgumentException} from "../index";
3
+ import Utils from "../requiments/Utils";
4
+
5
+
6
+ interface Role {
7
+ type: number;
8
+ name: string;
9
+ description: string;
10
+ ruleName: string;
11
+ data: string;
12
+ params: string;
13
+ }
14
+
15
+ interface Permission {
16
+ type: number;
17
+ name: string;
18
+ description: string;
19
+ ruleName: string;
20
+ data: string;
21
+ params: string;
22
+ }
23
+
24
+
25
+ export class AuthManager extends Component {
26
+ static readonly TYPE_ROLE = 1;
27
+ static readonly TYPE_PERMISSION = 2;
28
+
29
+ init() {
30
+ BaseChyz.info("Auth Manager init....")
31
+ }
32
+
33
+ /**
34
+ * @var Item[] all auth items (name => Item)
35
+ */
36
+ protected items: any;
37
+ checkAccessAssignments: any = {}
38
+ defaultRoles: any = {}
39
+
40
+
41
+ /**
42
+ *
43
+ */
44
+
45
+ public async checkAccess(userId: number, permissionName: string, params: any[] = []): Promise<boolean> {
46
+ let assignments: any;
47
+ if (!this.checkAccessAssignments[userId.toString()]) {
48
+ assignments = await this.getAssignments(userId);
49
+ this.checkAccessAssignments[userId.toString()] = assignments;
50
+ } else {
51
+ assignments = this.checkAccessAssignments[userId.toString()]
52
+ }
53
+
54
+
55
+ // BaseChyz.info("assignments",assignments)
56
+ if (this.hasNoAssignments(assignments)) {
57
+ return false;
58
+ }
59
+
60
+
61
+ return await this.checkAccessRecursive(userId, permissionName, params, assignments);
62
+ }
63
+
64
+ async checkAccessFromCache() {
65
+
66
+
67
+ }
68
+
69
+ public async checkAccessRecursive(user: string | number, itemname: string, params: any[], assignments: any): Promise<boolean> {
70
+ let item: any = await this.getItem(itemname);
71
+ if (!item) return false;
72
+
73
+ /**
74
+ * @todo
75
+ * Rule test edilmeli
76
+ */
77
+
78
+ if (assignments[itemname] || Utils.find(this.defaultRoles, itemname)) {
79
+ return true;
80
+ }
81
+
82
+ /**
83
+ * item child
84
+ */
85
+ let parents = await ModelManager.AuthItemChild.findAll({attributes:["parent"], where: {child: itemname}});
86
+ for (const parent of parents) {
87
+ let r = await this.checkAccessRecursive(user, parent.parent, params, assignments);
88
+ if (r) {
89
+ return true;
90
+ }
91
+ }
92
+
93
+ return false;
94
+
95
+ }
96
+
97
+ /**
98
+ *
99
+ * @param name
100
+ */
101
+ public async getItem(name: string) {
102
+ if (!name) return null;
103
+
104
+ return await ModelManager.AuthItem.findOne({where: {name: name}})
105
+
106
+ }
107
+
108
+ public async getItems(type: number) {
109
+ let items: any = {};
110
+ let _items = await ModelManager.AuthItem.findAll({where: {type: type}})
111
+ if (_items)
112
+ _items.forEach((item: any) => {
113
+ items[item["name"]] = item.dataValues as Role;
114
+ })
115
+
116
+ return items
117
+
118
+ }
119
+
120
+ public async getRolesByUser(userId: number) {
121
+ if (this.isEmptyUserId(userId.toString())) {
122
+ return [];
123
+ }
124
+
125
+
126
+ let roles: any = {}
127
+ let items = await ModelManager.AuthAssignment.findAll({
128
+ where: {
129
+ user_id: userId.toString(),
130
+ '$AuthItemClasses.type$': AuthManager.TYPE_ROLE
131
+ },
132
+ include: [{
133
+ model: ModelManager.AuthItem.model()
134
+ }]
135
+ })
136
+ for (const item of items) {
137
+ for (const i of item.AuthItemClasses)
138
+ roles[i["name"]] = i.dataValues as Role;
139
+ }
140
+
141
+ return roles;
142
+
143
+ }
144
+
145
+ /**
146
+ *
147
+ * @param roleName
148
+ */
149
+ public async getChildRoles(roleName: string) {
150
+ let role = await this.getRole(roleName);
151
+ if (role === null) {
152
+ throw new InvalidArgumentException(`Role "${roleName}" not found.`);
153
+ }
154
+ const result: any = {result: {}};
155
+ await this.getChildrenRecursive(roleName, await this.getChildrenList(), result);
156
+ let roles: any = {};
157
+ roles[roleName] = role;
158
+ let _roles = await this.getRoles();
159
+ let _r: any = {};
160
+ Utils.forEach(_roles, (item: Role) => {
161
+ if (result.result[item.name])
162
+ _r[item.name] = item;
163
+ })
164
+
165
+
166
+ return Utils.merge(roles, _r);
167
+ }
168
+
169
+ /**
170
+ *
171
+ * @param roleName
172
+ */
173
+ public async getPermissionsByRole(roleName: string) {
174
+ let childrenList = this.getChildrenList();
175
+ const result = {result: {}}
176
+ let permissions: any = {}
177
+ await this.getChildrenRecursive(roleName, childrenList, result);
178
+ if (Utils.isEmpty(result.result)) {
179
+ return {};
180
+ }
181
+
182
+ let itemResult = await ModelManager.AuthItem.findAll({
183
+ where: {
184
+ type: AuthManager.TYPE_PERMISSION,
185
+ name: Object.keys(result.result)
186
+ }
187
+ });
188
+ for (const itemElement of itemResult) {
189
+ permissions[itemElement["name"]] = itemElement.dataValues as Permission
190
+ }
191
+
192
+ return permissions;
193
+
194
+ }
195
+
196
+ /**
197
+ *
198
+ * @param userId
199
+ */
200
+ public async getPermissionsByUser(userId: number) {
201
+
202
+ if (this.isEmptyUserId(userId.toString())) {
203
+ return {};
204
+ }
205
+
206
+ let directPermission = await this.getDirectPermissionsByUser(userId);
207
+ let inheritedPermission = await this.getInheritedPermissionsByUser(userId);
208
+
209
+ return Utils.merge(directPermission, inheritedPermission);
210
+ }
211
+
212
+ /**
213
+ * Returns all permissions that are directly assigned to user.
214
+ * @return Permission[] all direct permissions that the user has. The array is indexed by the permission names.
215
+ */
216
+ protected async getDirectPermissionsByUser(userId: number) {
217
+ let permissions: any = {}
218
+ let result = await ModelManager.AuthAssignment.findAll({
219
+ where: {
220
+ user_id: userId.toString(),
221
+ '$AuthItemClasses.type$': AuthManager.TYPE_PERMISSION
222
+ },
223
+ include: [
224
+ {
225
+ model: ModelManager.AuthItem.model()
226
+ }
227
+ ]
228
+ })
229
+
230
+ for (const resultElement of result) {
231
+ for (const i of resultElement.AuthItemClasses)
232
+ permissions[i["name"]] = i.dataValues as Permission;
233
+ }
234
+
235
+
236
+ return permissions;
237
+ }
238
+
239
+ protected async getInheritedPermissionsByUser(userId: number) {
240
+ let userAssignment = await ModelManager.AuthAssignment.findAll({where: {user_id: userId.toString()}, attributes: ["item_name"]});
241
+ let childrenList = await this.getChildrenList();
242
+ const result: any = {result: {}}
243
+ let permissions: any = {}
244
+
245
+ for (const userAssignmentElement of userAssignment) {
246
+ this.getChildrenRecursive(userAssignmentElement.item_name, childrenList, result);
247
+ }
248
+
249
+ if (Utils.isEmpty(result.result)) {
250
+ return {};
251
+ }
252
+
253
+ let itemResult = await ModelManager.AuthItem.findAll({
254
+ where: {
255
+ type: AuthManager.TYPE_PERMISSION,
256
+ name: Object.keys(result.result)
257
+ }
258
+ });
259
+ for (const itemElement of itemResult) {
260
+ permissions[itemElement["name"]] = itemElement.dataValues as Permission
261
+ }
262
+
263
+ return permissions;
264
+ }
265
+
266
+
267
+ /**
268
+ *
269
+ * @param userId
270
+ */
271
+ public async getItemsByUser(userId: number) {
272
+ let items = await ModelManager.AuthAssignment.findAll({
273
+ where: {
274
+ user_id: userId.toString()
275
+ },
276
+ include: [{
277
+ model: ModelManager.AuthItem.model()
278
+ }]
279
+ })
280
+
281
+ return items;
282
+ }
283
+
284
+
285
+ /**
286
+ * Returns all role assignment information for the specified role.
287
+ * @param $roleName
288
+ */
289
+ public async getUserIdsByRole(roleName: number) {
290
+ if (!roleName) return [];
291
+
292
+ return await ModelManager.AuthAssignment.findAll({where: {"item_name": roleName}, attributes: ["user_id"]});
293
+ }
294
+
295
+
296
+ /**
297
+ * {@inheritdoc}
298
+ */
299
+ public async getRole(name: string) {
300
+ let item: Role = await this.getItem(name);
301
+ return item && item.type == AuthManager.TYPE_ROLE ? item : null;
302
+ }
303
+
304
+
305
+ /**
306
+ * {@inheritdoc}
307
+ */
308
+ public getRoles() {
309
+ return this.getItems(AuthManager.TYPE_ROLE);
310
+ }
311
+
312
+ /**
313
+ * Recursively finds all children and grand children of the specified item.
314
+ * @param string $name the name of the item whose children are to be looked for.
315
+ * @param array $childrenList the child list built via [[getChildrenList()]]
316
+ * @param array $result the children and grand children (in array keys)
317
+ */
318
+ protected getChildrenRecursive(name: string, childrenList: any, model: any) {
319
+ if (childrenList[name]) {
320
+ for (const child of childrenList[name]) {
321
+ model.result[child] = true;
322
+ this.getChildrenRecursive(child, childrenList, model);
323
+ }
324
+ }
325
+
326
+ }
327
+
328
+
329
+ /**
330
+ *
331
+ * @param roleName
332
+ * @param userId
333
+ */
334
+ public getAssignment(roleName: string, userId: string) {
335
+ if (this.isEmptyUserId(userId)) {
336
+ return [];
337
+ }
338
+ return ModelManager.AuthAssignment.findAll({where: {user_id: userId, items_name: roleName}});
339
+
340
+ }
341
+
342
+ /**
343
+ *
344
+ */
345
+ public async getAssignments(userId: number) {
346
+ if (this.isEmptyUserId(userId.toString())) {
347
+ return {};
348
+ }
349
+
350
+ let assignments: any = {};
351
+ try {
352
+
353
+ let as = await ModelManager.AuthAssignment.findAll({where: {user_id: userId.toString()}});
354
+ for (const a of as) {
355
+ assignments[a["item_name"]] = a;
356
+ }
357
+ } catch (e) {
358
+ throw new InvalidConfigException('The user application component must be available to specify roles in AccessRule.');
359
+ }
360
+ return assignments;
361
+ }
362
+
363
+ /**
364
+ * Returns the children for every parent.
365
+ * @return array the children list. Each array key is a parent item name,
366
+ * and the corresponding array value is a list of child item names.
367
+ */
368
+ protected async getChildrenList() {
369
+ let items = await ModelManager.AuthItemChild.findAll();
370
+ let parents: any = {};
371
+ for (const item of items) {
372
+ parents[item["parent"]] = Utils.concat(parents[item["parent"]] || [], [item["child"]]);
373
+ }
374
+
375
+ return parents
376
+ }
377
+
378
+ /**
379
+ * Check whether $userId is empty.
380
+ * @param mixed $userId
381
+ * @return bool
382
+ * @since 2.0.26
383
+ */
384
+ protected isEmptyUserId(userId: string) {
385
+ return !userId || userId === '';
386
+ }
387
+
388
+ /**
389
+ * Checks whether array of $assignments is empty and [[defaultRoles]] property is empty as well.
390
+ *
391
+ * @param Assignment[] $assignments array of user's assignments
392
+ * @return bool whether array of $assignments is empty and [[defaultRoles]] property is empty as well
393
+ * @since 2.0.11
394
+ */
395
+ protected hasNoAssignments(assignments: any) {
396
+ return Utils.isEmpty(assignments) && Utils.isEmpty(this.defaultRoles)
397
+ }
398
+ }
@@ -48,7 +48,13 @@ function wildTest(wildcard: string, str: string) {
48
48
  const matchWildcard = (pattern: string, string: string, options: any = {}) => {
49
49
  return wildTest(pattern, string)
50
50
  }
51
+
52
+ const t = function (text: string) {
53
+ return text;
54
+ }
55
+
51
56
  export default {
57
+ t,
52
58
  createObject,
53
59
  findKeyValue,
54
60
  sleep,
@@ -59,4 +59,10 @@ export interface IdentityInterface {
59
59
  */
60
60
  validateAuthKey(authKey: string): (boolean | null);
61
61
 
62
+
63
+ /**
64
+ *
65
+ */
66
+ can(permissionName:string, params: any[] , allowCaching: boolean ): (boolean | null);
67
+
62
68
  }
package/web/WebUser.ts CHANGED
@@ -9,6 +9,8 @@ import {Component} from "../base/Component";
9
9
  import {ForbiddenHttpException} from "../base/ForbiddenHttpException";
10
10
  import {InvalidConfigException} from "../base/InvalidConfigException";
11
11
  import {IdentityInterface} from "./IdentityInterface";
12
+ import Utils from "../requiments/Utils";
13
+ import {AuthManager} from "../rbac/AuthManager";
12
14
 
13
15
  export class WebUser extends Component {
14
16
 
@@ -17,6 +19,13 @@ export class WebUser extends Component {
17
19
  */
18
20
  public identityClass: any;
19
21
  private _identity: any;
22
+ /**
23
+ * @var CheckAccessInterface|string|array The access checker object to use for checking access or the application
24
+ * component ID of the access checker.
25
+ * If not set the application auth manager will be used.
26
+ * @since 2.0.9
27
+ */
28
+ public accessChecker: any = null;
20
29
 
21
30
 
22
31
  get identity() {
@@ -75,7 +84,7 @@ export class WebUser extends Component {
75
84
  if (this.identity && this.login(this.identity)) {
76
85
  return this.identity;
77
86
  }
78
- }else{
87
+ } else {
79
88
  BaseChyz.error("WebUser::findIdentityByAccessToken undefined")
80
89
  }
81
90
  return null;
@@ -97,4 +106,82 @@ export class WebUser extends Component {
97
106
  public afterLogin() {
98
107
 
99
108
  }
109
+
110
+ public getId() {
111
+ let identity = this.getIdentity();
112
+ return identity !== null ? identity.id : null;
113
+ }
114
+
115
+ /**
116
+ * Checks if the user can perform the operation as specified by the given permission.
117
+ *
118
+ * Note that you must configure "authManager" application component in order to use this method.
119
+ * Otherwise it will always return false.
120
+ *
121
+ * @param string $permissionName the name of the permission (e.g. "edit post") that needs access check.
122
+ * @param array $params name-value pairs that would be passed to the rules associated
123
+ * with the roles and permissions assigned to the user.
124
+ * @param bool $allowCaching whether to allow caching the result of access check.
125
+ * When this parameter is true (default), if the access check of an operation was performed
126
+ * before, its result will be directly returned when calling this method to check the same
127
+ * operation. If this parameter is false, this method will always call
128
+ * [[\yii\rbac\CheckAccessInterface::checkAccess()]] to obtain the up-to-date access result. Note that this
129
+ * caching is effective only within the same request and only works when `$params = []`.
130
+ * @return bool whether the user can perform the operation as specified by the given permission.
131
+ */
132
+ // public function can($permissionName, $params = [], $allowCaching = true)
133
+ // {
134
+ // if ($allowCaching && empty($params) && isset($this->_access[$permissionName])) {
135
+ // return $this->_access[$permissionName];
136
+ // }
137
+ // if (($accessChecker = $this->getAccessChecker()) === null) {
138
+ // return false;
139
+ // }
140
+ // $access = $accessChecker->checkAccess($this->getId(), $permissionName, $params);
141
+ // if ($allowCaching && empty($params)) {
142
+ // $this->_access[$permissionName] = $access;
143
+ // }
144
+ //
145
+ // return $access;
146
+ // }
147
+
148
+ public async can(permissionName: string, params = [], allowCaching = true) {
149
+
150
+ let access;
151
+ let accessChecker: AuthManager;
152
+ if ((accessChecker = this.getAccessChecker()) == null)
153
+ return false;
154
+
155
+
156
+ access = await accessChecker.checkAccess(this.getId(), permissionName, params);
157
+
158
+ if (allowCaching && Utils.isEmpty(params)) {
159
+ // this._access[$permissionName] = $access;
160
+ }
161
+
162
+ return access;
163
+
164
+ }
165
+
166
+ /**
167
+ * Returns auth manager associated with the user component.
168
+ *
169
+ * By default this is the `authManager` application component.
170
+ * You may override this method to return a different auth manager instance if needed.
171
+ * @return \yii\rbac\ManagerInterface
172
+ * @since 2.0.6
173
+ */
174
+ protected getAuthManager(): AuthManager {
175
+ return BaseChyz.getComponent('authManager');
176
+ }
177
+
178
+ /**
179
+ * Returns the access checker used for checking access.
180
+ * @return CheckAccessInterface
181
+ */
182
+ protected getAccessChecker():AuthManager {
183
+ return this.accessChecker !== null ? this.accessChecker : this.getAuthManager();
184
+ }
185
+
186
+
100
187
  }