@edgedev/firebase 2.0.22 → 2.0.24
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/package.json +1 -1
- package/src/edgeFirebase.js +127 -45
package/package.json
CHANGED
package/src/edgeFirebase.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { onCall, HttpsError, logger, getFirestore, functions, admin, twilio, db, onSchedule, pubsub } = require('./config.js')
|
|
1
|
+
const { onCall, HttpsError, logger, getFirestore, functions, admin, twilio, db, onSchedule, onDocumentUpdated, pubsub } = require('./config.js')
|
|
2
2
|
|
|
3
3
|
const authToken = process.env.TWILIO_AUTH_TOKEN
|
|
4
4
|
const accountSid = process.env.TWILIO_SID
|
|
@@ -57,7 +57,8 @@ exports.topicQueue = onSchedule({ schedule: 'every 1 minutes', timeoutSeconds: 1
|
|
|
57
57
|
}
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
exports.sendVerificationCode =
|
|
60
|
+
exports.sendVerificationCode = onCall(async (request) => {
|
|
61
|
+
const data = request.data
|
|
61
62
|
const code = (Math.floor(Math.random() * 1000000) + 1000000).toString().substring(1)
|
|
62
63
|
const phone = formatPhoneNumber(data.phone)
|
|
63
64
|
|
|
@@ -87,7 +88,8 @@ exports.sendVerificationCode = functions.https.onCall(async (data, context) => {
|
|
|
87
88
|
}
|
|
88
89
|
})
|
|
89
90
|
|
|
90
|
-
exports.verifyPhoneNumber =
|
|
91
|
+
exports.verifyPhoneNumber = onCall(async (request) => {
|
|
92
|
+
const data = request.data
|
|
91
93
|
const phone = data.phone
|
|
92
94
|
const code = data.code
|
|
93
95
|
|
|
@@ -120,7 +122,7 @@ exports.verifyPhoneNumber = functions.https.onCall(async (data, context) => {
|
|
|
120
122
|
}
|
|
121
123
|
})
|
|
122
124
|
|
|
123
|
-
exports.initFirestore =
|
|
125
|
+
exports.initFirestore = onCall(async (request) => {
|
|
124
126
|
// checks to see of the collections 'collection-data' and 'staged-users' exist if not will seed them with data
|
|
125
127
|
const collectionData = await db.collection('collection-data').get()
|
|
126
128
|
const stagedUsers = await db.collection('staged-users').get()
|
|
@@ -154,8 +156,10 @@ exports.initFirestore = functions.https.onCall(async (data, context) => {
|
|
|
154
156
|
}
|
|
155
157
|
})
|
|
156
158
|
|
|
157
|
-
exports.removeNonRegisteredUser =
|
|
158
|
-
|
|
159
|
+
exports.removeNonRegisteredUser = onCall(async (request) => {
|
|
160
|
+
const data = request.data
|
|
161
|
+
const auth = request.auth
|
|
162
|
+
if (data.uid === auth.uid) {
|
|
159
163
|
const stagedUser = await db.collection('staged-users').doc(data.docId).get()
|
|
160
164
|
if (stagedUser.exists) {
|
|
161
165
|
const stagedUserData = stagedUser.data()
|
|
@@ -189,8 +193,10 @@ exports.removeNonRegisteredUser = functions.https.onCall(async (data, context) =
|
|
|
189
193
|
return { success: false, message: 'Non-registered user not found.' }
|
|
190
194
|
})
|
|
191
195
|
|
|
192
|
-
exports.currentUserRegister =
|
|
193
|
-
|
|
196
|
+
exports.currentUserRegister = onCall(async (request) => {
|
|
197
|
+
const data = request.data
|
|
198
|
+
const auth = request.auth
|
|
199
|
+
if (data.uid === auth.uid) {
|
|
194
200
|
const stagedUser = await db.collection('staged-users').doc(data.registrationCode).get()
|
|
195
201
|
if (!stagedUser.exists) {
|
|
196
202
|
return { success: false, message: 'Registration code not found.' }
|
|
@@ -246,10 +252,76 @@ exports.checkOrgIdExists = onCall(async (request) => {
|
|
|
246
252
|
return { exists: orgDoc.exists }
|
|
247
253
|
})
|
|
248
254
|
|
|
249
|
-
|
|
250
|
-
|
|
255
|
+
const permissionCheck = async (userId, action, collectionPath) => {
|
|
256
|
+
// Fetch user document
|
|
257
|
+
const userDoc = await db.collection('users').doc(userId).get()
|
|
258
|
+
const userData = userDoc.data()
|
|
259
|
+
|
|
260
|
+
// Fetch roles from user data
|
|
261
|
+
const roles = userData.roles || []
|
|
262
|
+
|
|
263
|
+
// Check each role for permission
|
|
264
|
+
for (let role of roles) {
|
|
265
|
+
if (role.collectionPath === collectionPath) {
|
|
266
|
+
// Fetch collection data
|
|
267
|
+
const collectionDoc = await db.collection('collection-data').doc(collectionPath).get()
|
|
268
|
+
const collectionData = collectionDoc.exists ? collectionDoc.data() : await db.collection('collection-data').doc('-default-').get().then(doc => doc.data())
|
|
269
|
+
|
|
270
|
+
// Check if action is permitted
|
|
271
|
+
if (collectionData && collectionData[role.role] && collectionData[role.role][action]) {
|
|
272
|
+
return true
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// If no permission found, return false
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
exports.deleteSelf = onCall(async (request) => {
|
|
282
|
+
if (request.data.uid === request.auth.uid) {
|
|
283
|
+
try {
|
|
284
|
+
const userDoc = await db.collection('staged-users').doc(request.auth.uid).get()
|
|
285
|
+
const userData = userDoc.data()
|
|
286
|
+
const userCollectionPaths = userData.collectionPaths || []
|
|
287
|
+
|
|
288
|
+
for (let path of userCollectionPaths) {
|
|
289
|
+
const usersWithSamePath = await db.collection('staged-users').where('collectionPaths', 'array-contains', path).get()
|
|
290
|
+
|
|
291
|
+
// If no other users have the same collection path, delete the path and all documents and collections under it
|
|
292
|
+
if (usersWithSamePath.size <= 1) {
|
|
293
|
+
const docsToDelete = await db.collection(path).get()
|
|
294
|
+
const batch = db.batch()
|
|
295
|
+
docsToDelete.docs.forEach((doc) => {
|
|
296
|
+
batch.delete(doc.ref)
|
|
297
|
+
})
|
|
298
|
+
await batch.commit()
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Delete from 'staged-users' collection
|
|
303
|
+
await db.collection('staged-users').doc(request.data.uid).delete()
|
|
304
|
+
|
|
305
|
+
// Delete from 'users' collection
|
|
306
|
+
await db.collection('users').doc(request.data.uid).delete()
|
|
307
|
+
|
|
308
|
+
// Delete the user from Firebase
|
|
309
|
+
await admin.auth().deleteUser(request.data.uid)
|
|
310
|
+
|
|
311
|
+
return { success: true }
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
console.error('Error deleting user:', error)
|
|
315
|
+
return { success: false, error }
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
exports.updateUser = onDocumentUpdated({ document: 'staged-users/{docId}', timeoutSeconds: 180 }, async (event) => {
|
|
321
|
+
const change = event.data
|
|
322
|
+
const eventId = event.id
|
|
251
323
|
const eventRef = db.collection('events').doc(eventId)
|
|
252
|
-
const stagedDocId =
|
|
324
|
+
const stagedDocId = event.params.docId
|
|
253
325
|
let newData = change.after.data()
|
|
254
326
|
const oldData = change.before.data()
|
|
255
327
|
|
|
@@ -286,7 +358,26 @@ exports.updateUser = functions.firestore.document('staged-users/{docId}').onUpda
|
|
|
286
358
|
if (Object.prototype.hasOwnProperty.call(newData, 'subCreate') && Object.values(newData.subCreate).length > 0) {
|
|
287
359
|
const subCreate = newData.subCreate
|
|
288
360
|
delete newData.subCreate
|
|
289
|
-
|
|
361
|
+
let newDocId = ''
|
|
362
|
+
if (Object.prototype.hasOwnProperty.call(newData, 'requestedOrgId')) {
|
|
363
|
+
newDocId = newData.requestedOrgId.toLowerCase()
|
|
364
|
+
delete newData.requestedOrgId
|
|
365
|
+
}
|
|
366
|
+
let addedDoc
|
|
367
|
+
if (newDocId) {
|
|
368
|
+
const docRef = db.collection(subCreate.rootPath).doc(newDocId)
|
|
369
|
+
const doc = await docRef.get()
|
|
370
|
+
if (!doc.exists) {
|
|
371
|
+
await docRef.set({ [subCreate.dynamicDocumentField]: newData.dynamicDocumentFieldValue })
|
|
372
|
+
addedDoc = docRef
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
addedDoc = await db.collection(subCreate.rootPath).add({ [subCreate.dynamicDocumentField]: newData.dynamicDocumentFieldValue })
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
addedDoc = await db.collection(subCreate.rootPath).add({ [subCreate.dynamicDocumentField]: newData.dynamicDocumentFieldValue })
|
|
380
|
+
}
|
|
290
381
|
await db.collection(subCreate.rootPath).doc(addedDoc.id).update({ docId: addedDoc.id })
|
|
291
382
|
delete newData.dynamicDocumentFieldValue
|
|
292
383
|
const newRole = { [`${subCreate.rootPath}-${addedDoc.id}`]: { collectionPath: `${subCreate.rootPath}-${addedDoc.id}`, role: subCreate.role } }
|
|
@@ -316,42 +407,33 @@ exports.updateUser = functions.firestore.document('staged-users/{docId}').onUpda
|
|
|
316
407
|
await markProcessed(eventRef)
|
|
317
408
|
})
|
|
318
409
|
|
|
319
|
-
function setUser(userRef, newData, oldData, stagedDocId) {
|
|
320
|
-
// IT's OK If "users" doesn't match exactly matched "staged-users" because this is only preventing
|
|
321
|
-
// writing from outside the @edgdev/firebase functions, so discrepancies will be rare since
|
|
322
|
-
// the package will prevent before it gets this far.
|
|
323
|
-
return userRef.get().then((user) => {
|
|
324
|
-
let userUpdate = { meta: newData.meta, stagedDocId }
|
|
325
|
-
|
|
326
|
-
if (newData.meta && newData.meta.name) {
|
|
327
|
-
const publicUserRef = db.collection('public-users').doc(newData.userId)
|
|
328
|
-
const publicMeta = { name: newData.meta.name }
|
|
329
|
-
publicUserRef.set({ uid: newData.uid, meta: publicMeta, collectionPaths: newData.collectionPaths, userId: newData.userId })
|
|
330
|
-
}
|
|
410
|
+
async function setUser(userRef, newData, oldData, stagedDocId) {
|
|
331
411
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
if (Object.prototype.hasOwnProperty.call(newData, 'specialPermissions')) {
|
|
336
|
-
userUpdate = { ...userUpdate, specialPermissions: newData.specialPermissions }
|
|
337
|
-
}
|
|
412
|
+
const user = await userRef.get()
|
|
413
|
+
let userUpdate = { meta: newData.meta, stagedDocId }
|
|
338
414
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
return userRef.update(userUpdate)
|
|
347
|
-
}
|
|
348
|
-
})
|
|
349
|
-
}
|
|
415
|
+
if (newData.meta && newData.meta.name) {
|
|
416
|
+
const publicUserRef = db.collection('public-users').doc(stagedDocId)
|
|
417
|
+
const publicMeta = { name: newData.meta.name }
|
|
418
|
+
publicUserRef.set({ uid: newData.uid, meta: publicMeta, collectionPaths: newData.collectionPaths, userId: stagedDocId })
|
|
419
|
+
}
|
|
350
420
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
421
|
+
if (Object.prototype.hasOwnProperty.call(newData, 'roles')) {
|
|
422
|
+
userUpdate = { ...userUpdate, roles: newData.roles }
|
|
423
|
+
}
|
|
424
|
+
if (Object.prototype.hasOwnProperty.call(newData, 'specialPermissions')) {
|
|
425
|
+
userUpdate = { ...userUpdate, specialPermissions: newData.specialPermissions }
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if (!oldData.userId) {
|
|
429
|
+
userUpdate = { ...userUpdate, userId: newData.uid }
|
|
430
|
+
}
|
|
431
|
+
if (!user.exists) {
|
|
432
|
+
return userRef.set(userUpdate)
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
return userRef.update(userUpdate)
|
|
436
|
+
}
|
|
355
437
|
}
|
|
356
438
|
|
|
357
439
|
function markProcessed(eventRef) {
|