Merge pull request #13606 from mozilla/fxa-5417

fix(auth): ensure /app-store-notification endpoint returns 200s
This commit is contained in:
Bianca Danforth 2022-07-14 19:17:40 -04:00 коммит произвёл GitHub
Родитель 55b88cf01a b494747e5f
Коммит 1e8634d3d5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 39 добавлений и 8 удалений

Просмотреть файл

@ -37,7 +37,7 @@ export class AppleIapHandler {
try {
({ bundleId, originalTransactionId, decodedPayload } =
await this.appStore.purchaseManager.decodeNotificationPayload(
request.payload as any
(request.payload as any).signedPayload
));
} catch (err) {
// app-store-server-api compiles CertificateValidationError to a function,
@ -157,7 +157,15 @@ export const appleIapRoutes = (): ServerRoute[] => {
options: {
...SUBSCRIPTIONS_DOCS.OAUTH_SUBSCRIPTIONS_IAP_APP_STORE_NOTIFICATION_POST,
validate: {
payload: isA.string().required() as any,
// https://developer.apple.com/documentation/appstoreservernotifications/responsebodyv2
payload: isA
.object({
signedPayload: isA.string().required(),
})
.required() as any,
},
payload: {
maxBytes: 37000, // twice the expected size
},
},
handler: (request: AuthRequest) =>

Просмотреть файл

@ -245,6 +245,24 @@ describe('PurchaseManager', () => {
assert.deepEqual(result, mockSubscriptionWithNotificationProps);
});
it('adds only notificationType to the purchase if notificationSubtype is undefined when passed in', async () => {
mockPurchaseDoc.data = sinon.fake.returns({});
mockPurchaseDoc.exists = true;
const notificationType = 'foo';
const notificationSubtype = undefined;
const mockSubscriptionWithNotificationProp = {
...mockSubscription,
latestNotificationType: notificationType,
};
const result = await purchaseManager.querySubscriptionPurchase(
mockBundleId,
mockOriginalTransactionId,
notificationType,
notificationSubtype
);
assert.deepEqual(result, mockSubscriptionWithNotificationProp);
});
it('throws unexpected library error', async () => {
mockPurchaseDoc.ref.set = sinon.fake.rejects(new Error('test'));
try {

Просмотреть файл

@ -162,7 +162,9 @@ describe('AppleIapHandler', () => {
userId: 'test1234',
};
mockRequest = {
payload: {},
payload: {
signedPayload: 'base64 encoded string',
},
};
appleIap.purchaseManager = {
decodeNotificationPayload: sinon.fake.resolves({
@ -178,7 +180,10 @@ describe('AppleIapHandler', () => {
it('handles a notification that requires profile updating', async () => {
const result = await appleIapHandler.processNotification(mockRequest);
assert.deepEqual(result, {});
assert.calledOnce(appleIap.purchaseManager.decodeNotificationPayload);
assert.calledOnceWithExactly(
appleIap.purchaseManager.decodeNotificationPayload,
mockRequest.payload.signedPayload
);
assert.calledOnce(appleIap.purchaseManager.getSubscriptionPurchase);
assert.calledOnce(appleIap.purchaseManager.processNotification);
assert.calledOnce(mockCapabilityService.iapUpdate);

Просмотреть файл

@ -93,11 +93,11 @@ export class PurchaseManager {
// triggered by a notification
if (triggerNotificationType !== undefined) {
subscriptionPurchase.latestNotificationType = triggerNotificationType;
// This may be `undefined`, but we assign regardless to clear any previous
// notification's subtype value.
if (triggerNotificationSubtype !== undefined) {
subscriptionPurchase.latestNotificationSubtype =
triggerNotificationSubtype;
}
}
// Convert subscriptionPurchase object to a format that to be stored in Firestore
const firestoreObject = subscriptionPurchase.toFirestoreObject();