@shopware-ag/app-server-sdk 1.1.28 → 2.0.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.
- package/dist/commonjs/app.d.ts +8 -2
- package/dist/commonjs/app.d.ts.map +1 -1
- package/dist/commonjs/app.js +3 -0
- package/dist/commonjs/app.js.map +1 -1
- package/dist/commonjs/context-resolver.d.ts.map +1 -1
- package/dist/commonjs/context-resolver.js +2 -8
- package/dist/commonjs/context-resolver.js.map +1 -1
- package/dist/commonjs/dual-signature-verifier.d.ts +31 -0
- package/dist/commonjs/dual-signature-verifier.d.ts.map +1 -0
- package/dist/commonjs/dual-signature-verifier.js +136 -0
- package/dist/commonjs/dual-signature-verifier.js.map +1 -0
- package/dist/commonjs/integration/better-sqlite3.d.ts.map +1 -1
- package/dist/commonjs/integration/better-sqlite3.js +35 -11
- package/dist/commonjs/integration/better-sqlite3.js.map +1 -1
- package/dist/commonjs/integration/bun-sqlite.d.ts.map +1 -1
- package/dist/commonjs/integration/bun-sqlite.js +40 -10
- package/dist/commonjs/integration/bun-sqlite.js.map +1 -1
- package/dist/commonjs/integration/cloudflare-kv.d.ts.map +1 -1
- package/dist/commonjs/integration/cloudflare-kv.js +24 -1
- package/dist/commonjs/integration/cloudflare-kv.js.map +1 -1
- package/dist/commonjs/integration/deno-kv.d.ts.map +1 -1
- package/dist/commonjs/integration/deno-kv.js +18 -0
- package/dist/commonjs/integration/deno-kv.js.map +1 -1
- package/dist/commonjs/integration/dynamodb.d.ts.map +1 -1
- package/dist/commonjs/integration/dynamodb.js +31 -1
- package/dist/commonjs/integration/dynamodb.js.map +1 -1
- package/dist/commonjs/integration/hono.d.ts +6 -0
- package/dist/commonjs/integration/hono.d.ts.map +1 -1
- package/dist/commonjs/integration/hono.js +1 -0
- package/dist/commonjs/integration/hono.js.map +1 -1
- package/dist/commonjs/mod.d.ts +2 -0
- package/dist/commonjs/mod.d.ts.map +1 -1
- package/dist/commonjs/mod.js +3 -1
- package/dist/commonjs/mod.js.map +1 -1
- package/dist/commonjs/registration.d.ts +4 -0
- package/dist/commonjs/registration.d.ts.map +1 -1
- package/dist/commonjs/registration.js +55 -11
- package/dist/commonjs/registration.js.map +1 -1
- package/dist/commonjs/repository.d.ts +53 -1
- package/dist/commonjs/repository.d.ts.map +1 -1
- package/dist/commonjs/repository.js +64 -1
- package/dist/commonjs/repository.js.map +1 -1
- package/dist/esm/app.d.ts +8 -2
- package/dist/esm/app.d.ts.map +1 -1
- package/dist/esm/app.js +3 -0
- package/dist/esm/app.js.map +1 -1
- package/dist/esm/context-resolver.d.ts.map +1 -1
- package/dist/esm/context-resolver.js +2 -8
- package/dist/esm/context-resolver.js.map +1 -1
- package/dist/esm/dual-signature-verifier.d.ts +31 -0
- package/dist/esm/dual-signature-verifier.d.ts.map +1 -0
- package/dist/esm/dual-signature-verifier.js +132 -0
- package/dist/esm/dual-signature-verifier.js.map +1 -0
- package/dist/esm/integration/better-sqlite3.d.ts.map +1 -1
- package/dist/esm/integration/better-sqlite3.js +35 -11
- package/dist/esm/integration/better-sqlite3.js.map +1 -1
- package/dist/esm/integration/bun-sqlite.d.ts.map +1 -1
- package/dist/esm/integration/bun-sqlite.js +40 -10
- package/dist/esm/integration/bun-sqlite.js.map +1 -1
- package/dist/esm/integration/cloudflare-kv.d.ts.map +1 -1
- package/dist/esm/integration/cloudflare-kv.js +24 -1
- package/dist/esm/integration/cloudflare-kv.js.map +1 -1
- package/dist/esm/integration/deno-kv.d.ts.map +1 -1
- package/dist/esm/integration/deno-kv.js +18 -0
- package/dist/esm/integration/deno-kv.js.map +1 -1
- package/dist/esm/integration/dynamodb.d.ts.map +1 -1
- package/dist/esm/integration/dynamodb.js +31 -1
- package/dist/esm/integration/dynamodb.js.map +1 -1
- package/dist/esm/integration/hono.d.ts +6 -0
- package/dist/esm/integration/hono.d.ts.map +1 -1
- package/dist/esm/integration/hono.js +1 -0
- package/dist/esm/integration/hono.js.map +1 -1
- package/dist/esm/mod.d.ts +2 -0
- package/dist/esm/mod.d.ts.map +1 -1
- package/dist/esm/mod.js +1 -0
- package/dist/esm/mod.js.map +1 -1
- package/dist/esm/registration.d.ts +4 -0
- package/dist/esm/registration.d.ts.map +1 -1
- package/dist/esm/registration.js +55 -11
- package/dist/esm/registration.js.map +1 -1
- package/dist/esm/repository.d.ts +53 -1
- package/dist/esm/repository.d.ts.map +1 -1
- package/dist/esm/repository.js +64 -1
- package/dist/esm/repository.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/registration.js
CHANGED
|
@@ -18,21 +18,39 @@ export class Registration {
|
|
|
18
18
|
}
|
|
19
19
|
const shopId = url.searchParams.get("shop-id");
|
|
20
20
|
const shopUrl = url.searchParams.get("shop-url");
|
|
21
|
-
const
|
|
21
|
+
const sanitizedShopUrl = shopUrl
|
|
22
|
+
.replace(/([^:])(\/\/+)/g, "$1/")
|
|
23
|
+
.replace(/\/+$/, "");
|
|
22
24
|
const beforeRegistrationEvent = new BeforeRegistrationEvent(req, shopId, shopUrl);
|
|
23
25
|
this.app.hooks.publish('onBeforeRegistrationEvent', beforeRegistrationEvent);
|
|
24
26
|
if (beforeRegistrationEvent.reason) {
|
|
25
27
|
return new InvalidRequestResponse(beforeRegistrationEvent.reason, 400);
|
|
26
28
|
}
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
+
const shop = await this.app.repository.getShopById(shopId);
|
|
30
|
+
try {
|
|
31
|
+
await this.app.requestVerifier.authenticateRegistrationRequest(req, {
|
|
32
|
+
appSecret: this.app.cfg.appSecret,
|
|
33
|
+
enforceDoubleSignature: this.app.cfg.enforceDoubleSignature ?? false,
|
|
34
|
+
}, shop);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
29
37
|
return new InvalidRequestResponse("Cannot validate app signature");
|
|
30
38
|
}
|
|
31
39
|
const shopSecret = randomString();
|
|
32
|
-
|
|
33
|
-
.
|
|
34
|
-
.
|
|
35
|
-
|
|
40
|
+
if (shop === null) {
|
|
41
|
+
await this.app.repository.createShop(shopId, sanitizedShopUrl, shopSecret);
|
|
42
|
+
const shop = (await this.app.repository.getShopById(shopId));
|
|
43
|
+
shop.setPendingShopSecret(shopSecret);
|
|
44
|
+
shop.setPendingShopUrl(sanitizedShopUrl);
|
|
45
|
+
this.setVerifiedWithDoubleSignature(shop, req);
|
|
46
|
+
await this.app.repository.updateShop(shop);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
shop.setPendingShopSecret(shopSecret);
|
|
50
|
+
shop.setPendingShopUrl(sanitizedShopUrl);
|
|
51
|
+
this.setVerifiedWithDoubleSignature(shop, req);
|
|
52
|
+
await this.app.repository.updateShop(shop);
|
|
53
|
+
}
|
|
36
54
|
return new Response(JSON.stringify({
|
|
37
55
|
proof: await this.app.signer.sign(shopId + shopUrl + this.app.cfg.appName, this.app.cfg.appSecret),
|
|
38
56
|
secret: shopSecret,
|
|
@@ -60,12 +78,29 @@ export class Registration {
|
|
|
60
78
|
if (shop === null) {
|
|
61
79
|
return new InvalidRequestResponse("Invalid shop given");
|
|
62
80
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
try {
|
|
82
|
+
await this.app.requestVerifier.authenticateRegistrationConfirmation(req, bodyContent, shop, {
|
|
83
|
+
appSecret: this.app.cfg.appSecret,
|
|
84
|
+
enforceDoubleSignature: this.app.cfg.enforceDoubleSignature ?? false,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
67
88
|
return new InvalidRequestResponse("Cannot validate app signature");
|
|
68
89
|
}
|
|
90
|
+
const pendingSecret = shop.getPendingShopSecret();
|
|
91
|
+
const pendingUrl = shop.getPendingShopUrl();
|
|
92
|
+
if (pendingSecret === null || pendingUrl === null) {
|
|
93
|
+
return new InvalidRequestResponse("Invalid Request", 400);
|
|
94
|
+
}
|
|
95
|
+
const previousSecret = shop.getShopSecret();
|
|
96
|
+
if (pendingSecret !== previousSecret) {
|
|
97
|
+
shop.setPreviousShopSecret(previousSecret);
|
|
98
|
+
shop.setShopSecret(pendingSecret);
|
|
99
|
+
shop.setSecretsRotatedAt(new Date());
|
|
100
|
+
}
|
|
101
|
+
shop.setPendingShopSecret(null);
|
|
102
|
+
shop.setShopUrl(pendingUrl);
|
|
103
|
+
shop.setPendingShopUrl(null);
|
|
69
104
|
shop.setShopCredentials(body.apiKey, body.secretKey);
|
|
70
105
|
const event = new ShopAuthorizeEvent(req, shop);
|
|
71
106
|
await this.app.hooks.publish("onAuthorize", event);
|
|
@@ -73,6 +108,7 @@ export class Registration {
|
|
|
73
108
|
await this.app.repository.deleteShop(shop.getShopId());
|
|
74
109
|
return new InvalidRequestResponse(event.reason, 403);
|
|
75
110
|
}
|
|
111
|
+
shop.setRegistrationConfirmed();
|
|
76
112
|
await this.app.repository.updateShop(shop);
|
|
77
113
|
return new Response(null, { status: 204 });
|
|
78
114
|
}
|
|
@@ -148,6 +184,14 @@ export class Registration {
|
|
|
148
184
|
}
|
|
149
185
|
return new Response(null, { status: 204 });
|
|
150
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
189
|
+
*/
|
|
190
|
+
setVerifiedWithDoubleSignature(shop, req) {
|
|
191
|
+
if (this.app.cfg.enforceDoubleSignature || req.headers.has('shopware-shop-signature')) {
|
|
192
|
+
shop.setVerifiedWithDoubleSignature();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
151
195
|
}
|
|
152
196
|
export function randomString(length = 120) {
|
|
153
197
|
let result = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registration.js","sourceRoot":"","sources":["../../src/registration.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppServer } from \"./app.js\";\nimport type { ShopInterface } from \"./repository.js\";\n\nexport class Registration<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(private app: AppServer<Shop>) {}\n\n\t/**\n\t * This method checks the request for the handshake with the Shopware Shop.\n\t * if it's valid a Shop will be created, and a proof will be responded with a confirmation url.\n\t * then the Shop will call the confirmation url, and this should be handled by the authorizeCallback method to finish the handshake.\n\t */\n\tpublic async authorize(req: Request): Promise<Response> {\n\t\tconst url = new URL(req.url);\n\n\t\tif (\n\t\t\t!url.searchParams.has(\"shop-url\") ||\n\t\t\t!req.headers.has(\"shopware-app-signature\") ||\n\t\t\t!url.searchParams.has(\"shop-id\") ||\n\t\t\t!url.searchParams.has(\"timestamp\")\n\t\t) {\n\t\t\treturn new InvalidRequestResponse(\"Invalid Request\", 400);\n\t\t}\n\n\t\tconst shopId = url.searchParams.get(\"shop-id\") as string;\n\t\tconst shopUrl = url.searchParams.get(\"shop-url\") as string;\n\t\tconst timestamp = url.searchParams.get(\"timestamp\") as string;\n\n\t\tconst beforeRegistrationEvent = new BeforeRegistrationEvent(req, shopId, shopUrl);\n\t\tthis.app.hooks.publish('onBeforeRegistrationEvent', beforeRegistrationEvent);\n\n\t\tif (beforeRegistrationEvent.reason) {\n\t\t\treturn new InvalidRequestResponse(beforeRegistrationEvent.reason, 400);\n\t\t}\n\n\t\tconst v = await this.app.signer.verify(\n\t\t\treq.headers.get(\"shopware-app-signature\") as string,\n\t\t\t`shop-id=${shopId}&shop-url=${shopUrl}×tamp=${timestamp}`,\n\t\t\tthis.app.cfg.appSecret,\n\t\t);\n\n\t\tif (!v) {\n\t\t\treturn new InvalidRequestResponse(\"Cannot validate app signature\");\n\t\t}\n\n\t\tconst shopSecret = randomString();\n\t\tconst sanitizedShopUrl = shopUrl\n\t\t\t.replace(/([^:])(\\/\\/+)/g, \"$1/\")\n\t\t\t.replace(/\\/+$/, \"\");\n\n\t\tawait this.app.repository.createShop(shopId, sanitizedShopUrl, shopSecret);\n\n\t\treturn new Response(\n\t\t\tJSON.stringify({\n\t\t\t\tproof: await this.app.signer.sign(\n\t\t\t\t\tshopId + shopUrl + this.app.cfg.appName,\n\t\t\t\t\tthis.app.cfg.appSecret,\n\t\t\t\t),\n\t\t\t\tsecret: shopSecret,\n\t\t\t\tconfirmation_url: this.app.cfg.authorizeCallbackUrl,\n\t\t\t}),\n\t\t\t{\n\t\t\t\theaders: {\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * This method is called by the Shopware Shop to confirm the handshake.\n\t * It will update the shop with the given oauth2 credentials.\n\t */\n\tpublic async authorizeCallback(req: Request): Promise<Response> {\n\t\tconst bodyContent = await req.text();\n\n\t\tconst body = JSON.parse(bodyContent);\n\n\t\tif (\n\t\t\ttypeof body.shopId !== \"string\" ||\n\t\t\ttypeof body.apiKey !== \"string\" ||\n\t\t\ttypeof body.secretKey !== \"string\" ||\n\t\t\t!req.headers.has(\"shopware-shop-signature\")\n\t\t) {\n\t\t\treturn new InvalidRequestResponse(\"Invalid Request\", 400);\n\t\t}\n\n\t\tconst shop = await this.app.repository.getShopById(body.shopId as string);\n\n\t\tif (shop === null) {\n\t\t\treturn new InvalidRequestResponse(\"Invalid shop given\");\n\t\t}\n\n\t\tconst v = await this.app.signer.verify(\n\t\t\treq.headers.get(\"shopware-shop-signature\") as string,\n\t\t\tbodyContent,\n\t\t\tshop.getShopSecret(),\n\t\t);\n\n\t\tif (!v) {\n\t\t\t// Shop has failed the verification. Delete it from our DB.\n\t\t\tawait this.app.repository.deleteShop(shop.getShopId());\n\n\t\t\treturn new InvalidRequestResponse(\"Cannot validate app signature\");\n\t\t}\n\n\t\tshop.setShopCredentials(body.apiKey, body.secretKey);\n\n\t\tconst event = new ShopAuthorizeEvent(req, shop);\n\t\tawait this.app.hooks.publish(\"onAuthorize\", event);\n\n\t\tif (event.reason) {\n\t\t\tawait this.app.repository.deleteShop(shop.getShopId());\n\n\t\t\treturn new InvalidRequestResponse(event.reason, 403);\n\t\t}\n\n\t\tawait this.app.repository.updateShop(shop);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware Shop to set the shop active.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appActivate\" url=\"http://localhost:3000/app/activate\" event=\"app.activated\"/>\n\t * </webhooks>\n\t */\n\tpublic async activate(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI(req);\n\n\t\tconst event = new AppActivateEvent(req, ctx.shop);\n\t\tawait this.app.hooks.publish(\"onAppActivate\", event);\n\n\t\tctx.shop.setShopActive(true);\n\n\t\tawait this.app.repository.updateShop(ctx.shop);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware when the app was installed.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appInstall\" url=\"http://localhost:3000/app/install\" event=\"app.installed\"/>\n\t * </webhooks>\n\t */\n\tpublic async install(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI<{\n\t\t\tdata: { payload: { appVersion: string } };\n\t\t}>(req);\n\n\t\tconst event = new AppInstallEvent(\n\t\t\treq,\n\t\t\tctx.shop,\n\t\t\tctx.payload?.data?.payload?.appVersion ?? null,\n\t\t);\n\t\tawait this.app.hooks.publish(\"onAppInstall\", event);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware Shop to set the shop in-active.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appDeactivated\" url=\"http://localhost:3000/app/deactivated\" event=\"app.deactivated\"/>\n\t * </webhooks>\n\t */\n\tpublic async deactivate(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI(req);\n\n\t\tconst event = new AppDeactivateEvent(req, ctx.shop);\n\t\tawait this.app.hooks.publish(\"onAppDeactivate\", event);\n\n\t\tctx.shop.setShopActive(false);\n\n\t\tawait this.app.repository.updateShop(ctx.shop);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware when the app was updated.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appUpdated\" url=\"http://localhost:3000/app/update\" event=\"app.updated\"/>\n\t * </webhooks>\n\t */\n\tpublic async update(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI<{\n\t\t\tdata: { payload: { appVersion: string } };\n\t\t}>(req);\n\n\t\tconst event = new AppUpdateEvent(\n\t\t\treq,\n\t\t\tctx.shop,\n\t\t\tctx.payload?.data?.payload?.appVersion ?? null,\n\t\t);\n\t\tawait this.app.hooks.publish(\"onAppUpdate\", event);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware Shop to delete the app.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appDelete\" url=\"http://localhost:3000/app/delete\" event=\"app.deleted\"/>\n\t * </webhooks>\n\t */\n\tpublic async delete(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI<{\n\t\t\tdata: { payload: { keepUserData?: boolean } };\n\t\t}>(req);\n\n\t\tconst event = new AppUninstallEvent(\n\t\t\treq,\n\t\t\tctx.shop,\n\t\t\tctx.payload?.data?.payload?.keepUserData ?? null,\n\t\t);\n\t\tawait this.app.hooks.publish(\"onAppUninstall\", event);\n\n\t\tif (event.keepUserData === false) {\n\t\t\tawait this.app.repository.deleteShop(ctx.shop.getShopId());\n\t\t}\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n}\n\nexport function randomString(length = 120) {\n\tlet result = \"\";\n\tconst characters =\n\t\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\tconst charactersLength = characters.length;\n\tfor (let i = 0; i < length; i++) {\n\t\tresult += characters.charAt(Math.floor(Math.random() * charactersLength));\n\t}\n\n\treturn result;\n}\n\nclass InvalidRequestResponse extends Response {\n\tconstructor(error: string, status = 401) {\n\t\tsuper(JSON.stringify({ error }), {\n\t\t\tstatus,\n\t\t\theaders: {\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t},\n\t\t});\n\t}\n}\n\nexport class ShopAuthorizeEvent<Shop extends ShopInterface = ShopInterface> {\n\tprivate reject: string | null = null;\n\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t) {}\n\n\tpublic rejectRegistration(reason: string) {\n\t\tthis.reject = reason;\n\t}\n\n\tpublic get reason() {\n\t\treturn this.reject;\n\t}\n}\n\nexport class AppInstallEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t\tpublic appVersion: string | null = null,\n\t) {}\n}\n\nexport class AppActivateEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t) {}\n}\n\nexport class AppDeactivateEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t) {}\n}\n\nexport class AppUpdateEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t\tpublic appVersion: string | null = null,\n\t) {}\n}\n\nexport class AppUninstallEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t\tpublic keepUserData: boolean | null = null,\n\t) {}\n}\n\nexport class BeforeRegistrationEvent<Shop extends ShopInterface = ShopInterface> {\n\tprivate cancellationReason: string | null = null;\n\t\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shopId: string,\n\t\tpublic shopUrl: string,\n\t) {}\n\n\tpublic rejectRegistration(reason: string) {\n\t\tthis.cancellationReason = reason;\n\t}\n\n\tpublic get reason() {\n\t\treturn this.cancellationReason;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"registration.js","sourceRoot":"","sources":["../../src/registration.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppServer } from \"./app.js\";\nimport type { ShopInterface } from \"./repository.js\";\n\nexport class Registration<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(private app: AppServer<Shop>) {}\n\n\t/**\n\t * This method checks the request for the handshake with the Shopware Shop.\n\t * if it's valid a Shop will be created, and a proof will be responded with a confirmation url.\n\t * then the Shop will call the confirmation url, and this should be handled by the authorizeCallback method to finish the handshake.\n\t */\n\tpublic async authorize(req: Request): Promise<Response> {\n\t\tconst url = new URL(req.url);\n\n\t\tif (\n\t\t\t!url.searchParams.has(\"shop-url\") ||\n\t\t\t!req.headers.has(\"shopware-app-signature\") ||\n\t\t\t!url.searchParams.has(\"shop-id\") ||\n\t\t\t!url.searchParams.has(\"timestamp\")\n\t\t) {\n\t\t\treturn new InvalidRequestResponse(\"Invalid Request\", 400);\n\t\t}\n\n\t\tconst shopId = url.searchParams.get(\"shop-id\") as string;\n\t\tconst shopUrl = url.searchParams.get(\"shop-url\") as string;\n\t\tconst sanitizedShopUrl = shopUrl\n\t\t\t.replace(/([^:])(\\/\\/+)/g, \"$1/\")\n\t\t\t.replace(/\\/+$/, \"\");\n\n\t\tconst beforeRegistrationEvent = new BeforeRegistrationEvent(req, shopId, shopUrl);\n\t\tthis.app.hooks.publish('onBeforeRegistrationEvent', beforeRegistrationEvent);\n\n\t\tif (beforeRegistrationEvent.reason) {\n\t\t\treturn new InvalidRequestResponse(beforeRegistrationEvent.reason, 400);\n\t\t}\n\n\t\tconst shop = await this.app.repository.getShopById(shopId);\n\n\t\ttry {\n\t\t\tawait this.app.requestVerifier.authenticateRegistrationRequest(req, {\n\t\t\t\t\tappSecret: this.app.cfg.appSecret,\n\t\t\t\t\tenforceDoubleSignature: this.app.cfg.enforceDoubleSignature ?? false,\n\t\t\t\t},\n\t\t\t\tshop,\n\t\t\t);\n\t\t} catch {\n\t\t\treturn new InvalidRequestResponse(\"Cannot validate app signature\");\n\t\t}\n\n\t\tconst shopSecret = randomString();\n\n\t\tif (shop === null) {\n\t\t\tawait this.app.repository.createShop(shopId, sanitizedShopUrl, shopSecret);\n\t\t\tconst shop = (await this.app.repository.getShopById(shopId))!;\n\t\t\tshop.setPendingShopSecret(shopSecret);\n\t\t\tshop.setPendingShopUrl(sanitizedShopUrl);\n\t\t\tthis.setVerifiedWithDoubleSignature(shop, req);\n\t\t\tawait this.app.repository.updateShop(shop);\n\t\t} else {\n\t\t\tshop.setPendingShopSecret(shopSecret);\n\t\t\tshop.setPendingShopUrl(sanitizedShopUrl);\n\t\t\tthis.setVerifiedWithDoubleSignature(shop, req);\n\t\t\tawait this.app.repository.updateShop(shop);\n\t\t}\n\n\t\treturn new Response(\n\t\t\tJSON.stringify({\n\t\t\t\tproof: await this.app.signer.sign(\n\t\t\t\t\tshopId + shopUrl + this.app.cfg.appName,\n\t\t\t\t\tthis.app.cfg.appSecret,\n\t\t\t\t),\n\t\t\t\tsecret: shopSecret,\n\t\t\t\tconfirmation_url: this.app.cfg.authorizeCallbackUrl,\n\t\t\t}),\n\t\t\t{\n\t\t\t\theaders: {\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * This method is called by the Shopware Shop to confirm the handshake.\n\t * It will update the shop with the given oauth2 credentials.\n\t */\n\tpublic async authorizeCallback(req: Request): Promise<Response> {\n\t\tconst bodyContent = await req.text();\n\n\t\tconst body = JSON.parse(bodyContent);\n\n\t\tif (\n\t\t\ttypeof body.shopId !== \"string\" ||\n\t\t\ttypeof body.apiKey !== \"string\" ||\n\t\t\ttypeof body.secretKey !== \"string\" ||\n\t\t\t!req.headers.has(\"shopware-shop-signature\")\n\t\t) {\n\t\t\treturn new InvalidRequestResponse(\"Invalid Request\", 400);\n\t\t}\n\n\t\tconst shop = await this.app.repository.getShopById(body.shopId as string);\n\n\t\tif (shop === null) {\n\t\t\treturn new InvalidRequestResponse(\"Invalid shop given\");\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.app.requestVerifier.authenticateRegistrationConfirmation(\n\t\t\t\treq,\n\t\t\t\tbodyContent,\n\t\t\t\tshop,\n\t\t\t\t{\n\t\t\t\t\tappSecret: this.app.cfg.appSecret,\n\t\t\t\t\tenforceDoubleSignature: this.app.cfg.enforceDoubleSignature ?? false,\n\t\t\t\t},\n\t\t\t);\n\t\t} catch {\n\t\t\treturn new InvalidRequestResponse(\"Cannot validate app signature\");\n\t\t}\n\n\t\tconst pendingSecret = shop.getPendingShopSecret();\n\t\tconst pendingUrl = shop.getPendingShopUrl();\n\t\tif (pendingSecret === null || pendingUrl === null) {\n\t\t\treturn new InvalidRequestResponse(\"Invalid Request\", 400);\n\t\t}\n\n\t\tconst previousSecret = shop.getShopSecret();\n\t\tif (pendingSecret !== previousSecret) {\n\t\t\tshop.setPreviousShopSecret(previousSecret);\n\t\t\tshop.setShopSecret(pendingSecret);\n\t\t\tshop.setSecretsRotatedAt(new Date());\n\t\t}\n\n\t\tshop.setPendingShopSecret(null);\n\t\tshop.setShopUrl(pendingUrl);\n\t\tshop.setPendingShopUrl(null);\n\n\t\tshop.setShopCredentials(body.apiKey, body.secretKey);\n\n\t\tconst event = new ShopAuthorizeEvent(req, shop);\n\t\tawait this.app.hooks.publish(\"onAuthorize\", event);\n\n\t\tif (event.reason) {\n\t\t\tawait this.app.repository.deleteShop(shop.getShopId());\n\n\t\t\treturn new InvalidRequestResponse(event.reason, 403);\n\t\t}\n\n\t\tshop.setRegistrationConfirmed();\n\n\t\tawait this.app.repository.updateShop(shop);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware Shop to set the shop active.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appActivate\" url=\"http://localhost:3000/app/activate\" event=\"app.activated\"/>\n\t * </webhooks>\n\t */\n\tpublic async activate(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI(req);\n\n\t\tconst event = new AppActivateEvent(req, ctx.shop);\n\t\tawait this.app.hooks.publish(\"onAppActivate\", event);\n\n\t\tctx.shop.setShopActive(true);\n\n\t\tawait this.app.repository.updateShop(ctx.shop);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware when the app was installed.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appInstall\" url=\"http://localhost:3000/app/install\" event=\"app.installed\"/>\n\t * </webhooks>\n\t */\n\tpublic async install(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI<{\n\t\t\tdata: { payload: { appVersion: string } };\n\t\t}>(req);\n\n\t\tconst event = new AppInstallEvent(\n\t\t\treq,\n\t\t\tctx.shop,\n\t\t\tctx.payload?.data?.payload?.appVersion ?? null,\n\t\t);\n\t\tawait this.app.hooks.publish(\"onAppInstall\", event);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware Shop to set the shop in-active.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appDeactivated\" url=\"http://localhost:3000/app/deactivated\" event=\"app.deactivated\"/>\n\t * </webhooks>\n\t */\n\tpublic async deactivate(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI(req);\n\n\t\tconst event = new AppDeactivateEvent(req, ctx.shop);\n\t\tawait this.app.hooks.publish(\"onAppDeactivate\", event);\n\n\t\tctx.shop.setShopActive(false);\n\n\t\tawait this.app.repository.updateShop(ctx.shop);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware when the app was updated.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appUpdated\" url=\"http://localhost:3000/app/update\" event=\"app.updated\"/>\n\t * </webhooks>\n\t */\n\tpublic async update(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI<{\n\t\t\tdata: { payload: { appVersion: string } };\n\t\t}>(req);\n\n\t\tconst event = new AppUpdateEvent(\n\t\t\treq,\n\t\t\tctx.shop,\n\t\t\tctx.payload?.data?.payload?.appVersion ?? null,\n\t\t);\n\t\tawait this.app.hooks.publish(\"onAppUpdate\", event);\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * This method should be called by Shopware Shop to delete the app.\n\t *\n\t * <webhooks>\n\t * <webhook name=\"appDelete\" url=\"http://localhost:3000/app/delete\" event=\"app.deleted\"/>\n\t * </webhooks>\n\t */\n\tpublic async delete(req: Request): Promise<Response> {\n\t\tconst ctx = await this.app.contextResolver.fromAPI<{\n\t\t\tdata: { payload: { keepUserData?: boolean } };\n\t\t}>(req);\n\n\t\tconst event = new AppUninstallEvent(\n\t\t\treq,\n\t\t\tctx.shop,\n\t\t\tctx.payload?.data?.payload?.keepUserData ?? null,\n\t\t);\n\t\tawait this.app.hooks.publish(\"onAppUninstall\", event);\n\n\t\tif (event.keepUserData === false) {\n\t\t\tawait this.app.repository.deleteShop(ctx.shop.getShopId());\n\t\t}\n\n\t\treturn new Response(null, { status: 204 });\n\t}\n\n\t/**\n\t * @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.\n\t */\n\tprivate setVerifiedWithDoubleSignature(shop: Shop, req: Request): void\n\t{\n\t\tif (this.app.cfg.enforceDoubleSignature || req.headers.has('shopware-shop-signature')) {\n\t\t\tshop.setVerifiedWithDoubleSignature();\n\t\t}\n\t}\n}\n\nexport function randomString(length = 120) {\n\tlet result = \"\";\n\tconst characters =\n\t\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\tconst charactersLength = characters.length;\n\tfor (let i = 0; i < length; i++) {\n\t\tresult += characters.charAt(Math.floor(Math.random() * charactersLength));\n\t}\n\n\treturn result;\n}\n\nclass InvalidRequestResponse extends Response {\n\tconstructor(error: string, status = 401) {\n\t\tsuper(JSON.stringify({ error }), {\n\t\t\tstatus,\n\t\t\theaders: {\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t},\n\t\t});\n\t}\n}\n\nexport class ShopAuthorizeEvent<Shop extends ShopInterface = ShopInterface> {\n\tprivate reject: string | null = null;\n\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t) {}\n\n\tpublic rejectRegistration(reason: string) {\n\t\tthis.reject = reason;\n\t}\n\n\tpublic get reason() {\n\t\treturn this.reject;\n\t}\n}\n\nexport class AppInstallEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t\tpublic appVersion: string | null = null,\n\t) {}\n}\n\nexport class AppActivateEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t) {}\n}\n\nexport class AppDeactivateEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t) {}\n}\n\nexport class AppUpdateEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t\tpublic appVersion: string | null = null,\n\t) {}\n}\n\nexport class AppUninstallEvent<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shop: Shop,\n\t\tpublic keepUserData: boolean | null = null,\n\t) {}\n}\n\nexport class BeforeRegistrationEvent<Shop extends ShopInterface = ShopInterface> {\n\tprivate cancellationReason: string | null = null;\n\t\n\tconstructor(\n\t\tpublic request: Request,\n\t\tpublic shopId: string,\n\t\tpublic shopUrl: string,\n\t) {}\n\n\tpublic rejectRegistration(reason: string) {\n\t\tthis.cancellationReason = reason;\n\t}\n\n\tpublic get reason() {\n\t\treturn this.cancellationReason;\n\t}\n}\n"]}
|
package/dist/esm/repository.d.ts
CHANGED
|
@@ -4,12 +4,35 @@
|
|
|
4
4
|
export interface ShopInterface {
|
|
5
5
|
getShopId(): string;
|
|
6
6
|
getShopUrl(): string;
|
|
7
|
+
setShopUrl(url: string): void;
|
|
7
8
|
getShopSecret(): string;
|
|
9
|
+
setShopSecret(secret: string): void;
|
|
10
|
+
getPreviousShopSecret(): string | null;
|
|
11
|
+
setPreviousShopSecret(secret: string | null): void;
|
|
12
|
+
getPendingShopSecret(): string | null;
|
|
13
|
+
setPendingShopSecret(secret: string | null): void;
|
|
14
|
+
getPendingShopUrl(): string | null;
|
|
15
|
+
setPendingShopUrl(url: string | null): void;
|
|
16
|
+
getSecretsRotatedAt(): Date | null;
|
|
17
|
+
setSecretsRotatedAt(rotatedAt: Date | null): void;
|
|
8
18
|
getShopClientId(): string | null;
|
|
9
19
|
getShopClientSecret(): string | null;
|
|
10
20
|
getShopActive(): boolean;
|
|
11
21
|
setShopCredentials(clientId: string, clientSecret: string): void;
|
|
12
22
|
setShopActive(active: boolean): void;
|
|
23
|
+
/**
|
|
24
|
+
* Indicates whether at least one registration confirmation has been completed.
|
|
25
|
+
*/
|
|
26
|
+
isRegistrationConfirmed(): boolean;
|
|
27
|
+
setRegistrationConfirmed(): void;
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
30
|
+
*/
|
|
31
|
+
setVerifiedWithDoubleSignature(): void;
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
34
|
+
*/
|
|
35
|
+
hasVerifiedWithDoubleSignature(): boolean;
|
|
13
36
|
}
|
|
14
37
|
/**
|
|
15
38
|
* ShopRepositoryInterface is the storage interface for the shops, you should implement this to save the shop data to your database
|
|
@@ -28,18 +51,47 @@ export declare class SimpleShop implements ShopInterface {
|
|
|
28
51
|
private shopId;
|
|
29
52
|
private shopUrl;
|
|
30
53
|
private shopSecret;
|
|
54
|
+
private previousShopSecret;
|
|
55
|
+
private pendingShopSecret;
|
|
56
|
+
private pendingShopUrl;
|
|
57
|
+
private secretsRotatedAt;
|
|
31
58
|
private shopClientId;
|
|
32
59
|
private shopClientSecret;
|
|
33
60
|
private shopActive;
|
|
34
|
-
|
|
61
|
+
private registrationConfirmed;
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
64
|
+
*/
|
|
65
|
+
private verifiedWithDoubleSignature;
|
|
66
|
+
constructor(shopId: string, shopUrl: string, shopSecret: string, registrationConfirmed?: boolean);
|
|
35
67
|
getShopActive(): boolean;
|
|
36
68
|
setShopActive(active: boolean): void;
|
|
37
69
|
getShopId(): string;
|
|
38
70
|
getShopUrl(): string;
|
|
71
|
+
setShopUrl(url: string): void;
|
|
39
72
|
getShopSecret(): string;
|
|
73
|
+
setShopSecret(secret: string): void;
|
|
74
|
+
getPreviousShopSecret(): string | null;
|
|
75
|
+
setPreviousShopSecret(secret: string | null): void;
|
|
76
|
+
getPendingShopSecret(): string | null;
|
|
77
|
+
setPendingShopSecret(secret: string | null): void;
|
|
78
|
+
getPendingShopUrl(): string | null;
|
|
79
|
+
setPendingShopUrl(url: string | null): void;
|
|
80
|
+
getSecretsRotatedAt(): Date | null;
|
|
81
|
+
setSecretsRotatedAt(rotatedAt: Date | null): void;
|
|
40
82
|
getShopClientId(): string | null;
|
|
41
83
|
getShopClientSecret(): string | null;
|
|
42
84
|
setShopCredentials(clientId: string, clientSecret: string): void;
|
|
85
|
+
isRegistrationConfirmed(): boolean;
|
|
86
|
+
setRegistrationConfirmed(): void;
|
|
87
|
+
/**
|
|
88
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
89
|
+
*/
|
|
90
|
+
setVerifiedWithDoubleSignature(): void;
|
|
91
|
+
/**
|
|
92
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
93
|
+
*/
|
|
94
|
+
hasVerifiedWithDoubleSignature(): boolean;
|
|
43
95
|
}
|
|
44
96
|
/**
|
|
45
97
|
* InMemoryShopRepository is a simple implementation of the ShopRepositoryInterface, it stores the shop data in memory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,IAAI,MAAM,CAAC;IACpB,UAAU,IAAI,MAAM,CAAC;IACrB,aAAa,IAAI,MAAM,CAAC;IACxB,eAAe,IAAI,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAAC;IACrC,aAAa,IAAI,OAAO,CAAC;IACzB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACjE,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/repository.js
CHANGED
|
@@ -5,15 +5,30 @@ export class SimpleShop {
|
|
|
5
5
|
shopId;
|
|
6
6
|
shopUrl;
|
|
7
7
|
shopSecret;
|
|
8
|
+
previousShopSecret;
|
|
9
|
+
pendingShopSecret;
|
|
10
|
+
pendingShopUrl;
|
|
11
|
+
secretsRotatedAt;
|
|
8
12
|
shopClientId;
|
|
9
13
|
shopClientSecret;
|
|
10
14
|
shopActive = false;
|
|
11
|
-
|
|
15
|
+
registrationConfirmed;
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
18
|
+
*/
|
|
19
|
+
verifiedWithDoubleSignature;
|
|
20
|
+
constructor(shopId, shopUrl, shopSecret, registrationConfirmed = false) {
|
|
12
21
|
this.shopId = shopId;
|
|
13
22
|
this.shopUrl = shopUrl;
|
|
14
23
|
this.shopSecret = shopSecret;
|
|
24
|
+
this.previousShopSecret = null;
|
|
25
|
+
this.pendingShopSecret = null;
|
|
26
|
+
this.pendingShopUrl = null;
|
|
27
|
+
this.secretsRotatedAt = null;
|
|
15
28
|
this.shopClientId = null;
|
|
16
29
|
this.shopClientSecret = null;
|
|
30
|
+
this.verifiedWithDoubleSignature = false;
|
|
31
|
+
this.registrationConfirmed = registrationConfirmed;
|
|
17
32
|
}
|
|
18
33
|
getShopActive() {
|
|
19
34
|
return this.shopActive;
|
|
@@ -27,9 +42,39 @@ export class SimpleShop {
|
|
|
27
42
|
getShopUrl() {
|
|
28
43
|
return this.shopUrl;
|
|
29
44
|
}
|
|
45
|
+
setShopUrl(url) {
|
|
46
|
+
this.shopUrl = url;
|
|
47
|
+
}
|
|
30
48
|
getShopSecret() {
|
|
31
49
|
return this.shopSecret;
|
|
32
50
|
}
|
|
51
|
+
setShopSecret(secret) {
|
|
52
|
+
this.shopSecret = secret;
|
|
53
|
+
}
|
|
54
|
+
getPreviousShopSecret() {
|
|
55
|
+
return this.previousShopSecret;
|
|
56
|
+
}
|
|
57
|
+
setPreviousShopSecret(secret) {
|
|
58
|
+
this.previousShopSecret = secret;
|
|
59
|
+
}
|
|
60
|
+
getPendingShopSecret() {
|
|
61
|
+
return this.pendingShopSecret;
|
|
62
|
+
}
|
|
63
|
+
setPendingShopSecret(secret) {
|
|
64
|
+
this.pendingShopSecret = secret;
|
|
65
|
+
}
|
|
66
|
+
getPendingShopUrl() {
|
|
67
|
+
return this.pendingShopUrl;
|
|
68
|
+
}
|
|
69
|
+
setPendingShopUrl(url) {
|
|
70
|
+
this.pendingShopUrl = url;
|
|
71
|
+
}
|
|
72
|
+
getSecretsRotatedAt() {
|
|
73
|
+
return this.secretsRotatedAt;
|
|
74
|
+
}
|
|
75
|
+
setSecretsRotatedAt(rotatedAt) {
|
|
76
|
+
this.secretsRotatedAt = rotatedAt;
|
|
77
|
+
}
|
|
33
78
|
getShopClientId() {
|
|
34
79
|
return this.shopClientId;
|
|
35
80
|
}
|
|
@@ -40,6 +85,24 @@ export class SimpleShop {
|
|
|
40
85
|
this.shopClientId = clientId;
|
|
41
86
|
this.shopClientSecret = clientSecret;
|
|
42
87
|
}
|
|
88
|
+
isRegistrationConfirmed() {
|
|
89
|
+
return this.registrationConfirmed;
|
|
90
|
+
}
|
|
91
|
+
setRegistrationConfirmed() {
|
|
92
|
+
this.registrationConfirmed = true;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
96
|
+
*/
|
|
97
|
+
setVerifiedWithDoubleSignature() {
|
|
98
|
+
this.verifiedWithDoubleSignature = true;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
102
|
+
*/
|
|
103
|
+
hasVerifiedWithDoubleSignature() {
|
|
104
|
+
return this.verifiedWithDoubleSignature;
|
|
105
|
+
}
|
|
43
106
|
}
|
|
44
107
|
/**
|
|
45
108
|
* InMemoryShopRepository is a simple implementation of the ShopRepositoryInterface, it stores the shop data in memory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ShopInterface defines the object that given back from the ShopRepository, it should methods to get the shop data and set them\n */\nexport interface ShopInterface {\n\tgetShopId(): string;\n\tgetShopUrl(): string;\n\tsetShopUrl(url: string): void;\n\tgetShopSecret(): string;\n\tsetShopSecret(secret: string): void;\n\tgetPreviousShopSecret(): string | null;\n\tsetPreviousShopSecret(secret: string | null): void;\n\tgetPendingShopSecret(): string | null;\n\tsetPendingShopSecret(secret: string | null): void;\n\tgetPendingShopUrl(): string | null;\n\tsetPendingShopUrl(url: string | null): void;\n\tgetSecretsRotatedAt(): Date | null;\n\tsetSecretsRotatedAt(rotatedAt: Date | null): void;\n\tgetShopClientId(): string | null;\n\tgetShopClientSecret(): string | null;\n\tgetShopActive(): boolean;\n\tsetShopCredentials(clientId: string, clientSecret: string): void;\n\tsetShopActive(active: boolean): void;\n\t/**\n\t * Indicates whether at least one registration confirmation has been completed.\n\t */\n\tisRegistrationConfirmed(): boolean;\n\tsetRegistrationConfirmed(): void;\n\n /**\n * @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.\n */\n setVerifiedWithDoubleSignature(): void;\n\n /**\n * @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.\n */\n hasVerifiedWithDoubleSignature(): boolean;\n}\n\n/**\n * ShopRepositoryInterface is the storage interface for the shops, you should implement this to save the shop data to your database\n * For testing cases the InMemoryShopRepository can be used\n */\nexport interface ShopRepositoryInterface<\n\tShop extends ShopInterface = ShopInterface,\n> {\n\tcreateShop(id: string, url: string, secret: string): Promise<void>;\n\n\tgetShopById(id: string): Promise<Shop | null>;\n\n\tupdateShop(shop: Shop): Promise<void>;\n\n\tdeleteShop(id: string): Promise<void>;\n}\n\n/**\n * SimpleShop is a simple implementation of the ShopInterface, it stores the shop data in memory\n */\nexport class SimpleShop implements ShopInterface {\n\tprivate shopId: string;\n\tprivate shopUrl: string;\n\tprivate shopSecret: string;\n\tprivate previousShopSecret: string | null;\n\tprivate pendingShopSecret: string | null;\n\tprivate pendingShopUrl: string | null;\n\tprivate secretsRotatedAt: Date | null;\n\tprivate shopClientId: string | null;\n\tprivate shopClientSecret: string | null;\n\tprivate shopActive = false;\n\tprivate registrationConfirmed: boolean;\n /**\n * @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.\n */\n\tprivate verifiedWithDoubleSignature: boolean;\n\n\tconstructor(\n\t\tshopId: string,\n\t\tshopUrl: string,\n\t\tshopSecret: string,\n\t\tregistrationConfirmed = false,\n\t) {\n\t\tthis.shopId = shopId;\n\t\tthis.shopUrl = shopUrl;\n\t\tthis.shopSecret = shopSecret;\n\t\tthis.previousShopSecret = null;\n\t\tthis.pendingShopSecret = null;\n\t\tthis.pendingShopUrl = null;\n\t\tthis.secretsRotatedAt = null;\n\t\tthis.shopClientId = null;\n\t\tthis.shopClientSecret = null;\n this.verifiedWithDoubleSignature = false;\n\t\tthis.registrationConfirmed = registrationConfirmed;\n\t}\n\n\tgetShopActive(): boolean {\n\t\treturn this.shopActive;\n\t}\n\tsetShopActive(active: boolean): void {\n\t\tthis.shopActive = active;\n\t}\n\tgetShopId(): string {\n\t\treturn this.shopId;\n\t}\n\tgetShopUrl(): string {\n\t\treturn this.shopUrl;\n\t}\n\tsetShopUrl(url: string): void {\n\t\tthis.shopUrl = url;\n\t}\n\tgetShopSecret(): string {\n\t\treturn this.shopSecret;\n\t}\n\tsetShopSecret(secret: string): void {\n\t\tthis.shopSecret = secret;\n\t}\n\tgetPreviousShopSecret(): string | null {\n\t\treturn this.previousShopSecret;\n\t}\n\tsetPreviousShopSecret(secret: string | null): void {\n\t\tthis.previousShopSecret = secret;\n\t}\n\tgetPendingShopSecret(): string | null {\n\t\treturn this.pendingShopSecret;\n\t}\n\tsetPendingShopSecret(secret: string | null): void {\n\t\tthis.pendingShopSecret = secret;\n\t}\n\tgetPendingShopUrl(): string | null {\n\t\treturn this.pendingShopUrl;\n\t}\n\tsetPendingShopUrl(url: string | null): void {\n\t\tthis.pendingShopUrl = url;\n\t}\n\tgetSecretsRotatedAt(): Date | null {\n\t\treturn this.secretsRotatedAt;\n\t}\n\tsetSecretsRotatedAt(rotatedAt: Date | null): void {\n\t\tthis.secretsRotatedAt = rotatedAt;\n\t}\n\tgetShopClientId(): string | null {\n\t\treturn this.shopClientId;\n\t}\n\tgetShopClientSecret(): string | null {\n\t\treturn this.shopClientSecret;\n\t}\n\tsetShopCredentials(clientId: string, clientSecret: string): void {\n\t\tthis.shopClientId = clientId;\n\t\tthis.shopClientSecret = clientSecret;\n\t}\n\tisRegistrationConfirmed(): boolean {\n\t\treturn this.registrationConfirmed;\n\t}\n\tsetRegistrationConfirmed(): void {\n\t\tthis.registrationConfirmed = true;\n\t}\n /**\n * @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.\n */\n setVerifiedWithDoubleSignature(): void {\n this.verifiedWithDoubleSignature = true;\n }\n /**\n * @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.\n */\n hasVerifiedWithDoubleSignature(): boolean {\n return this.verifiedWithDoubleSignature;\n }\n}\n\n/**\n * InMemoryShopRepository is a simple implementation of the ShopRepositoryInterface, it stores the shop data in memory\n */\nexport class InMemoryShopRepository\n\timplements ShopRepositoryInterface<SimpleShop>\n{\n\tprivate storage: Map<string, SimpleShop>;\n\n\tconstructor() {\n\t\tthis.storage = new Map<string, SimpleShop>();\n\t}\n\n\tasync createShop(id: string, url: string, secret: string) {\n\t\tthis.storage.set(id, new SimpleShop(id, url, secret));\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst shop = this.storage.get(id);\n\n\t\tif (shop === undefined) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn shop;\n\t}\n\n\tasync updateShop(shop: SimpleShop) {\n\t\tthis.storage.set(shop.getShopId(), shop);\n\t}\n\n\tasync deleteShop(id: string) {\n\t\tthis.storage.delete(id);\n\t}\n}\n"]}
|