Skip to content

Add the platform logging header to generateAuthToken requests #2400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 6, 2019
Merged
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
2 changes: 1 addition & 1 deletion packages/installations/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"license": "Apache-2.0",
"scripts": {
"lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'",
"lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts'",
"lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'",
"build": "rollup -c",
"test": "yarn type-check && yarn test:karma && yarn lint",
"test:karma": "karma start --single-run",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
RequestStatus
} from '../interfaces/installation-entry';
import { compareHeaders } from '../testing/compare-headers';
import { getFakeAppConfig } from '../testing/get-fake-app';
import { getFakeAppConfig } from '../testing/fake-generators';
import '../testing/setup';
import {
INSTALLATIONS_API_URL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
RequestStatus
} from '../interfaces/installation-entry';
import { compareHeaders } from '../testing/compare-headers';
import { getFakeAppConfig } from '../testing/get-fake-app';
import { getFakeAppConfig } from '../testing/fake-generators';
import '../testing/setup';
import {
INSTALLATIONS_API_URL,
Expand Down
19 changes: 10 additions & 9 deletions packages/installations/src/api/generate-auth-token-request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import { FirebaseError } from '@firebase/util';
import { expect } from 'chai';
import { SinonStub, stub } from 'sinon';
import { GenerateAuthTokenResponse } from '../interfaces/api-response';
import { AppConfig } from '../interfaces/app-config';
import { FirebaseDependencies } from '../interfaces/firebase-dependencies';
import {
CompletedAuthToken,
RegisteredInstallationEntry,
RequestStatus
} from '../interfaces/installation-entry';
import { compareHeaders } from '../testing/compare-headers';
import { getFakeAppConfig } from '../testing/get-fake-app';
import { getFakeDependencies } from '../testing/fake-generators';
import '../testing/setup';
import {
INSTALLATIONS_API_URL,
Expand All @@ -39,13 +39,13 @@ import { generateAuthTokenRequest } from './generate-auth-token-request';
const FID = 'evil-has-no-boundaries';

describe('generateAuthTokenRequest', () => {
let appConfig: AppConfig;
let dependencies: FirebaseDependencies;
let fetchSpy: SinonStub<[RequestInfo, RequestInit?], Promise<Response>>;
let registeredInstallationEntry: RegisteredInstallationEntry;
let response: GenerateAuthTokenResponse;

beforeEach(() => {
appConfig = getFakeAppConfig();
dependencies = getFakeDependencies();

registeredInstallationEntry = {
fid: FID,
Expand All @@ -72,7 +72,7 @@ describe('generateAuthTokenRequest', () => {

it('fetches a new Authentication Token', async () => {
const completedAuthToken: CompletedAuthToken = await generateAuthTokenRequest(
appConfig,
dependencies,
registeredInstallationEntry
);
expect(completedAuthToken.requestStatus).to.equal(
Expand All @@ -85,7 +85,8 @@ describe('generateAuthTokenRequest', () => {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `${INTERNAL_AUTH_VERSION} refreshToken`,
'x-goog-api-key': 'apiKey'
'x-goog-api-key': 'apiKey',
'x-firebase-client': 'a/1.2.3 b/2.3.4'
});
const expectedBody = {
installation: {
Expand All @@ -99,7 +100,7 @@ describe('generateAuthTokenRequest', () => {
};
const expectedEndpoint = `${INSTALLATIONS_API_URL}/projects/projectId/installations/${FID}/authTokens:generate`;

await generateAuthTokenRequest(appConfig, registeredInstallationEntry);
await generateAuthTokenRequest(dependencies, registeredInstallationEntry);

expect(fetchSpy).to.be.calledOnceWith(expectedEndpoint, expectedRequest);
const actualHeaders = fetchSpy.lastCall.lastArg.headers;
Expand All @@ -122,7 +123,7 @@ describe('generateAuthTokenRequest', () => {
);

await expect(
generateAuthTokenRequest(appConfig, registeredInstallationEntry)
generateAuthTokenRequest(dependencies, registeredInstallationEntry)
).to.be.rejectedWith(FirebaseError);
});

Expand All @@ -141,7 +142,7 @@ describe('generateAuthTokenRequest', () => {
fetchSpy.onCall(1).resolves(new Response(JSON.stringify(response)));

await expect(
generateAuthTokenRequest(appConfig, registeredInstallationEntry)
generateAuthTokenRequest(dependencies, registeredInstallationEntry)
).to.be.fulfilled;
expect(fetchSpy).to.be.calledTwice;
});
Expand Down
12 changes: 11 additions & 1 deletion packages/installations/src/api/generate-auth-token-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import { GenerateAuthTokenResponse } from '../interfaces/api-response';
import { AppConfig } from '../interfaces/app-config';
import { FirebaseDependencies } from '../interfaces/firebase-dependencies';
import {
CompletedAuthToken,
RegisteredInstallationEntry
Expand All @@ -31,12 +32,21 @@ import {
} from './common';

export async function generateAuthTokenRequest(
appConfig: AppConfig,
{ appConfig, platformLoggerProvider }: FirebaseDependencies,
installationEntry: RegisteredInstallationEntry
): Promise<CompletedAuthToken> {
const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);

const headers = getHeadersWithAuth(appConfig, installationEntry);

// If platform logger exists, add the platform info string to the header.
const platformLogger = platformLoggerProvider.getImmediate({
optional: true
});
if (platformLogger) {
headers.append('x-firebase-client', platformLogger.getPlatformInfoString());
}

const body = {
installation: {
sdkVersion: PACKAGE_VERSION
Expand Down
35 changes: 16 additions & 19 deletions packages/installations/src/functions/delete-installation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@
* limitations under the License.
*/

import { FirebaseApp } from '@firebase/app-types';
import { expect } from 'chai';
import { SinonStub, stub } from 'sinon';
import * as deleteInstallationRequestModule from '../api/delete-installation-request';
import { extractAppConfig } from '../helpers/extract-app-config';
import { get, set } from '../helpers/idb-manager';
import { AppConfig } from '../interfaces/app-config';
import { FirebaseDependencies } from '../interfaces/firebase-dependencies';
import {
InProgressInstallationEntry,
RegisteredInstallationEntry,
RequestStatus,
UnregisteredInstallationEntry
} from '../interfaces/installation-entry';
import { getFakeApp } from '../testing/get-fake-app';
import { getFakeDependencies } from '../testing/fake-generators';
import '../testing/setup';
import { ErrorCode } from '../util/errors';
import { sleep } from '../util/sleep';
Expand All @@ -37,16 +36,14 @@ import { deleteInstallation } from './delete-installation';
const FID = 'children-of-the-damned';

describe('deleteInstallation', () => {
let app: FirebaseApp;
let appConfig: AppConfig;
let dependencies: FirebaseDependencies;
let deleteInstallationRequestSpy: SinonStub<
[AppConfig, RegisteredInstallationEntry],
Promise<void>
>;

beforeEach(() => {
app = getFakeApp();
appConfig = extractAppConfig(app);
dependencies = getFakeDependencies();

deleteInstallationRequestSpy = stub(
deleteInstallationRequestModule,
Expand All @@ -57,7 +54,7 @@ describe('deleteInstallation', () => {
});

it('resolves without calling server API if there is no installation', async () => {
await expect(deleteInstallation(app)).to.be.fulfilled;
await expect(deleteInstallation(dependencies)).to.be.fulfilled;
expect(deleteInstallationRequestSpy).not.to.have.been.called;
});

Expand All @@ -66,11 +63,11 @@ describe('deleteInstallation', () => {
registrationStatus: RequestStatus.NOT_STARTED,
fid: FID
};
await set(appConfig, entry);
await set(dependencies.appConfig, entry);

await expect(deleteInstallation(app)).to.be.fulfilled;
await expect(deleteInstallation(dependencies)).to.be.fulfilled;
expect(deleteInstallationRequestSpy).not.to.have.been.called;
await expect(get(appConfig)).to.eventually.be.undefined;
await expect(get(dependencies.appConfig)).to.eventually.be.undefined;
});

it('rejects without calling server API if the installation is pending', async () => {
Expand All @@ -79,9 +76,9 @@ describe('deleteInstallation', () => {
registrationStatus: RequestStatus.IN_PROGRESS,
registrationTime: Date.now() - 3 * 1000
};
await set(appConfig, entry);
await set(dependencies.appConfig, entry);

await expect(deleteInstallation(app)).to.be.rejectedWith(
await expect(deleteInstallation(dependencies)).to.be.rejectedWith(
ErrorCode.DELETE_PENDING_REGISTRATION
);
expect(deleteInstallationRequestSpy).not.to.have.been.called;
Expand All @@ -99,10 +96,10 @@ describe('deleteInstallation', () => {
creationTime: Date.now()
}
};
await set(appConfig, entry);
await set(dependencies.appConfig, entry);
stub(navigator, 'onLine').value(false);

await expect(deleteInstallation(app)).to.be.rejectedWith(
await expect(deleteInstallation(dependencies)).to.be.rejectedWith(
ErrorCode.APP_OFFLINE
);
expect(deleteInstallationRequestSpy).not.to.have.been.called;
Expand All @@ -120,13 +117,13 @@ describe('deleteInstallation', () => {
creationTime: Date.now()
}
};
await set(appConfig, entry);
await set(dependencies.appConfig, entry);

await expect(deleteInstallation(app)).to.be.fulfilled;
await expect(deleteInstallation(dependencies)).to.be.fulfilled;
expect(deleteInstallationRequestSpy).to.have.been.calledOnceWith(
appConfig,
dependencies.appConfig,
entry
);
await expect(get(appConfig)).to.eventually.be.undefined;
await expect(get(dependencies.appConfig)).to.eventually.be.undefined;
});
});
9 changes: 5 additions & 4 deletions packages/installations/src/functions/delete-installation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
* limitations under the License.
*/

import { FirebaseApp } from '@firebase/app-types';
import { deleteInstallationRequest } from '../api/delete-installation-request';
import { extractAppConfig } from '../helpers/extract-app-config';
import { remove, update } from '../helpers/idb-manager';
import { FirebaseDependencies } from '../interfaces/firebase-dependencies';
import { RequestStatus } from '../interfaces/installation-entry';
import { ERROR_FACTORY, ErrorCode } from '../util/errors';

export async function deleteInstallation(app: FirebaseApp): Promise<void> {
const appConfig = extractAppConfig(app);
export async function deleteInstallation(
dependencies: FirebaseDependencies
): Promise<void> {
const { appConfig } = dependencies;

const entry = await update(appConfig, oldEntry => {
if (oldEntry && oldEntry.registrationStatus === RequestStatus.NOT_STARTED) {
Expand Down
16 changes: 9 additions & 7 deletions packages/installations/src/functions/get-id.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,27 @@ import { SinonStub, stub } from 'sinon';
import * as getInstallationEntryModule from '../helpers/get-installation-entry';
import * as refreshAuthTokenModule from '../helpers/refresh-auth-token';
import { AppConfig } from '../interfaces/app-config';
import { FirebaseDependencies } from '../interfaces/firebase-dependencies';
import {
RequestStatus,
RegisteredInstallationEntry
RegisteredInstallationEntry,
RequestStatus
} from '../interfaces/installation-entry';
import { getFakeApp } from '../testing/get-fake-app';
import { getFakeDependencies } from '../testing/fake-generators';
import '../testing/setup';
import { getId } from './get-id';

const FID = 'disciples-of-the-watch';

describe('getId', () => {
let dependencies: FirebaseDependencies;
let getInstallationEntrySpy: SinonStub<
[AppConfig],
Promise<getInstallationEntryModule.InstallationEntryWithRegistrationPromise>
>;

beforeEach(() => {
dependencies = getFakeDependencies();

getInstallationEntrySpy = stub(
getInstallationEntryModule,
'getInstallationEntry'
Expand All @@ -52,8 +56,7 @@ describe('getId', () => {
registrationPromise: Promise.resolve({} as RegisteredInstallationEntry)
});

const firebaseApp = getFakeApp();
const fid = await getId(firebaseApp);
const fid = await getId(dependencies);
expect(fid).to.equal(FID);
expect(getInstallationEntrySpy).to.be.calledOnce;
});
Expand All @@ -80,8 +83,7 @@ describe('getId', () => {
creationTime: Date.now()
});

const firebaseApp = getFakeApp();
await getId(firebaseApp);
await getId(dependencies);
expect(refreshAuthTokenSpy).to.be.calledOnce;
});
});
12 changes: 6 additions & 6 deletions packages/installations/src/functions/get-id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@
* limitations under the License.
*/

import { FirebaseApp } from '@firebase/app-types';
import { extractAppConfig } from '../helpers/extract-app-config';
import { getInstallationEntry } from '../helpers/get-installation-entry';
import { refreshAuthToken } from '../helpers/refresh-auth-token';
import { FirebaseDependencies } from '../interfaces/firebase-dependencies';

export async function getId(app: FirebaseApp): Promise<string> {
const appConfig = extractAppConfig(app);
export async function getId(
dependencies: FirebaseDependencies
): Promise<string> {
const { installationEntry, registrationPromise } = await getInstallationEntry(
appConfig
dependencies.appConfig
);

if (registrationPromise) {
registrationPromise.catch(console.error);
} else {
// If the installation is already registered, update the authentication
// token if needed.
refreshAuthToken(appConfig).catch(console.error);
refreshAuthToken(dependencies).catch(console.error);
}

return installationEntry.fid;
Expand Down
Loading