backend-manager 4.0.15 → 4.0.17
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
CHANGED
|
@@ -355,6 +355,11 @@ Module.prototype.uploadPost = function (content) {
|
|
|
355
355
|
return reject(existing);
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
+
// We have to arbitrarily wait for a bit to ensure the images have started the GitHub build action
|
|
359
|
+
// Otherwise, the GH action might say: "Canceling since a higher priority waiting request for 'refs/heads/master' exists"
|
|
360
|
+
// The result of this is that the file will be comitted in the repo but not included in the public build
|
|
361
|
+
await powertools.wait(30000);
|
|
362
|
+
|
|
358
363
|
// Upload post
|
|
359
364
|
await self.octokit.rest.repos.createOrUpdateFileContents({
|
|
360
365
|
owner: owner,
|
|
@@ -562,15 +562,22 @@ function _attachHeaderProperties(self, options, error) {
|
|
|
562
562
|
BackendAssistant.prototype.authenticate = async function (options) {
|
|
563
563
|
const self = this;
|
|
564
564
|
|
|
565
|
+
// Shortcuts
|
|
565
566
|
let admin = self.ref.admin;
|
|
566
567
|
let functions = self.ref.functions;
|
|
567
568
|
let req = self.ref.req;
|
|
568
569
|
let res = self.ref.res;
|
|
569
570
|
let data = self.request.data;
|
|
571
|
+
|
|
572
|
+
// Build the ID token from the request
|
|
570
573
|
let idToken;
|
|
574
|
+
let backendManagerKey;
|
|
575
|
+
// let user;
|
|
571
576
|
|
|
577
|
+
// Set options
|
|
572
578
|
options = options || {};
|
|
573
579
|
options.resolve = typeof options.resolve === 'undefined' ? true : options.resolve;
|
|
580
|
+
options.debug = typeof options.debug === 'undefined' ? false : options.debug;
|
|
574
581
|
|
|
575
582
|
function _resolve(user) {
|
|
576
583
|
user = user || {};
|
|
@@ -586,51 +593,89 @@ BackendAssistant.prototype.authenticate = async function (options) {
|
|
|
586
593
|
}
|
|
587
594
|
}
|
|
588
595
|
|
|
596
|
+
// Extract the BEM token
|
|
597
|
+
// Having this is separate from the ID token allows for the user to be authenticated as an ADMIN
|
|
598
|
+
if (options.backendManagerKey || data.backendManagerKey) {
|
|
599
|
+
// Read token from backendManagerKey or authenticationToken or apiKey
|
|
600
|
+
backendManagerKey = options.backendManagerKey || data.backendManagerKey;
|
|
601
|
+
|
|
602
|
+
// Log the token
|
|
603
|
+
self.log('Found "backendManagerKey" parameter', backendManagerKey);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// Extract the token / API key
|
|
607
|
+
// This is the main token that will be used to authenticate the user (it can be a JWT or a user's API key)
|
|
589
608
|
if (req?.headers?.authorization && req?.headers?.authorization?.startsWith('Bearer ')) {
|
|
590
609
|
// Read the ID Token from the Authorization header.
|
|
591
610
|
idToken = req.headers.authorization.split('Bearer ')[1];
|
|
611
|
+
|
|
612
|
+
// Log the token
|
|
592
613
|
self.log('Found "Authorization" header', idToken);
|
|
593
614
|
} else if (req?.cookies?.__session) {
|
|
594
615
|
// Read the ID Token from cookie.
|
|
595
616
|
idToken = req.cookies.__session;
|
|
617
|
+
|
|
618
|
+
// Log the token
|
|
596
619
|
self.log('Found "__session" cookie', idToken);
|
|
597
|
-
} else if (
|
|
598
|
-
|
|
599
|
-
|
|
620
|
+
} else if (
|
|
621
|
+
options.authenticationToken || data.authenticationToken
|
|
622
|
+
|| options.apiKey || data.apiKey
|
|
623
|
+
) {
|
|
624
|
+
// Read token OR API Key from options or data
|
|
625
|
+
idToken = options.authenticationToken || data.authenticationToken
|
|
626
|
+
|| options.apiKey || data.apiKey;
|
|
627
|
+
|
|
628
|
+
// Log the token
|
|
629
|
+
self.log('Found "authenticationToken" parameter', idToken);
|
|
630
|
+
} else {
|
|
631
|
+
// No token found
|
|
632
|
+
return _resolve(self.request.user);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// Check if the token is a JWT
|
|
636
|
+
if (isJWT(idToken)) {
|
|
637
|
+
// Check with firebase
|
|
600
638
|
try {
|
|
601
|
-
|
|
602
|
-
// const workingConfig = self.Manager?.config || functions.config();
|
|
603
|
-
storedApiKey = self.Manager?.config?.backend_manager?.key || '';
|
|
604
|
-
} catch (e) {
|
|
605
|
-
// Do nothing
|
|
606
|
-
}
|
|
639
|
+
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
|
|
607
640
|
|
|
608
|
-
|
|
609
|
-
|
|
641
|
+
// Log the token
|
|
642
|
+
if (options.debug) {
|
|
643
|
+
self.log('JWT token decoded', decodedIdToken.email, decodedIdToken.user_id);
|
|
644
|
+
}
|
|
610
645
|
|
|
611
|
-
|
|
612
|
-
|
|
646
|
+
// Get the user
|
|
647
|
+
await admin.firestore().doc(`users/${decodedIdToken.user_id}`)
|
|
648
|
+
.get()
|
|
649
|
+
.then((doc) => {
|
|
650
|
+
// Set the user
|
|
651
|
+
if (doc.exists) {
|
|
652
|
+
self.request.user = Object.assign({}, self.request.user, doc.data());
|
|
653
|
+
self.request.user.authenticated = true;
|
|
654
|
+
self.request.user.auth.uid = decodedIdToken.user_id;
|
|
655
|
+
self.request.user.auth.email = decodedIdToken.email;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Log the user
|
|
659
|
+
if (options.debug) {
|
|
660
|
+
self.log('Found user doc', self.request.user)
|
|
661
|
+
}
|
|
662
|
+
})
|
|
613
663
|
|
|
614
|
-
|
|
615
|
-
if (storedApiKey && (storedApiKey === data.backendManagerKey || storedApiKey === data.authenticationToken)) {
|
|
616
|
-
self.request.user.authenticated = true;
|
|
617
|
-
self.request.user.roles.admin = true;
|
|
664
|
+
// Return the user
|
|
618
665
|
return _resolve(self.request.user);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
const apiKey = options.apiKey || data.apiKey;
|
|
622
|
-
self.log('Found "options.apiKey"', apiKey);
|
|
623
|
-
|
|
624
|
-
if (apiKey.includes('test')) {
|
|
666
|
+
} catch (error) {
|
|
667
|
+
self.error('Error while verifying JWT:', error);
|
|
625
668
|
return _resolve(self.request.user);
|
|
626
669
|
}
|
|
627
|
-
|
|
670
|
+
} else {
|
|
671
|
+
// Query by API key
|
|
628
672
|
await admin.firestore().collection(`users`)
|
|
629
673
|
.where('api.privateKey', '==', apiKey)
|
|
630
674
|
.get()
|
|
631
675
|
.then(function(querySnapshot) {
|
|
632
676
|
querySnapshot.forEach(function(doc) {
|
|
633
677
|
self.request.user = doc.data();
|
|
678
|
+
self.request.user = Object.assign({}, self.request.user, doc.data());
|
|
634
679
|
self.request.user.authenticated = true;
|
|
635
680
|
});
|
|
636
681
|
})
|
|
@@ -639,39 +684,6 @@ BackendAssistant.prototype.authenticate = async function (options) {
|
|
|
639
684
|
});
|
|
640
685
|
|
|
641
686
|
return _resolve(self.request.user);
|
|
642
|
-
} else {
|
|
643
|
-
// self.log('No Firebase ID token was able to be extracted.',
|
|
644
|
-
// 'Make sure you authenticate your request by providing either the following HTTP header:',
|
|
645
|
-
// 'Authorization: Bearer <Firebase ID Token>',
|
|
646
|
-
// 'or by passing a "__session" cookie',
|
|
647
|
-
// 'or by passing backendManagerKey or authenticationToken in the body or query');
|
|
648
|
-
|
|
649
|
-
return _resolve(self.request.user);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
// Check with firebase
|
|
653
|
-
try {
|
|
654
|
-
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
|
|
655
|
-
if (options.debug) {
|
|
656
|
-
self.log('Token correctly decoded', decodedIdToken.email, decodedIdToken.user_id);
|
|
657
|
-
}
|
|
658
|
-
await admin.firestore().doc(`users/${decodedIdToken.user_id}`)
|
|
659
|
-
.get()
|
|
660
|
-
.then(async function (doc) {
|
|
661
|
-
if (doc.exists) {
|
|
662
|
-
self.request.user = Object.assign({}, self.request.user, doc.data());
|
|
663
|
-
}
|
|
664
|
-
self.request.user.authenticated = true;
|
|
665
|
-
self.request.user.auth.uid = decodedIdToken.user_id;
|
|
666
|
-
self.request.user.auth.email = decodedIdToken.email;
|
|
667
|
-
if (options.debug) {
|
|
668
|
-
self.log('Found user doc', self.request.user)
|
|
669
|
-
}
|
|
670
|
-
})
|
|
671
|
-
return _resolve(self.request.user);
|
|
672
|
-
} catch (error) {
|
|
673
|
-
self.error('Error while verifying Firebase ID token:', error);
|
|
674
|
-
return _resolve(self.request.user);
|
|
675
687
|
}
|
|
676
688
|
};
|
|
677
689
|
|
|
@@ -992,6 +1004,21 @@ BackendAssistant.prototype.parseMultipartFormData = function (options) {
|
|
|
992
1004
|
});
|
|
993
1005
|
}
|
|
994
1006
|
|
|
1007
|
+
const isJWT = (token) => {
|
|
1008
|
+
// Ensure the token has three parts separated by dots
|
|
1009
|
+
const parts = token.split('.');
|
|
1010
|
+
|
|
1011
|
+
try {
|
|
1012
|
+
// Decode the header (first part) to verify it is JSON
|
|
1013
|
+
const header = JSON.parse(Buffer.from(parts[0], 'base64').toString('utf8'));
|
|
1014
|
+
// Check for expected JWT keys in the header
|
|
1015
|
+
return header.alg && header.typ === 'JWT';
|
|
1016
|
+
} catch (err) {
|
|
1017
|
+
// If parsing fails, it's not a valid JWT
|
|
1018
|
+
return false;
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
|
|
995
1022
|
// Not sure what this is for? But it has a good serializer code
|
|
996
1023
|
// Disabled 2024-03-21 because there was another stringify() function that i was intending to use but it was actually using this
|
|
997
1024
|
// It was adding escaped quotes to strings
|
|
@@ -562,22 +562,15 @@ function _attachHeaderProperties(self, options, error) {
|
|
|
562
562
|
BackendAssistant.prototype.authenticate = async function (options) {
|
|
563
563
|
const self = this;
|
|
564
564
|
|
|
565
|
-
// Shortcuts
|
|
566
565
|
let admin = self.ref.admin;
|
|
567
566
|
let functions = self.ref.functions;
|
|
568
567
|
let req = self.ref.req;
|
|
569
568
|
let res = self.ref.res;
|
|
570
569
|
let data = self.request.data;
|
|
571
|
-
|
|
572
|
-
// Build the ID token from the request
|
|
573
570
|
let idToken;
|
|
574
|
-
let backendManagerKey;
|
|
575
|
-
// let user;
|
|
576
571
|
|
|
577
|
-
// Set options
|
|
578
572
|
options = options || {};
|
|
579
573
|
options.resolve = typeof options.resolve === 'undefined' ? true : options.resolve;
|
|
580
|
-
options.debug = typeof options.debug === 'undefined' ? false : options.debug;
|
|
581
574
|
|
|
582
575
|
function _resolve(user) {
|
|
583
576
|
user = user || {};
|
|
@@ -593,89 +586,51 @@ BackendAssistant.prototype.authenticate = async function (options) {
|
|
|
593
586
|
}
|
|
594
587
|
}
|
|
595
588
|
|
|
596
|
-
// Extract the BEM token
|
|
597
|
-
// Having this is separate from the ID token allows for the user to be authenticated as an ADMIN
|
|
598
|
-
if (options.backendManagerKey || data.backendManagerKey) {
|
|
599
|
-
// Read token from backendManagerKey or authenticationToken or apiKey
|
|
600
|
-
backendManagerKey = options.backendManagerKey || data.backendManagerKey;
|
|
601
|
-
|
|
602
|
-
// Log the token
|
|
603
|
-
self.log('Found "backendManagerKey" parameter', backendManagerKey);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
// Extract the token / API key
|
|
607
|
-
// This is the main token that will be used to authenticate the user (it can be a JWT or a user's API key)
|
|
608
589
|
if (req?.headers?.authorization && req?.headers?.authorization?.startsWith('Bearer ')) {
|
|
609
590
|
// Read the ID Token from the Authorization header.
|
|
610
591
|
idToken = req.headers.authorization.split('Bearer ')[1];
|
|
611
|
-
|
|
612
|
-
// Log the token
|
|
613
592
|
self.log('Found "Authorization" header', idToken);
|
|
614
593
|
} else if (req?.cookies?.__session) {
|
|
615
594
|
// Read the ID Token from cookie.
|
|
616
595
|
idToken = req.cookies.__session;
|
|
617
|
-
|
|
618
|
-
// Log the token
|
|
619
596
|
self.log('Found "__session" cookie', idToken);
|
|
620
|
-
} else if (
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
) {
|
|
624
|
-
// Read token OR API Key from options or data
|
|
625
|
-
idToken = options.authenticationToken || data.authenticationToken
|
|
626
|
-
|| options.apiKey || data.apiKey;
|
|
627
|
-
|
|
628
|
-
// Log the token
|
|
629
|
-
self.log('Found "authenticationToken" parameter', idToken);
|
|
630
|
-
} else {
|
|
631
|
-
// No token found
|
|
632
|
-
return _resolve(self.request.user);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// Check if the token is a JWT
|
|
636
|
-
if (isJWT(idToken)) {
|
|
637
|
-
// Check with firebase
|
|
597
|
+
} else if (data.backendManagerKey || data.authenticationToken) {
|
|
598
|
+
// Check with custom BEM Token
|
|
599
|
+
let storedApiKey;
|
|
638
600
|
try {
|
|
639
|
-
|
|
601
|
+
// Disabled this 5/11/24 because i dont know why we would need to do functions.config() if we already have the Manager
|
|
602
|
+
// const workingConfig = self.Manager?.config || functions.config();
|
|
603
|
+
storedApiKey = self.Manager?.config?.backend_manager?.key || '';
|
|
604
|
+
} catch (e) {
|
|
605
|
+
// Do nothing
|
|
606
|
+
}
|
|
640
607
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
self.log('JWT token decoded', decodedIdToken.email, decodedIdToken.user_id);
|
|
644
|
-
}
|
|
608
|
+
// Set idToken as working token of either backendManagerKey or authenticationToken
|
|
609
|
+
idToken = data.backendManagerKey || data.authenticationToken;
|
|
645
610
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
.get()
|
|
649
|
-
.then((doc) => {
|
|
650
|
-
// Set the user
|
|
651
|
-
if (doc.exists) {
|
|
652
|
-
self.request.user = Object.assign({}, self.request.user, doc.data());
|
|
653
|
-
self.request.user.authenticated = true;
|
|
654
|
-
self.request.user.auth.uid = decodedIdToken.user_id;
|
|
655
|
-
self.request.user.auth.email = decodedIdToken.email;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// Log the user
|
|
659
|
-
if (options.debug) {
|
|
660
|
-
self.log('Found user doc', self.request.user)
|
|
661
|
-
}
|
|
662
|
-
})
|
|
611
|
+
// Log the token
|
|
612
|
+
self.log('Found "backendManagerKey" or "authenticationToken" parameter', {storedApiKey: storedApiKey, idToken: idToken});
|
|
663
613
|
|
|
664
|
-
|
|
614
|
+
// Check if the token is correct
|
|
615
|
+
if (storedApiKey && (storedApiKey === data.backendManagerKey || storedApiKey === data.authenticationToken)) {
|
|
616
|
+
self.request.user.authenticated = true;
|
|
617
|
+
self.request.user.roles.admin = true;
|
|
665
618
|
return _resolve(self.request.user);
|
|
666
|
-
}
|
|
667
|
-
|
|
619
|
+
}
|
|
620
|
+
} else if (options.apiKey || data.apiKey) {
|
|
621
|
+
const apiKey = options.apiKey || data.apiKey;
|
|
622
|
+
self.log('Found "options.apiKey"', apiKey);
|
|
623
|
+
|
|
624
|
+
if (apiKey.includes('test')) {
|
|
668
625
|
return _resolve(self.request.user);
|
|
669
626
|
}
|
|
670
|
-
|
|
671
|
-
// Query by API key
|
|
627
|
+
|
|
672
628
|
await admin.firestore().collection(`users`)
|
|
673
629
|
.where('api.privateKey', '==', apiKey)
|
|
674
630
|
.get()
|
|
675
631
|
.then(function(querySnapshot) {
|
|
676
632
|
querySnapshot.forEach(function(doc) {
|
|
677
633
|
self.request.user = doc.data();
|
|
678
|
-
self.request.user = Object.assign({}, self.request.user, doc.data());
|
|
679
634
|
self.request.user.authenticated = true;
|
|
680
635
|
});
|
|
681
636
|
})
|
|
@@ -684,6 +639,39 @@ BackendAssistant.prototype.authenticate = async function (options) {
|
|
|
684
639
|
});
|
|
685
640
|
|
|
686
641
|
return _resolve(self.request.user);
|
|
642
|
+
} else {
|
|
643
|
+
// self.log('No Firebase ID token was able to be extracted.',
|
|
644
|
+
// 'Make sure you authenticate your request by providing either the following HTTP header:',
|
|
645
|
+
// 'Authorization: Bearer <Firebase ID Token>',
|
|
646
|
+
// 'or by passing a "__session" cookie',
|
|
647
|
+
// 'or by passing backendManagerKey or authenticationToken in the body or query');
|
|
648
|
+
|
|
649
|
+
return _resolve(self.request.user);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Check with firebase
|
|
653
|
+
try {
|
|
654
|
+
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
|
|
655
|
+
if (options.debug) {
|
|
656
|
+
self.log('Token correctly decoded', decodedIdToken.email, decodedIdToken.user_id);
|
|
657
|
+
}
|
|
658
|
+
await admin.firestore().doc(`users/${decodedIdToken.user_id}`)
|
|
659
|
+
.get()
|
|
660
|
+
.then(async function (doc) {
|
|
661
|
+
if (doc.exists) {
|
|
662
|
+
self.request.user = Object.assign({}, self.request.user, doc.data());
|
|
663
|
+
}
|
|
664
|
+
self.request.user.authenticated = true;
|
|
665
|
+
self.request.user.auth.uid = decodedIdToken.user_id;
|
|
666
|
+
self.request.user.auth.email = decodedIdToken.email;
|
|
667
|
+
if (options.debug) {
|
|
668
|
+
self.log('Found user doc', self.request.user)
|
|
669
|
+
}
|
|
670
|
+
})
|
|
671
|
+
return _resolve(self.request.user);
|
|
672
|
+
} catch (error) {
|
|
673
|
+
self.error('Error while verifying Firebase ID token:', error);
|
|
674
|
+
return _resolve(self.request.user);
|
|
687
675
|
}
|
|
688
676
|
};
|
|
689
677
|
|
|
@@ -1004,21 +992,6 @@ BackendAssistant.prototype.parseMultipartFormData = function (options) {
|
|
|
1004
992
|
});
|
|
1005
993
|
}
|
|
1006
994
|
|
|
1007
|
-
const isJWT = (token) => {
|
|
1008
|
-
// Ensure the token has three parts separated by dots
|
|
1009
|
-
const parts = token.split('.');
|
|
1010
|
-
|
|
1011
|
-
try {
|
|
1012
|
-
// Decode the header (first part) to verify it is JSON
|
|
1013
|
-
const header = JSON.parse(Buffer.from(parts[0], 'base64').toString('utf8'));
|
|
1014
|
-
// Check for expected JWT keys in the header
|
|
1015
|
-
return header.alg && header.typ === 'JWT';
|
|
1016
|
-
} catch (err) {
|
|
1017
|
-
// If parsing fails, it's not a valid JWT
|
|
1018
|
-
return false;
|
|
1019
|
-
}
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
995
|
// Not sure what this is for? But it has a good serializer code
|
|
1023
996
|
// Disabled 2024-03-21 because there was another stringify() function that i was intending to use but it was actually using this
|
|
1024
997
|
// It was adding escaped quotes to strings
|
|
@@ -27,6 +27,7 @@ Utilities.prototype.iterateCollection = function (callback, options) {
|
|
|
27
27
|
// Set counters
|
|
28
28
|
let batch = -1;
|
|
29
29
|
let collectionCount = 0;
|
|
30
|
+
let callbackResults = [];
|
|
30
31
|
|
|
31
32
|
// Set defaults
|
|
32
33
|
options = options || {};
|
|
@@ -116,7 +117,7 @@ Utilities.prototype.iterateCollection = function (callback, options) {
|
|
|
116
117
|
|
|
117
118
|
// If no documents, resolve
|
|
118
119
|
if (snap.docs.length === 0) {
|
|
119
|
-
return resolve();
|
|
120
|
+
return resolve(callbackResults);
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
// Log
|
|
@@ -134,11 +135,14 @@ Utilities.prototype.iterateCollection = function (callback, options) {
|
|
|
134
135
|
collectionCount,
|
|
135
136
|
)
|
|
136
137
|
.then((r) => {
|
|
138
|
+
// Append to result
|
|
139
|
+
callbackResults.push(r);
|
|
140
|
+
|
|
137
141
|
// Construct a new query starting at this document (unless we've reached the end)
|
|
138
142
|
if (lastVisible && batch + 1 < options.maxBatches) {
|
|
139
143
|
iterate(lastVisible)
|
|
140
144
|
} else {
|
|
141
|
-
return resolve();
|
|
145
|
+
return resolve(callbackResults);
|
|
142
146
|
}
|
|
143
147
|
})
|
|
144
148
|
.catch((e) => {
|
|
@@ -180,6 +184,7 @@ Utilities.prototype.iterateUsers = function (callback, options) {
|
|
|
180
184
|
|
|
181
185
|
// Set counters
|
|
182
186
|
let batch = -1;
|
|
187
|
+
let callbackResults = [];
|
|
183
188
|
|
|
184
189
|
// Set defaults
|
|
185
190
|
options = options || {};
|
|
@@ -199,7 +204,7 @@ Utilities.prototype.iterateUsers = function (callback, options) {
|
|
|
199
204
|
|
|
200
205
|
// If no users, resolve
|
|
201
206
|
if (listUsersResult.users.length === 0) {
|
|
202
|
-
return resolve();
|
|
207
|
+
return resolve(callbackResults);
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
// Log
|
|
@@ -213,12 +218,15 @@ Utilities.prototype.iterateUsers = function (callback, options) {
|
|
|
213
218
|
users: listUsersResult.users,
|
|
214
219
|
pageToken: listUsersResult.pageToken,
|
|
215
220
|
}, batch)
|
|
216
|
-
.then(r => {
|
|
221
|
+
.then((r) => {
|
|
222
|
+
// Append to result
|
|
223
|
+
callbackResults.push(r);
|
|
224
|
+
|
|
217
225
|
// Construct a new query starting at this document (unless we've reached the end)
|
|
218
226
|
if (listUsersResult.pageToken && batch + 1 < options.maxBatches) {
|
|
219
227
|
iterate(listUsersResult.pageToken);
|
|
220
228
|
} else {
|
|
221
|
-
return resolve();
|
|
229
|
+
return resolve(callbackResults);
|
|
222
230
|
}
|
|
223
231
|
})
|
|
224
232
|
.catch((e) => {
|
|
@@ -279,7 +287,7 @@ Utilities.prototype.getDocumentWithOwnerUser = function (path, options) {
|
|
|
279
287
|
// Get document
|
|
280
288
|
const document = await admin.firestore().doc(path)
|
|
281
289
|
.get()
|
|
282
|
-
.then(doc => {
|
|
290
|
+
.then((doc) => {
|
|
283
291
|
const data = doc.data();
|
|
284
292
|
|
|
285
293
|
// If the document doesn't exist, throw an error
|
|
@@ -308,7 +316,7 @@ Utilities.prototype.getDocumentWithOwnerUser = function (path, options) {
|
|
|
308
316
|
// Get the owner user
|
|
309
317
|
const user = admin.firestore().doc(`users/${ownerUID}`)
|
|
310
318
|
.get()
|
|
311
|
-
.then(doc => {
|
|
319
|
+
.then((doc) => {
|
|
312
320
|
const data = doc.data();
|
|
313
321
|
|
|
314
322
|
// If the user doesn't exist, throw an error
|