@edgedev/firebase 2.2.81 → 2.2.82
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/cms.js +12 -10
- package/src/edgeFirebase.js +124 -124
package/package.json
CHANGED
package/src/cms.js
CHANGED
|
@@ -1839,12 +1839,18 @@ const buildBlockAiPrompt = ({
|
|
|
1839
1839
|
].join('\n')
|
|
1840
1840
|
}
|
|
1841
1841
|
|
|
1842
|
+
const assertCallableUser = (request) => {
|
|
1843
|
+
if (!request?.auth?.uid)
|
|
1844
|
+
throw new HttpsError('unauthenticated', 'Authentication required.')
|
|
1845
|
+
if (request?.data?.uid !== request.auth.uid)
|
|
1846
|
+
throw new HttpsError('permission-denied', 'UID mismatch.')
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1842
1849
|
exports.updateSeoFromAi = onCall({ timeoutSeconds: 180 }, async (request) => {
|
|
1850
|
+
assertCallableUser(request)
|
|
1843
1851
|
const data = request.data || {}
|
|
1844
1852
|
const auth = request.auth
|
|
1845
|
-
const { orgId, siteId, pageId
|
|
1846
|
-
if (!auth?.uid || auth.uid !== uid)
|
|
1847
|
-
throw new HttpsError('permission-denied', 'Unauthorized')
|
|
1853
|
+
const { orgId, siteId, pageId } = data
|
|
1848
1854
|
if (!orgId || !siteId || !pageId)
|
|
1849
1855
|
throw new HttpsError('invalid-argument', 'Missing orgId, siteId, or pageId')
|
|
1850
1856
|
const allowed = await permissionCheck(auth.uid, 'write', `organizations/${orgId}/sites/${siteId}/pages`)
|
|
@@ -1910,9 +1916,7 @@ exports.updateSeoFromAi = onCall({ timeoutSeconds: 180 }, async (request) => {
|
|
|
1910
1916
|
})
|
|
1911
1917
|
|
|
1912
1918
|
exports.getCloudflarePagesProject = onCall(async (request) => {
|
|
1913
|
-
|
|
1914
|
-
throw new HttpsError('unauthenticated', 'Authentication required.')
|
|
1915
|
-
}
|
|
1919
|
+
assertCallableUser(request)
|
|
1916
1920
|
|
|
1917
1921
|
if (!CLOUDFLARE_PAGES_PROJECT) {
|
|
1918
1922
|
logger.warn('CLOUDFLARE_PAGES_PROJECT is not set.')
|
|
@@ -1923,12 +1927,10 @@ exports.getCloudflarePagesProject = onCall(async (request) => {
|
|
|
1923
1927
|
})
|
|
1924
1928
|
|
|
1925
1929
|
exports.generateBlockFields = onCall({ timeoutSeconds: 180 }, async (request) => {
|
|
1930
|
+
assertCallableUser(request)
|
|
1926
1931
|
const data = request.data || {}
|
|
1927
1932
|
const auth = request.auth
|
|
1928
|
-
const { orgId,
|
|
1929
|
-
|
|
1930
|
-
if (!auth?.uid || auth.uid !== uid)
|
|
1931
|
-
throw new HttpsError('permission-denied', 'Unauthorized')
|
|
1933
|
+
const { orgId, blockId, blockName, content, fields, currentValues, meta, instructions } = data
|
|
1932
1934
|
if (!orgId || !blockId)
|
|
1933
1935
|
throw new HttpsError('invalid-argument', 'Missing orgId or blockId')
|
|
1934
1936
|
if (!Array.isArray(fields) || fields.length === 0)
|
package/src/edgeFirebase.js
CHANGED
|
@@ -14,6 +14,13 @@ function formatPhoneNumber(phone) {
|
|
|
14
14
|
return `+1${numericPhone}`
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const assertCallableUser = (request) => {
|
|
18
|
+
if (!request?.auth?.uid)
|
|
19
|
+
throw new HttpsError('unauthenticated', 'Authentication required.')
|
|
20
|
+
if (request?.data?.uid !== request.auth.uid)
|
|
21
|
+
throw new HttpsError('permission-denied', 'UID mismatch.')
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
exports.uploadDocumentDeleted = onDocumentDeleted(
|
|
18
25
|
{ document: 'organizations/{orgId}/files/{docId}', timeoutSeconds: 180 },
|
|
19
26
|
async (event) => {
|
|
@@ -34,21 +41,19 @@ exports.uploadDocumentDeleted = onDocumentDeleted(
|
|
|
34
41
|
)
|
|
35
42
|
|
|
36
43
|
exports.addUpdateFileDoc = onCall(async (request) => {
|
|
44
|
+
assertCallableUser(request)
|
|
37
45
|
const data = request.data
|
|
38
|
-
const auth = request.auth
|
|
39
46
|
let docId = data?.docId
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
docId = docRef.id
|
|
51
|
-
}
|
|
47
|
+
console.log(data)
|
|
48
|
+
const orgId = data.orgId
|
|
49
|
+
if (docId) {
|
|
50
|
+
const docRef = db.collection(`organizations/${orgId}/files`).doc(docId)
|
|
51
|
+
await docRef.set(data, { merge: true })
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const docRef = db.collection(`organizations/${orgId}/files`).doc()
|
|
55
|
+
await docRef.set(data)
|
|
56
|
+
docId = docRef.id
|
|
52
57
|
}
|
|
53
58
|
console.log(docId)
|
|
54
59
|
return { docId }
|
|
@@ -426,91 +431,87 @@ exports.initFirestore = onCall(async (request) => {
|
|
|
426
431
|
})
|
|
427
432
|
|
|
428
433
|
exports.removeNonRegisteredUser = onCall(async (request) => {
|
|
434
|
+
assertCallableUser(request)
|
|
429
435
|
const data = request.data
|
|
430
|
-
const
|
|
431
|
-
if (
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
436
|
+
const stagedUser = await db.collection('staged-users').doc(data.docId).get()
|
|
437
|
+
if (stagedUser.exists) {
|
|
438
|
+
const stagedUserData = stagedUser.data()
|
|
439
|
+
|
|
440
|
+
const rolesExist = stagedUserData.roles && Object.keys(stagedUserData.roles).length !== 0
|
|
441
|
+
const specialPermissionsExist = stagedUserData.specialPermissions && Object.keys(stagedUserData.specialPermissions).length !== 0
|
|
442
|
+
const userIdExistsAndNotBlank = stagedUserData.userId && stagedUserData.userId !== ''
|
|
443
|
+
|
|
444
|
+
if (!rolesExist && !specialPermissionsExist && !userIdExistsAndNotBlank) {
|
|
445
|
+
await db.collection('staged-users').doc(data.docId).delete()
|
|
446
|
+
return { success: true, message: '' }
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
let message = ''
|
|
450
|
+
if (rolesExist && specialPermissionsExist) {
|
|
451
|
+
message = 'Cannot delete because the non-registered user still has roles and special permissions assigned.'
|
|
443
452
|
}
|
|
444
|
-
else {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
else if (specialPermissionsExist) {
|
|
453
|
-
message = 'Cannot delete because the non-registered user still has special permissions assigned.'
|
|
454
|
-
}
|
|
455
|
-
else if (userIdExistsAndNotBlank) {
|
|
456
|
-
message = 'Cannot delete because the user is registered.'
|
|
457
|
-
}
|
|
458
|
-
return { success: false, message }
|
|
453
|
+
else if (rolesExist) {
|
|
454
|
+
message = 'Cannot delete because the non-registered user still has roles assigned.'
|
|
455
|
+
}
|
|
456
|
+
else if (specialPermissionsExist) {
|
|
457
|
+
message = 'Cannot delete because the non-registered user still has special permissions assigned.'
|
|
458
|
+
}
|
|
459
|
+
else if (userIdExistsAndNotBlank) {
|
|
460
|
+
message = 'Cannot delete because the user is registered.'
|
|
459
461
|
}
|
|
462
|
+
return { success: false, message }
|
|
460
463
|
}
|
|
461
464
|
}
|
|
462
465
|
return { success: false, message: 'Non-registered user not found.' }
|
|
463
466
|
})
|
|
464
467
|
|
|
465
468
|
exports.currentUserRegister = onCall(async (request) => {
|
|
469
|
+
assertCallableUser(request)
|
|
466
470
|
const data = request.data
|
|
467
|
-
const
|
|
468
|
-
if (
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
471
|
+
const stagedUser = await db.collection('staged-users').doc(data.registrationCode).get()
|
|
472
|
+
if (!stagedUser.exists) {
|
|
473
|
+
return { success: false, message: 'Registration code not found.' }
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
const stagedUserData = await stagedUser.data()
|
|
477
|
+
let process = false
|
|
478
|
+
if (stagedUserData.isTemplate) {
|
|
479
|
+
process = true
|
|
472
480
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
const currentRoles = currentUserData.roles || {}
|
|
489
|
-
const currentUserCollectionPaths = currentUserData.collectionPaths || []
|
|
490
|
-
let newRole = {}
|
|
491
|
-
if (stagedUserData.subCreate && Object.keys(stagedUserData.subCreate).length !== 0 && stagedUserData.isTemplate) {
|
|
492
|
-
if (!data.dynamicDocumentFieldValue) {
|
|
493
|
-
return { success: false, message: 'Dynamic document field value is required.' }
|
|
494
|
-
}
|
|
495
|
-
const rootPath = stagedUserData.subCreate.rootPath
|
|
496
|
-
const newDoc = stagedUserData.subCreate.documentStructure
|
|
497
|
-
newDoc[stagedUserData.subCreate.dynamicDocumentField] = data.dynamicDocumentFieldValue
|
|
498
|
-
const addedDoc = await db.collection(rootPath).add(newDoc)
|
|
499
|
-
await db.collection(rootPath).doc(addedDoc.id).update({ docId: addedDoc.id })
|
|
500
|
-
newRole = { [`${rootPath}-${addedDoc.id}`]: { collectionPath: `${rootPath}-${addedDoc.id}`, role: stagedUserData.subCreate.role } }
|
|
481
|
+
if (!stagedUserData.isTemplate && stagedUserData.userId === '') {
|
|
482
|
+
process = true
|
|
483
|
+
}
|
|
484
|
+
if (!process) {
|
|
485
|
+
return { success: false, message: 'Registration code not valid.' }
|
|
486
|
+
}
|
|
487
|
+
const newRoles = stagedUserData.roles || {}
|
|
488
|
+
const currentUser = await db.collection('users').doc(data.uid).get()
|
|
489
|
+
const currentUserData = await currentUser.data()
|
|
490
|
+
const currentRoles = currentUserData.roles || {}
|
|
491
|
+
const currentUserCollectionPaths = currentUserData.collectionPaths || []
|
|
492
|
+
let newRole = {}
|
|
493
|
+
if (stagedUserData.subCreate && Object.keys(stagedUserData.subCreate).length !== 0 && stagedUserData.isTemplate) {
|
|
494
|
+
if (!data.dynamicDocumentFieldValue) {
|
|
495
|
+
return { success: false, message: 'Dynamic document field value is required.' }
|
|
501
496
|
}
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
497
|
+
const rootPath = stagedUserData.subCreate.rootPath
|
|
498
|
+
const newDoc = stagedUserData.subCreate.documentStructure
|
|
499
|
+
newDoc[stagedUserData.subCreate.dynamicDocumentField] = data.dynamicDocumentFieldValue
|
|
500
|
+
const addedDoc = await db.collection(rootPath).add(newDoc)
|
|
501
|
+
await db.collection(rootPath).doc(addedDoc.id).update({ docId: addedDoc.id })
|
|
502
|
+
newRole = { [`${rootPath}-${addedDoc.id}`]: { collectionPath: `${rootPath}-${addedDoc.id}`, role: stagedUserData.subCreate.role } }
|
|
503
|
+
}
|
|
504
|
+
const combinedRoles = { ...currentRoles, ...newRoles, ...newRole }
|
|
505
|
+
Object.values(combinedRoles).forEach((role) => {
|
|
506
|
+
if (!currentUserCollectionPaths.includes(role.collectionPath)) {
|
|
507
|
+
currentUserCollectionPaths.push(role.collectionPath)
|
|
511
508
|
}
|
|
512
|
-
|
|
509
|
+
})
|
|
510
|
+
await db.collection('staged-users').doc(currentUserData.stagedDocId).update({ roles: combinedRoles, collectionPaths: currentUserCollectionPaths })
|
|
511
|
+
if (!stagedUserData.isTemplate) {
|
|
512
|
+
await db.collection('staged-users').doc(data.registrationCode).delete()
|
|
513
513
|
}
|
|
514
|
+
return { success: true, message: '' }
|
|
514
515
|
}
|
|
515
516
|
})
|
|
516
517
|
|
|
@@ -522,52 +523,51 @@ exports.checkOrgIdExists = onCall(async (request) => {
|
|
|
522
523
|
})
|
|
523
524
|
|
|
524
525
|
exports.deleteSelf = onCall(async (request) => {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
}
|
|
526
|
+
assertCallableUser(request)
|
|
527
|
+
try {
|
|
528
|
+
const userDoc = await db.collection('staged-users').doc(request.auth.uid).get()
|
|
529
|
+
const userData = userDoc.data()
|
|
530
|
+
const userCollectionPaths = userData.collectionPaths || []
|
|
531
|
+
|
|
532
|
+
for (const path of userCollectionPaths) {
|
|
533
|
+
const usersWithSamePath = await db.collection('staged-users').where('collectionPaths', 'array-contains', path).get()
|
|
534
|
+
|
|
535
|
+
// If no other users have the same collection path, delete the path and all documents and collections under it
|
|
536
|
+
if (usersWithSamePath.size <= 1) {
|
|
537
|
+
const adjustedPath = path.replace(/-/g, '/')
|
|
538
|
+
const docRef = db.doc(adjustedPath)
|
|
539
|
+
const doc = await docRef.get()
|
|
540
|
+
|
|
541
|
+
if (doc.exists) {
|
|
542
|
+
// If the path is a document, delete it directly
|
|
543
|
+
await docRef.delete()
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
// If the path is a collection, delete all documents under it
|
|
547
|
+
const docsToDelete = await db.collection(adjustedPath).get()
|
|
548
|
+
const batch = db.batch()
|
|
549
|
+
docsToDelete.docs.forEach((doc) => {
|
|
550
|
+
batch.delete(doc.ref)
|
|
551
|
+
})
|
|
552
|
+
await batch.commit()
|
|
553
553
|
}
|
|
554
554
|
}
|
|
555
|
+
}
|
|
555
556
|
|
|
556
|
-
|
|
557
|
-
|
|
557
|
+
// Delete from 'staged-users' collection
|
|
558
|
+
await db.collection('staged-users').doc(request.data.uid).delete()
|
|
558
559
|
|
|
559
|
-
|
|
560
|
-
|
|
560
|
+
// Delete from 'users' collection
|
|
561
|
+
await db.collection('users').doc(request.data.uid).delete()
|
|
561
562
|
|
|
562
|
-
|
|
563
|
-
|
|
563
|
+
// Delete the user from Firebase
|
|
564
|
+
await admin.auth().deleteUser(request.data.uid)
|
|
564
565
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
}
|
|
566
|
+
return { success: true }
|
|
567
|
+
}
|
|
568
|
+
catch (error) {
|
|
569
|
+
console.error('Error deleting user:', error)
|
|
570
|
+
return { success: false, error }
|
|
571
571
|
}
|
|
572
572
|
})
|
|
573
573
|
|