@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 +28 -0
- package/CoCreate.config.js +1 -2
- package/docs/index.html +2 -2
- package/package.json +3 -3
- package/src/index.js +102 -183
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
|
|
package/CoCreate.config.js
CHANGED
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
49
|
-
"@cocreate/utils": "^1.26.
|
|
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
|
|
18
|
+
const organizations = {}
|
|
19
19
|
|
|
20
20
|
if (isBrowser) {
|
|
21
|
-
crud.listen('update
|
|
21
|
+
crud.listen('object.update', function (data) {
|
|
22
22
|
updateAuthorization(data)
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
crud.listen('delete
|
|
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 &&
|
|
39
|
+
if (authorization && authorization.key && organizations[organization_id] && organizations[organization_id][authorization.key]) {
|
|
40
40
|
let newAuthorization = await readAuthorization(authorization.key, organization_id)
|
|
41
|
-
|
|
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 &&
|
|
52
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
-
|
|
81
|
-
|
|
61
|
+
if (!organizations[organization_id][key])
|
|
62
|
+
organizations[organization_id][key] = readAuthorization(key, organization_id);
|
|
82
63
|
|
|
83
|
-
|
|
84
|
-
|
|
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
|
|
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
|
|
128
|
-
delete 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
|
-
|
|
202
|
-
|
|
203
|
-
if (!
|
|
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
|
|
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
|
-
|
|
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(
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
let
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (
|
|
291
|
-
|
|
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.
|
|
324
|
-
} else
|
|
325
|
-
status = true
|
|
326
|
-
return status
|
|
327
|
-
}
|
|
277
|
+
data.$filter.query.push(query)
|
|
328
278
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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'))
|