@qikdev/sdk 0.1.14 → 0.1.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qikdev/sdk",
3
- "version": "0.1.14",
3
+ "version": "0.1.18",
4
4
  "type": "module",
5
5
  "description": "Promise based Javascript SDK",
6
6
  "scripts": {
@@ -40,7 +40,7 @@
40
40
  "dependencies": {
41
41
  "axios": "^0.19.2",
42
42
  "axios-extensions": "^3.1.2",
43
- "lodash": "^4.17.15"
43
+ "lodash": "^4.17.21"
44
44
  },
45
45
  "directories": {
46
46
  "test": "test"
@@ -1,18 +1,3 @@
1
- import _ from 'lodash';
2
- import { EventDispatcher } from './qik.utils.js';
3
-
4
-
5
- ///////////////////////////////////////////////////////////////////////////////
6
-
7
- /**
8
- * Creates a new QikAccess service
9
- * This module provides helpful functions and tools for managing and understanding a user's permissions and access control
10
- *
11
- * @alias access
12
- * @constructor
13
- * @hideconstructor
14
- * @param {QikCore} qik A reference to the parent instance of the QikCore module. This module is usually created by a QikCore instance that passes itself in as the first argument.
15
- */
16
1
  var QikAccess = function(QikCore) {
17
2
 
18
3
 
@@ -20,66 +5,435 @@ var QikAccess = function(QikCore) {
20
5
  throw new Error(`Can't Instantiate QikAccess before QikAccess has been initialized`);
21
6
  }
22
7
 
8
+ if (!QikCore.utils) {
9
+ throw new Error(`Can't Instantiate QikAccess before QikUtils has been initialized`);
10
+ }
11
+
23
12
  //////////////////////////////////
24
13
 
25
- var store = {};
26
14
  var service = {};
27
15
 
28
- //Create a new dispatcher
29
- var dispatcher = new EventDispatcher();
30
- dispatcher.bootstrap(service);
16
+ ///////////////////////////////////////////////
17
+
18
+ service.isAdministrator = function(user) {
19
+ return user && user.userType == 'administrator';
20
+ }
21
+
22
+ ///////////////////////////////////////////////
23
+
24
+ service.getAllDescendants = function(scope) {
25
+
26
+ //Start by including the scope id
27
+ var results = [];
28
+
29
+ addScope(scope);
30
+
31
+ function addScope(entry) {
32
+ //Add this scope to the results
33
+ var id = QikCore.utils.id(entry);
34
+ results.push(id);
35
+
36
+ (entry.children || []).forEach(function(child) {
37
+ addScope(child);
38
+ })
39
+ }
40
+ return results;
41
+
42
+
43
+ }
44
+
45
+ ///////////////////////////////////////////////
46
+
47
+ service.hashPermissions = function(user) {
48
+
49
+ var results = {};
50
+
51
+ for (var key in (user.permissions || {})) {
31
52
 
53
+ //Get the permission set
54
+ var permissionSet = user.permissions[key];
32
55
 
33
- ///////////////////////////////////////////////////////////////////////////////
56
+ //Get all Scope ids from the permission set
57
+ var allIDs = service.getAllDescendants(permissionSet);
34
58
 
35
- /**
36
- * Check whether a user has a specific permission, useful for checking custom permissions
37
- * or simply whether or not a user has a permission in any realm
38
- * @param {String} permission The permission to check
39
- * @return {Boolean}
40
- * @alias access.has
41
- * @example
42
- *
43
- * //Returns true or false if the user has the permission
44
- * var hasPermission = qik.access.has('create photo');
45
- */
46
- service.has = function(permission, webMode) {
59
+ //For each permission defined in the set
60
+ (permissionSet.permissions || []).forEach(function(permissionString) {
61
+ //Include the top scope
62
+ if (!results[permissionString]) {
63
+ results[permissionString] = []
64
+ }
65
+ results[permissionString] = [...new Set(results[permissionString].concat(allIDs))]
66
+ });
67
+ }
68
+
69
+ ///////////////////////////////////////////////
70
+
71
+ return results;
72
+
73
+ }
74
+
75
+
76
+ ///////////////////////////////////////////////
77
+
78
+ service.allUserScopes = function(user) {
79
+
80
+ var collected = {};
81
+ var permissions = user.permissions || {};
82
+
83
+ ////////////////////////
84
+
85
+ function pluckScope(scopeObject) {
86
+
87
+ if (!scopeObject) {
88
+ return;
89
+ }
90
+
91
+ var scopeID = QikUtils.id(scopeObject);
92
+ if (!scopeID) {
93
+ return;
94
+ }
95
+
96
+ //Add to the collection
97
+ collected[scopeID] = 1;
98
+
99
+ //If there are children, then recursively pluck the ids
100
+ if (scopeObject.children && scopeObject.children.length) {
101
+ scopeObject.children.forEach(function(scope) {
102
+ pluckScope(scope);
103
+ })
104
+ }
105
+ }
106
+
107
+ ////////////////////////
108
+
109
+ for (var scopeID in permissions) {
110
+ pluckScope(permissions[scopeID]);
111
+ }
112
+
113
+ ////////////////////////
114
+
115
+ return Object.keys(collected);
116
+ }
47
117
 
48
- //Get the current acting user session
49
- var user = service.retrieveCurrentSession(webMode);
118
+ ///////////////////////////////////////////////
50
119
 
51
- if (!user) {
120
+ service.actionableScopes = function(user, action, definition, type, options) {
121
+ options = options || {}
122
+
123
+ /////////////////////////
124
+
125
+ var validScopes = [];
126
+
127
+ if (user.userType == 'administrator') {
128
+ validScopes = service.allUserScopes(user, options)
129
+ } else {
130
+ var permissionsLookup = service.hashPermissions(user);
131
+
132
+ var checkTypeName = definition || type;
133
+ if (!checkTypeName) {
134
+ return validScopes;
135
+ }
136
+
137
+ var stringKey = `${checkTypeName}.${action}`;
138
+ validScopes = permissionsLookup[stringKey]
139
+ }
140
+
141
+ /////////////////////////
142
+
143
+ return validScopes || []
144
+ }
145
+
146
+
147
+ ///////////////////////////////////////////////
148
+
149
+ service.isOwner = function(user, item) {
150
+ var userID = QikUtils.id(user);
151
+ var personaID = QikUtils.id(user.persona);
152
+
153
+
154
+ var metaObject = item.meta;
155
+ if (!metaObject) {
52
156
  return false;
53
157
  }
54
158
 
55
- if (service.isQikAdmin() && !webMode) {
159
+ /////////////////////////////////////////////
160
+
161
+ var users = QikUtils.ids([...metaObject.userOwners, metaObject.userAuthor]);
162
+ var userHash = helpers.hash(users);
163
+ // console.log('USERS', users, userHash, '-', metaObject.userAuthor, metaObject.userOwners);
164
+
165
+ if (userHash[userID]) {
56
166
  return true;
57
167
  }
58
168
 
59
- ///////////////////////////////////////////////////////////////////////////////
169
+ /////////////////////////////////////////////
170
+
171
+ var personas = QikUtils.ids([...metaObject.personaOwners, metaObject.personaAuthor]);
172
+ var personaHash = helpers.hash(personas);
173
+ // console.log('PERSONAS', personas, personaHash, '-', metaObject.personaAuthor, metaObject.personaOwners)
174
+
175
+ if (personaHash[personaID]) {
176
+ return true;
177
+ }
178
+
179
+ }
60
180
 
61
- var permissionSets = user.permissionSets;
62
181
 
63
- //Get all of the possible permissions
64
- var permissions = _.chain(permissionSets)
65
- .reduce(function(results, set, key) {
182
+ ///////////////////////////////////////////////
66
183
 
67
- results.push(set.permissions);
184
+ service.allPermissions = function(user) {
68
185
 
69
- return results;
70
- }, [])
71
- // .map(retrieveSubRealms)
72
- .flattenDeep()
73
- .compact()
74
- .uniq()
75
- .value();
186
+ var allPermissions = Object.values(user.permissions)
187
+ .map(function(permissionScope) {
188
+ return permissionScope.permissions;
189
+ })
190
+ .flat();
76
191
 
77
- //Check if any of the users permissions include the one
78
- //we are looking for
79
- return _.includes(permissions, permission);
192
+ return allPermissions;
80
193
  }
81
194
 
82
- //////////////////////////////////
195
+ ///////////////////////////////////////////////
196
+
197
+ service.allPermissionTypes = function(user, asHash) {
198
+ if (asHash) {
199
+ return service.allPermissions(user).reduce(function(set, string) {
200
+ var type = string.split('.')[0];
201
+ set[type] = true;
202
+ return set;
203
+ }, {});
204
+ } else {
205
+ return service.allPermissions(user).map(function(string) {
206
+ return string.split('.')[0];
207
+ });
208
+ }
209
+
210
+ }
211
+
212
+ ///////////////////////////////////////////////
213
+
214
+ service.canKnowOf = function(user, typeKey, options) {
215
+ options = options || {};
216
+ options.cache = options.cache || {};
217
+
218
+ //Let us know if there are any permissions for this user
219
+ return service.allPermissionTypes(user)[typeKey];
220
+ }
221
+
222
+
223
+ ///////////////////////////////////////////////
224
+
225
+ service.checkActionAccess = function(user, item, ANY_ACTION, OWN_ACTION, options) {
226
+
227
+ options = options || {};
228
+ options.cache = options.cache || {};
229
+
230
+ //Allow everything if we're a super user
231
+ if (service.isAdministrator(user)) {
232
+ return true;
233
+ }
234
+
235
+ //////////////////////////////////
236
+
237
+ var type = item.meta.type;
238
+ var definition = item.meta.definition || type;
239
+
240
+ //////////////////////////////////
241
+
242
+ var itemScopes = item.meta.scopes || [];
243
+
244
+ //////////////////////////////////
245
+
246
+ var actionAnyScopesHash;
247
+ var anyCacheKey = `access-${user.cacheKey}-${ANY_ACTION}-${definition}-${type}`
248
+
249
+ if (options.cache[anyCacheKey]) {
250
+ actionAnyScopesHash = options.cache[anyCacheKey];
251
+
252
+ } else {
253
+ //Check if we can view this type of thing in any scopes
254
+ var actionAnyScopes = service.actionableScopes(user, ANY_ACTION, definition, type, options);
255
+
256
+ //Get a fash hash of the scopes
257
+ actionAnyScopesHash = helpers.hash(actionAnyScopes);
258
+ options.cache[anyCacheKey] = actionAnyScopesHash;
259
+ }
260
+
261
+ //////////////////////////////////
262
+
263
+ //If we have data about what they can do
264
+ if (actionAnyScopesHash) {
265
+ //Check if the item is in any of the scopes the user can access
266
+ var isInAnyScopes = itemScopes.some(function(scopeID) {
267
+ return actionAnyScopesHash[scopeID];
268
+ })
269
+
270
+ if (isInAnyScopes) {
271
+ return true;
272
+ }
273
+ }
274
+
275
+ //////////////////////////////////
276
+
277
+ //Check if the user owns this content
278
+ var isOwner = service.isOwner(user, item);
279
+
280
+ //If the user is the owner
281
+ if (isOwner) {
282
+ var actionOwnScopesHash;
283
+ var ownCacheKey = `access-${user.cacheKey}-${OWN_ACTION}-${definition}-${type}`
284
+
285
+ if (options.cache[ownCacheKey]) {
286
+ actionOwnScopesHash = options.cache[ownCacheKey];
287
+ } else {
288
+
289
+ //Check if we can view this type of thing in any scopes
290
+ var actionOwnScopes = service.actionableScopes(user, OWN_ACTION, definition, type, options);
291
+ //Get a fash hash of the scopes
292
+ actionOwnScopesHash = helpers.hash(actionOwnScopes);
293
+ options.cache[ownCacheKey] = actionOwnScopesHash;
294
+ }
295
+
296
+ //If we have data about what they can do
297
+ if (actionOwnScopesHash) {
298
+ //Check if the item is in any of the scopes the user can access
299
+ var isInOwnScopes = itemScopes.some(function(scopeID) {
300
+ return actionOwnScopesHash[scopeID];
301
+ })
302
+
303
+ if (isInOwnScopes) {
304
+ return true;
305
+ }
306
+ }
307
+ }
308
+
309
+ //////////////////////////////////
310
+
311
+ //No access by default
312
+ return false
313
+ }
314
+
315
+
316
+ ///////////////////////////////////////////////
317
+
318
+ service.has = function(user, permission) {
319
+
320
+ //Allow everything if we're a super user
321
+ if (service.isAdministrator(user)) {
322
+ return true;
323
+ }
324
+
325
+ var permissionsLookup = service.hashPermissions(user);
326
+ return permissionsLookup[permission];
327
+ }
328
+
329
+
330
+ ///////////////////////////////////////////////
331
+
332
+ service.canCreate = function(user, definition, type, options) {
333
+
334
+ options = options || {}
335
+ options.cache = options.cache || {}
336
+
337
+
338
+ //Allow everything if we're a super user
339
+ if (service.isAdministrator(user)) {
340
+ return true;
341
+ }
342
+
343
+ var createableScopes = service.actionableScopes(user, 'create', definition, type);
344
+ return createableScopes.length
345
+ }
346
+
347
+
348
+ ///////////////////////////////////////////////
349
+
350
+ service.canListItem = function(user, item, options) {
351
+ options = options || {};
352
+ options.cache = options.cache || {}
353
+
354
+
355
+ //Check if we can list the item
356
+ var canList = service.checkActionAccess(user, item, 'listany', 'listown', options);
357
+
358
+
359
+ if (canList) {
360
+ return true;
361
+ }
362
+
363
+ //If we can view the item then we should be able to list it also
364
+ var canView = service.canViewItem(user, item, options);
365
+ if (canView) {
366
+ return true;
367
+ }
368
+
369
+ return false;
370
+
371
+ }
372
+
373
+
374
+ ///////////////////////////////////////////////
375
+
376
+ service.canViewItem = function(user, item, options) {
377
+
378
+ options = options || {}
379
+ options.cache = options.cache || {}
380
+
381
+
382
+
383
+ //Check if we can view the item
384
+ var canView = service.checkActionAccess(user, item, 'viewany', 'viewOwn', options);
385
+ if (canView) {
386
+ return true;
387
+ }
388
+
389
+ //If we can edit the item then we should be able to view it also
390
+ var canEdit = service.canEditItem(user, item, options);
391
+ if (canEdit) {
392
+ return true;
393
+ }
394
+
395
+ return false;
396
+ }
397
+
398
+
399
+ ///////////////////////////////////////////////
400
+
401
+ service.canEditItem = function(user, item, options) {
402
+ options = options || {}
403
+ options.cache = options.cache || {}
404
+
405
+ var allowed = service.checkActionAccess(user, item, 'editany', 'editown', options);
406
+ return allowed;
407
+ }
408
+
409
+ ///////////////////////////////////////////////
410
+
411
+ service.canDeleteItem = function(user, item, options) {
412
+ options = options || {}
413
+ options.cache = options.cache || {}
414
+
415
+ return service.checkActionAccess(user, item, 'deleteany', 'deleteown', options);
416
+ }
417
+
418
+ ///////////////////////////////////////////////
419
+
420
+ service.canRestoreItem = function(user, item, options) {
421
+ options = options || {}
422
+ options.cache = options.cache || {}
423
+
424
+ return service.checkActionAccess(user, item, 'restoreany', 'restoreown', options);
425
+ }
426
+
427
+ ///////////////////////////////////////////////
428
+
429
+ service.canEraseItem = function(user, item, options) {
430
+ options = options || {}
431
+ options.cache = options.cache || {}
432
+
433
+ return service.checkActionAccess(user, item, 'eraseany', 'eraseown', options);
434
+ }
435
+
436
+
83
437
 
84
438
  return service;
85
439