зеркало из https://github.com/mozilla/fxa.git
Merge pull request #13606 from mozilla/fxa-5417
fix(auth): ensure /app-store-notification endpoint returns 200s
This commit is contained in:
Коммит
1e8634d3d5
|
@ -37,7 +37,7 @@ export class AppleIapHandler {
|
||||||
try {
|
try {
|
||||||
({ bundleId, originalTransactionId, decodedPayload } =
|
({ bundleId, originalTransactionId, decodedPayload } =
|
||||||
await this.appStore.purchaseManager.decodeNotificationPayload(
|
await this.appStore.purchaseManager.decodeNotificationPayload(
|
||||||
request.payload as any
|
(request.payload as any).signedPayload
|
||||||
));
|
));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// app-store-server-api compiles CertificateValidationError to a function,
|
// app-store-server-api compiles CertificateValidationError to a function,
|
||||||
|
@ -157,7 +157,15 @@ export const appleIapRoutes = (): ServerRoute[] => {
|
||||||
options: {
|
options: {
|
||||||
...SUBSCRIPTIONS_DOCS.OAUTH_SUBSCRIPTIONS_IAP_APP_STORE_NOTIFICATION_POST,
|
...SUBSCRIPTIONS_DOCS.OAUTH_SUBSCRIPTIONS_IAP_APP_STORE_NOTIFICATION_POST,
|
||||||
validate: {
|
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) =>
|
handler: (request: AuthRequest) =>
|
||||||
|
|
|
@ -245,6 +245,24 @@ describe('PurchaseManager', () => {
|
||||||
assert.deepEqual(result, mockSubscriptionWithNotificationProps);
|
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 () => {
|
it('throws unexpected library error', async () => {
|
||||||
mockPurchaseDoc.ref.set = sinon.fake.rejects(new Error('test'));
|
mockPurchaseDoc.ref.set = sinon.fake.rejects(new Error('test'));
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -162,7 +162,9 @@ describe('AppleIapHandler', () => {
|
||||||
userId: 'test1234',
|
userId: 'test1234',
|
||||||
};
|
};
|
||||||
mockRequest = {
|
mockRequest = {
|
||||||
payload: {},
|
payload: {
|
||||||
|
signedPayload: 'base64 encoded string',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
appleIap.purchaseManager = {
|
appleIap.purchaseManager = {
|
||||||
decodeNotificationPayload: sinon.fake.resolves({
|
decodeNotificationPayload: sinon.fake.resolves({
|
||||||
|
@ -178,7 +180,10 @@ describe('AppleIapHandler', () => {
|
||||||
it('handles a notification that requires profile updating', async () => {
|
it('handles a notification that requires profile updating', async () => {
|
||||||
const result = await appleIapHandler.processNotification(mockRequest);
|
const result = await appleIapHandler.processNotification(mockRequest);
|
||||||
assert.deepEqual(result, {});
|
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.getSubscriptionPurchase);
|
||||||
assert.calledOnce(appleIap.purchaseManager.processNotification);
|
assert.calledOnce(appleIap.purchaseManager.processNotification);
|
||||||
assert.calledOnce(mockCapabilityService.iapUpdate);
|
assert.calledOnce(mockCapabilityService.iapUpdate);
|
||||||
|
|
|
@ -93,10 +93,10 @@ export class PurchaseManager {
|
||||||
// triggered by a notification
|
// triggered by a notification
|
||||||
if (triggerNotificationType !== undefined) {
|
if (triggerNotificationType !== undefined) {
|
||||||
subscriptionPurchase.latestNotificationType = triggerNotificationType;
|
subscriptionPurchase.latestNotificationType = triggerNotificationType;
|
||||||
// This may be `undefined`, but we assign regardless to clear any previous
|
if (triggerNotificationSubtype !== undefined) {
|
||||||
// notification's subtype value.
|
subscriptionPurchase.latestNotificationSubtype =
|
||||||
subscriptionPurchase.latestNotificationSubtype =
|
triggerNotificationSubtype;
|
||||||
triggerNotificationSubtype;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert subscriptionPurchase object to a format that to be stored in Firestore
|
// Convert subscriptionPurchase object to a format that to be stored in Firestore
|
||||||
|
|
Загрузка…
Ссылка в новой задаче