diff --git a/.changeset/afraid-baboons-develop.md b/.changeset/afraid-baboons-develop.md new file mode 100644 index 00000000000..84e4e923f43 --- /dev/null +++ b/.changeset/afraid-baboons-develop.md @@ -0,0 +1,8 @@ +--- +'@firebase/app-check': minor +'@firebase/app': minor +'@firebase/app-compat': minor +'firebase': minor +--- + +Default automaticDataCollectionEnabled to true without changing App Check's default behavior. diff --git a/docs-devsite/app.firebaseappsettings.md b/docs-devsite/app.firebaseappsettings.md index 1515e21ac93..e7838ab4185 100644 --- a/docs-devsite/app.firebaseappsettings.md +++ b/docs-devsite/app.firebaseappsettings.md @@ -22,12 +22,12 @@ export interface FirebaseAppSettings | Property | Type | Description | | --- | --- | --- | -| [automaticDataCollectionEnabled](./app.firebaseappsettings.md#firebaseappsettingsautomaticdatacollectionenabled) | boolean | The settable config flag for GDPR opt-in/opt-out | +| [automaticDataCollectionEnabled](./app.firebaseappsettings.md#firebaseappsettingsautomaticdatacollectionenabled) | boolean | The settable config flag for GDPR opt-in/opt-out. Defaults to true. | | [name](./app.firebaseappsettings.md#firebaseappsettingsname) | string | custom name for the Firebase App. The default value is "[DEFAULT]". | ## FirebaseAppSettings.automaticDataCollectionEnabled -The settable config flag for GDPR opt-in/opt-out +The settable config flag for GDPR opt-in/opt-out. Defaults to true. Signature: diff --git a/packages/app-check/src/api.test.ts b/packages/app-check/src/api.test.ts index a6805d1b0b3..b71971e9d70 100644 --- a/packages/app-check/src/api.test.ts +++ b/packages/app-check/src/api.test.ts @@ -239,7 +239,7 @@ describe('api', () => { expect(getStateReference(app).activated).to.equal(true); }); - it('isTokenAutoRefreshEnabled value defaults to global setting', () => { + it('global false + local unset = false', () => { app.automaticDataCollectionEnabled = false; initializeAppCheck(app, { provider: new ReCaptchaV3Provider(FAKE_SITE_KEY) @@ -247,8 +247,77 @@ describe('api', () => { expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(false); }); - it('sets isTokenAutoRefreshEnabled correctly, overriding global setting', () => { + it('global false + local true = false', () => { app.automaticDataCollectionEnabled = false; + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY), + isTokenAutoRefreshEnabled: true + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(false); + }); + + it('global false + local false = false', () => { + app.automaticDataCollectionEnabled = false; + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY), + isTokenAutoRefreshEnabled: false + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(false); + }); + + it('global unset + local unset = false', () => { + // Global unset should default to true. + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY) + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(false); + }); + + it('global unset + local false = false', () => { + // Global unset should default to true. + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY), + isTokenAutoRefreshEnabled: false + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(false); + }); + + it('global unset + local true = true', () => { + // Global unset should default to true. + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY), + isTokenAutoRefreshEnabled: true + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(true); + }); + + it('global true + local unset = false', () => { + app.automaticDataCollectionEnabled = true; + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY) + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(false); + }); + + it('global true + local false = false', () => { + app.automaticDataCollectionEnabled = true; + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY), + isTokenAutoRefreshEnabled: false + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(false); + }); + + it('global true + local true = true', () => { + app.automaticDataCollectionEnabled = true; + initializeAppCheck(app, { + provider: new ReCaptchaV3Provider(FAKE_SITE_KEY), + isTokenAutoRefreshEnabled: true + }); + expect(getStateReference(app).isTokenAutoRefreshEnabled).to.equal(true); + }); + + it('sets isTokenAutoRefreshEnabled correctly, overriding global setting', () => { initializeAppCheck(app, { provider: new ReCaptchaV3Provider(FAKE_SITE_KEY), isTokenAutoRefreshEnabled: true diff --git a/packages/app-check/src/api.ts b/packages/app-check/src/api.ts index a4dd87a4e77..e7c9f8cfcf9 100644 --- a/packages/app-check/src/api.ts +++ b/packages/app-check/src/api.ts @@ -43,6 +43,7 @@ import { } from './internal-api'; import { readTokenFromStorage } from './storage'; import { getDebugToken, initializeDebugMode, isDebugMode } from './debug'; +import { logger } from './logger'; declare module '@firebase/component' { interface NameServiceMapping { @@ -132,7 +133,7 @@ export function initializeAppCheck( function _activate( app: FirebaseApp, provider: AppCheckProvider, - isTokenAutoRefreshEnabled?: boolean + isTokenAutoRefreshEnabled: boolean = false ): void { // Create an entry in the APP_CHECK_STATES map. Further changes should // directly mutate this object. @@ -149,13 +150,18 @@ function _activate( return cachedToken; }); - // Use value of global `automaticDataCollectionEnabled` (which - // itself defaults to false if not specified in config) if - // `isTokenAutoRefreshEnabled` param was not provided by user. + // Global `automaticDataCollectionEnabled` (defaults to true) and + // `isTokenAutoRefreshEnabled` must both be true. state.isTokenAutoRefreshEnabled = - isTokenAutoRefreshEnabled === undefined - ? app.automaticDataCollectionEnabled - : isTokenAutoRefreshEnabled; + isTokenAutoRefreshEnabled && app.automaticDataCollectionEnabled; + + if (!app.automaticDataCollectionEnabled && isTokenAutoRefreshEnabled) { + logger.warn( + '`isTokenAutoRefreshEnabled` is true but ' + + '`automaticDataCollectionEnabled` was set to false during' + + ' `initializeApp()`. This blocks automatic token refresh.' + ); + } state.provider.initialize(app); } diff --git a/packages/app-compat/test/firebaseAppCompat.test.ts b/packages/app-compat/test/firebaseAppCompat.test.ts index f12a73e61a8..61bbed848d8 100644 --- a/packages/app-compat/test/firebaseAppCompat.test.ts +++ b/packages/app-compat/test/firebaseAppCompat.test.ts @@ -403,17 +403,17 @@ function firebaseAppTests( ).throws(/'abc'.*exists/i); }); - it('automaticDataCollectionEnabled is `false` by default', () => { + it('automaticDataCollectionEnabled is `true` by default', () => { const app = firebase.initializeApp({}, 'my-app'); - expect(app.automaticDataCollectionEnabled).to.eq(false); + expect(app.automaticDataCollectionEnabled).to.eq(true); }); it('automaticDataCollectionEnabled can be set via the config object', () => { const app = firebase.initializeApp( {}, - { automaticDataCollectionEnabled: true } + { automaticDataCollectionEnabled: false } ); - expect(app.automaticDataCollectionEnabled).to.eq(true); + expect(app.automaticDataCollectionEnabled).to.eq(false); }); it('Modifying options object does not change options.', () => { diff --git a/packages/app/src/api.test.ts b/packages/app/src/api.test.ts index f6cf922ba05..4e79ad58d82 100644 --- a/packages/app/src/api.test.ts +++ b/packages/app/src/api.test.ts @@ -128,14 +128,14 @@ describe('API tests', () => { { apiKey: 'test1' }, - { automaticDataCollectionEnabled: true } + { automaticDataCollectionEnabled: false } ); expect(() => initializeApp( { apiKey: 'test1' }, - { automaticDataCollectionEnabled: false } + { automaticDataCollectionEnabled: true } ) ).throws(/\[DEFAULT\].*exists/i); }); @@ -146,14 +146,14 @@ describe('API tests', () => { { apiKey: 'test1' }, - { name: appName, automaticDataCollectionEnabled: true } + { name: appName, automaticDataCollectionEnabled: false } ); expect(() => initializeApp( { apiKey: 'test1' }, - { name: appName, automaticDataCollectionEnabled: false } + { name: appName, automaticDataCollectionEnabled: true } ) ).throws(/'MyApp'.*exists/i); }); @@ -164,11 +164,16 @@ describe('API tests', () => { expect(app.name).to.equal(appName); }); - it('sets automaticDataCollectionEnabled', () => { - const app = initializeApp({}, { automaticDataCollectionEnabled: true }); + it('sets automaticDataCollectionEnabled to true by default', () => { + const app = initializeApp({}); expect(app.automaticDataCollectionEnabled).to.be.true; }); + it('sets a new automaticDataCollectionEnabled value if provided', () => { + const app = initializeApp({}, { automaticDataCollectionEnabled: false }); + expect(app.automaticDataCollectionEnabled).to.be.false; + }); + it('adds registered components to App', () => { _clearComponents(); const comp1 = createTestComponent('test1'); @@ -211,7 +216,7 @@ describe('API tests', () => { const app = initializeServerApp(options, serverAppSettings); expect(app).to.not.equal(null); - expect(app.automaticDataCollectionEnabled).to.be.false; + expect(app.automaticDataCollectionEnabled).to.be.true; await deleteApp(app); expect((app as FirebaseServerAppImpl).isDeleted).to.be.true; }); diff --git a/packages/app/src/api.ts b/packages/app/src/api.ts index b8ec25fc509..9cba8ec6f50 100644 --- a/packages/app/src/api.ts +++ b/packages/app/src/api.ts @@ -143,7 +143,7 @@ export function initializeApp( const config: Required = { name: DEFAULT_ENTRY_NAME, - automaticDataCollectionEnabled: false, + automaticDataCollectionEnabled: true, ...rawConfig }; const name = config.name; @@ -241,7 +241,7 @@ export function initializeServerApp( } if (_serverAppConfig.automaticDataCollectionEnabled === undefined) { - _serverAppConfig.automaticDataCollectionEnabled = false; + _serverAppConfig.automaticDataCollectionEnabled = true; } let appOptions: FirebaseOptions; diff --git a/packages/app/src/firebaseApp.test.ts b/packages/app/src/firebaseApp.test.ts index 419eeef4f1f..3acbb4a2869 100644 --- a/packages/app/src/firebaseApp.test.ts +++ b/packages/app/src/firebaseApp.test.ts @@ -27,11 +27,11 @@ describe('FirebaseAppNext', () => { }; const app = new FirebaseAppImpl( options, - { name: 'test', automaticDataCollectionEnabled: false }, + { name: 'test', automaticDataCollectionEnabled: true }, new ComponentContainer('test') ); - expect(app.automaticDataCollectionEnabled).to.be.false; + expect(app.automaticDataCollectionEnabled).to.be.true; expect(app.name).to.equal('test'); expect(app.options).to.deep.equal(options); }); diff --git a/packages/app/src/firebaseServerApp.ts b/packages/app/src/firebaseServerApp.ts index 21232869c3c..2bb8efc7a63 100644 --- a/packages/app/src/firebaseServerApp.ts +++ b/packages/app/src/firebaseServerApp.ts @@ -74,7 +74,7 @@ export class FirebaseServerAppImpl const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== undefined ? serverConfig.automaticDataCollectionEnabled - : false; + : true; // Create the FirebaseAppSettings object for the FirebaseAppImp constructor. const config: Required = { diff --git a/packages/app/src/public-types.ts b/packages/app/src/public-types.ts index ea68579a7e9..4f8373f2250 100644 --- a/packages/app/src/public-types.ts +++ b/packages/app/src/public-types.ts @@ -165,7 +165,7 @@ export interface FirebaseAppSettings { */ name?: string; /** - * The settable config flag for GDPR opt-in/opt-out + * The settable config flag for GDPR opt-in/opt-out. Defaults to true. */ automaticDataCollectionEnabled?: boolean; }