Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"test:firefox-headless": "npx --yes firebase-tools@latest emulators:exec --project=demo-123 \"ng test --watch=false --browsers=FirefoxHeadless\"",
"lint": "ng lint",
"lint:fix": "ng lint --fix",
"test:node": "node -r tsconfig-paths/register ./dist/out-tsc/jasmine/tools/jasmine.mjs --input-type=commonjs",
"test:node-esm": "node -r tsconfig-paths/register ./dist/out-tsc/jasmine/tools/jasmine.mjs",
"test:node": "node --import ./tools/jasmine-register-angular-fire.mjs -r tsconfig-paths/register ./dist/out-tsc/jasmine/tools/jasmine.mjs --input-type=commonjs",
"test:node-esm": "node --import ./tools/jasmine-register-angular-fire.mjs -r tsconfig-paths/register ./dist/out-tsc/jasmine/tools/jasmine.mjs",
"test:typings": "node ./tools/run-typings-test.js",
"test:build": "bash ./test/ng-build/build.sh",
"test:all": "npm run test:node-esm && npm run test:chrome-headless && npm run test:typings && npm run test:build",
Expand Down
7 changes: 6 additions & 1 deletion src/app-check/app-check.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,17 @@ const isLocalhost = typeof window !== 'undefined' && LOCALHOSTS.includes(window.

let warnedServerSkip = false;

/** Resets the server-rendering warning for specs, which share one process. */
export const ɵresetAppCheckServerWarning = (): void => {
warnedServerSkip = false;
};

export function appCheckInstanceFactory(fn: (injector: Injector) => FirebaseAppCheck) {
return (zone: NgZone, injector: Injector, platformId: unknown) => {
if (isPlatformServer(platformId) && !injector.get(APP_CHECK_ON_SERVER)) {
if (isDevMode() && !warnedServerSkip) {
warnedServerSkip = true;
console.warn("AngularFire skips App Check during server rendering, so server-side Firebase requests carry no App Check token. To run App Check there, provide APP_CHECK_ON_SERVER as true in your server config. Find more at https://github.com/angular/angularfire/blob/main/docs/app-check.md");
console.warn("AngularFire skips App Check during server rendering, so server renders without a relayed App Check token send none. To relay the browser's App Check token, build the app with initializeBrowserOrServerApp and hand the token to the render as the appCheckToken key of the request context. To run App Check on the server instead, provide APP_CHECK_ON_SERVER as true in your server config. Find more at https://github.com/angular/angularfire/blob/main/docs/app-check.md");
}
return undefined;
}
Expand Down
35 changes: 34 additions & 1 deletion src/app-check/app-check.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PLATFORM_ID, PendingTasks } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { FirebaseApp, deleteApp, getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { APP_CHECK_ON_SERVER, AppCheck, CustomProvider, initializeAppCheck, onTokenChanged, provideAppCheck } from '@angular/fire/app-check';
import { APP_CHECK_ON_SERVER, AppCheck, CustomProvider, initializeAppCheck, onTokenChanged, provideAppCheck, ɵresetAppCheckServerWarning } from '@angular/fire/app-check';
import { Auth, connectAuthEmulator, getAuth, provideAuth } from '@angular/fire/auth';
import { COMMON_CONFIG } from '../test-config';
import { rando } from '../utils';
Expand Down Expand Up @@ -54,6 +54,39 @@ describe('AppCheck', () => {
beforeEach(() => {
appName = rando();
setupCalls = 0;
ɵresetAppCheckServerWarning();
});

const configureServerPlatform = () => {
TestBed.configureTestingModule({
providers: [
{ provide: PLATFORM_ID, useValue: 'server' },
provideFirebaseApp(() => initializeApp(COMMON_CONFIG, appName)),
provideTestAppCheck(),
],
});
};

it('warns once during server rendering, saying what a relayed token changes', () => {
const warn = spyOn(console, 'warn');
configureServerPlatform();
TestBed.inject(AppCheck);
expect(warn).toHaveBeenCalledTimes(1);
const message = warn.calls.argsFor(0).join(' ');
expect(message).toContain('server renders without a relayed App Check token send none');
expect(message).toContain('APP_CHECK_ON_SERVER');
expect(message).toContain('initializeBrowserOrServerApp');
});

it('warns once per process, not once per render', () => {
const warn = spyOn(console, 'warn');
configureServerPlatform();
TestBed.inject(AppCheck);
TestBed.resetTestingModule();
appName = rando();
configureServerPlatform();
TestBed.inject(AppCheck);
expect(warn).toHaveBeenCalledTimes(1);
});

it('should skip App Check during server rendering by default', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/app-check/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { AppCheck, appCheckInstance$, AppCheckInstances } from './app-check';
export { provideAppCheck, AppCheckModule, APP_CHECK_ON_SERVER } from './app-check.module';
export { provideAppCheck, AppCheckModule, APP_CHECK_ON_SERVER, ɵresetAppCheckServerWarning } from './app-check.module';
export * from './firebase';
18 changes: 17 additions & 1 deletion src/app/app.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PendingTasks } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { FirebaseApp, deleteApp, initializeApp, onLog, provideFirebaseApp } from '@angular/fire/app';
import { FirebaseApp, deleteApp, getApp, initializeApp, initializeBrowserOrServerApp, onLog, provideFirebaseApp } from '@angular/fire/app';
import { COMMON_CONFIG } from '../test-config';
import { rando } from '../utils';

Expand Down Expand Up @@ -55,4 +55,20 @@ describe('FirebaseApp', () => {

});

describe('initializeBrowserOrServerApp', () => {

// The default app is shared with other specs that build it from COMMON_CONFIG, so no other settings and no deleteApp here.
it('returns the default app in the browser whatever tokens it is given', () => {
TestBed.configureTestingModule({
providers: [
provideFirebaseApp(() => initializeBrowserOrServerApp(COMMON_CONFIG, { authIdToken: 'h.e.s', appCheckToken: 'h.e.s' })),
],
});
const browserApp = TestBed.inject(FirebaseApp);
expect(browserApp).toBe(getApp());
expect('settings' in browserApp).toBeFalse();
});

});

});
4 changes: 2 additions & 2 deletions src/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { concatMap, distinct } from 'rxjs/operators';
// back when we constructed our own class. Then in the "new class" we just return the FirebaseApp in the
// constructor, this also has the added benefit of Firebase methods taking our DI class without
// casting. E.g,
// constructor(private app: FirebaseApp) { }
// ngOnDestroy() { deleteApp(this.app); }
// private readonly app = inject(FirebaseApp);
// readonly firestore = getFirestore(this.app);
//

export interface FirebaseApp extends IFirebaseApp {}
Expand Down
Loading
Loading