@cocreate/authorize 1.7.6 → 1.8.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ ## [1.8.1](https://github.com/CoCreate-app/CoCreate-authorize/compare/v1.8.0...v1.8.1) (2023-11-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * meta name typo ([a21a4b5](https://github.com/CoCreate-app/CoCreate-authorize/commit/a21a4b5a8b92d17dabb9d60274526e43235ef9d5))
7
+ * return error if no authorization.actions ([61cff63](https://github.com/CoCreate-app/CoCreate-authorize/commit/61cff637a565305032fc4356b24b039e428d7b6d))
8
+ * typos ([48eecb4](https://github.com/CoCreate-app/CoCreate-authorize/commit/48eecb43925bf0b70d7daabb5e82a5d7cd5e305f))
9
+ * update crud methods ([c416245](https://github.com/CoCreate-app/CoCreate-authorize/commit/c41624522c9688321b5cdb7c2c401b38cc057ead))
10
+ * update host ([a86a448](https://github.com/CoCreate-app/CoCreate-authorize/commit/a86a4489d6fbc18c3989735db1edf4fb0125fb15))
11
+
12
+ # [1.8.0](https://github.com/CoCreate-app/CoCreate-authorize/compare/v1.7.6...v1.8.0) (2023-11-03)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * if organization_id does not exist error ([5dbdd8f](https://github.com/CoCreate-app/CoCreate-authorize/commit/5dbdd8f285418618575efc8a1e525dbde6ea81a1))
18
+ * improve authorization promise handling ([df00618](https://github.com/CoCreate-app/CoCreate-authorize/commit/df00618c03c129b20abb5878f73d6522dbec5401))
19
+ * Improve conditions ([689e6fa](https://github.com/CoCreate-app/CoCreate-authorize/commit/689e6fa95d8378f2d7bed22c1e2a2f29bc5c7be0))
20
+ * request.request param removed ([06a656d](https://github.com/CoCreate-app/CoCreate-authorize/commit/06a656d8b2a354ff473e8de1cfa5b44abc81bd89))
21
+ * update dependencies to the lates versions ([0a19463](https://github.com/CoCreate-app/CoCreate-authorize/commit/0a1946353c787a5dee1f54324e1fb2290c4b7a0f))
22
+
23
+
24
+ ### Features
25
+
26
+ * check if authoriztion keys has a query operator and apply query ([e2dfa5c](https://github.com/CoCreate-app/CoCreate-authorize/commit/e2dfa5c02bbb537454e2f5d9a9b07444dd60c3a6))
27
+ * support adding querires for crud methods ([9b68d24](https://github.com/CoCreate-app/CoCreate-authorize/commit/9b68d244982fe08f680043cd7f1a1b06cc6be301))
28
+
1
29
  ## [1.7.6](https://github.com/CoCreate-app/CoCreate-authorize/compare/v1.7.5...v1.7.6) (2023-10-26)
2
30
 
3
31
 
@@ -12,8 +12,7 @@ module.exports = {
12
12
  "pathname": "/docs/authorize/index.html",
13
13
  "src": "{{./docs/index.html}}",
14
14
  "host": [
15
- "*",
16
- "general.cocreate.app"
15
+ "*"
17
16
  ],
18
17
  "directory": "authorize",
19
18
  "content-type": "text/html",
package/docs/index.html CHANGED
@@ -11,10 +11,10 @@
11
11
  sizes="32x32"
12
12
  href="https://cocreate.app/images/favicon.ico" />
13
13
  <meta
14
- key="description"
14
+ name="description"
15
15
  content="A simple HTML5 and pure javascript component. Easy configuration using data-attributes and highly styleable." />
16
16
  <meta
17
- key="keywords"
17
+ name="keywords"
18
18
  content="helper classes, utility classes, css framework, css library, inline style classes" />
19
19
  <meta name="robots" content="index,follow" />
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/authorize",
3
- "version": "1.7.6",
3
+ "version": "1.8.1",
4
4
  "description": "A simple authorize component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "authorize",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "main": "./src/index.js",
47
47
  "dependencies": {
48
- "@cocreate/crud-client": "^1.28.10",
49
- "@cocreate/utils": "^1.26.1"
48
+ "@cocreate/crud-client": "^1.28.12",
49
+ "@cocreate/utils": "^1.26.2"
50
50
  }
51
51
  }
package/src/index.js CHANGED
@@ -15,14 +15,14 @@
15
15
  }
16
16
  }(typeof self !== 'undefined' ? self : this, function (isBrowser, crud, { getValueFromObject, dotNotationToObject }) {
17
17
 
18
- const authorizations = new Map()
18
+ const organizations = {}
19
19
 
20
20
  if (isBrowser) {
21
- crud.listen('update.object', function (data) {
21
+ crud.listen('object.update', function (data) {
22
22
  updateAuthorization(data)
23
23
  });
24
24
 
25
- crud.listen('delete.object', function (data) {
25
+ crud.listen('object.delete', function (data) {
26
26
  deleteAuthorization(data)
27
27
  });
28
28
  } else {
@@ -36,9 +36,9 @@
36
36
 
37
37
  if (array === 'keys' && object) {
38
38
  let authorization = object[0]
39
- if (authorization && authorization.key && hasAuthorization(authorization.key)) {
39
+ if (authorization && authorization.key && organizations[organization_id] && organizations[organization_id][authorization.key]) {
40
40
  let newAuthorization = await readAuthorization(authorization.key, organization_id)
41
- setAuthorization(authorization.key, newAuthorization)
41
+ organizations[organization_id][authorization.key] = newAuthorization
42
42
  }
43
43
  }
44
44
  }
@@ -48,44 +48,21 @@
48
48
 
49
49
  if (array === 'keys' && object) {
50
50
  let authorization = object[0]
51
- if (authorization && authorization.key && hasAuthorization(authorization.key)) {
52
- authorizations.delete(authorization.key)
51
+ if (authorization && authorization.key && organizations[organization_id] && organizations[organization_id][authorization.key]) {
52
+ delete organizations[organization_id][authorization.key]
53
53
  }
54
54
  }
55
55
  }
56
56
 
57
- function setAuthorization(key, authorization) {
58
- authorizations.set(key, authorization)
59
- }
60
-
61
- function hasAuthorization(key) {
62
- return authorizations.has(key)
63
- }
64
-
65
57
  async function getAuthorization(key, organization_id) {
66
- // Check if there is a value orpending promise for this key
67
- if (key && authorizations.has(key)) {
68
- // Return the value or pending promise
69
- return await authorizations.get(key);
70
- }
71
-
72
- // Create a new promise and store it
73
- const authorizationPromise = readAuthorization(key, organization_id);
74
- authorizations.set(key, authorizationPromise);
75
-
76
- try {
77
- // Wait for the authorization to be resolved
78
- const authorization = await authorizationPromise;
58
+ if (!organizations[organization_id])
59
+ organizations[organization_id] = {}
79
60
 
80
- // Once resolved, store the resolved authorization in the map
81
- authorizations.set(key, authorization);
61
+ if (!organizations[organization_id][key])
62
+ organizations[organization_id][key] = readAuthorization(key, organization_id);
82
63
 
83
- return authorization;
84
- } catch (error) {
85
- // Handle errors if necessary
86
- authorizations.delete(key);
87
- throw error;
88
- }
64
+ organizations[organization_id][key] = await organizations[organization_id][key]
65
+ return organizations[organization_id][key]
89
66
  }
90
67
 
91
68
  async function readAuthorization(key, organization_id) {
@@ -94,10 +71,10 @@
94
71
  return { error: 'An organization_id is required' };
95
72
 
96
73
  let request = {
97
- method: 'read.object',
74
+ method: 'object.read',
75
+ database: organization_id,
98
76
  array: 'keys',
99
77
  organization_id,
100
- object: {},
101
78
  $filter: {
102
79
  query: []
103
80
  }
@@ -124,20 +101,19 @@
124
101
  role_ids.push({ _id })
125
102
  })
126
103
 
127
- delete request.object.$filter
128
- delete request.request
104
+ delete request.$filter
105
+ delete request.isFilter
106
+
129
107
  request.object = role_ids
130
108
 
131
109
  let roles = await crud.send(request)
132
110
  roles = roles.object
133
111
 
134
- authorization = createAuthorization(authorization, roles)
112
+ authorization = await createAuthorization(authorization, roles)
135
113
  }
136
-
137
- }
138
-
139
- return authorization;
140
-
114
+ return authorization;
115
+ } else
116
+ return {}
141
117
  } catch (error) {
142
118
  console.log("authorization Error", error)
143
119
  return { error };
@@ -198,171 +174,113 @@
198
174
  }
199
175
 
200
176
  async function checkAuthorization({ key, data }) {
201
- // let method = data.method
202
- let { method, organization_id, endPoint } = data
203
- if (!organization_id)
204
- return { error: '' };
177
+ if (!data.organization_id)
178
+ return { error: 'organization_id is required' };
179
+ if (!data.method)
180
+ return { error: 'method is required' };
205
181
 
206
- let authorized = await getAuthorization(key, organization_id)
182
+ let authorized = await getAuthorization(key, data.organization_id)
207
183
  if (!authorized || authorized.error)
208
184
  return authorized
209
- if (authorized.organization_id !== organization_id)
185
+ if (authorized.organization_id !== data.organization_id)
210
186
  return false;
211
187
  if (authorized.host && authorized.host.length) {
212
188
  if (!authorized.host || (!authorized.host.includes(data.host) && !authorized.host.includes("*")))
213
189
  return false;
214
-
215
190
  }
216
- if (authorized.admin == 'true' || authorized.admin === true)
191
+ if (authorized.admin === 'true' || authorized.admin === true)
217
192
  return true;
193
+ if (!authorized.actions)
194
+ return { error: "Authorization does not have any actions defined" };
195
+
196
+ let status = await checkMethod(data, authorized.actions, data.method)
218
197
 
219
- let status = await checkMethod(authorized.actions, method, endPoint, data)
198
+ // console.log(data.method, status)
220
199
 
221
- if (!status)
200
+ if (!status) {
222
201
  return false
202
+ }
223
203
 
224
204
  return { authorized: data };
225
205
  }
226
206
 
227
- async function checkMethod(autorized, method, endPoint, data) {
228
- if (!autorized || !method || !autorized[method] || autorized[method] == 'false') return false;
229
- if (autorized[method] === true || autorized[method] == 'true' || autorized[method] == '*') return true;
230
-
231
- let authorized = autorized[method].authorize
232
- if (authorized) {
233
- let status = await checkAthorized(authorized, method, endPoint, data)
234
- if (!status)
235
- return false
236
- else {
237
- let unauthorized = autorized[method].unauthorize
238
- if (unauthorized) {
239
- let status = await checkAthorized(unauthorized, method, endPoint, data, true)
240
- if (status)
241
- return false
242
- }
243
- return true
207
+ async function checkMethod(data, authorized, method) {
208
+ if (authorized[method]) {
209
+ return await checkMethodMatch(data, authorized[method], method)
210
+ } else if (method.includes('.')) {
211
+ let match = ''
212
+ let splitMethod = method.split('.')
213
+ for (let i = 0; i < splitMethod.length; i++) {
214
+ if (!match)
215
+ match = splitMethod[i]
216
+ else
217
+ match += '.' + splitMethod[i]
218
+ if (authorized[match]) {
219
+ return await checkMethodMatch(data, authorized[match], match)
220
+ } else if (i === splitMethod.length - 1)
221
+ return false
244
222
  }
245
223
  } else
246
- return false
224
+ return false;
247
225
  }
248
226
 
249
- async function checkAthorized(authorized, method, endPoint, data, unauthorize) {
250
- if (!Array.isArray(authorized))
251
- authorized = [authorized]
252
-
253
- let status = false
254
- for (let i = 0; i < authorized.length; i++) {
255
- // if authorized[i] is a booleaan
256
- if (authorized[i] === true)
227
+ async function checkMethodMatch(data, authorized, match) {
228
+ if (typeof authorized === 'boolean') {
229
+ return authorized
230
+ } else if (typeof authorized === 'string') {
231
+ if (authorized === 'false')
232
+ return false
233
+ else if (authorized === 'true')
257
234
  return true
258
-
259
- // if authorized[i] is a string or an array
260
- if (typeof authorized[i] === "string" || Array.isArray(authorized[i])) {
261
- if (authorized[i].includes(true) || authorized[i].includes('true') || authorized[i].includes('*'))
262
- return true
263
- else if (endPoint)
264
- return authorized.includes(endPoint)
265
- else
266
- return false
267
- }
268
-
269
- // if authorized[i] is an object
270
- for (const key of Object.keys(authorized[i])) {
271
- status = await checkAthorizedKey(authorized[i], method, endPoint, data, key, unauthorize)
235
+ else if (authorized === match)
236
+ return true // check string for match or mutate data
237
+ else
238
+ return true // check string for match or mutate data
239
+ } else if (typeof authorized === 'number') {
240
+ return !!authorized
241
+ } else {
242
+ let status = false
243
+ let newmatch = data.method.replace(match + '.', '')
244
+
245
+ if (Array.isArray(authorized)) {
246
+ for (let i = 0; i < authorized.length; i++) {
247
+ status = await checkMethodMatch(data, authorized[i], newmatch)
248
+ }
249
+ } else if (typeof authorized === 'object') {
250
+ let keys = Object.keys(authorized);
251
+
252
+ for (const key of keys) {
253
+ if (key.includes('$'))
254
+ status = await checkMethodOperators(data, key, authorized[key])
255
+ else if (newmatch && (authorized[newmatch] || authorized['*'])) {
256
+ status = await checkMethodMatch(data, authorized[newmatch] || authorized['*'], newmatch)
257
+ }
258
+ }
272
259
  }
273
-
260
+ return status
274
261
  }
275
-
276
- return status
277
-
278
262
  }
279
263
 
280
- async function checkAthorizedKey(authorized, method, endPoint, data, key, unauthorize) {
281
- let status = false;
282
- let keyStatus = false;
283
-
284
- // if authorized[key] is a booleaan
285
- if (authorized[key] === true)
286
- keyStatus = true
287
-
288
- // if authorized[key] is a string or number
289
- else if (typeof authorized[key] === "string" || typeof authorized[key] === "number") {
290
- if (authorized[key] === true || authorized[key] === 'true' || authorized[key] === '*')
291
- keyStatus = true
292
- else if (data[key]) {
293
- keyStatus = await checkArray(authorized, data, key, unauthorize)
294
- if (await checkFilter(authorized, data, key, unauthorize))
295
- status = true
296
- }
297
- }
298
-
299
- // if authorized[key] is an array
300
- else if (Array.isArray(authorized[key])) {
301
- if (authorized[key].includes(true) || authorized[key].includes('true') || authorized[key].includes('*'))
302
- keyStatus = true
303
- else if (data[key]) {
304
- keyStatus = await checkArray(authorized, data, key, unauthorize)
305
- if (await checkFilter(authorized, data, key, unauthorize))
306
- status = true
307
- }
308
- }
309
-
310
- // if authorized[key] is an object
311
- else if (typeof authorized[key] === "object") {
312
- console.log('authorized[key] is an object', authorized[key])
313
- } else
314
- delete data[key]
315
-
316
- // if key status is false for unauthorized case
317
- if (!keyStatus || keyStatus && unauthorize) {
318
- if (!data.unauthorized || !data.unauthorized[method])
319
- data.unauthorized = { [method]: { [key]: [data[key]] } }
320
- else if (!data.unauthorized[method][key])
321
- data.unauthorized[method][key] = [data[key]]
264
+ async function checkMethodOperators(data, key, value) {
265
+ if (value === 'this.userId' && data.socket)
266
+ value = data.socket.user_id
267
+
268
+ let keys = key.split('.')
269
+ if (['$eq', '$ne', '$lt', '$lte', '$gt', '$gte', '$in', '$nin', '$or', '$and', '$not', '$nor', '$exists', '$type', '$mod', '$regex', '$text', '$where', '$all', '$elemMatch', '$size'].includes(keys[0])) {
270
+ // let keys = key.split('.')
271
+ let query = { key: keys[1], value, operator: keys[0] }
272
+ if (!data.$filter)
273
+ data.$filter = { query: [query] }
274
+ else if (!data.$filter.query)
275
+ data.$filter.query = [query]
322
276
  else
323
- data.unauthorized[method][key].push(data[key])
324
- } else
325
- status = true
326
- return status
327
- }
277
+ data.$filter.query.push(query)
328
278
 
329
- async function checkArray(authorized, data, key, unauthorize) {
330
- let keyStatus = false
331
- let authorizedValue = getValueFromObject(authorized, key);
332
- let dataValue = getValueFromObject(data, key);
333
-
334
- if (!authorizedValue && !unauthorize) {
335
- data = deleteKey(data, key)
336
- } else if (typeof dataValue == "string") {
337
- if (unauthorize && authorizedValue.includes(dataValue))
338
- data = deleteKey(data, key)
339
- else {
340
- if (!authorizedValue.includes(dataValue))
341
- data = deleteKey(data, key)
342
- else
343
- keyStatus = true
344
- }
345
- } else if (Array.isArray(dataValue)) {
346
- for (let i = 0; i < dataValue.length; i++) {
347
- keyStatus = await checkArray(authorized, data, `${key}[${i}]`, unauthorize)
348
- }
349
- } else if (typeof dataValue === "object") {
350
- let checkKeys = true
351
- if (dataValue['_id']) {
352
- if (authorized.object.includes(dataValue['_id']))
353
- checkKeys = true
354
- }
355
- if (checkKeys) {
356
- if (authorizedValue['*'] || authorizedValue['*'] == '')
357
- keyStatus = true
358
- else
359
- for (const k of Object.keys(dataValue)) {
360
- keyStatus = await checkArray(authorized, data, `${key}.${k}`, unauthorize)
361
- }
362
- }
279
+ } else {
280
+ // TODO: sanitize data by removing items user does not have access to.
281
+ // console.log('key is a query operator', key)
363
282
  }
364
-
365
- return keyStatus
283
+ return true
366
284
  }
367
285
 
368
286
  async function checkFilter(authorized, data, apikey, unauthorize) {
@@ -387,6 +305,7 @@
387
305
  }
388
306
  }
389
307
 
308
+
390
309
  function deleteKey(data, path) {
391
310
  if (!data || !path) return
392
311
  if (path.includes('._id'))