@unchainedshop/ticketing 4.0.0-rc.16 → 4.0.0-rc.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/fastify.js +2 -2
- package/lib/fastify.js.map +1 -1
- package/lib/magic-key.js +4 -4
- package/lib/magic-key.js.map +1 -1
- package/lib/mobile-tickets/apple-handler-express.d.ts.map +1 -1
- package/lib/mobile-tickets/apple-handler-express.js +48 -28
- package/lib/mobile-tickets/apple-handler-express.js.map +1 -1
- package/lib/mobile-tickets/apple-handler-fastify.d.ts.map +1 -1
- package/lib/mobile-tickets/apple-handler-fastify.js +55 -37
- package/lib/mobile-tickets/apple-handler-fastify.js.map +1 -1
- package/lib/mobile-tickets/apple-wallet.d.ts +1 -1
- package/lib/mobile-tickets/apple-wallet.d.ts.map +1 -1
- package/lib/mobile-tickets/apple-wallet.js +2 -2
- package/lib/mobile-tickets/apple-wallet.js.map +1 -1
- package/lib/mobile-tickets/apple-webservice.d.ts +7 -0
- package/lib/mobile-tickets/apple-webservice.d.ts.map +1 -0
- package/lib/mobile-tickets/apple-webservice.js +177 -0
- package/lib/mobile-tickets/apple-webservice.js.map +1 -0
- package/lib/mobile-tickets/google-handler-express.d.ts.map +1 -1
- package/lib/mobile-tickets/google-handler-express.js +4 -1
- package/lib/mobile-tickets/google-handler-express.js.map +1 -1
- package/lib/mobile-tickets/google-handler-fastify.d.ts.map +1 -1
- package/lib/mobile-tickets/google-handler-fastify.js +4 -1
- package/lib/mobile-tickets/google-handler-fastify.js.map +1 -1
- package/lib/mobile-tickets/google-webservice.d.ts +7 -0
- package/lib/mobile-tickets/google-webservice.d.ts.map +1 -0
- package/lib/mobile-tickets/google-webservice.js +52 -0
- package/lib/mobile-tickets/google-webservice.js.map +1 -0
- package/lib/module.d.ts +8 -8
- package/lib/module.d.ts.map +1 -1
- package/lib/module.js +2 -2
- package/lib/module.js.map +1 -1
- package/lib/pdf-tickets/print-webservice.d.ts +7 -0
- package/lib/pdf-tickets/print-webservice.d.ts.map +1 -0
- package/lib/pdf-tickets/print-webservice.js +31 -0
- package/lib/pdf-tickets/print-webservice.js.map +1 -0
- package/lib/template-registry.d.ts +2 -2
- package/lib/template-registry.d.ts.map +1 -1
- package/package.json +9 -9
- package/readme.md +1 -1
- package/src/fastify.ts +2 -2
- package/src/magic-key.ts +4 -4
- package/src/mobile-tickets/apple-handler-express.ts +56 -33
- package/src/mobile-tickets/apple-handler-fastify.ts +63 -42
- package/src/mobile-tickets/apple-wallet.ts +2 -2
- package/src/mobile-tickets/google-handler-express.ts +5 -1
- package/src/mobile-tickets/google-handler-fastify.ts +6 -1
- package/src/module.ts +3 -3
- package/src/template-registry.ts +2 -2
- package/tsconfig.json +2 -1
|
@@ -45,7 +45,7 @@ const appleWalletHandler: RouteHandlerMethod = async (
|
|
|
45
45
|
|
|
46
46
|
const { hash } = req.query as Record<string, string>;
|
|
47
47
|
const correctHash = await modules.warehousing.buildAccessKeyForToken(tokenId);
|
|
48
|
-
if (hash !== correctHash) {
|
|
48
|
+
if (!hash || hash !== correctHash) {
|
|
49
49
|
logger.error('Token hash invalid for current owner', { tokenId });
|
|
50
50
|
reply.status(403);
|
|
51
51
|
return reply.send({
|
|
@@ -61,6 +61,15 @@ const appleWalletHandler: RouteHandlerMethod = async (
|
|
|
61
61
|
const signedUrl = await fileUploadAdapter.createDownloadURL(passFile);
|
|
62
62
|
const url = signedUrl && (await modules.files.normalizeUrl(signedUrl, {}));
|
|
63
63
|
|
|
64
|
+
if (!url) {
|
|
65
|
+
reply.status(500);
|
|
66
|
+
return reply.send({
|
|
67
|
+
success: false,
|
|
68
|
+
message: 'Could not create download URL',
|
|
69
|
+
name: 'URL_SIGNING_FAILED',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
64
73
|
const response = await fetch(url);
|
|
65
74
|
const data = await response.arrayBuffer();
|
|
66
75
|
const uint8View = new Uint8Array(data);
|
|
@@ -93,7 +102,7 @@ const appleWalletHandler: RouteHandlerMethod = async (
|
|
|
93
102
|
if (
|
|
94
103
|
!isAuthenticationTokenCorrect(
|
|
95
104
|
req,
|
|
96
|
-
(pass.meta
|
|
105
|
+
(pass.meta?.rawData as any)?._id || (pass.meta?.rawData as any)?.tokenId,
|
|
97
106
|
)
|
|
98
107
|
) {
|
|
99
108
|
logger.error('Unauthorized', { passTypeIdentifier, serialNumber });
|
|
@@ -135,7 +144,7 @@ const appleWalletHandler: RouteHandlerMethod = async (
|
|
|
135
144
|
deviceLibraryIdentifier,
|
|
136
145
|
passesUpdatedSince,
|
|
137
146
|
);
|
|
138
|
-
const serialNumbers = passes.map((t) => t.meta
|
|
147
|
+
const serialNumbers = passes.map((t) => t.meta?.serialNumber).filter(Boolean) as string[];
|
|
139
148
|
|
|
140
149
|
if (serialNumbers?.length) {
|
|
141
150
|
reply.status(200);
|
|
@@ -158,7 +167,7 @@ const appleWalletHandler: RouteHandlerMethod = async (
|
|
|
158
167
|
if (
|
|
159
168
|
!isAuthenticationTokenCorrect(
|
|
160
169
|
req,
|
|
161
|
-
(pass.meta
|
|
170
|
+
(pass.meta?.rawData as any)?._id || (pass.meta?.rawData as any)?.tokenId,
|
|
162
171
|
)
|
|
163
172
|
) {
|
|
164
173
|
logger.error('Unauthorized', { passTypeIdentifier, serialNumber });
|
|
@@ -202,52 +211,64 @@ const appleWalletHandler: RouteHandlerMethod = async (
|
|
|
202
211
|
|
|
203
212
|
const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
|
|
204
213
|
|
|
205
|
-
if (pass) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
(pass.meta.rawData as any)._id || (pass.meta.rawData as any).tokenId,
|
|
210
|
-
)
|
|
211
|
-
) {
|
|
212
|
-
logger.error('Unauthorized', { passTypeIdentifier, serialNumber });
|
|
213
|
-
reply.status(401);
|
|
214
|
-
return reply.send({
|
|
215
|
-
success: false,
|
|
216
|
-
message: 'Unauthorized',
|
|
217
|
-
name: 'UNAUTHORIZED',
|
|
218
|
-
});
|
|
219
|
-
}
|
|
214
|
+
if (!pass) {
|
|
215
|
+
reply.status(404);
|
|
216
|
+
return reply.send();
|
|
217
|
+
}
|
|
220
218
|
|
|
221
|
-
|
|
219
|
+
if (
|
|
220
|
+
!isAuthenticationTokenCorrect(
|
|
221
|
+
req,
|
|
222
|
+
(pass.meta?.rawData as any)?._id || (pass.meta?.rawData as any)?.tokenId,
|
|
223
|
+
)
|
|
224
|
+
) {
|
|
225
|
+
logger.error('Unauthorized', { passTypeIdentifier, serialNumber });
|
|
226
|
+
reply.status(401);
|
|
227
|
+
return reply.send({
|
|
228
|
+
success: false,
|
|
229
|
+
message: 'Unauthorized',
|
|
230
|
+
name: 'UNAUTHORIZED',
|
|
231
|
+
});
|
|
232
|
+
}
|
|
222
233
|
|
|
223
|
-
|
|
224
|
-
lastModifiedDate.setMilliseconds(0);
|
|
234
|
+
const { updated, created } = pass;
|
|
225
235
|
|
|
226
|
-
|
|
227
|
-
|
|
236
|
+
const lastModifiedDate = new Date(updated || created);
|
|
237
|
+
lastModifiedDate.setMilliseconds(0);
|
|
228
238
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return reply.send({
|
|
232
|
-
success: true,
|
|
233
|
-
message: 'Not modified',
|
|
234
|
-
name: 'NOT_MODIFIED',
|
|
235
|
-
});
|
|
236
|
-
}
|
|
239
|
+
const ifModifiedSinceDate = new Date(req.headers['if-modified-since']!);
|
|
240
|
+
ifModifiedSinceDate.setMilliseconds(0);
|
|
237
241
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
242
|
+
if (ifModifiedSinceDate.getTime() >= lastModifiedDate.getTime()) {
|
|
243
|
+
reply.status(304);
|
|
244
|
+
return reply.send({
|
|
245
|
+
success: true,
|
|
246
|
+
message: 'Not modified',
|
|
247
|
+
name: 'NOT_MODIFIED',
|
|
248
|
+
});
|
|
249
|
+
}
|
|
241
250
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
251
|
+
const fileUploadAdapter = getFileAdapter();
|
|
252
|
+
const signedUrl = await fileUploadAdapter.createDownloadURL(pass);
|
|
253
|
+
const url = signedUrl && (await modules.files.normalizeUrl(signedUrl, {}));
|
|
245
254
|
|
|
246
|
-
|
|
247
|
-
reply.
|
|
248
|
-
reply.
|
|
249
|
-
|
|
255
|
+
if (!url) {
|
|
256
|
+
reply.status(500);
|
|
257
|
+
return reply.send({
|
|
258
|
+
success: false,
|
|
259
|
+
message: 'Could not create download URL',
|
|
260
|
+
name: 'URL_SIGNING_FAILED',
|
|
261
|
+
});
|
|
250
262
|
}
|
|
263
|
+
|
|
264
|
+
const result = await fetch(url);
|
|
265
|
+
const data = await result.arrayBuffer();
|
|
266
|
+
const uint8View = new Uint8Array(data);
|
|
267
|
+
|
|
268
|
+
reply.status(200);
|
|
269
|
+
reply.header('content-type', 'application/vnd.apple.pkpass');
|
|
270
|
+
reply.header('last-modified', lastModifiedDate.toUTCString());
|
|
271
|
+
return reply.send(uint8View);
|
|
251
272
|
}
|
|
252
273
|
}
|
|
253
274
|
|
|
@@ -14,7 +14,7 @@ export const pushToApplePushNotificationService = async (deviceTokens) => {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export const buildPassBinary = async (
|
|
17
|
-
|
|
17
|
+
tokenSerialNumber: string,
|
|
18
18
|
pass: {
|
|
19
19
|
serialNumber: string;
|
|
20
20
|
asBuffer: () => Promise<Buffer>;
|
|
@@ -23,7 +23,7 @@ export const buildPassBinary = async (
|
|
|
23
23
|
const passBuffer = await pass.asBuffer();
|
|
24
24
|
const rawFile = {
|
|
25
25
|
_id: pass.serialNumber,
|
|
26
|
-
filename: `${
|
|
26
|
+
filename: `${tokenSerialNumber}-${new Date().getTime()}.pkpass`,
|
|
27
27
|
createReadStream: () => Readable.from(passBuffer),
|
|
28
28
|
mimetype: 'application/vnd.apple.pkpass',
|
|
29
29
|
};
|
|
@@ -32,13 +32,17 @@ export const googleWalletHandler = async (
|
|
|
32
32
|
|
|
33
33
|
const { hash } = req.query;
|
|
34
34
|
const correctHash = await modules.warehousing.buildAccessKeyForToken(tokenId);
|
|
35
|
-
if (hash !== correctHash) {
|
|
35
|
+
if (!hash || hash !== correctHash) {
|
|
36
36
|
res.status(403).send('Token hash invalid for current owner');
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const pass = await modules.passes.upsertGoogleWalletPass(token, resolvedContext);
|
|
41
41
|
|
|
42
|
+
if (!pass) {
|
|
43
|
+
throw new Error('Could not create Google Wallet pass');
|
|
44
|
+
}
|
|
45
|
+
|
|
42
46
|
res.redirect(await pass.asURL());
|
|
43
47
|
return;
|
|
44
48
|
} catch (e) {
|
|
@@ -38,7 +38,7 @@ const googleWalletHandler: RouteHandlerMethod = async (
|
|
|
38
38
|
|
|
39
39
|
const { hash } = req.query as Record<string, string>;
|
|
40
40
|
const correctHash = await modules.warehousing.buildAccessKeyForToken(tokenId);
|
|
41
|
-
if (hash !== correctHash) {
|
|
41
|
+
if (!hash || hash !== correctHash) {
|
|
42
42
|
logger.error('Token hash invalid for current owner', { tokenId });
|
|
43
43
|
reply.status(403);
|
|
44
44
|
return reply.send({
|
|
@@ -49,6 +49,11 @@ const googleWalletHandler: RouteHandlerMethod = async (
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
const pass = await modules.passes.upsertGoogleWalletPass(token, resolvedContext);
|
|
52
|
+
|
|
53
|
+
if (!pass) {
|
|
54
|
+
throw new Error('Could not create Google Wallet pass');
|
|
55
|
+
}
|
|
56
|
+
|
|
52
57
|
return reply.redirect(await pass.asURL());
|
|
53
58
|
} catch (e) {
|
|
54
59
|
logger.error(e);
|
package/src/module.ts
CHANGED
|
@@ -37,7 +37,7 @@ const configurePasses = async ({ db }: ModuleInput<Record<string, never>>) => {
|
|
|
37
37
|
const pass = await createAppleWalletPass(token, unchainedAPI);
|
|
38
38
|
const rawFile = Promise.resolve(
|
|
39
39
|
// wrap in promise to make stream upload work
|
|
40
|
-
await buildPassBinary(token.
|
|
40
|
+
await buildPassBinary(token.tokenSerialNumber, pass as any),
|
|
41
41
|
);
|
|
42
42
|
|
|
43
43
|
const previousFile = await MediaObjects.findOne({
|
|
@@ -84,7 +84,7 @@ const configurePasses = async ({ db }: ModuleInput<Record<string, never>>) => {
|
|
|
84
84
|
return pass;
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
const findAppleWalletPass = async (passTypeIdentifier, serialNumber)
|
|
87
|
+
const findAppleWalletPass = async (passTypeIdentifier, serialNumber) => {
|
|
88
88
|
const mediaObject = await MediaObjects.findOne({
|
|
89
89
|
path: APPLE_WALLET_PASSES_FILE_DIRECTORY,
|
|
90
90
|
'meta.passTypeIdentifier': passTypeIdentifier,
|
|
@@ -172,7 +172,7 @@ const configurePasses = async ({ db }: ModuleInput<Record<string, never>>) => {
|
|
|
172
172
|
|
|
173
173
|
for (const pass of allPasses) {
|
|
174
174
|
// Check if binary is already invalidated, if so, skip
|
|
175
|
-
const rawData = pass.meta
|
|
175
|
+
const rawData = pass.meta?.rawData as TokenSurrogate;
|
|
176
176
|
if (rawData.invalidatedDate) continue;
|
|
177
177
|
|
|
178
178
|
const redeemedToken = allTokens.find((t) => t._id === rawData._id && t.invalidatedDate);
|
package/src/template-registry.ts
CHANGED
|
@@ -16,8 +16,8 @@ export type PassRenderer = (
|
|
|
16
16
|
token: TokenSurrogate,
|
|
17
17
|
context: UnchainedCore,
|
|
18
18
|
) => Promise<{
|
|
19
|
-
asURL
|
|
20
|
-
asBuffer
|
|
19
|
+
asURL: () => Promise<string>;
|
|
20
|
+
asBuffer: () => Promise<Buffer>;
|
|
21
21
|
serialNumber?: string;
|
|
22
22
|
passTypeIdentifier?: string;
|
|
23
23
|
}>;
|