@edgedev/firebase 1.7.2 → 1.7.4

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.
Files changed (3) hide show
  1. package/README.md +6 -10
  2. package/edgeFirebase.ts +104 -40
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -125,7 +125,6 @@ exports.updateUser = functions.firestore.document('staged-users/{docId}').onUpda
125
125
  return shouldProcess(eventRef).then((process) => {
126
126
  if (process) {
127
127
  // Note: we can trust on newData.uid because we are checking in rules that it matches the auth.uid
128
- // TODO: user might be invited to join another org with reg code.. if used when logged will combine new staged-user doc into first stage-user doc and sync to users.
129
128
  if (newData.userId) {
130
129
  const userRef = db.collection('users').doc(newData.userId)
131
130
  setUser(userRef, newData, oldData, stagedDocId).then(() => {
@@ -181,9 +180,6 @@ exports.updateUser = functions.firestore.document('staged-users/{docId}').onUpda
181
180
  })
182
181
 
183
182
  function setUser(userRef, newData, oldData, stagedDocId) {
184
- // IT's OK If "users" doesn't match exactly matched "staged-users" because this is only preventing
185
- // writing from outside the @edgdev/firebase functions, so discrepancies will be rare since
186
- // the package will prevent before it gets this far.
187
183
  return userRef.get().then((user) => {
188
184
  let userUpdate = { meta: newData.meta, stagedDocId }
189
185
 
@@ -1009,38 +1005,38 @@ service cloud.firestore {
1009
1005
  allow get: if checkPermission(seg1 + "-" + seg2, "read");
1010
1006
  allow list: if checkPermission(seg1, "read");
1011
1007
  allow create: if checkPermission(seg1, "write");
1012
- allow update: if checkPermission(seg1, "write");
1008
+ allow update: if checkPermission(seg1 + "-" + seg2, "write");
1013
1009
  allow delete: if checkPermission(seg1, "delete");
1014
1010
  match /{seg3} {
1015
1011
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "read");
1016
1012
  allow list: if checkPermission(seg1 + "-" + seg2, "read");
1017
1013
  allow create: if checkPermission(seg1 + "-" + seg2, "write");
1018
- allow update: if checkPermission(seg1 + "-" + seg2, "write");
1014
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "write");
1019
1015
  allow delete: if checkPermission(seg1 + "-" + seg2, "delete");
1020
1016
  match /{seg4} {
1021
1017
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "read");
1022
1018
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "read");
1023
1019
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "write");
1024
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "write");
1020
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "write");
1025
1021
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3, "delete");
1026
1022
 
1027
1023
  match /{seg5} {
1028
1024
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "read");
1029
1025
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "read");
1030
1026
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "write");
1031
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "write");
1027
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "write");
1032
1028
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4, "delete");
1033
1029
  match /{seg6} {
1034
1030
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "read");
1035
1031
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "read");
1036
1032
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "write");
1037
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "write");
1033
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "write");
1038
1034
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5, "delete");
1039
1035
  match /{seg7} {
1040
1036
  allow get: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6 + "-" + seg7, "read");
1041
1037
  allow list: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "read");
1042
1038
  allow create: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "write");
1043
- allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "write");
1039
+ allow update: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6 + "-" + seg7, "write");
1044
1040
  allow delete: if checkPermission(seg1 + "-" + seg2 + "-" + seg3 + "-" + seg4 + "-" + seg5 + "-" + seg6, "delete");
1045
1041
  }
1046
1042
  }
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgedev/firebase",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
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": {