Skip to content

Commit ddcddb3

Browse files
Merge branch 'master' into patch-1
2 parents 5c8181d + f6f7cb9 commit ddcddb3

File tree

10 files changed

+621
-668
lines changed

10 files changed

+621
-668
lines changed

package-lock.json

Lines changed: 542 additions & 636 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,12 @@
200200
"@firebase/database-compat": "^1.0.2",
201201
"@firebase/database-types": "^1.0.0",
202202
"@types/node": "^20.10.3",
203-
"farmhash": "^3.3.1",
203+
"farmhash-modern": "^1.1.0",
204204
"jsonwebtoken": "^9.0.0",
205205
"jwks-rsa": "^3.1.0",
206206
"long": "^5.2.3",
207207
"node-forge": "^1.3.1",
208-
"uuid": "^9.0.0"
208+
"uuid": "^10.0.0"
209209
},
210210
"optionalDependencies": {
211211
"@google-cloud/firestore": "^7.7.0",

src/remote-config/condition-evaluator-internal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
PercentCondition,
2626
PercentConditionOperator
2727
} from './remote-config-api';
28-
import * as farmhash from 'farmhash';
28+
import * as farmhash from 'farmhash-modern';
2929
import long = require('long');
3030

3131
/**
@@ -149,7 +149,7 @@ export class ConditionEvaluator {
149149

150150

151151
// Using a 64-bit long for consistency with the Remote Config fetch endpoint.
152-
let hash64 = long.fromString(farmhash.fingerprint64(stringToHash));
152+
let hash64 = long.fromString(farmhash.fingerprint64(stringToHash).toString());
153153

154154
// Negate the hash if its value is less than 0. We handle this manually because the
155155
// Long library doesn't provided an absolute value method.

src/utils/api-request.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,12 @@ export class AuthorizedHttpClient extends HttpClient {
818818
const authHeader = 'Authorization';
819819
requestCopy.headers[authHeader] = `Bearer ${token}`;
820820

821+
// Fix issue where firebase-admin does not specify quota project that is
822+
// necessary for use when utilizing human account with ADC (RSDF)
823+
if (!requestCopy.headers['x-goog-user-project'] && this.app.options.projectId) {
824+
requestCopy.headers['x-goog-user-project'] = this.app.options.projectId
825+
}
826+
821827
if (!requestCopy.httpAgent && this.app.options.httpAgent) {
822828
requestCopy.httpAgent = this.app.options.httpAgent;
823829
}

test/unit/app-check/app-check-api-client-internal.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ describe('AppCheckApiClient', () => {
4545
const EXPECTED_HEADERS = {
4646
'Authorization': 'Bearer mock-token',
4747
'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`,
48+
'x-goog-user-project': 'test-project',
4849
};
4950

5051
const noProjectId = 'Failed to determine project ID. Initialize the SDK with service '

test/unit/functions/functions-api-client-internal.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ describe('FunctionsApiClient', () => {
4444

4545
const EXPECTED_HEADERS = {
4646
'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`,
47-
'Authorization': 'Bearer mock-token'
47+
'Authorization': 'Bearer mock-token',
48+
'x-goog-user-project': 'test-project',
4849
};
4950

5051
const noProjectId = 'Failed to determine project ID. Initialize the SDK with service '

test/unit/machine-learning/machine-learning-api-client.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ describe('MachineLearningApiClient', () => {
117117
const EXPECTED_HEADERS = {
118118
'Authorization': 'Bearer mock-token',
119119
'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`,
120+
'x-goog-user-project': 'test-project',
120121
};
121122
const noProjectId = 'Failed to determine project ID. Initialize the SDK with service '
122123
+ 'account credentials, or set project ID as an app option. Alternatively, set the '

test/unit/remote-config/condition-evaluator.spec.ts

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ import {
2525
} from '../../../src/remote-config/remote-config-api';
2626
import { v4 as uuidv4 } from 'uuid';
2727
import { clone } from 'lodash';
28-
import * as farmhash from 'farmhash';
28+
import * as farmhash from 'farmhash-modern';
2929

3030
const expect = chai.expect;
3131

32-
32+
const nodeVersion = process.versions.node;
3333

3434
describe('ConditionEvaluator', () => {
3535
let stubs: sinon.SinonStub[] = [];
@@ -145,7 +145,10 @@ describe('ConditionEvaluator', () => {
145145
});
146146

147147
describe('percentCondition', () => {
148-
it('should evaluate an unknown operator to false', () => {
148+
it('should evaluate an unknown operator to false', function() {
149+
if (nodeVersion.startsWith('14')) {
150+
this.skip();
151+
}
149152
// Verifies future operators won't trigger errors.
150153
const condition = {
151154
name: 'is_enabled',
@@ -169,7 +172,10 @@ describe('ConditionEvaluator', () => {
169172
new Map([['is_enabled', false]]));
170173
});
171174

172-
it('should evaluate less or equal to max to true', () => {
175+
it('should evaluate less or equal to max to true', function() {
176+
if (nodeVersion.startsWith('14')) {
177+
this.skip();
178+
}
173179
const condition = {
174180
name: 'is_enabled',
175181
condition: {
@@ -194,7 +200,10 @@ describe('ConditionEvaluator', () => {
194200
new Map([['is_enabled', true]]));
195201
});
196202

197-
it('should evaluate less or equal to min to false', () => {
203+
it('should evaluate less or equal to min to false', function() {
204+
if (nodeVersion.startsWith('14')) {
205+
this.skip();
206+
}
198207
const condition = {
199208
name: 'is_enabled',
200209
condition: {
@@ -223,7 +232,7 @@ describe('ConditionEvaluator', () => {
223232
// Stubs ID hasher to return a number larger than zero.
224233
const stub = sinon
225234
.stub(farmhash, 'fingerprint64')
226-
.returns('1');
235+
.returns(1n);
227236
stubs.push(stub);
228237

229238
const condition = {
@@ -256,7 +265,7 @@ describe('ConditionEvaluator', () => {
256265
// Stubs ID hasher to return a number in range.
257266
const stub = sinon
258267
.stub(farmhash, 'fingerprint64')
259-
.returns('1');
268+
.returns(1n);
260269
stubs.push(stub);
261270

262271
const condition = {
@@ -289,7 +298,7 @@ describe('ConditionEvaluator', () => {
289298
// Stubs ID hasher to return a number outside range.
290299
const stub = sinon
291300
.stub(farmhash, 'fingerprint64')
292-
.returns('1');
301+
.returns(1n);
293302
stubs.push(stub);
294303

295304
const condition = {
@@ -325,7 +334,7 @@ describe('ConditionEvaluator', () => {
325334
// Stubs ID hasher to return a number in range.
326335
const stub = sinon
327336
.stub(farmhash, 'fingerprint64')
328-
.returns('1');
337+
.returns(1n);
329338
stubs.push(stub);
330339

331340
const condition = {
@@ -360,7 +369,7 @@ describe('ConditionEvaluator', () => {
360369
it('should evaluate 9 as less or equal to 10', () => {
361370
const stub = sinon
362371
.stub(farmhash, 'fingerprint64')
363-
.returns('9');
372+
.returns(9n);
364373

365374
stubs.push(stub);
366375
const condition = {
@@ -391,7 +400,7 @@ describe('ConditionEvaluator', () => {
391400
it('should evaluate 10 as less or equal to 10', () => {
392401
const stub = sinon
393402
.stub(farmhash, 'fingerprint64')
394-
.returns('10');
403+
.returns(10n);
395404

396405
stubs.push(stub);
397406
const condition = {
@@ -422,7 +431,7 @@ describe('ConditionEvaluator', () => {
422431
it('should evaluate 11 as not less or equal to 10', () => {
423432
const stub = sinon
424433
.stub(farmhash, 'fingerprint64')
425-
.returns('11');
434+
.returns(11n);
426435

427436
stubs.push(stub);
428437
const condition = {
@@ -453,7 +462,7 @@ describe('ConditionEvaluator', () => {
453462
it('should negate -11 to 11 and evaluate as not less or equal to 10', () => {
454463
const stub = sinon
455464
.stub(farmhash, 'fingerprint64')
456-
.returns('-11');
465+
.returns(-11n);
457466

458467
stubs.push(stub);
459468
const condition = {
@@ -481,7 +490,10 @@ describe('ConditionEvaluator', () => {
481490
expect(actual).to.be.false;
482491
});
483492

484-
it('should evaluate greater than min to true', () => {
493+
it('should evaluate greater than min to true', function() {
494+
if (nodeVersion.startsWith('14')) {
495+
this.skip();
496+
}
485497
const condition = {
486498
name: 'is_enabled',
487499
condition: {
@@ -509,7 +521,7 @@ describe('ConditionEvaluator', () => {
509521
it('should evaluate 11M as greater than 10M', () => {
510522
const stub = sinon
511523
.stub(farmhash, 'fingerprint64')
512-
.returns('11');
524+
.returns(11n);
513525

514526
stubs.push(stub);
515527
const condition = {
@@ -540,7 +552,7 @@ describe('ConditionEvaluator', () => {
540552
it('should evaluate 9 as not greater than 10', () => {
541553
const stub = sinon
542554
.stub(farmhash, 'fingerprint64')
543-
.returns('9');
555+
.returns(9n);
544556
stubs.push(stub);
545557

546558
const condition = {
@@ -568,7 +580,10 @@ describe('ConditionEvaluator', () => {
568580
expect(actual).to.be.false;
569581
});
570582

571-
it('should evaluate greater than max to false', () => {
583+
it('should evaluate greater than max to false', function() {
584+
if (nodeVersion.startsWith('14')) {
585+
this.skip();
586+
}
572587
const condition = {
573588
name: 'is_enabled',
574589
condition: {
@@ -593,7 +608,10 @@ describe('ConditionEvaluator', () => {
593608
new Map([['is_enabled', false]]));
594609
});
595610

596-
it('should evaluate between min and max to true', () => {
611+
it('should evaluate between min and max to true', function() {
612+
if (nodeVersion.startsWith('14')) {
613+
this.skip();
614+
}
597615
const condition = {
598616
name: 'is_enabled',
599617
condition: {
@@ -624,7 +642,7 @@ describe('ConditionEvaluator', () => {
624642
it('should evaluate 10 as between 9 and 11', () => {
625643
const stub = sinon
626644
.stub(farmhash, 'fingerprint64')
627-
.returns('10');
645+
.returns(10n);
628646
stubs.push(stub);
629647

630648
const condition = {
@@ -655,7 +673,10 @@ describe('ConditionEvaluator', () => {
655673
expect(actual).to.be.true;
656674
});
657675

658-
it('should evaluate between equal bounds to false', () => {
676+
it('should evaluate between equal bounds to false', function() {
677+
if (nodeVersion.startsWith('14')) {
678+
this.skip();
679+
}
659680
const condition = {
660681
name: 'is_enabled',
661682
condition: {
@@ -686,7 +707,7 @@ describe('ConditionEvaluator', () => {
686707
it('should evaluate 12 as not between 9 and 11', () => {
687708
const stub = sinon
688709
.stub(farmhash, 'fingerprint64')
689-
.returns('12');
710+
.returns(12n);
690711
stubs.push(stub);
691712

692713
const condition = {
@@ -717,15 +738,18 @@ describe('ConditionEvaluator', () => {
717738
expect(actual).to.be.false;
718739
});
719740

720-
// The following tests are probablistic. They use tolerances based on
741+
// The following tests are probabilistic. They use tolerances based on
721742
// standard deviations to balance accuracy and flakiness. Random IDs will
722743
// hash to the target range + 3 standard deviations 99.7% of the time,
723744
// which minimizes flakiness.
724745
// Use python to calculate standard deviation. For example, for 100k
725746
// trials with 50% probability:
726747
// from scipy.stats import binom
727748
// print(binom.std(100_000, 0.5) * 3)
728-
it('should evaluate less or equal to 10% to approx 10%', () => {
749+
it('should evaluate less or equal to 10% to approx 10%', function() {
750+
if (nodeVersion.startsWith('14')) {
751+
this.skip();
752+
}
729753
const percentCondition = {
730754
percentOperator: PercentConditionOperator.LESS_OR_EQUAL,
731755
microPercent: 10_000_000 // 10%
@@ -738,7 +762,10 @@ describe('ConditionEvaluator', () => {
738762
expect(truthyAssignments).to.be.lessThanOrEqual(10000 + tolerance);
739763
});
740764

741-
it('should evaluate between 0 to 10% to approx 10%', () => {
765+
it('should evaluate between 0 to 10% to approx 10%', function() {
766+
if (nodeVersion.startsWith('14')) {
767+
this.skip();
768+
}
742769
const percentCondition = {
743770
percentOperator: PercentConditionOperator.BETWEEN,
744771
microPercentRange: {
@@ -754,7 +781,10 @@ describe('ConditionEvaluator', () => {
754781
expect(truthyAssignments).to.be.lessThanOrEqual(10000 + tolerance);
755782
});
756783

757-
it('should evaluate greater than 10% to approx 90%', () => {
784+
it('should evaluate greater than 10% to approx 90%', function() {
785+
if (nodeVersion.startsWith('14')) {
786+
this.skip();
787+
}
758788
const percentCondition = {
759789
percentOperator: PercentConditionOperator.GREATER_THAN,
760790
microPercent: 10_000_000
@@ -767,7 +797,10 @@ describe('ConditionEvaluator', () => {
767797
expect(truthyAssignments).to.be.lessThanOrEqual(90000 + tolerance);
768798
});
769799

770-
it('should evaluate between 40% to 60% to approx 20%', () => {
800+
it('should evaluate between 40% to 60% to approx 20%', function() {
801+
if (nodeVersion.startsWith('14')) {
802+
this.skip();
803+
}
771804
const percentCondition = {
772805
percentOperator: PercentConditionOperator.BETWEEN,
773806
microPercentRange: {
@@ -783,7 +816,10 @@ describe('ConditionEvaluator', () => {
783816
expect(truthyAssignments).to.be.lessThanOrEqual(20000 + tolerance);
784817
});
785818

786-
it('should evaluate between interquartile range to approx 50%', () => {
819+
it('should evaluate between interquartile range to approx 50%', function() {
820+
if (nodeVersion.startsWith('14')) {
821+
this.skip();
822+
}
787823
const percentCondition = {
788824
percentOperator: PercentConditionOperator.BETWEEN,
789825
microPercentRange: {

test/unit/remote-config/remote-config-api-client.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ describe('RemoteConfigApiClient', () => {
5757
'Authorization': 'Bearer mock-token',
5858
'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`,
5959
'Accept-Encoding': 'gzip',
60+
'x-goog-user-project': 'test-project',
6061
};
6162

6263
const VERSION_INFO: Version = {

test/unit/security-rules/security-rules-api-client.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ describe('SecurityRulesApiClient', () => {
4444
const EXPECTED_HEADERS = {
4545
'Authorization': 'Bearer mock-token',
4646
'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`,
47+
'x-goog-user-project': 'test-project',
4748
};
4849
const noProjectId = 'Failed to determine project ID. Initialize the SDK with service '
4950
+ 'account credentials, or set project ID as an app option. Alternatively, set the '

0 commit comments

Comments
 (0)