Skip to content

Commit

Permalink
fix: migrate FCM channel authentication from ApiKey to ServiceToken b…
Browse files Browse the repository at this point in the history
…ased (#13826)

* fix: migrate FCM channel authentication from ApiKey to ServiceToken based

* fix: explicitly set DefaultAuthenticationMethod
  • Loading branch information
Amplifiyer committed Jun 19, 2024
1 parent 33da5c7 commit 252093f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ jest.mock('@aws-amplify/amplify-cli-core', () => {
};
});

const apiKey = 'ApiKey-abc123';
const serviceJSONFilePath = '/my/service/account/jsonFile.json';
const serviceAccountJson = '{ "valid": { "service": "accountJson"}}';
jest.mock('fs-extra', () => ({
readFile: () => Promise.resolve(serviceAccountJson),
existsSync: () => true,
}));
jest.mock('@aws-amplify/amplify-prompts');
const prompterMock = prompter as jest.Mocked<typeof prompter>;

Expand Down Expand Up @@ -97,7 +102,7 @@ describe('channel-FCM', () => {
test('configure', async () => {
mockChannelEnabledOutput.Enabled = true;
prompterMock.yesOrNo.mockResolvedValueOnce(true);
prompterMock.input.mockResolvedValueOnce(apiKey);
prompterMock.input.mockResolvedValueOnce(serviceJSONFilePath);

const mockContextObj = mockContext(mockChannelEnabledOutput, mockPinpointClient);
await channelFCM.configure(mockContextObj).then(() => {
Expand All @@ -118,28 +123,22 @@ describe('channel-FCM', () => {
});

test('enable', async () => {
prompterMock.input.mockResolvedValueOnce(apiKey);
prompterMock.input.mockResolvedValueOnce(serviceJSONFilePath);
const mockContextObj = mockContext(mockChannelEnabledOutput, mockPinpointClient);
const data = await channelFCM.enable(mockContextObj, 'successMessage');
expect(mockPinpointClient.updateGcmChannel).toBeCalled();
expect(data).toEqual(mockPinpointResponseData(true, ChannelAction.ENABLE));
});

test('enable with newline', async () => {
prompterMock.input.mockResolvedValueOnce(`${apiKey}\n`);
const data = await channelFCM.enable(mockContext(mockChannelEnabledOutput, mockPinpointClient), 'successMessage');
expect(mockPinpointClient.updateGcmChannel).toBeCalledWith({
ApplicationId: undefined,
GCMChannelRequest: {
ApiKey: apiKey,
ServiceJson: serviceAccountJson,
DefaultAuthenticationMethod: 'TOKEN',
Enabled: true,
},
});
expect(data).toEqual(mockPinpointResponseData(true, ChannelAction.ENABLE));
});

test('enable unsuccessful', async () => {
prompterMock.input.mockResolvedValueOnce(apiKey);
prompterMock.input.mockResolvedValueOnce(serviceJSONFilePath);

const context = mockContextReject(mockServiceOutput, mockPinpointClientReject);
const errCert: AmplifyFault = await getError(async () => channelFCM.enable(context as unknown as $TSContext, 'successMessage'));
Expand Down
28 changes: 15 additions & 13 deletions packages/amplify-category-notifications/src/channel-fcm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { printer, prompter } from '@aws-amplify/amplify-prompts';
import ora from 'ora';
import { ChannelAction, ChannelConfigDeploymentType, IChannelAPIResponse } from './channel-types';
import { buildPinpointChannelResponseSuccess } from './pinpoint-helper';
import { validateFilePath } from './validate-filepath';
import fs from 'fs-extra';

const channelName = 'FCM';
const spinner = ora('');
Expand Down Expand Up @@ -42,19 +44,19 @@ export const enable = async (context: $TSContext, successMessage: string | undef
if (context.exeInfo.pinpointInputParams?.[channelName]) {
answers = validateInputParams(context.exeInfo.pinpointInputParams[channelName]);
} else {
let channelOutput: $TSAny = {};
if (context.exeInfo.serviceMeta.output[channelName]) {
channelOutput = context.exeInfo.serviceMeta.output[channelName];
}
answers = {
ApiKey: await prompter.input('Server Key', { initial: channelOutput.ApiKey, transform: (input) => input.trim() }),
ServiceJson: await fs.readFile(
await prompter.input('The service account file path (.json): ', { validate: validateFilePath }),
'utf8',
),
};
}

const params = {
ApplicationId: context.exeInfo.serviceMeta.output.Id,
GCMChannelRequest: {
...answers,
DefaultAuthenticationMethod: 'TOKEN',
Enabled: true,
},
};
Expand All @@ -78,10 +80,10 @@ export const enable = async (context: $TSContext, successMessage: string | undef
};

const validateInputParams = (channelInput: $TSAny): $TSAny => {
if (!channelInput.ApiKey) {
if (!channelInput.ServiceJson) {
throw new AmplifyError('UserInputError', {
message: 'Server Key is missing for the FCM channel',
resolution: 'Server Key for the FCM channel',
message: 'ServiceJson is missing for the FCM channel',
resolution: 'Provide the JSON from your Firebase service account json file',
});
}
return channelInput;
Expand All @@ -97,18 +99,18 @@ export const disable = async (context: $TSContext): Promise<$TSAny> => {
if (context.exeInfo.pinpointInputParams?.[channelName]) {
answers = validateInputParams(context.exeInfo.pinpointInputParams[channelName]);
} else {
let channelOutput: $TSAny = {};
if (context.exeInfo.serviceMeta.output[channelName]) {
channelOutput = context.exeInfo.serviceMeta.output[channelName];
}
answers = {
ApiKey: await prompter.input('Server Key', { initial: channelOutput.ApiKey, transform: (input) => input.trim() }),
ServiceJson: await fs.readFile(
await prompter.input('The service account file path (.json): ', { validate: validateFilePath }),
'utf8',
),
};
}
const params = {
ApplicationId: context.exeInfo.serviceMeta.output.Id,
GCMChannelRequest: {
...answers,
DefaultAuthenticationMethod: 'TOKEN',
Enabled: false,
},
};
Expand Down

0 comments on commit 252093f

Please sign in to comment.