@unchainedshop/ticketing 4.3.3 → 4.4.0

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.
Files changed (95) hide show
  1. package/README.md +168 -0
  2. package/lib/express.d.ts +0 -1
  3. package/lib/express.js +3 -4
  4. package/lib/fastify.d.ts +0 -1
  5. package/lib/fastify.js +3 -4
  6. package/lib/index.d.ts +6 -7
  7. package/lib/index.js +4 -5
  8. package/lib/magic-key.d.ts +0 -1
  9. package/lib/magic-key.js +0 -4
  10. package/lib/mobile-tickets/apple-handler-express.d.ts +1 -2
  11. package/lib/mobile-tickets/apple-handler-express.js +1 -8
  12. package/lib/mobile-tickets/apple-handler-fastify.d.ts +0 -1
  13. package/lib/mobile-tickets/apple-handler-fastify.js +1 -8
  14. package/lib/mobile-tickets/apple-wallet.d.ts +0 -1
  15. package/lib/mobile-tickets/apple-wallet.js +0 -1
  16. package/lib/mobile-tickets/google-handler-express.d.ts +1 -2
  17. package/lib/mobile-tickets/google-handler-express.js +0 -1
  18. package/lib/mobile-tickets/google-handler-fastify.d.ts +0 -1
  19. package/lib/mobile-tickets/google-handler-fastify.js +0 -1
  20. package/lib/module.d.ts +4 -5
  21. package/lib/module.js +3 -10
  22. package/lib/pdf-tickets/print-handler-express.d.ts +1 -2
  23. package/lib/pdf-tickets/print-handler-express.js +1 -2
  24. package/lib/pdf-tickets/print-handler-fastify.d.ts +0 -1
  25. package/lib/pdf-tickets/print-handler-fastify.js +1 -2
  26. package/lib/services.d.ts +2 -3
  27. package/lib/services.js +0 -1
  28. package/lib/template-registry.d.ts +10 -10
  29. package/lib/template-registry.js +5 -7
  30. package/lib/types.d.ts +3 -4
  31. package/lib/types.js +0 -1
  32. package/package.json +17 -15
  33. package/lib/express.d.ts.map +0 -1
  34. package/lib/express.js.map +0 -1
  35. package/lib/fastify.d.ts.map +0 -1
  36. package/lib/fastify.js.map +0 -1
  37. package/lib/index.d.ts.map +0 -1
  38. package/lib/index.js.map +0 -1
  39. package/lib/magic-key.d.ts.map +0 -1
  40. package/lib/magic-key.js.map +0 -1
  41. package/lib/mobile-tickets/apple-handler-express.d.ts.map +0 -1
  42. package/lib/mobile-tickets/apple-handler-express.js.map +0 -1
  43. package/lib/mobile-tickets/apple-handler-fastify.d.ts.map +0 -1
  44. package/lib/mobile-tickets/apple-handler-fastify.js.map +0 -1
  45. package/lib/mobile-tickets/apple-wallet.d.ts.map +0 -1
  46. package/lib/mobile-tickets/apple-wallet.js.map +0 -1
  47. package/lib/mobile-tickets/apple-webservice.d.ts +0 -7
  48. package/lib/mobile-tickets/apple-webservice.d.ts.map +0 -1
  49. package/lib/mobile-tickets/apple-webservice.js +0 -177
  50. package/lib/mobile-tickets/apple-webservice.js.map +0 -1
  51. package/lib/mobile-tickets/google-handler-express.d.ts.map +0 -1
  52. package/lib/mobile-tickets/google-handler-express.js.map +0 -1
  53. package/lib/mobile-tickets/google-handler-fastify.d.ts.map +0 -1
  54. package/lib/mobile-tickets/google-handler-fastify.js.map +0 -1
  55. package/lib/mobile-tickets/google-webservice.d.ts +0 -7
  56. package/lib/mobile-tickets/google-webservice.d.ts.map +0 -1
  57. package/lib/mobile-tickets/google-webservice.js +0 -52
  58. package/lib/mobile-tickets/google-webservice.js.map +0 -1
  59. package/lib/module.d.ts.map +0 -1
  60. package/lib/module.js.map +0 -1
  61. package/lib/pdf-tickets/print-handler-express.d.ts.map +0 -1
  62. package/lib/pdf-tickets/print-handler-express.js.map +0 -1
  63. package/lib/pdf-tickets/print-handler-fastify.d.ts.map +0 -1
  64. package/lib/pdf-tickets/print-handler-fastify.js.map +0 -1
  65. package/lib/pdf-tickets/print-webservice.d.ts +0 -7
  66. package/lib/pdf-tickets/print-webservice.d.ts.map +0 -1
  67. package/lib/pdf-tickets/print-webservice.js +0 -31
  68. package/lib/pdf-tickets/print-webservice.js.map +0 -1
  69. package/lib/services.d.ts.map +0 -1
  70. package/lib/services.js.map +0 -1
  71. package/lib/template-registry.d.ts.map +0 -1
  72. package/lib/template-registry.js.map +0 -1
  73. package/lib/ticketing-index.d.ts +0 -19
  74. package/lib/ticketing-index.d.ts.map +0 -1
  75. package/lib/ticketing-index.js +0 -40
  76. package/lib/ticketing-index.js.map +0 -1
  77. package/lib/types.d.ts.map +0 -1
  78. package/lib/types.js.map +0 -1
  79. package/readme.md +0 -118
  80. package/src/express.ts +0 -35
  81. package/src/fastify.ts +0 -30
  82. package/src/index.ts +0 -66
  83. package/src/magic-key.ts +0 -43
  84. package/src/mobile-tickets/apple-handler-express.ts +0 -237
  85. package/src/mobile-tickets/apple-handler-fastify.ts +0 -279
  86. package/src/mobile-tickets/apple-wallet.ts +0 -31
  87. package/src/mobile-tickets/google-handler-express.ts +0 -57
  88. package/src/mobile-tickets/google-handler-fastify.ts +0 -69
  89. package/src/module.ts +0 -251
  90. package/src/pdf-tickets/print-handler-express.ts +0 -34
  91. package/src/pdf-tickets/print-handler-fastify.ts +0 -43
  92. package/src/services.ts +0 -35
  93. package/src/template-registry.ts +0 -48
  94. package/src/types.ts +0 -8
  95. package/tsconfig.json +0 -10
@@ -1 +0,0 @@
1
- {"version":3,"file":"ticketing-index.d.ts","sourceRoot":"","sources":["../src/ticketing-index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAoB,MAAM,wBAAwB,CAAC;AACzE,OAAO,gBAAgB,EAAE,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,iBAAiB,EAAE,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAErE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,CAAC;AAQnF,wBAAgB,eAAe,CAAC,EAAE,cAAc,EAAE,EAAE;IAAE,cAAc,EAAE,GAAG,CAAA;CAAE,QAE1E;AAED,wBAAgB,kBAAkB,CAAC,EACjC,sBAAsB,EACtB,qBAAqB,GACtB,EAAE;IACD,sBAAsB,EAAE,GAAG,CAAC;IAC5B,qBAAqB,EAAE,GAAG,CAAC;CAC5B,QAGA;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,YAAY,EAAE,YAAY,EAC1B,EACE,cAAwC,EACxC,qBAAqB,EACrB,sBAAsB,GACvB,EAAE;IACD,cAAc,CAAC,EAAE,GAAG,CAAC;IACrB,qBAAqB,EAAE,GAAG,CAAC;IAC3B,sBAAsB,EAAE,GAAG,CAAC;CAC7B,QA0BF"}
@@ -1,40 +0,0 @@
1
- import { subscribe } from '@unchainedshop/events';
2
- import { WorkerEventTypes } from '@unchainedshop/core-worker';
3
- import { RendererTypes, registerRenderer } from './template-registry.js';
4
- import ticketingModules from './module.js';
5
- import setupMagicKey from './magic-key.js';
6
- import ticketingServices from './services.js';
7
- export { ticketingServices, ticketingModules };
8
- const defaultOrderPDFRenderer = async ({ orderId }, context) => {
9
- const order = await context.modules.orders.findOrder({ orderId });
10
- console.log(order);
11
- return;
12
- };
13
- export function setupPDFTickets({ renderOrderPDF }) {
14
- registerRenderer(RendererTypes.ORDER_PDF, renderOrderPDF);
15
- }
16
- export function setupMobileTickets({ createGoogleWalletPass, createAppleWalletPass, }) {
17
- registerRenderer(RendererTypes.GOOGLE_WALLET, createGoogleWalletPass);
18
- registerRenderer(RendererTypes.APPLE_WALLET, createAppleWalletPass);
19
- }
20
- export default function setupTicketing(unchainedAPI, { renderOrderPDF = defaultOrderPDFRenderer, createAppleWalletPass, createGoogleWalletPass, }) {
21
- setupPDFTickets({
22
- renderOrderPDF,
23
- });
24
- setupMobileTickets({
25
- createAppleWalletPass,
26
- createGoogleWalletPass,
27
- });
28
- if (!process.env.UNCHAINED_SECRET)
29
- throw new Error('Unchained Ticketing needs the UNCHAINED_SECRET environment variable to be set in order to allow magic key access to orders and tokens.');
30
- setupMagicKey();
31
- subscribe('TOKEN_INVALIDATED', async () => {
32
- await unchainedAPI.modules.passes.invalidateAppleWalletPasses(unchainedAPI);
33
- });
34
- subscribe(WorkerEventTypes.FINISHED, async ({ payload: work }) => {
35
- if ((work.type === 'EXPORT_TOKEN' || work.type === 'UPDATE_TOKEN_OWNERSHIP') && work.success) {
36
- await unchainedAPI.modules.passes.invalidateAppleWalletPasses(unchainedAPI);
37
- }
38
- });
39
- }
40
- //# sourceMappingURL=ticketing-index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ticketing-index.js","sourceRoot":"","sources":["../src/ticketing-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAQ,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,gBAAqC,MAAM,aAAa,CAAC;AAGhE,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,iBAAwC,MAAM,eAAe,CAAC;AAIrE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAsC,CAAC;AACnF,MAAM,uBAAuB,GAAG,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,OAAqB,EAAE,EAAE;IAC3E,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEnB,OAAO;AACT,CAAC,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,EAAE,cAAc,EAA2B;IACzE,gBAAgB,CAAC,aAAa,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,EACjC,sBAAsB,EACtB,qBAAqB,GAItB;IACC,gBAAgB,CAAC,aAAa,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC;IACtE,gBAAgB,CAAC,aAAa,CAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,YAA0B,EAC1B,EACE,cAAc,GAAG,uBAAuB,EACxC,qBAAqB,EACrB,sBAAsB,GAKvB;IAED,eAAe,CAAC;QACd,cAAc;KACf,CAAC,CAAC;IACH,kBAAkB,CAAC;QACjB,qBAAqB;QACrB,sBAAsB;KACvB,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC/B,MAAM,IAAI,KAAK,CACb,wIAAwI,CACzI,CAAC;IAEJ,aAAa,EAAE,CAAC;IAEhB,SAAS,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,YAAY,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAwB,EAAE,EAAE;QACrF,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,IAAI,KAAK,wBAAwB,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7F,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,YAAY,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG;IACzC,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,iBAAiB,CAAC;CAC7B,CAAC"}
package/lib/types.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/readme.md DELETED
@@ -1,118 +0,0 @@
1
- # Unchained Ticketing Extension
2
-
3
- ## Prepare Apple Certificate
4
-
5
- 1. Add a new Pass Type ID on [developer.apple.com](https://developer.apple.com/account), then gernerate fresh production certificate. Download the Certificate and import it into your Keychain.
6
-
7
- 2. Export with Keychain: Select the "Certificates" Tab, then the Pass Type ID, then select both the ID and the key, export in p12 format.
8
-
9
- 3. Convert to PEM
10
- It's important you set a PEM passphrase as it is required for Unchained Ticketing
11
- ```
12
- openssl pkcs12 -in Zertifikate.p12 -legacy -clcerts -out cert_and_key.pem
13
- ```
14
-
15
- 4. Configure the path and your Team ID by Env:
16
-
17
- ```
18
- PASS_CERTIFICATE_PATH=./cert_and_key.pem
19
- PASS_CERTIFICATE_SECRET=YOUR_PEM_PASSPHRASE
20
- PASS_TEAM_ID=SSCB95CV6U
21
- ```
22
-
23
- ## Setup Example
24
-
25
- boot.js:
26
- ```js
27
- import { modules, setupTicketing } from "@unchainedshop/ticketing";
28
- import { connect } from '@unchainedshop/api/express/index.js';
29
-
30
- ...
31
- const app = express();
32
-
33
- const httpServer = http.createServer(app);
34
-
35
- const engine = await startPlatform({
36
- modules,
37
- options: {},
38
- });
39
-
40
- connect(app, engine, { corsOrigins: [] });
41
-
42
- // Unchained Ticketing Extension
43
- setupTicketing(app, engine.unchainedAPI as TicketingAPI, {
44
- renderOrderPDF,
45
- createAppleWalletPass,
46
- createGoogleWalletPass,
47
- });
48
- ...
49
- ```
50
-
51
-
52
- renderOrderPDF.ts:
53
- ```tsx
54
- import React from "react";
55
- import ReactPDF, { Document } from "@react-pdf/renderer";
56
-
57
- const TicketTemplate = ({ tickets }: { tickets: Array<any> }) => {
58
- return (
59
- <Document>
60
- Hello World
61
- </Document>
62
- );
63
- };
64
-
65
- export default async (
66
- { orderId, variant }: { orderId: string },
67
- { modules },
68
- ) => {
69
- const order = await modules.orders.findOrder({ orderId });
70
- ...
71
- const pdfStream = await ReactPDF.renderToStream(
72
- <TicketTemplate tickets={tickets} />,
73
- );
74
- return pdfStream;
75
- };
76
- ```
77
-
78
- createAppleWalletPass.ts:
79
- ```ts
80
- import { UnchainedCore } from "@unchainedshop/core";
81
- import { Template, constants } from "@walletpass/pass-js";
82
-
83
- export default async (token, unchainedAPI: UnchainedCore) => {
84
- const template = new Template(
85
- "eventTicket",
86
- ...
87
- );
88
- const pass = await template.createPass(...);
89
- return pass;
90
- };
91
- ```
92
-
93
- createGoogleWalletPass.ts:
94
- ```ts
95
- import { UnchainedCore } from "@unchainedshop/core";
96
- import { google } from "googleapis";
97
- import jwt from "jsonwebtoken";
98
-
99
- export default async (token, unchainedAPI: UnchainedCore) => {
100
-
101
- const product = ...;
102
-
103
- // upsert class
104
-
105
- // upsert object
106
-
107
- const asURL = async () =>
108
- createJwtNewObjects(issuerId, product._id, token.tokenSerialNumber);
109
-
110
- return { asURL };
111
- };
112
- ```
113
-
114
- ## Magic Key Order Access
115
-
116
- Sometimes it's handy for users to allow them to access their orders and their tickets without actually logging in. For this you can generate a "magic key" that allows access to a single order and it's tickets via a request http header called `x-magic-key`.
117
-
118
- For example: To retrieve the magic-key when sending an order-confirmation e-mail, just call `await modules.passes.buildMagicKey(orderId);` and append it to an URL like https://my-shop/:orderId?otp=:magicKey and then in the storefront, use the magic key and send it along via x-magic-key http header when using queries that are guarded by the actions `viewOrder`, `updateToken` and `viewToken`
package/src/express.ts DELETED
@@ -1,35 +0,0 @@
1
- import express from 'express';
2
- import appleWalletHandler from './mobile-tickets/apple-handler-express.js';
3
- import googleWalletHandler from './mobile-tickets/google-handler-express.js';
4
- import printTicketsHandler from './pdf-tickets/print-handler-express.js';
5
-
6
- export default (app: express.Express) => {
7
- const {
8
- APPLE_WALLET_WEBSERVICE_PATH = '/rest/apple-wallet',
9
- GOOGLE_WALLET_WEBSERVICE_PATH = '/rest/google-wallet',
10
- UNCHAINED_PDF_PRINT_HANDLER_PATH = '/rest/print_tickets',
11
- } = process.env;
12
-
13
- app.use(
14
- UNCHAINED_PDF_PRINT_HANDLER_PATH,
15
- express.json({
16
- type: 'application/json',
17
- }),
18
- printTicketsHandler,
19
- );
20
- app.use(
21
- APPLE_WALLET_WEBSERVICE_PATH,
22
- express.json({
23
- type: 'application/json',
24
- }),
25
- appleWalletHandler,
26
- );
27
-
28
- app.use(
29
- `${GOOGLE_WALLET_WEBSERVICE_PATH}/download/:tokenId`,
30
- express.json({
31
- type: 'application/json',
32
- }),
33
- googleWalletHandler,
34
- );
35
- };
package/src/fastify.ts DELETED
@@ -1,30 +0,0 @@
1
- import type { FastifyInstance } from 'fastify';
2
- import appleWalletHandler from './mobile-tickets/apple-handler-fastify.js';
3
- import googleWalletHandler from './mobile-tickets/google-handler-fastify.js';
4
- import printTicketsHandler from './pdf-tickets/print-handler-fastify.js';
5
-
6
- export default (app: FastifyInstance) => {
7
- const {
8
- APPLE_WALLET_WEBSERVICE_PATH = '/rest/apple-wallet',
9
- GOOGLE_WALLET_WEBSERVICE_PATH = '/rest/google-wallet',
10
- UNCHAINED_PDF_PRINT_HANDLER_PATH = '/rest/print_tickets',
11
- } = process.env;
12
-
13
- app.route({
14
- url: `${APPLE_WALLET_WEBSERVICE_PATH}*`,
15
- method: ['GET', 'POST', 'DELETE'],
16
- handler: appleWalletHandler,
17
- });
18
-
19
- app.route({
20
- url: `${GOOGLE_WALLET_WEBSERVICE_PATH}/download/:tokenId`,
21
- method: 'GET',
22
- handler: googleWalletHandler,
23
- });
24
-
25
- app.route({
26
- url: `${UNCHAINED_PDF_PRINT_HANDLER_PATH}/*`,
27
- method: 'GET',
28
- handler: printTicketsHandler,
29
- });
30
- };
package/src/index.ts DELETED
@@ -1,66 +0,0 @@
1
- import { subscribe } from '@unchainedshop/events';
2
- import { RawPayloadType } from '@unchainedshop/events';
3
- import { WorkerEventTypes, Work } from '@unchainedshop/core-worker';
4
- import { RendererTypes, registerRenderer } from './template-registry.js';
5
- import ticketingModules, { TicketingModule } from './module.js';
6
-
7
- import { TicketingAPI } from './types.js';
8
- import setupMagicKey from './magic-key.js';
9
- import ticketingServices, { TicketingServices } from './services.js';
10
-
11
- export type { TicketingAPI, RendererTypes };
12
-
13
- export { ticketingServices, ticketingModules, TicketingModule, TicketingServices };
14
-
15
- export function setupPDFTickets({ renderOrderPDF }: { renderOrderPDF: any }) {
16
- registerRenderer(RendererTypes.ORDER_PDF, renderOrderPDF);
17
- }
18
-
19
- export function setupMobileTickets({
20
- createGoogleWalletPass,
21
- createAppleWalletPass,
22
- }: {
23
- createGoogleWalletPass: any;
24
- createAppleWalletPass: any;
25
- }) {
26
- registerRenderer(RendererTypes.GOOGLE_WALLET, createGoogleWalletPass);
27
- registerRenderer(RendererTypes.APPLE_WALLET, createAppleWalletPass);
28
- }
29
-
30
- export default function setupTicketing(
31
- unchainedAPI: TicketingAPI,
32
- {
33
- renderOrderPDF,
34
- createAppleWalletPass,
35
- createGoogleWalletPass,
36
- }: {
37
- renderOrderPDF: any;
38
- createAppleWalletPass: any;
39
- createGoogleWalletPass: any;
40
- },
41
- ) {
42
- setupPDFTickets({
43
- renderOrderPDF,
44
- });
45
- setupMobileTickets({
46
- createAppleWalletPass,
47
- createGoogleWalletPass,
48
- });
49
-
50
- if (!process.env.UNCHAINED_SECRET)
51
- throw new Error(
52
- 'Unchained Ticketing needs the UNCHAINED_SECRET environment variable to be set in order to allow magic key access to orders and tokens.',
53
- );
54
-
55
- setupMagicKey();
56
-
57
- subscribe('TOKEN_INVALIDATED', async () => {
58
- await unchainedAPI.modules.passes.invalidateAppleWalletPasses(unchainedAPI);
59
- });
60
-
61
- subscribe(WorkerEventTypes.FINISHED, async ({ payload: work }: RawPayloadType<Work>) => {
62
- if ((work.type === 'EXPORT_TOKEN' || work.type === 'UPDATE_TOKEN_OWNERSHIP') && work.success) {
63
- await unchainedAPI.modules.passes.invalidateAppleWalletPasses(unchainedAPI);
64
- }
65
- });
66
- }
package/src/magic-key.ts DELETED
@@ -1,43 +0,0 @@
1
- import { Context } from '@unchainedshop/api';
2
- import { roles } from '@unchainedshop/api';
3
- import { TicketingAPI } from './types.js';
4
-
5
- const isMagicKeyValidForOrder = async (
6
- obj: any,
7
- { orderId }: { orderId: string },
8
- { modules, getHeader }: Context & TicketingAPI,
9
- ) => {
10
- const order = await modules.orders.findOrder({ orderId });
11
- // always return true if orderId leads to nothing to show potentially allowed actions
12
- if (!order) return true;
13
-
14
- const magicKey = await modules.passes.buildMagicKey(order._id);
15
- return magicKey === getHeader('x-magic-key');
16
- };
17
-
18
- const isMagicKeyValidForToken = async (
19
- root: any,
20
- params: { tokenId: string } | null,
21
- { modules, getHeader }: Context & TicketingAPI,
22
- ) => {
23
- const tokenId = params?.tokenId || (root && 'tokenSerialNumber' in root && root._id) || null;
24
-
25
- const token = await modules.warehousing.findToken({ tokenId });
26
- // always return true if tokenId leads to nothing to show potentially allowed actions
27
- if (!token) return true;
28
-
29
- const order = await modules.orders.findOrder({ orderId: token.meta.orderId });
30
- if (!order) return false;
31
-
32
- // Restrict access if token does not belong to the original user anymore (for ex. web3 owned)
33
- if (order.userId !== token.userId) return false;
34
-
35
- const magicKey = await modules.passes.buildMagicKey(order._id);
36
- return magicKey === getHeader('x-magic-key');
37
- };
38
-
39
- export default () => {
40
- roles.allRoles?.ALL?.allow(roles.actions.viewOrder, isMagicKeyValidForOrder);
41
- roles.allRoles?.ALL?.allow(roles.actions.viewToken, isMagicKeyValidForToken);
42
- roles.allRoles?.ALL?.allow(roles.actions.updateToken, isMagicKeyValidForToken);
43
- };
@@ -1,237 +0,0 @@
1
- import { createLogger } from '@unchainedshop/logger';
2
- import type { Request, Response } from 'express';
3
- import { TicketingAPI } from '../types.js';
4
- import { getFileAdapter } from '@unchainedshop/core-files';
5
-
6
- const logger = createLogger('unchained:apple-wallet-webservice');
7
-
8
- const isAuthenticationTokenCorrect = (req, authenticationToken) => {
9
- const expectedAuthorizationValue = `ApplePass ${authenticationToken}`;
10
- return req.headers.authorization === expectedAuthorizationValue;
11
- };
12
-
13
- const appleWalletHandler = async (req: Request & { unchainedContext: TicketingAPI }, res: Response) => {
14
- const resolvedContext = req.unchainedContext;
15
- const { modules } = resolvedContext;
16
- logger.info(`${req.path} (${JSON.stringify(req.query)})`);
17
-
18
- if (req.path.startsWith('/download/')) {
19
- try {
20
- const [, , passFileName] = req.path.split('/');
21
- const [tokenId] = passFileName.split('.pkpass');
22
-
23
- if (!tokenId) {
24
- res.status(404).end();
25
- return;
26
- }
27
-
28
- const token = await modules.warehousing.findToken({
29
- tokenId,
30
- });
31
-
32
- if (!token) {
33
- res.status(404).send('Token not found');
34
- return;
35
- }
36
-
37
- const { hash } = req.query;
38
- const correctHash = await modules.warehousing.buildAccessKeyForToken(tokenId);
39
- if (!hash || hash !== correctHash) {
40
- res.status(403).send('Token hash invalid for current owner');
41
- return;
42
- }
43
-
44
- const passFile = await modules.passes.upsertAppleWalletPass(token, resolvedContext);
45
-
46
- const fileUploadAdapter = getFileAdapter();
47
- const signedUrl = await fileUploadAdapter.createDownloadURL(passFile);
48
- const url = signedUrl && (await modules.files.normalizeUrl(signedUrl, {}));
49
-
50
- if (!url) {
51
- res.status(500);
52
- res.send({
53
- success: false,
54
- message: 'Could not create download URL',
55
- name: 'URL_SIGNING_FAILED',
56
- });
57
- return;
58
- }
59
-
60
- const response = await fetch(url);
61
- const data = await response.arrayBuffer();
62
- const uint8View = new Uint8Array(data);
63
-
64
- res.status(200);
65
- res.setHeader('Content-Type', 'application/vnd.apple.pkpass');
66
- res.setHeader('Content-Disposition', `attachment; filename=${tokenId}.pkpass`);
67
- res.send(uint8View);
68
- return;
69
- } catch (e) {
70
- logger.error(e);
71
- }
72
- res.status(500).end();
73
- return;
74
- }
75
-
76
- const [, apiVersion, endpoint, ...pathComponents] = req.path.split("/"); /* eslint-disable-line */
77
- if (endpoint === 'devices') {
78
- if (req.method === 'POST') {
79
- // Register Device
80
- const [deviceLibraryIdentifier, , passTypeIdentifier, serialNumber] = pathComponents;
81
- const { pushToken } = req.body;
82
-
83
- const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
84
-
85
- if (pass) {
86
- if (
87
- !isAuthenticationTokenCorrect(
88
- req,
89
- (pass.meta?.rawData as any)?._id || (pass.meta?.rawData as any)?.tokenId,
90
- )
91
- ) {
92
- res.status(401).end();
93
- return;
94
- }
95
-
96
- const newRegistration = await modules.passes.registerDeviceForAppleWalletPass(
97
- passTypeIdentifier,
98
- serialNumber,
99
- {
100
- deviceLibraryIdentifier,
101
- pushToken,
102
- },
103
- );
104
-
105
- if (!newRegistration) {
106
- res.status(200).end();
107
- return;
108
- }
109
-
110
- res.status(201).end();
111
- return;
112
- }
113
- } else if (req.method === 'GET') {
114
- // Get the List of Updatable Passes
115
- const lastUpdated = new Date();
116
- const [deviceLibraryIdentifier, , passTypeIdentifier] = pathComponents;
117
- const passesUpdatedSince =
118
- req.query?.passesUpdatedSince && new Date(req.query.passesUpdatedSince as string);
119
-
120
- const passes = await modules.passes.findUpdatedAppleWalletPasses(
121
- passTypeIdentifier,
122
- deviceLibraryIdentifier,
123
- passesUpdatedSince,
124
- );
125
- const serialNumbers = passes.map((t) => t.meta?.serialNumber).filter(Boolean) as string[];
126
-
127
- if (serialNumbers?.length) {
128
- res.status(200).send({ serialNumbers, lastUpdated });
129
- return;
130
- }
131
-
132
- res.status(204).end();
133
- return;
134
- } else if (req.method === 'DELETE') {
135
- // Unregister Device
136
- const [deviceLibraryIdentifier, , passTypeIdentifier, serialNumber] = pathComponents;
137
-
138
- const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
139
-
140
- if (pass) {
141
- if (
142
- !isAuthenticationTokenCorrect(
143
- req,
144
- (pass.meta?.rawData as any)?._id || (pass.meta?.rawData as any)?.tokenId,
145
- )
146
- ) {
147
- res.status(401).end();
148
- return;
149
- }
150
-
151
- await modules.passes.unregisterDeviceForAppleWalletPass(
152
- passTypeIdentifier,
153
- serialNumber,
154
- deviceLibraryIdentifier,
155
- );
156
-
157
- // Unregistered
158
- res.status(200).end();
159
- return;
160
- }
161
- }
162
- } else if (endpoint === 'log') {
163
- // Log Mesage
164
- const { logs } = req.body;
165
- logs?.forEach((log) => {
166
- if (typeof log === 'string') {
167
- logger.info(log);
168
- }
169
- });
170
- res.status(200).end();
171
- return;
172
- } else if (endpoint === 'passes') {
173
- if (req.method === 'GET') {
174
- // Get an updated Pass
175
- const [passTypeIdentifier, serialNumber] = pathComponents;
176
-
177
- const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
178
-
179
- if (!pass) {
180
- res.status(404).end();
181
- return;
182
- }
183
-
184
- if (
185
- !isAuthenticationTokenCorrect(
186
- req,
187
- (pass.meta?.rawData as any)?._id || (pass.meta?.rawData as any)?.tokenId,
188
- )
189
- ) {
190
- res.status(401).end();
191
- return;
192
- }
193
-
194
- const { updated, created } = pass;
195
-
196
- const lastModifiedDate = new Date(updated || created);
197
- lastModifiedDate.setMilliseconds(0);
198
-
199
- const ifModifiedSinceDate = new Date(req.header('if-modified-since')!);
200
- ifModifiedSinceDate.setMilliseconds(0);
201
-
202
- if (ifModifiedSinceDate.getTime() >= lastModifiedDate.getTime()) {
203
- res.status(304).end();
204
- return;
205
- }
206
-
207
- const fileUploadAdapter = getFileAdapter();
208
- const signedUrl = await fileUploadAdapter.createDownloadURL(pass);
209
- const url = signedUrl && (await modules.files.normalizeUrl(signedUrl, {}));
210
-
211
- if (!url) {
212
- res.status(500);
213
- res.send({
214
- success: false,
215
- message: 'Could not create download URL',
216
- name: 'URL_SIGNING_FAILED',
217
- });
218
- return;
219
- }
220
-
221
- const result = await fetch(url);
222
- const data = await result.arrayBuffer();
223
- const uint8View = new Uint8Array(data);
224
-
225
- res.writeHead(200, {
226
- 'Content-Type': 'application/vnd.apple.pkpass',
227
- 'Last-Modified': lastModifiedDate.toUTCString(),
228
- });
229
- res.send(uint8View);
230
- return;
231
- }
232
- }
233
-
234
- res.status(404).end();
235
- };
236
-
237
- export default appleWalletHandler;