@edgedev/firebase 1.6.2 → 1.7.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 +463 -19
- package/edgeFirebase.ts +367 -288
- package/package.json +1 -1
package/edgeFirebase.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { initializeApp } from "firebase/app";
|
|
2
|
-
import { reactive
|
|
2
|
+
import { reactive } from "vue";
|
|
3
3
|
import {
|
|
4
4
|
getFirestore,
|
|
5
5
|
collection,
|
|
@@ -95,27 +95,44 @@ interface UserDataObject {
|
|
|
95
95
|
meta: object;
|
|
96
96
|
roles: role[];
|
|
97
97
|
specialPermissions: specialPermission[];
|
|
98
|
+
stagedDocId: string;
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
interface newUser {
|
|
101
|
-
email: string;
|
|
102
102
|
roles: role[];
|
|
103
103
|
specialPermissions: specialPermission[];
|
|
104
104
|
meta: object;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
isTemplate?: boolean;
|
|
106
|
+
subCreate?: {
|
|
107
|
+
rootPath: string, // This must be a collection path (odd number of segments) since a document will be created and assigned to ther user here.
|
|
108
|
+
role: string,
|
|
109
|
+
dynamicDocumentField: string, // This is the field in the document that will be set by the value of "dynamicDocumentFieldValue" passed during registration, like "name"
|
|
110
|
+
documentStructure: {
|
|
111
|
+
[key: string]: any
|
|
112
|
+
}
|
|
113
|
+
};
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
interface userRegister {
|
|
114
117
|
email: string;
|
|
115
118
|
password: string;
|
|
116
119
|
meta: object;
|
|
120
|
+
registrationCode: string;
|
|
121
|
+
dynamicDocumentFieldValue?: string;
|
|
117
122
|
}
|
|
118
123
|
|
|
124
|
+
|
|
125
|
+
interface RuleCheck {
|
|
126
|
+
permissionType: string;
|
|
127
|
+
permissionCheckPath: string;
|
|
128
|
+
fullPath: string;
|
|
129
|
+
action: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// interface RuleCheck {
|
|
133
|
+
// [key: string]: RuleCheckItem | string;
|
|
134
|
+
// }
|
|
135
|
+
|
|
119
136
|
interface Credentials {
|
|
120
137
|
email: string;
|
|
121
138
|
password: string;
|
|
@@ -188,14 +205,9 @@ export const EdgeFirebase = class {
|
|
|
188
205
|
public auth = null;
|
|
189
206
|
public db = null;
|
|
190
207
|
|
|
191
|
-
private initUserMetaPermissions = async (): Promise<void> => {
|
|
192
|
-
updateDoc(doc(this.db, "users", this.user.email), {
|
|
193
|
-
userId: this.user.uid
|
|
194
|
-
});
|
|
208
|
+
private initUserMetaPermissions = async (docSnap): Promise<void> => {
|
|
195
209
|
this.user.meta = {};
|
|
196
|
-
|
|
197
|
-
const docSnap = await getDoc(docRef);
|
|
198
|
-
if (docSnap) {
|
|
210
|
+
if (docSnap.exists()) {
|
|
199
211
|
this.user.meta = docSnap.data().meta;
|
|
200
212
|
const roles: role[] = [];
|
|
201
213
|
if (docSnap.data().roles) {
|
|
@@ -219,44 +231,35 @@ export const EdgeFirebase = class {
|
|
|
219
231
|
}
|
|
220
232
|
}
|
|
221
233
|
this.user.specialPermissions = specialPermissions;
|
|
234
|
+
this.user.stagedDocId = docSnap.data().stagedDocId;
|
|
222
235
|
}
|
|
223
236
|
this.stopSnapshot('userMeta')
|
|
224
237
|
const metaUnsubscribe = onSnapshot(
|
|
225
|
-
doc(this.db, "users", this.user.
|
|
238
|
+
doc(this.db, "users", this.user.uid),
|
|
226
239
|
(doc) => {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
} else {
|
|
236
|
-
this.user.meta = doc.data().meta;
|
|
237
|
-
const roles: role[] = [];
|
|
238
|
-
if (doc.data().roles) {
|
|
239
|
-
for (const collectionPath in doc.data().roles) {
|
|
240
|
-
roles.push({
|
|
241
|
-
collectionPath,
|
|
242
|
-
role: doc.data().roles[collectionPath].role
|
|
243
|
-
});
|
|
244
|
-
}
|
|
240
|
+
this.user.meta = doc.data().meta;
|
|
241
|
+
const roles: role[] = [];
|
|
242
|
+
if (doc.data().roles) {
|
|
243
|
+
for (const collectionPath in doc.data().roles) {
|
|
244
|
+
roles.push({
|
|
245
|
+
collectionPath,
|
|
246
|
+
role: doc.data().roles[collectionPath].role
|
|
247
|
+
});
|
|
245
248
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
249
|
+
}
|
|
250
|
+
this.user.roles = roles;
|
|
251
|
+
|
|
252
|
+
const specialPermissions: specialPermission[] = [];
|
|
253
|
+
if (doc.data().specialPermissions) {
|
|
254
|
+
for (const collectionPath in doc.data().specialPermissions) {
|
|
255
|
+
specialPermissions.push({
|
|
256
|
+
collectionPath,
|
|
257
|
+
permissions:
|
|
258
|
+
doc.data().specialPermissions[collectionPath].permissions
|
|
259
|
+
});
|
|
257
260
|
}
|
|
258
|
-
this.user.specialPermissions = specialPermissions;
|
|
259
261
|
}
|
|
262
|
+
this.user.specialPermissions = specialPermissions;
|
|
260
263
|
}
|
|
261
264
|
);
|
|
262
265
|
this.unsubscibe.userMeta = metaUnsubscribe;
|
|
@@ -323,12 +326,25 @@ export const EdgeFirebase = class {
|
|
|
323
326
|
|
|
324
327
|
|
|
325
328
|
|
|
326
|
-
private startUserMetaSync = async (): Promise<void> => {
|
|
329
|
+
private startUserMetaSync = async (docSnap): Promise<void> => {
|
|
327
330
|
await this.startCollectionPermissionsSync()
|
|
328
|
-
await this.initUserMetaPermissions();
|
|
331
|
+
await this.initUserMetaPermissions(docSnap);
|
|
329
332
|
this.user.loggedIn = true;
|
|
330
333
|
};
|
|
331
334
|
|
|
335
|
+
private waitForUser = async(): Promise<void> => {
|
|
336
|
+
//On registration may take a second for user to be created
|
|
337
|
+
const docRef = doc(this.db, "users", this.user.uid);
|
|
338
|
+
const docSnap = await getDoc(docRef);
|
|
339
|
+
if (docSnap.exists()) {
|
|
340
|
+
this.startUserMetaSync(docSnap);
|
|
341
|
+
} else {
|
|
342
|
+
setTimeout(() => {
|
|
343
|
+
this.waitForUser();
|
|
344
|
+
}, 1000);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
332
348
|
private setOnAuthStateChanged = (): void => {
|
|
333
349
|
onAuthStateChanged(this.auth, (userAuth) => {
|
|
334
350
|
if (userAuth) {
|
|
@@ -336,7 +352,7 @@ export const EdgeFirebase = class {
|
|
|
336
352
|
this.user.uid = userAuth.uid;
|
|
337
353
|
this.user.logInError = false;
|
|
338
354
|
this.user.logInErrorMessage = "";
|
|
339
|
-
this.
|
|
355
|
+
this.waitForUser();
|
|
340
356
|
} else {
|
|
341
357
|
this.user.email = "";
|
|
342
358
|
this.user.uid = null;
|
|
@@ -346,11 +362,17 @@ export const EdgeFirebase = class {
|
|
|
346
362
|
}
|
|
347
363
|
});
|
|
348
364
|
};
|
|
349
|
-
|
|
350
365
|
public registerUser = async (
|
|
351
366
|
userRegister: userRegister
|
|
352
367
|
): Promise<actionResponse> => {
|
|
353
|
-
|
|
368
|
+
if (!Object.prototype.hasOwnProperty.call(userRegister, 'registrationCode') || userRegister.registrationCode === "") {
|
|
369
|
+
return this.sendResponse({
|
|
370
|
+
success: false,
|
|
371
|
+
message: "Registration code is required.",
|
|
372
|
+
meta: {}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
const userRef = doc(this.db, "staged-users", userRegister.registrationCode);
|
|
354
376
|
const userSnap = await getDoc(userRef);
|
|
355
377
|
if (userSnap.exists()) {
|
|
356
378
|
const user = userSnap.data();
|
|
@@ -361,29 +383,52 @@ export const EdgeFirebase = class {
|
|
|
361
383
|
meta: {}
|
|
362
384
|
});
|
|
363
385
|
} else {
|
|
364
|
-
|
|
386
|
+
if (user.isTemplate && Object.prototype.hasOwnProperty.call("subCreate", user) && Object.values(user.subCreate).length > 0) {
|
|
387
|
+
if (!Object.prototype.hasOwnProperty.call(userRegister, 'dynamicDocumentFieldValue') || userRegister.dynamicDocumentFieldValue === "") {
|
|
388
|
+
return this.sendResponse({
|
|
389
|
+
success: false,
|
|
390
|
+
message: "Dynamic document field value is required for registration when template user has subCreate.",
|
|
391
|
+
meta: {}
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// TODO: check if user is already registered, if so return error with auth
|
|
396
|
+
const response = await createUserWithEmailAndPassword(
|
|
365
397
|
this.auth,
|
|
366
398
|
userRegister.email,
|
|
367
399
|
userRegister.password
|
|
368
|
-
)
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
let metaUpdate = {};
|
|
403
|
+
if (Object.prototype.hasOwnProperty.call(userRegister, 'meta')) {
|
|
404
|
+
metaUpdate = userRegister.meta;
|
|
405
|
+
}else{
|
|
406
|
+
metaUpdate = user.meta;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
let stagedUserUpdate: {userId?: string, templateUserId?: string, dynamicDocumentFieldValue?: string, uid: string, meta: unknown, templateMeta?: unknown} = {userId: response.user.uid, uid: response.user.uid, meta: metaUpdate}
|
|
410
|
+
if (user.isTemplate) {
|
|
411
|
+
stagedUserUpdate = {templateUserId: response.user.uid, uid: response.user.uid, meta: user.meta, templateMeta: metaUpdate}
|
|
412
|
+
if (Object.prototype.hasOwnProperty.call(userRegister, 'dynamicDocumentFieldValue')) {
|
|
413
|
+
stagedUserUpdate = {templateUserId: response.user.uid, uid: response.user.uid, dynamicDocumentFieldValue: userRegister.dynamicDocumentFieldValue, meta: user.meta, templateMeta: metaUpdate}
|
|
375
414
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
415
|
+
}
|
|
416
|
+
const initRoleHelper = {uid: response.user.uid}
|
|
417
|
+
initRoleHelper["edge-assignment-helper"] = {permissionType: "roles"}
|
|
418
|
+
await setDoc(doc(this.db, "rule-helpers", response.user.uid), initRoleHelper);
|
|
419
|
+
await updateDoc(doc(this.db, "staged-users/" + userRegister.registrationCode), stagedUserUpdate)
|
|
420
|
+
|
|
421
|
+
return this.sendResponse({
|
|
422
|
+
success: true,
|
|
423
|
+
message: "",
|
|
424
|
+
meta: {}
|
|
381
425
|
});
|
|
426
|
+
|
|
382
427
|
}
|
|
383
428
|
} else {
|
|
384
429
|
return this.sendResponse({
|
|
385
430
|
success: false,
|
|
386
|
-
message: "
|
|
431
|
+
message: "Registration code not valid.",
|
|
387
432
|
meta: {}
|
|
388
433
|
});
|
|
389
434
|
}
|
|
@@ -453,10 +498,12 @@ export const EdgeFirebase = class {
|
|
|
453
498
|
}
|
|
454
499
|
};
|
|
455
500
|
|
|
456
|
-
setUserMeta = async (meta: unknown): Promise<actionResponse> => {
|
|
501
|
+
public setUserMeta = async (meta: unknown): Promise<actionResponse> => {
|
|
502
|
+
//TODO: Change setUserMeta to also be used by someone with assign permissions and
|
|
503
|
+
// add a permissionCheck here for it.
|
|
457
504
|
for (const [key, value] of Object.entries(meta)) {
|
|
458
|
-
await updateDoc(doc(this.db, "users/" + this.user.
|
|
459
|
-
["meta." + key]: value
|
|
505
|
+
await updateDoc(doc(this.db, "staged-users/" + this.user.stagedDocId), {
|
|
506
|
+
["meta." + key]: value, uid: this.user.uid
|
|
460
507
|
});
|
|
461
508
|
}
|
|
462
509
|
return this.sendResponse({
|
|
@@ -466,31 +513,31 @@ export const EdgeFirebase = class {
|
|
|
466
513
|
});
|
|
467
514
|
};
|
|
468
515
|
|
|
469
|
-
public removeUser = async (
|
|
516
|
+
public removeUser = async (docId: string): Promise<actionResponse> => {
|
|
470
517
|
const removedFrom = [];
|
|
471
|
-
const userRef = doc(this.db, "users",
|
|
518
|
+
const userRef = doc(this.db, "users", docId);
|
|
472
519
|
const userSnap = await getDoc(userRef);
|
|
473
520
|
if (userSnap.data().roles) {
|
|
474
521
|
for (const collectionPath in userSnap.data().roles) {
|
|
475
|
-
const canAssign = this.permissionCheck(
|
|
522
|
+
const canAssign = await this.permissionCheck(
|
|
476
523
|
"assign",
|
|
477
524
|
collectionPath.replaceAll("-", "/")
|
|
478
525
|
);
|
|
479
526
|
if (canAssign) {
|
|
480
|
-
await this.removeUserRoles(
|
|
527
|
+
await this.removeUserRoles(docId, collectionPath.replaceAll("-", "/"));
|
|
481
528
|
removedFrom.push(collectionPath.replaceAll("-", "/"));
|
|
482
529
|
}
|
|
483
530
|
}
|
|
484
531
|
}
|
|
485
532
|
if (userSnap.data().specialPermissions) {
|
|
486
533
|
for (const collectionPath in userSnap.data().specialPermissions) {
|
|
487
|
-
const canAssign = this.permissionCheck(
|
|
534
|
+
const canAssign = await this.permissionCheck(
|
|
488
535
|
"assign",
|
|
489
536
|
collectionPath.replaceAll("-", "/")
|
|
490
537
|
);
|
|
491
538
|
if (canAssign) {
|
|
492
539
|
this.removeUserSpecialPermissions(
|
|
493
|
-
|
|
540
|
+
docId,
|
|
494
541
|
collectionPath.replaceAll("-", "/")
|
|
495
542
|
);
|
|
496
543
|
removedFrom.push(collectionPath.replaceAll("-", "/"));
|
|
@@ -511,8 +558,8 @@ export const EdgeFirebase = class {
|
|
|
511
558
|
});
|
|
512
559
|
}
|
|
513
560
|
};
|
|
514
|
-
|
|
515
|
-
public
|
|
561
|
+
|
|
562
|
+
public addUser = async (newUser: newUser): Promise<actionResponse> => {
|
|
516
563
|
const canAssignRole = this.multiPermissionCheck(
|
|
517
564
|
"assign",
|
|
518
565
|
newUser.roles
|
|
@@ -522,30 +569,8 @@ export const EdgeFirebase = class {
|
|
|
522
569
|
newUser.specialPermissions
|
|
523
570
|
);
|
|
524
571
|
if (canAssignRole.canDo && canAssignSpecialPermissions.canDo) {
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
if (!userSnap.exists()) {
|
|
528
|
-
const userMeta: userMeta = {
|
|
529
|
-
docId: newUser.email,
|
|
530
|
-
userId: "",
|
|
531
|
-
email: newUser.email,
|
|
532
|
-
roles: newUser.roles,
|
|
533
|
-
specialPermissions: newUser.specialPermissions,
|
|
534
|
-
meta: newUser.meta
|
|
535
|
-
};
|
|
536
|
-
await this.generateUserMeta(userMeta);
|
|
537
|
-
return this.sendResponse({
|
|
538
|
-
success: true,
|
|
539
|
-
message: "",
|
|
540
|
-
meta: {}
|
|
541
|
-
});
|
|
542
|
-
} else {
|
|
543
|
-
return this.sendResponse({
|
|
544
|
-
success: false,
|
|
545
|
-
message: "User already exists",
|
|
546
|
-
meta: {}
|
|
547
|
-
});
|
|
548
|
-
}
|
|
572
|
+
const response = await this.generateUserMeta(newUser);
|
|
573
|
+
return this.sendResponse(response);
|
|
549
574
|
} else {
|
|
550
575
|
return this.sendResponse({
|
|
551
576
|
success: false,
|
|
@@ -569,7 +594,7 @@ export const EdgeFirebase = class {
|
|
|
569
594
|
// canDo = false;
|
|
570
595
|
// }
|
|
571
596
|
for (const collection of collections) {
|
|
572
|
-
if (!(this.
|
|
597
|
+
if (!(this.permissionCheckOnly(action, collection.collectionPath))) {
|
|
573
598
|
badCollectionPaths.push(collection.collectionPath);
|
|
574
599
|
canDo = false;
|
|
575
600
|
}
|
|
@@ -592,11 +617,52 @@ export const EdgeFirebase = class {
|
|
|
592
617
|
return response;
|
|
593
618
|
};
|
|
594
619
|
|
|
595
|
-
private
|
|
596
|
-
|
|
597
|
-
collectionPath
|
|
598
|
-
|
|
599
|
-
|
|
620
|
+
private setRuleHelper = async(collectionPath: string, action): Promise<void> => {
|
|
621
|
+
const collection = collectionPath.replaceAll("-", "/").split("/");
|
|
622
|
+
let ruleKey = collectionPath.replaceAll("/", "-");
|
|
623
|
+
if (action === "assign") {
|
|
624
|
+
ruleKey = "edge-assignment-helper";
|
|
625
|
+
}
|
|
626
|
+
let index = collection.length;
|
|
627
|
+
const ruleCheck: RuleCheck = { permissionType: "", permissionCheckPath: "", fullPath: collectionPath.replaceAll("/", "-"), action };
|
|
628
|
+
|
|
629
|
+
while (index > 0) {
|
|
630
|
+
const collectionArray = JSON.parse(JSON.stringify(collection));
|
|
631
|
+
const permissionCheck = collectionArray.splice(0, index).join("-");
|
|
632
|
+
const role = this.user.roles.find(
|
|
633
|
+
(r) => r.collectionPath === permissionCheck
|
|
634
|
+
);
|
|
635
|
+
if (role) {
|
|
636
|
+
ruleCheck.permissionCheckPath = permissionCheck;
|
|
637
|
+
ruleCheck.permissionType = "roles";
|
|
638
|
+
}
|
|
639
|
+
const specialPermission = this.user.specialPermissions.find(
|
|
640
|
+
(r) => r.collectionPath === permissionCheck
|
|
641
|
+
);
|
|
642
|
+
if (specialPermission) {
|
|
643
|
+
ruleCheck.permissionCheckPath = permissionCheck;
|
|
644
|
+
ruleCheck.permissionType = "specialPermissions";
|
|
645
|
+
}
|
|
646
|
+
index--;
|
|
647
|
+
}
|
|
648
|
+
const rootRole = this.user.roles.find((r) => r.collectionPath === "-");
|
|
649
|
+
if (rootRole) {
|
|
650
|
+
ruleCheck.permissionCheckPath = "-";
|
|
651
|
+
ruleCheck.permissionType = "roles";
|
|
652
|
+
}
|
|
653
|
+
const rootSpecialPermission = this.user.specialPermissions.find(
|
|
654
|
+
(r) => r.collectionPath === "-"
|
|
655
|
+
);
|
|
656
|
+
if (rootSpecialPermission) {
|
|
657
|
+
ruleCheck.permissionCheckPath = "-";
|
|
658
|
+
ruleCheck.permissionType = "specialPermissions";
|
|
659
|
+
}
|
|
660
|
+
const check = {[ruleKey]: ruleCheck, uid: this.user.uid };
|
|
661
|
+
await setDoc(doc(this.db, "rule-helpers", this.user.uid), check, { merge: true });
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
public permissionCheckOnly = (action: action, collectionPath: string): boolean => {
|
|
665
|
+
const collection = collectionPath.replaceAll("-", "/").split("/");
|
|
600
666
|
let index = collection.length;
|
|
601
667
|
let permissionData = {};
|
|
602
668
|
permissionData = {
|
|
@@ -644,6 +710,17 @@ export const EdgeFirebase = class {
|
|
|
644
710
|
}
|
|
645
711
|
}
|
|
646
712
|
return permissionData[action];
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
public permissionCheck = async(
|
|
716
|
+
action: action,
|
|
717
|
+
collectionPath: string,
|
|
718
|
+
): Promise<boolean> => {
|
|
719
|
+
const check = this.permissionCheckOnly(action, collectionPath);
|
|
720
|
+
if (check) {
|
|
721
|
+
await this.setRuleHelper(collectionPath, action);
|
|
722
|
+
}
|
|
723
|
+
return check;
|
|
647
724
|
};
|
|
648
725
|
|
|
649
726
|
private getCollectionPermissions = (
|
|
@@ -672,48 +749,78 @@ export const EdgeFirebase = class {
|
|
|
672
749
|
};
|
|
673
750
|
};
|
|
674
751
|
|
|
675
|
-
private generateUserMeta = async (userMeta:
|
|
752
|
+
private generateUserMeta = async (userMeta: newUser): Promise<actionResponse> => {
|
|
676
753
|
const roles: role[] = userMeta.roles;
|
|
677
754
|
const specialPermissions: specialPermission[] = userMeta.specialPermissions;
|
|
678
755
|
delete userMeta.roles;
|
|
679
756
|
delete userMeta.specialPermissions;
|
|
680
757
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
const canWrite = this.permissionCheck("write", "users");
|
|
685
|
-
if (!docData || canWrite) {
|
|
686
|
-
await setDoc(doc(this.db, "users", userMeta.docId), userMeta);
|
|
758
|
+
let isTemplate = false
|
|
759
|
+
if (Object.prototype.hasOwnProperty.call(userMeta, "isTemplate") && userMeta.isTemplate) {
|
|
760
|
+
isTemplate = true
|
|
687
761
|
}
|
|
762
|
+
|
|
763
|
+
let subCreate = {}
|
|
764
|
+
if (Object.prototype.hasOwnProperty.call(userMeta, "subCreate")) {
|
|
765
|
+
if (userMeta.subCreate.rootPath.split("-").length % 2==0){
|
|
766
|
+
return {
|
|
767
|
+
success: false,
|
|
768
|
+
message: "subCreate.rootPath must contain an odd number of segments.",
|
|
769
|
+
meta: {}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
const canAssign = await this.permissionCheck("assign", userMeta.subCreate.rootPath)
|
|
773
|
+
if (canAssign) {
|
|
774
|
+
subCreate = userMeta.subCreate
|
|
775
|
+
} else {
|
|
776
|
+
return {
|
|
777
|
+
success: false,
|
|
778
|
+
message: "You do not have assign permission to '" + userMeta.subCreate.rootPath + "'",
|
|
779
|
+
meta: {}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
const onlyMeta = { meta: userMeta.meta, userId: "", uid: this.user.uid, roles:{}, specialPermissions:{}, isTemplate, subCreate };
|
|
785
|
+
|
|
786
|
+
const docRef = await addDoc(collection(this.db, "staged-users"), onlyMeta );
|
|
688
787
|
for (const role of roles) {
|
|
689
|
-
await this.storeUserRoles(
|
|
788
|
+
await this.storeUserRoles(docRef.id, role.collectionPath, role.role);
|
|
690
789
|
}
|
|
691
790
|
for (const specialPermission of specialPermissions) {
|
|
692
791
|
await this.storeUserSpecialPermissions(
|
|
693
|
-
|
|
792
|
+
docRef.id,
|
|
694
793
|
specialPermission.collectionPath,
|
|
695
794
|
specialPermission.permissions
|
|
696
795
|
);
|
|
697
796
|
}
|
|
797
|
+
return {
|
|
798
|
+
success: true,
|
|
799
|
+
message: "",
|
|
800
|
+
meta: {}
|
|
801
|
+
}
|
|
698
802
|
};
|
|
699
803
|
|
|
700
|
-
// Composable to logout
|
|
701
804
|
public logOut = (): void => {
|
|
702
|
-
|
|
703
|
-
.
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
.
|
|
712
|
-
|
|
713
|
-
|
|
805
|
+
for (const key of Object.keys(this.unsubscibe)) {
|
|
806
|
+
if (this.unsubscibe[key] instanceof Function) {
|
|
807
|
+
this.unsubscibe[key]();
|
|
808
|
+
this.unsubscibe[key] = null;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
signOut(this.auth).then(() => {
|
|
812
|
+
this.user.uid = null;
|
|
813
|
+
this.user.email = "";
|
|
814
|
+
this.user.loggedIn = false;
|
|
815
|
+
this.user.logInError = false;
|
|
816
|
+
this.user.logInErrorMessage = "";
|
|
817
|
+
this.user.meta = {};
|
|
818
|
+
this.user.roles = [];
|
|
819
|
+
this.user.specialPermissions = [];
|
|
820
|
+
this.user.stagedDocId = null;
|
|
821
|
+
})
|
|
714
822
|
};
|
|
715
823
|
|
|
716
|
-
// Composable to login and set persistence
|
|
717
824
|
public logIn = (credentials: Credentials): void => {
|
|
718
825
|
this.logOut();
|
|
719
826
|
signInWithEmailAndPassword(
|
|
@@ -745,64 +852,9 @@ export const EdgeFirebase = class {
|
|
|
745
852
|
|
|
746
853
|
// Simple Store Items (add matching key per firebase collection)
|
|
747
854
|
public data: CollectionDataObject = reactive({});
|
|
748
|
-
private usersByCollections: CollectionDataObject = reactive({});
|
|
749
|
-
|
|
750
|
-
public users = computed(() => {
|
|
751
|
-
const userList = {};
|
|
752
|
-
const keys = Object.keys(JSON.parse(JSON.stringify(this.usersByCollections)));
|
|
753
|
-
keys.forEach(key => {
|
|
754
|
-
const users = this.usersByCollections[key];
|
|
755
|
-
if (key.startsWith("ROLES|")) {
|
|
756
|
-
const collectionPathCheck = key.replace("ROLES|", "")
|
|
757
|
-
const userKeys = Object.keys(users);
|
|
758
|
-
if (Object.keys(users).length > 0) {
|
|
759
|
-
userKeys.forEach(userKey => {
|
|
760
|
-
const user = users[userKey];
|
|
761
|
-
if (!Object.prototype.hasOwnProperty.call(userList, user.docId)) {
|
|
762
|
-
userList[user.email] = {
|
|
763
|
-
docId: user.docId,
|
|
764
|
-
email: user.email,
|
|
765
|
-
roles: [{collectionPath: collectionPathCheck, role: user.roles[collectionPathCheck].role }],
|
|
766
|
-
specialPermissions: [],
|
|
767
|
-
meta: user.meta,
|
|
768
|
-
last_updated: user.last_updated,
|
|
769
|
-
userId: user.userId,
|
|
770
|
-
uid: user.uid
|
|
771
|
-
}
|
|
772
|
-
} else {
|
|
773
|
-
userList[user.email].roles.push({ collectionPath: collectionPathCheck, role: user.roles[collectionPathCheck].role })
|
|
774
|
-
}
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
if (key.startsWith("SPECIALPERMISSIONS|")) {
|
|
779
|
-
const collectionPathCheck = key.replace("SPECIALPERMISSIONS|", "")
|
|
780
|
-
const userKeys = Object.keys(users);
|
|
781
|
-
if (Object.keys(users).length > 0) {
|
|
782
|
-
userKeys.forEach(userKey => {
|
|
783
|
-
const user = users[userKey];
|
|
784
|
-
if (!Object.prototype.hasOwnProperty.call(userList, user.docId)) {
|
|
785
|
-
userList[user.email] = {
|
|
786
|
-
docId: user.docId,
|
|
787
|
-
email: user.email,
|
|
788
|
-
roles: [],
|
|
789
|
-
specialPermissions: [{ collectionPath: collectionPathCheck, permissions: user.specialPermissions[collectionPathCheck].permissions }],
|
|
790
|
-
meta: user.meta,
|
|
791
|
-
last_updated: user.last_updated,
|
|
792
|
-
userId: user.userId,
|
|
793
|
-
uid: user.uid
|
|
794
|
-
}
|
|
795
|
-
} else {
|
|
796
|
-
userList[user.email].specialPermissions.push({ collectionPath: collectionPathCheck, permissions: user.specialPermissions[collectionPathCheck].permissions })
|
|
797
|
-
}
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
});
|
|
802
|
-
return userList;
|
|
803
|
-
});
|
|
804
855
|
|
|
805
856
|
public unsubscibe: CollectionUnsubscribeObject = reactive({});
|
|
857
|
+
|
|
806
858
|
public user: UserDataObject = reactive({
|
|
807
859
|
uid: null,
|
|
808
860
|
email: "",
|
|
@@ -812,22 +864,33 @@ export const EdgeFirebase = class {
|
|
|
812
864
|
meta: {},
|
|
813
865
|
roles: [],
|
|
814
866
|
specialPermissions: [],
|
|
867
|
+
stagedDocId: null,
|
|
815
868
|
});
|
|
816
869
|
|
|
817
870
|
public state = reactive({
|
|
818
871
|
collectionPermissions: {},
|
|
819
872
|
users: {},
|
|
873
|
+
registrationCode: "",
|
|
874
|
+
registrationMeta: {},
|
|
820
875
|
});
|
|
821
876
|
|
|
822
877
|
public getDocData = async (
|
|
823
878
|
collectionPath: string,
|
|
824
879
|
docId: string
|
|
825
880
|
): Promise<{ [key: string]: unknown }> => {
|
|
826
|
-
const
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
881
|
+
const canRead = await this.permissionCheck("read", collectionPath + "/" + docId);
|
|
882
|
+
if (canRead) {
|
|
883
|
+
const docRef = doc(this.db, collectionPath, docId);
|
|
884
|
+
const docSnap = await getDoc(docRef);
|
|
885
|
+
const docData = docSnap.data();
|
|
886
|
+
docData.docId = docSnap.id;
|
|
887
|
+
return docData;
|
|
888
|
+
}
|
|
889
|
+
return {
|
|
890
|
+
success: false,
|
|
891
|
+
message: "Permission Denied",
|
|
892
|
+
meta: {}
|
|
893
|
+
}
|
|
831
894
|
};
|
|
832
895
|
|
|
833
896
|
private collectionExists = (
|
|
@@ -844,25 +907,27 @@ export const EdgeFirebase = class {
|
|
|
844
907
|
last: DocumentData | null = null
|
|
845
908
|
): Promise<StaticDataResult> => {
|
|
846
909
|
const data: object = {};
|
|
910
|
+
let nextLast: DocumentData | null = null;
|
|
911
|
+
const canRead = await this.permissionCheck("read", collectionPath);
|
|
912
|
+
if (canRead) {
|
|
913
|
+
const q = this.getQuery(collectionPath, queryList, orderList, max, last);
|
|
847
914
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const docs = await getDocs(q);
|
|
851
|
-
|
|
852
|
-
const nextLast: DocumentData = docs.docs[docs.docs.length - 1];
|
|
853
|
-
docs.forEach((doc) => {
|
|
854
|
-
const item = doc.data();
|
|
855
|
-
item.docId = doc.id;
|
|
856
|
-
data[doc.id] = item;
|
|
857
|
-
});
|
|
915
|
+
const docs = await getDocs(q);
|
|
858
916
|
|
|
917
|
+
nextLast = docs.docs[docs.docs.length - 1];
|
|
918
|
+
docs.forEach((doc) => {
|
|
919
|
+
const item = doc.data();
|
|
920
|
+
item.docId = doc.id;
|
|
921
|
+
data[doc.id] = item;
|
|
922
|
+
});
|
|
923
|
+
}
|
|
859
924
|
return { data, next: nextLast };
|
|
860
925
|
};
|
|
861
926
|
|
|
862
927
|
// Class for wrapping a getSaticData to handle pagination
|
|
863
928
|
get SearchStaticData() {
|
|
864
929
|
const getStaticData = this.getStaticData;
|
|
865
|
-
const
|
|
930
|
+
const permissionCheckOnly = this.permissionCheckOnly;
|
|
866
931
|
const sendResponse = this.sendResponse;
|
|
867
932
|
return class {
|
|
868
933
|
private collectionPath = "";
|
|
@@ -965,7 +1030,7 @@ export const EdgeFirebase = class {
|
|
|
965
1030
|
orderList: FirestoreOrderBy[] = [],
|
|
966
1031
|
max = 0
|
|
967
1032
|
): Promise<actionResponse> => {
|
|
968
|
-
const canRead =
|
|
1033
|
+
const canRead = permissionCheckOnly("read", collectionPath);
|
|
969
1034
|
|
|
970
1035
|
if (canRead) {
|
|
971
1036
|
this.collectionPath = collectionPath;
|
|
@@ -1051,13 +1116,13 @@ export const EdgeFirebase = class {
|
|
|
1051
1116
|
);
|
|
1052
1117
|
};
|
|
1053
1118
|
|
|
1054
|
-
public startSnapshot = (
|
|
1119
|
+
public startSnapshot = async(
|
|
1055
1120
|
collectionPath: string,
|
|
1056
1121
|
queryList: FirestoreQuery[] = [],
|
|
1057
1122
|
orderList: FirestoreOrderBy[] = [],
|
|
1058
1123
|
max = 0
|
|
1059
|
-
): actionResponse => {
|
|
1060
|
-
const canRead = this.permissionCheck("read", collectionPath);
|
|
1124
|
+
): Promise<actionResponse> => {
|
|
1125
|
+
const canRead = await this.permissionCheck("read", collectionPath);
|
|
1061
1126
|
this.data[collectionPath] = {};
|
|
1062
1127
|
this.stopSnapshot(collectionPath);
|
|
1063
1128
|
this.unsubscibe[collectionPath] = null;
|
|
@@ -1087,73 +1152,85 @@ export const EdgeFirebase = class {
|
|
|
1087
1152
|
}
|
|
1088
1153
|
};
|
|
1089
1154
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
if (
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1155
|
+
private usersSnapshotStarting = false;
|
|
1156
|
+
|
|
1157
|
+
public startUsersSnapshot = async(collectionPath = ''): Promise<void> => {
|
|
1158
|
+
if (!this.usersSnapshotStarting) {
|
|
1159
|
+
this.usersSnapshotStarting = true;
|
|
1160
|
+
this.stopSnapshot("staged-users");
|
|
1161
|
+
this.state.users = {};
|
|
1162
|
+
if (collectionPath) {
|
|
1163
|
+
const canAssign = await this.permissionCheck('assign', collectionPath);
|
|
1164
|
+
if (canAssign) {
|
|
1165
|
+
const q = query(
|
|
1166
|
+
collection(this.db, "staged-users"),
|
|
1167
|
+
where(
|
|
1168
|
+
"collectionPaths",
|
|
1169
|
+
"array-contains",
|
|
1170
|
+
collectionPath.replaceAll('/', '-')
|
|
1171
|
+
)
|
|
1101
1172
|
)
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1173
|
+
const unsubscibe = await onSnapshot(q, (querySnapshot) => {
|
|
1174
|
+
const items = {};
|
|
1175
|
+
querySnapshot.forEach((doc) => {
|
|
1176
|
+
const user = doc.data();
|
|
1177
|
+
const docId = doc.id;
|
|
1178
|
+
const newRoles = [];
|
|
1179
|
+
const newSpecialPermissions = [];
|
|
1180
|
+
|
|
1181
|
+
if (user.roles) {
|
|
1182
|
+
const roles: role[] = Object.values(user.roles);
|
|
1183
|
+
for (const role of roles) {
|
|
1184
|
+
if (this.permissionCheckOnly('assign', role.collectionPath)) {
|
|
1185
|
+
newRoles.push(role)
|
|
1186
|
+
}
|
|
1115
1187
|
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1188
|
+
}
|
|
1189
|
+
if (user.specialPermissions) {
|
|
1190
|
+
const permissions: specialPermission[] = Object.values(user.specialPermissions);
|
|
1191
|
+
for (const permission of permissions) {
|
|
1192
|
+
if (this.permissionCheckOnly('assign', permission.collectionPath)) {
|
|
1193
|
+
newSpecialPermissions.push(permission)
|
|
1194
|
+
}
|
|
1123
1195
|
}
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1196
|
+
}
|
|
1197
|
+
const item = {
|
|
1198
|
+
docId,
|
|
1199
|
+
email: user.email,
|
|
1200
|
+
roles: newRoles,
|
|
1201
|
+
specialPermissions: newSpecialPermissions,
|
|
1202
|
+
meta: user.meta,
|
|
1203
|
+
last_updated: user.last_updated,
|
|
1204
|
+
isTemplate: user.isTemplate,
|
|
1205
|
+
subCreate: user.subCreate,
|
|
1206
|
+
userId: user.userId,
|
|
1207
|
+
uid: user.uid
|
|
1208
|
+
}
|
|
1209
|
+
items[doc.id] = item;
|
|
1210
|
+
});
|
|
1211
|
+
this.state.users = items;
|
|
1137
1212
|
});
|
|
1138
|
-
this.
|
|
1139
|
-
}
|
|
1140
|
-
this.unsubscibe.users = unsubscibe;
|
|
1213
|
+
this.unsubscibe["staged-users"] = unsubscibe;
|
|
1214
|
+
}
|
|
1141
1215
|
}
|
|
1142
|
-
}
|
|
1216
|
+
};
|
|
1217
|
+
this.usersSnapshotStarting = false;
|
|
1143
1218
|
};
|
|
1144
1219
|
|
|
1145
1220
|
public removeUserRoles = async (
|
|
1146
|
-
|
|
1221
|
+
docId: string,
|
|
1147
1222
|
collectionPath: string
|
|
1148
1223
|
): Promise<actionResponse> => {
|
|
1149
|
-
|
|
1224
|
+
let canAssign = await this.permissionCheck("assign", collectionPath);
|
|
1225
|
+
if (docId === this.user.stagedDocId) {
|
|
1226
|
+
// User can remove themselves from any role
|
|
1227
|
+
canAssign = true;
|
|
1228
|
+
}
|
|
1150
1229
|
if (canAssign) {
|
|
1151
|
-
await updateDoc(doc(this.db, "users/" +
|
|
1230
|
+
await updateDoc(doc(this.db, "staged-users/" + docId), {
|
|
1231
|
+
collectionPaths: arrayRemove(collectionPath.replaceAll("/", "-")),
|
|
1152
1232
|
["roles." + collectionPath.replaceAll("/", "-")]: deleteField()
|
|
1153
1233
|
});
|
|
1154
|
-
await updateDoc(doc(this.db, "users/" + email), {
|
|
1155
|
-
collectionPaths: arrayRemove(collectionPath.replaceAll("/", "-"))
|
|
1156
|
-
});
|
|
1157
1234
|
return this.sendResponse({
|
|
1158
1235
|
success: true,
|
|
1159
1236
|
message: "",
|
|
@@ -1170,18 +1247,20 @@ export const EdgeFirebase = class {
|
|
|
1170
1247
|
};
|
|
1171
1248
|
|
|
1172
1249
|
public removeUserSpecialPermissions = async (
|
|
1173
|
-
|
|
1250
|
+
docId: string,
|
|
1174
1251
|
collectionPath: string
|
|
1175
1252
|
): Promise<actionResponse> => {
|
|
1176
|
-
|
|
1253
|
+
let canAssign = await this.permissionCheck("assign", collectionPath);
|
|
1254
|
+
if (docId === this.user.stagedDocId) {
|
|
1255
|
+
// User can remove themselves from any special permission
|
|
1256
|
+
canAssign = true;
|
|
1257
|
+
}
|
|
1177
1258
|
if (canAssign) {
|
|
1178
|
-
await updateDoc(doc(this.db, "users/" +
|
|
1259
|
+
await updateDoc(doc(this.db, "staged-users/" + docId), {
|
|
1260
|
+
collectionPaths: arrayRemove(collectionPath.replaceAll("/", "-")),
|
|
1179
1261
|
["specialPermissions." + collectionPath.replaceAll("/", "-")]:
|
|
1180
1262
|
deleteField()
|
|
1181
1263
|
});
|
|
1182
|
-
await updateDoc(doc(this.db, "users/" + email), {
|
|
1183
|
-
collectionPaths: arrayRemove(collectionPath.replaceAll("/", "-"))
|
|
1184
|
-
});
|
|
1185
1264
|
return this.sendResponse({
|
|
1186
1265
|
success: true,
|
|
1187
1266
|
message: "",
|
|
@@ -1198,11 +1277,11 @@ export const EdgeFirebase = class {
|
|
|
1198
1277
|
};
|
|
1199
1278
|
|
|
1200
1279
|
public storeUserSpecialPermissions = async (
|
|
1201
|
-
|
|
1280
|
+
docId: string,
|
|
1202
1281
|
collectionPath: string,
|
|
1203
1282
|
permissions: permissions
|
|
1204
1283
|
): Promise<actionResponse> => {
|
|
1205
|
-
const canAssign = this.permissionCheck("assign", collectionPath);
|
|
1284
|
+
const canAssign = await this.permissionCheck("assign", collectionPath);
|
|
1206
1285
|
if (canAssign) {
|
|
1207
1286
|
const collectionExists = await this.collectionExists(collectionPath);
|
|
1208
1287
|
if (collectionExists) {
|
|
@@ -1210,11 +1289,13 @@ export const EdgeFirebase = class {
|
|
|
1210
1289
|
["specialPermissions." + collectionPath.replaceAll("/", "-")]: {
|
|
1211
1290
|
collectionPath: collectionPath.replaceAll("/", "-"),
|
|
1212
1291
|
permissions
|
|
1213
|
-
}
|
|
1292
|
+
},
|
|
1293
|
+
uid: this.user.uid
|
|
1214
1294
|
};
|
|
1215
|
-
await updateDoc(doc(this.db, "users/" +
|
|
1216
|
-
|
|
1217
|
-
collectionPaths: arrayUnion(collectionPath.replaceAll("/", "-"))
|
|
1295
|
+
await updateDoc(doc(this.db, "staged-users/" + docId), {
|
|
1296
|
+
...permissionItem,
|
|
1297
|
+
collectionPaths: arrayUnion(collectionPath.replaceAll("/", "-")),
|
|
1298
|
+
uid: this.user.uid
|
|
1218
1299
|
});
|
|
1219
1300
|
return this.sendResponse({
|
|
1220
1301
|
success: true,
|
|
@@ -1239,12 +1320,11 @@ export const EdgeFirebase = class {
|
|
|
1239
1320
|
};
|
|
1240
1321
|
|
|
1241
1322
|
private storeUserRoles = async (
|
|
1242
|
-
|
|
1323
|
+
docId: string,
|
|
1243
1324
|
collectionPath: string,
|
|
1244
1325
|
role: "admin" | "editor" | "writer" | "user"
|
|
1245
1326
|
): Promise<actionResponse> => {
|
|
1246
|
-
const canAssign = this.permissionCheck("assign", collectionPath);
|
|
1247
|
-
|
|
1327
|
+
const canAssign = await this.permissionCheck("assign", collectionPath);
|
|
1248
1328
|
if (canAssign) {
|
|
1249
1329
|
if (role === "admin" || role === "user" || role === "editor" || role === "writer") {
|
|
1250
1330
|
const collectionExists = await this.collectionExists(collectionPath);
|
|
@@ -1253,13 +1333,13 @@ export const EdgeFirebase = class {
|
|
|
1253
1333
|
["roles." + collectionPath.replaceAll("/", "-")]: {
|
|
1254
1334
|
collectionPath: collectionPath.replaceAll("/", "-"),
|
|
1255
1335
|
role
|
|
1256
|
-
}
|
|
1336
|
+
},
|
|
1337
|
+
uid: this.user.uid
|
|
1257
1338
|
};
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
});
|
|
1339
|
+
await updateDoc(doc(this.db, "staged-users/" + docId), {
|
|
1340
|
+
...roleItem,
|
|
1341
|
+
collectionPaths: arrayUnion(collectionPath.replaceAll("/", "-")),
|
|
1342
|
+
uid: this.user.uid } );
|
|
1263
1343
|
return this.sendResponse({
|
|
1264
1344
|
success: true,
|
|
1265
1345
|
message: "",
|
|
@@ -1292,7 +1372,7 @@ export const EdgeFirebase = class {
|
|
|
1292
1372
|
public removeCollectionPermissions = async (
|
|
1293
1373
|
collectionPath: string,
|
|
1294
1374
|
): Promise<actionResponse> => {
|
|
1295
|
-
const canAssign = this.permissionCheck("assign", collectionPath);
|
|
1375
|
+
const canAssign = await this.permissionCheck("assign", collectionPath);
|
|
1296
1376
|
if (canAssign) {
|
|
1297
1377
|
await deleteDoc(doc(this.db, "collection-data", collectionPath.replaceAll("/", "-")));
|
|
1298
1378
|
return this.sendResponse({
|
|
@@ -1314,8 +1394,7 @@ export const EdgeFirebase = class {
|
|
|
1314
1394
|
role: "admin" | "editor" | "writer" | "user",
|
|
1315
1395
|
permissions: permissions
|
|
1316
1396
|
): Promise<actionResponse> => {
|
|
1317
|
-
const canAssign = this.permissionCheck("assign", collectionPath);
|
|
1318
|
-
// TODO: check if collectionPath starts with "users" and deny if so
|
|
1397
|
+
const canAssign = await this.permissionCheck("assign", collectionPath);
|
|
1319
1398
|
if (canAssign) {
|
|
1320
1399
|
if (role === "admin" || role === "editor" || role === "writer" || role === "user") {
|
|
1321
1400
|
const currentTime = new Date().getTime();
|
|
@@ -1368,7 +1447,7 @@ export const EdgeFirebase = class {
|
|
|
1368
1447
|
collectionPath: string,
|
|
1369
1448
|
item: object,
|
|
1370
1449
|
): Promise<actionResponse> => {
|
|
1371
|
-
const canWrite = this.permissionCheck("write", collectionPath);
|
|
1450
|
+
const canWrite = await this.permissionCheck("write", collectionPath);
|
|
1372
1451
|
if (!canWrite) {
|
|
1373
1452
|
return this.sendResponse({
|
|
1374
1453
|
success: false,
|
|
@@ -1385,7 +1464,7 @@ export const EdgeFirebase = class {
|
|
|
1385
1464
|
}
|
|
1386
1465
|
if (Object.prototype.hasOwnProperty.call(cloneItem, "docId")) {
|
|
1387
1466
|
const docId = cloneItem.docId;
|
|
1388
|
-
const canRead = this.
|
|
1467
|
+
const canRead = this.permissionCheckOnly("read", collectionPath);
|
|
1389
1468
|
if (canRead) {
|
|
1390
1469
|
if (Object.prototype.hasOwnProperty.call(this.data, collectionPath)) {
|
|
1391
1470
|
this.data[collectionPath][docId] = cloneItem;
|
|
@@ -1402,7 +1481,7 @@ export const EdgeFirebase = class {
|
|
|
1402
1481
|
collection(this.db, collectionPath),
|
|
1403
1482
|
cloneItem
|
|
1404
1483
|
);
|
|
1405
|
-
const canRead = this.
|
|
1484
|
+
const canRead = this.permissionCheckOnly("read", collectionPath);
|
|
1406
1485
|
if (canRead) {
|
|
1407
1486
|
if (Object.prototype.hasOwnProperty.call(this.data, collectionPath)) {
|
|
1408
1487
|
this.data[collectionPath][docRef.id] = cloneItem;
|
|
@@ -1426,7 +1505,7 @@ export const EdgeFirebase = class {
|
|
|
1426
1505
|
collectionPath: string,
|
|
1427
1506
|
docId: string
|
|
1428
1507
|
): Promise<actionResponse> => {
|
|
1429
|
-
const canDelete = this.permissionCheck("delete", collectionPath);
|
|
1508
|
+
const canDelete = await this.permissionCheck("delete", collectionPath);
|
|
1430
1509
|
if (canDelete) {
|
|
1431
1510
|
if (Object.prototype.hasOwnProperty.call(this.data, collectionPath)) {
|
|
1432
1511
|
if (
|
|
@@ -1457,4 +1536,4 @@ export const EdgeFirebase = class {
|
|
|
1457
1536
|
this.unsubscibe[collectionPath] = null;
|
|
1458
1537
|
}
|
|
1459
1538
|
};
|
|
1460
|
-
};
|
|
1539
|
+
};
|