-
Notifications
You must be signed in to change notification settings - Fork 212
/
Copy pathuser-manager.ts
121 lines (110 loc) · 4.25 KB
/
user-manager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* Copyright 2018 Google LLC. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { CollectionReference } from '@google-cloud/firestore';
import Container from 'typedi';
import { AuthLogger } from '../../../types';
import { PurchaseManager } from './purchase-manager';
import {
GOOGLE_PLAY_FORM_OF_PAYMENT,
SubscriptionPurchase,
} from './subscription-purchase';
import { PurchaseQueryError } from './types/errors';
import { SkuType } from './types/purchases';
/*
* A class that allows looking up purchases registered to a particular user
*/
export class UserManager {
private log: AuthLogger;
/*
* This class is intended to be initialized by the library.
* Library consumer should not initialize this class themselves.
*/
constructor(
private purchasesDbRef: CollectionReference,
private purchaseManager: PurchaseManager
) {
this.log = Container.get(AuthLogger);
}
/*
* Query subscriptions registered to a particular user, that are either active or in account hold.
* Note: Other subscriptions which don't meet the above criteria still exists in Firestore purchase records, but not accessible from outside of the library.
*/
async queryCurrentSubscriptions(
userId: string,
sku?: string,
packageName?: string
): Promise<Array<SubscriptionPurchase>> {
const purchaseList = new Array<SubscriptionPurchase>();
try {
// Create query to fetch possibly active subscriptions from Firestore
let query = this.purchasesDbRef
.where('formOfPayment', '==', GOOGLE_PLAY_FORM_OF_PAYMENT)
.where('skuType', '==', SkuType.SUBS)
.where('userId', '==', userId)
.where('isMutable', '==', true);
if (sku) {
query = query.where('sku', '==', sku);
}
if (packageName) {
query = query.where('packageName', '==', packageName);
}
// Do fetch possibly active subscription from Firestore
const queryResult = await query.get();
// Loop through these subscriptions and filter those that are indeed active
for (const purchaseRecordSnapshot of queryResult.docs) {
let purchase: SubscriptionPurchase =
SubscriptionPurchase.fromFirestoreObject(
purchaseRecordSnapshot.data()
);
if (
!purchase.isEntitlementActive() &&
!purchase.isAccountHold() &&
!purchase.isPaused()
) {
// If a subscription purchase record in Firestore indicates says that it has expired,
// and we haven't confirmed that it's in Account Hold,
// and we know that its status could have been changed since we last fetch its details,
// then we should query Play Developer API to get its latest status
this.log.info('queryCurrentSubscriptions.cache.update', {
purchaseToken: purchase.purchaseToken,
});
purchase = await this.purchaseManager.querySubscriptionPurchase(
purchase.packageName,
purchase.sku,
purchase.purchaseToken
);
}
// Add the updated purchase to list to returned to clients
if (
purchase.isEntitlementActive() ||
purchase.isAccountHold() ||
purchase.isPaused()
) {
purchaseList.push(purchase);
}
}
return purchaseList;
} catch (err) {
this.log.error('queryCurrentSubscriptions.firestoreFetch', { err });
const libraryError = new Error(err.message);
libraryError.name = PurchaseQueryError.OTHER_ERROR;
throw libraryError;
}
}
}