@edgedev/firebase 1.7.3 → 1.7.5

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 CHANGED
@@ -374,12 +374,13 @@ Remove a role from a user for a collection:
374
374
 
375
375
  ### Root permissions and first user
376
376
 
377
- You can assign a user access to all collections in the entire project by giving them a role on "-", which is used to define the root collection path. This would be for someone who is acting like a super admin. If this is your first user, you will need to manually set them up in the Firstore console. Once a root user is added manually you can use this user to add other "root users" or setup other collections and assign roles to them. The first time you login with your root user the collection-data/-default- role permissions document (mentioned above) will be automatically created.
377
+ You can assign a user access to all collections in the entire project by giving them a role on "-", which is used to define the root collection path. This would be for someone who is acting like a super admin. If this is your first user, you will need to manually set them up in the Firstore console inside the "staged-users". Once a root user is added manually, you will need to "Register" that user using the docId of the "staged user" as the registration code, please see the user registration section of this documentation. You can use this user to add other "root users" or setup other collections and assign roles to them. You will also need to manually create the collection-data/-default- role permissions document (mentioned above) and the root permission document, see examples below:
378
378
 
379
- | ![root-collection-roles](./images/root-collection-roles.png) | ![root-user](./images/root-user.jpg) |
380
- | ------------------------------------------------------------ | ------------------------------------ |
379
+ ![root-collection-roles](./images/default-collection-roles.png)
381
380
 
381
+ ![root-collection-roles](./images/root-collection-roles.png)
382
382
 
383
+ ![root-user](./images/root-user.png)
383
384
 
384
385
  ### User special permissions
385
386
 
@@ -1005,38 +1006,38 @@ service cloud.firestore {
1005
1006
  allow get: if checkPermission(seg1 + "-" + seg2, "read");
1006
1007
  allow list: if checkPermission(seg1, "read");
1007
1008
  allow create: if checkPermission(seg1, "write");
1008
- allow update: if checkPermission(seg1, "write");
1009
+ allow update: if checkPermission(seg1 + "-" + seg2, "write");
1009
1010
  allow delete: if checkPermission(seg1, "delete");
1010
1011
  match /{seg3} {
1011
1012
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "read");
1012
1013
  allow list: if checkPermission(seg1 + "-" + seg2, "read");
1013
1014
  allow create: if checkPermission(seg1 + "-" + seg2, "write");
1014
- allow update: if checkPermission(seg1 + "-" + seg2, "write");
1015
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "write");
1015
1016
  allow delete: if checkPermission(seg1 + "-" + seg2, "delete");
1016
1017
  match /{seg4} {
1017
1018
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "read");
1018
1019
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "read");
1019
1020
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "write");
1020
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "write");
1021
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "write");
1021
1022
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "delete");
1022
1023
 
1023
1024
  match /{seg5} {
1024
1025
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "read");
1025
1026
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "read");
1026
1027
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "write");
1027
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "write");
1028
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "write");
1028
1029
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "delete");
1029
1030
  match /{seg6} {
1030
1031
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "read");
1031
1032
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "read");
1032
1033
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "write");
1033
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "write");
1034
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "write");
1034
1035
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "delete");
1035
1036
  match /{seg7} {
1036
1037
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6 + "-" + seg7, "read");
1037
1038
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "read");
1038
1039
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "write");
1039
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "write");
1040
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6 + "-" + seg7, "write");
1040
1041
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "delete");
1041
1042
  }
1042
1043
  }
package/edgeFirebase.ts CHANGED
@@ -44,6 +44,9 @@ import {
44
44
  connectAuthEmulator,
45
45
  } from "firebase/auth";
46
46
 
47
+
48
+ import { getAnalytics, logEvent } from "firebase/analytics";
49
+
47
50
  interface FirestoreQuery {
48
51
  field: string;
49
52
  operator: WhereFilterOp; // '==' | '<' | '<=' | '>' | '>=' | 'array-contains' | 'in' | 'array-contains-any';
@@ -108,7 +111,7 @@ interface newUser {
108
111
  role: string,
109
112
  dynamicDocumentField: string, // This is the field in the document that will be set by the value of "dynamicDocumentFieldValue" passed during registration, like "name"
110
113
  documentStructure: {
111
- [key: string]: any
114
+ [key: string]: unknown
112
115
  }
113
116
  };
114
117
  }
@@ -151,6 +154,7 @@ interface firebaseConfig {
151
154
  messagingSenderId: string;
152
155
  appId: string;
153
156
  emulatorAuth?: string;
157
+ measurementId?: string;
154
158
  emulatorFirestore?: string;
155
159
  }
156
160
 
@@ -174,6 +178,7 @@ export const EdgeFirebase = class {
174
178
  storageBucket: "",
175
179
  messagingSenderId: "",
176
180
  appId: "",
181
+ measurementId: "",
177
182
  emulatorAuth: "",
178
183
  emulatorFirestore: ""
179
184
  },
@@ -196,6 +201,10 @@ export const EdgeFirebase = class {
196
201
  connectFirestoreEmulator(this.db, "localhost", this.firebaseConfig.emulatorFirestore)
197
202
  }
198
203
 
204
+ if (this.firebaseConfig.measurementId) {
205
+ this.anaytics = getAnalytics(this.app);
206
+ }
207
+
199
208
  this.setOnAuthStateChanged();
200
209
  }
201
210
 
@@ -205,6 +214,14 @@ export const EdgeFirebase = class {
205
214
  public auth = null;
206
215
  public db = null;
207
216
 
217
+ private anaytics = null;
218
+
219
+ public logAnalyticsEvent = (eventName: string, eventParams: object = {}) => {
220
+ if (this.anaytics) {
221
+ logEvent(this.anaytics, eventName, eventParams);
222
+ }
223
+ };
224
+
208
225
  private initUserMetaPermissions = async (docSnap): Promise<void> => {
209
226
  this.user.meta = {};
210
227
  if (docSnap.exists()) {
@@ -352,6 +369,7 @@ export const EdgeFirebase = class {
352
369
  this.user.uid = userAuth.uid;
353
370
  this.user.logInError = false;
354
371
  this.user.logInErrorMessage = "";
372
+ this.logAnalyticsEvent("login", { uid: this.user.uid });
355
373
  this.waitForUser();
356
374
  } else {
357
375
  this.user.email = "";
@@ -417,7 +435,7 @@ export const EdgeFirebase = class {
417
435
  initRoleHelper["edge-assignment-helper"] = {permissionType: "roles"}
418
436
  await setDoc(doc(this.db, "rule-helpers", response.user.uid), initRoleHelper);
419
437
  await updateDoc(doc(this.db, "staged-users/" + userRegister.registrationCode), stagedUserUpdate)
420
-
438
+ this.logAnalyticsEvent("sign_up", { uid: response.user.uid});
421
439
  return this.sendResponse({
422
440
  success: true,
423
441
  message: "",
@@ -806,6 +824,7 @@ export const EdgeFirebase = class {
806
824
  if (this.unsubscibe[key] instanceof Function) {
807
825
  this.unsubscibe[key]();
808
826
  this.unsubscibe[key] = null;
827
+ this.data[key] = {};
809
828
  }
810
829
  }
811
830
  signOut(this.auth).then(() => {
@@ -829,7 +848,7 @@ export const EdgeFirebase = class {
829
848
  credentials.password
830
849
  )
831
850
  .then(() => {
832
- // do nothing
851
+ // Do nothing
833
852
  })
834
853
  .catch((error) => {
835
854
  this.user.email = "";
@@ -1480,62 +1499,107 @@ export const EdgeFirebase = class {
1480
1499
  }
1481
1500
  };
1482
1501
 
1483
- // Composable to update/add a document
1484
- public storeDoc = async (
1502
+ // TODO: Add documentation for this function
1503
+ public changeDoc = async (
1485
1504
  collectionPath: string,
1486
- item: object,
1505
+ docId: string,
1506
+ item: object
1487
1507
  ): Promise<actionResponse> => {
1488
- const canWrite = await this.permissionCheck("write", collectionPath);
1508
+ const canWrite = await this.permissionCheck("write", collectionPath + "/" + docId);
1489
1509
  if (!canWrite) {
1490
1510
  return this.sendResponse({
1491
1511
  success: false,
1492
- message: `You do not have permission to write to "${collectionPath}"`,
1512
+ message: `You do not have permission to write to "${collectionPath}/${docId}"`,
1493
1513
  meta: {}
1494
1514
  });
1495
1515
  } else {
1516
+ const docRef = doc(this.db, collectionPath, docId);
1517
+ const docSnap = await getDoc(docRef);
1518
+ if (!docSnap.exists()) {
1519
+ return this.sendResponse({
1520
+ success: false,
1521
+ message: `Document "${docId}" does not exist in "${collectionPath}"`,
1522
+ meta: {}
1523
+ });
1524
+ }
1496
1525
  const cloneItem = JSON.parse(JSON.stringify(item));
1497
1526
  const currentTime = new Date().getTime();
1498
1527
  cloneItem.last_updated = currentTime;
1499
1528
  cloneItem.uid = this.user.uid;
1500
- if (!Object.prototype.hasOwnProperty.call(cloneItem, "doc_created_at")) {
1501
- cloneItem.doc_created_at = currentTime;
1502
- }
1503
- if (Object.prototype.hasOwnProperty.call(cloneItem, "docId")) {
1504
- const docId = cloneItem.docId;
1505
- const canRead = this.permissionCheckOnly("read", collectionPath);
1506
- if (canRead) {
1507
- if (Object.prototype.hasOwnProperty.call(this.data, collectionPath)) {
1508
- this.data[collectionPath][docId] = cloneItem;
1509
- }
1510
- }
1511
- await setDoc(doc(this.db, collectionPath, docId), cloneItem);
1529
+ await updateDoc(doc(this.db, collectionPath, docId), cloneItem);
1530
+ return this.sendResponse({
1531
+ success: true,
1532
+ message: "",
1533
+ meta: {}
1534
+ });
1535
+ }
1536
+ };
1537
+
1538
+
1539
+ public storeDoc = async (
1540
+ collectionPath: string,
1541
+ item: object,
1542
+ ): Promise<actionResponse> => {
1543
+
1544
+ const cloneItem = JSON.parse(JSON.stringify(item));
1545
+ const currentTime = new Date().getTime();
1546
+ cloneItem.last_updated = currentTime;
1547
+ cloneItem.uid = this.user.uid;
1548
+ if (!Object.prototype.hasOwnProperty.call(cloneItem, "doc_created_at")) {
1549
+ cloneItem.doc_created_at = currentTime;
1550
+ }
1551
+ if (Object.prototype.hasOwnProperty.call(cloneItem, "docId")) {
1552
+ const canWrite = await this.permissionCheck("write", collectionPath + "/" + cloneItem.docId);
1553
+ if (!canWrite) {
1512
1554
  return this.sendResponse({
1513
- success: true,
1514
- message: "",
1515
- meta: {docId}
1555
+ success: false,
1556
+ message: `You do not have permission to write to "${collectionPath}/${cloneItem.docId}"`,
1557
+ meta: {}
1516
1558
  });
1517
- } else {
1518
- const docRef = await addDoc(
1519
- collection(this.db, collectionPath),
1520
- cloneItem
1521
- );
1522
- const canRead = this.permissionCheckOnly("read", collectionPath);
1523
- if (canRead) {
1524
- if (Object.prototype.hasOwnProperty.call(this.data, collectionPath)) {
1525
- this.data[collectionPath][docRef.id] = cloneItem;
1526
- }
1559
+ }
1560
+ const docId = cloneItem.docId;
1561
+ const canRead = this.permissionCheckOnly("read", collectionPath);
1562
+ if (canRead) {
1563
+ if (Object.prototype.hasOwnProperty.call(this.data, collectionPath)) {
1564
+ this.data[collectionPath][docId] = cloneItem;
1527
1565
  }
1528
- await this.storeDoc(
1529
- collectionPath,
1530
- { ...cloneItem, docId: docRef.id }
1531
- );
1566
+ }
1567
+ await setDoc(doc(this.db, collectionPath, docId), cloneItem);
1568
+ return this.sendResponse({
1569
+ success: true,
1570
+ message: "",
1571
+ meta: {docId}
1572
+ });
1573
+ } else {
1574
+ const canWrite = await this.permissionCheck("write", collectionPath);
1575
+ if (!canWrite) {
1532
1576
  return this.sendResponse({
1533
- success: true,
1534
- message: "",
1535
- meta: {docId: docRef.id}
1577
+ success: false,
1578
+ message: `You do not have permission to write to "${collectionPath}"`,
1579
+ meta: {}
1536
1580
  });
1537
1581
  }
1582
+ const docRef = await addDoc(
1583
+ collection(this.db, collectionPath),
1584
+ cloneItem
1585
+ );
1586
+ const canRead = this.permissionCheckOnly("read", collectionPath);
1587
+ if (canRead) {
1588
+ if (Object.prototype.hasOwnProperty.call(this.data, collectionPath)) {
1589
+ this.data[collectionPath][docRef.id] = cloneItem;
1590
+ }
1591
+ }
1592
+ await this.storeDoc(
1593
+ collectionPath,
1594
+ { ...cloneItem, docId: docRef.id }
1595
+ );
1596
+ return this.sendResponse({
1597
+ success: true,
1598
+ message: "",
1599
+ meta: {docId: docRef.id}
1600
+ });
1538
1601
  }
1602
+
1539
1603
  };
1540
1604
 
1541
1605
  // Composable to delete a document
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgedev/firebase",
3
- "version": "1.7.3",
3
+ "version": "1.7.5",
4
4
  "description": "Vue 3 / Nuxt 3 Plugin or Nuxt 3 plugin for firebase authentication and firestore.",
5
5
  "main": "index.ts",
6
6
  "scripts": {
File without changes