@shopware-ag/app-server-sdk 1.1.29 → 2.0.1
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 +7 -1
- 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 +7 -1
- 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
|
@@ -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"]}
|
|
@@ -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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"}
|
|
@@ -8,15 +8,30 @@ class SimpleShop {
|
|
|
8
8
|
shopId;
|
|
9
9
|
shopUrl;
|
|
10
10
|
shopSecret;
|
|
11
|
+
previousShopSecret;
|
|
12
|
+
pendingShopSecret;
|
|
13
|
+
pendingShopUrl;
|
|
14
|
+
secretsRotatedAt;
|
|
11
15
|
shopClientId;
|
|
12
16
|
shopClientSecret;
|
|
13
17
|
shopActive = false;
|
|
14
|
-
|
|
18
|
+
registrationConfirmed;
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
21
|
+
*/
|
|
22
|
+
verifiedWithDoubleSignature;
|
|
23
|
+
constructor(shopId, shopUrl, shopSecret, registrationConfirmed = false) {
|
|
15
24
|
this.shopId = shopId;
|
|
16
25
|
this.shopUrl = shopUrl;
|
|
17
26
|
this.shopSecret = shopSecret;
|
|
27
|
+
this.previousShopSecret = null;
|
|
28
|
+
this.pendingShopSecret = null;
|
|
29
|
+
this.pendingShopUrl = null;
|
|
30
|
+
this.secretsRotatedAt = null;
|
|
18
31
|
this.shopClientId = null;
|
|
19
32
|
this.shopClientSecret = null;
|
|
33
|
+
this.verifiedWithDoubleSignature = false;
|
|
34
|
+
this.registrationConfirmed = registrationConfirmed;
|
|
20
35
|
}
|
|
21
36
|
getShopActive() {
|
|
22
37
|
return this.shopActive;
|
|
@@ -30,9 +45,39 @@ class SimpleShop {
|
|
|
30
45
|
getShopUrl() {
|
|
31
46
|
return this.shopUrl;
|
|
32
47
|
}
|
|
48
|
+
setShopUrl(url) {
|
|
49
|
+
this.shopUrl = url;
|
|
50
|
+
}
|
|
33
51
|
getShopSecret() {
|
|
34
52
|
return this.shopSecret;
|
|
35
53
|
}
|
|
54
|
+
setShopSecret(secret) {
|
|
55
|
+
this.shopSecret = secret;
|
|
56
|
+
}
|
|
57
|
+
getPreviousShopSecret() {
|
|
58
|
+
return this.previousShopSecret;
|
|
59
|
+
}
|
|
60
|
+
setPreviousShopSecret(secret) {
|
|
61
|
+
this.previousShopSecret = secret;
|
|
62
|
+
}
|
|
63
|
+
getPendingShopSecret() {
|
|
64
|
+
return this.pendingShopSecret;
|
|
65
|
+
}
|
|
66
|
+
setPendingShopSecret(secret) {
|
|
67
|
+
this.pendingShopSecret = secret;
|
|
68
|
+
}
|
|
69
|
+
getPendingShopUrl() {
|
|
70
|
+
return this.pendingShopUrl;
|
|
71
|
+
}
|
|
72
|
+
setPendingShopUrl(url) {
|
|
73
|
+
this.pendingShopUrl = url;
|
|
74
|
+
}
|
|
75
|
+
getSecretsRotatedAt() {
|
|
76
|
+
return this.secretsRotatedAt;
|
|
77
|
+
}
|
|
78
|
+
setSecretsRotatedAt(rotatedAt) {
|
|
79
|
+
this.secretsRotatedAt = rotatedAt;
|
|
80
|
+
}
|
|
36
81
|
getShopClientId() {
|
|
37
82
|
return this.shopClientId;
|
|
38
83
|
}
|
|
@@ -43,6 +88,24 @@ class SimpleShop {
|
|
|
43
88
|
this.shopClientId = clientId;
|
|
44
89
|
this.shopClientSecret = clientSecret;
|
|
45
90
|
}
|
|
91
|
+
isRegistrationConfirmed() {
|
|
92
|
+
return this.registrationConfirmed;
|
|
93
|
+
}
|
|
94
|
+
setRegistrationConfirmed() {
|
|
95
|
+
this.registrationConfirmed = true;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
99
|
+
*/
|
|
100
|
+
setVerifiedWithDoubleSignature() {
|
|
101
|
+
this.verifiedWithDoubleSignature = true;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
105
|
+
*/
|
|
106
|
+
hasVerifiedWithDoubleSignature() {
|
|
107
|
+
return this.verifiedWithDoubleSignature;
|
|
108
|
+
}
|
|
46
109
|
}
|
|
47
110
|
exports.SimpleShop = SimpleShop;
|
|
48
111
|
/**
|
|
@@ -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"]}
|
package/dist/esm/app.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ContextResolver } from "./context-resolver.js";
|
|
2
|
+
import { DualSignatureVerifier } from "./dual-signature-verifier.js";
|
|
2
3
|
import { Hooks } from "./hooks.js";
|
|
3
4
|
import { HttpClientTokenCacheInterface } from "./http-client.js";
|
|
4
5
|
import { Registration } from "./registration.js";
|
|
@@ -14,10 +15,11 @@ export declare class AppServer<Shop extends ShopInterface = ShopInterface> {
|
|
|
14
15
|
registration: Registration<Shop>;
|
|
15
16
|
contextResolver: ContextResolver<Shop>;
|
|
16
17
|
signer: WebCryptoHmacSigner;
|
|
18
|
+
requestVerifier: DualSignatureVerifier<Shop>;
|
|
17
19
|
hooks: Hooks<Shop>;
|
|
18
20
|
constructor(cfg: Configuration, repository: ShopRepositoryInterface<Shop>, httpClientTokenCache?: HttpClientTokenCacheInterface);
|
|
19
21
|
}
|
|
20
|
-
interface Configuration {
|
|
22
|
+
export interface Configuration {
|
|
21
23
|
/**
|
|
22
24
|
* Your app name
|
|
23
25
|
*/
|
|
@@ -30,6 +32,10 @@ interface Configuration {
|
|
|
30
32
|
* URL to authorize callback url
|
|
31
33
|
*/
|
|
32
34
|
authorizeCallbackUrl: string;
|
|
35
|
+
/**
|
|
36
|
+
* When true, registration requires both app and shop signatures during re-registration and confirmation.
|
|
37
|
+
* Defaults to false.
|
|
38
|
+
*/
|
|
39
|
+
enforceDoubleSignature?: boolean;
|
|
33
40
|
}
|
|
34
|
-
export {};
|
|
35
41
|
//# sourceMappingURL=app.d.ts.map
|
package/dist/esm/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,6BAA6B,EAAgC,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;GAEG;AACH,qBAAa,SAAS,CAAC,IAAI,SAAS,aAAa,GAAG,aAAa;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,6BAA6B,EAAgC,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;GAEG;AACH,qBAAa,SAAS,CAAC,IAAI,SAAS,aAAa,GAAG,aAAa;IAQxD,GAAG,EAAE,aAAa;IAClB,UAAU,EAAE,uBAAuB,CAAC,IAAI,CAAC;IACzC,oBAAoB,EAAE,6BAA6B;IATpD,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,eAAe,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,eAAe,EAAE,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAGlB,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,uBAAuB,CAAC,IAAI,CAAC,EACzC,oBAAoB,GAAE,6BAAkE;CAQhG;AAED,MAAM,WAAW,aAAa;IAC7B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACjC"}
|
package/dist/esm/app.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ContextResolver } from "./context-resolver.js";
|
|
2
|
+
import { DualSignatureVerifier } from "./dual-signature-verifier.js";
|
|
2
3
|
import { Hooks } from "./hooks.js";
|
|
3
4
|
import { InMemoryHttpClientTokenCache } from "./http-client.js";
|
|
4
5
|
import { Registration } from "./registration.js";
|
|
@@ -13,6 +14,7 @@ export class AppServer {
|
|
|
13
14
|
registration;
|
|
14
15
|
contextResolver;
|
|
15
16
|
signer;
|
|
17
|
+
requestVerifier;
|
|
16
18
|
hooks;
|
|
17
19
|
constructor(cfg, repository, httpClientTokenCache = new InMemoryHttpClientTokenCache()) {
|
|
18
20
|
this.cfg = cfg;
|
|
@@ -21,6 +23,7 @@ export class AppServer {
|
|
|
21
23
|
this.registration = new Registration(this);
|
|
22
24
|
this.contextResolver = new ContextResolver(this, httpClientTokenCache);
|
|
23
25
|
this.signer = new WebCryptoHmacSigner();
|
|
26
|
+
this.requestVerifier = new DualSignatureVerifier(this.signer);
|
|
24
27
|
this.hooks = new Hooks();
|
|
25
28
|
}
|
|
26
29
|
}
|
package/dist/esm/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAiC,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;GAEG;AACH,MAAM,OAAO,SAAS;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAiC,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;GAEG;AACH,MAAM,OAAO,SAAS;IAQb;IACA;IACA;IATD,YAAY,CAAqB;IACjC,eAAe,CAAwB;IACvC,MAAM,CAAsB;IAC5B,eAAe,CAA8B;IAC7C,KAAK,CAAc;IAE1B,YACQ,GAAkB,EAClB,UAAyC,EACzC,uBAAsD,IAAI,4BAA4B,EAAE;QAFxF,QAAG,GAAH,GAAG,CAAe;QAClB,eAAU,GAAV,UAAU,CAA+B;QACzC,yBAAoB,GAApB,oBAAoB,CAAoE;QAE/F,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAO,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAO,IAAI,EAAE,oBAAoB,CAAC,CAAC;QAC7E,IAAI,CAAC,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;QACxC,IAAI,CAAC,eAAe,GAAG,IAAI,qBAAqB,CAAO,IAAI,CAAC,MAAM,CAAC,CAAC;QACpE,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,EAAQ,CAAC;IAChC,CAAC;CACD","sourcesContent":["import { ContextResolver } from \"./context-resolver.js\";\nimport { DualSignatureVerifier } from \"./dual-signature-verifier.js\";\nimport { Hooks } from \"./hooks.js\";\nimport { HttpClientTokenCacheInterface, InMemoryHttpClientTokenCache } from \"./http-client.js\";\nimport { Registration } from \"./registration.js\";\nimport type { ShopInterface, ShopRepositoryInterface } from \"./repository.js\";\nimport { WebCryptoHmacSigner } from \"./signer.js\";\n\n/**\n * AppServer is the main class, this is where you start your app\n */\nexport class AppServer<Shop extends ShopInterface = ShopInterface> {\n\tpublic registration: Registration<Shop>;\n\tpublic contextResolver: ContextResolver<Shop>;\n\tpublic signer: WebCryptoHmacSigner;\n\tpublic requestVerifier: DualSignatureVerifier<Shop>;\n\tpublic hooks: Hooks<Shop>;\n\n\tconstructor(\n\t\tpublic cfg: Configuration,\n\t\tpublic repository: ShopRepositoryInterface<Shop>,\n\t\tpublic httpClientTokenCache: HttpClientTokenCacheInterface = new InMemoryHttpClientTokenCache()\n\t) {\n\t\tthis.registration = new Registration<Shop>(this);\n\t\tthis.contextResolver = new ContextResolver<Shop>(this, httpClientTokenCache);\n\t\tthis.signer = new WebCryptoHmacSigner();\n\t\tthis.requestVerifier = new DualSignatureVerifier<Shop>(this.signer);\n\t\tthis.hooks = new Hooks<Shop>();\n\t}\n}\n\nexport interface Configuration {\n\t/**\n\t * Your app name\n\t */\n\tappName: string;\n\n\t/**\n\t * Your app secret\n\t */\n\tappSecret: string;\n\n\t/**\n\t * URL to authorize callback url\n\t */\n\tauthorizeCallbackUrl: string;\n\n\t/**\n\t * When true, registration requires both app and shop signatures during re-registration and confirmation.\n\t * Defaults to false.\n\t */\n\tenforceDoubleSignature?: boolean;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-resolver.d.ts","sourceRoot":"","sources":["../../src/context-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,KAAK,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;GAGG;AACH,qBAAa,eAAe,CAAC,IAAI,SAAS,aAAa,GAAG,aAAa;IAC1D,OAAO,CAAC,GAAG;IAAmB,OAAO,CAAC,oBAAoB;gBAAlD,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,EAAU,oBAAoB,EAAE,6BAA6B;IAErG;;OAEG;IACU,OAAO,CAAC,OAAO,GAAG,OAAO,EACrC,GAAG,EAAE,OAAO,GACV,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"context-resolver.d.ts","sourceRoot":"","sources":["../../src/context-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,KAAK,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;GAGG;AACH,qBAAa,eAAe,CAAC,IAAI,SAAS,aAAa,GAAG,aAAa;IAC1D,OAAO,CAAC,GAAG;IAAmB,OAAO,CAAC,oBAAoB;gBAAlD,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,EAAU,oBAAoB,EAAE,6BAA6B;IAErG;;OAEG;IACU,OAAO,CAAC,OAAO,GAAG,OAAO,EACrC,GAAG,EAAE,OAAO,GACV,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IA4BlC;;;OAGG;IACU,WAAW,CAAC,OAAO,GAAG,OAAO,EACzC,GAAG,EAAE,OAAO,GACV,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;CA6BlC;AAED;;GAEG;AACH,qBAAa,OAAO,CACnB,IAAI,SAAS,aAAa,GAAG,aAAa,EAC1C,OAAO,GAAG,OAAO;IAGT,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,OAAO;IAChB,UAAU,EAAE,UAAU;gBAFtB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU;CAE9B"}
|
|
@@ -24,13 +24,7 @@ export class ContextResolver {
|
|
|
24
24
|
if (shop === null) {
|
|
25
25
|
throw new Error(`Cannot find shop by id ${webHookBody.source.shopId}`);
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
if (signature === null) {
|
|
29
|
-
throw new Error("Missing shopware-shop-signature header");
|
|
30
|
-
}
|
|
31
|
-
if (!(await this.app.signer.verify(signature, webHookContent, shop.getShopSecret()))) {
|
|
32
|
-
throw new Error("Invalid signature");
|
|
33
|
-
}
|
|
27
|
+
await this.app.requestVerifier.authenticatePostRequest(req, webHookContent, shop);
|
|
34
28
|
return new Context(shop, webHookBody, new HttpClient(shop, this.httpClientTokenCache));
|
|
35
29
|
}
|
|
36
30
|
/**
|
|
@@ -47,7 +41,7 @@ export class ContextResolver {
|
|
|
47
41
|
if (shop === null) {
|
|
48
42
|
throw new Error(`Cannot find shop by id ${shopId}`);
|
|
49
43
|
}
|
|
50
|
-
await this.app.
|
|
44
|
+
await this.app.requestVerifier.authenticateGetRequest(req, shop);
|
|
51
45
|
const paramsObject = {};
|
|
52
46
|
url.searchParams.forEach((value, key) => {
|
|
53
47
|
paramsObject[key] = value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-resolver.js","sourceRoot":"","sources":["../../src/context-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAsC,MAAM,kBAAkB,CAAC;AAGlF;;;GAGG;AACH,MAAM,OAAO,eAAe;IACP;IAA8B;IAAlD,YAAoB,GAAoB,EAAU,oBAAmD;QAAjF,QAAG,GAAH,GAAG,CAAiB;QAAU,yBAAoB,GAApB,oBAAoB,CAA+B;IAAG,CAAC;IAEzG;;OAEG;IACI,KAAK,CAAC,OAAO,CACnB,GAAY;QAEZ,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAE/C,IACC,WAAW,CAAC,MAAM,KAAK,SAAS;YAChC,WAAW,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,EACtC,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CACjD,WAAW,CAAC,MAAM,CAAC,MAAM,CACzB,CAAC;QAEF,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,
|
|
1
|
+
{"version":3,"file":"context-resolver.js","sourceRoot":"","sources":["../../src/context-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAsC,MAAM,kBAAkB,CAAC;AAGlF;;;GAGG;AACH,MAAM,OAAO,eAAe;IACP;IAA8B;IAAlD,YAAoB,GAAoB,EAAU,oBAAmD;QAAjF,QAAG,GAAH,GAAG,CAAiB;QAAU,yBAAoB,GAApB,oBAAoB,CAA+B;IAAG,CAAC;IAEzG;;OAEG;IACI,KAAK,CAAC,OAAO,CACnB,GAAY;QAEZ,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAE/C,IACC,WAAW,CAAC,MAAM,KAAK,SAAS;YAChC,WAAW,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,EACtC,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CACjD,WAAW,CAAC,MAAM,CAAC,MAAM,CACzB,CAAC;QAEF,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,uBAAuB,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC;QAElF,OAAO,IAAI,OAAO,CACjB,IAAY,EACZ,WAAW,EACX,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAC/C,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,WAAW,CACvB,GAAY;QAEZ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE7B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAE/C,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAE3D,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAEjE,MAAM,YAAY,GAA2B,EAAE,CAAC;QAEhD,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACvC,YAAY,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,OAAO,CACjB,IAAY,EACZ,YAAuB,EACvB,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAC/C,CAAC;IACH,CAAC;CACD;AAED;;GAEG;AACH,MAAM,OAAO,OAAO;IAKX;IACA;IACA;IAHR,YACQ,IAAU,EACV,OAAgB,EAChB,UAAsB;QAFtB,SAAI,GAAJ,IAAI,CAAM;QACV,YAAO,GAAP,OAAO,CAAS;QAChB,eAAU,GAAV,UAAU,CAAY;IAC3B,CAAC;CACJ","sourcesContent":["import type { AppServer } from \"./app.js\";\nimport { HttpClient, type HttpClientTokenCacheInterface } from \"./http-client.js\";\nimport type { ShopInterface } from \"./repository.js\";\n\n/**\n * ContextResolver is a helper class to create a Context object from a request.\n * The context contains the shop, the payload and an instance of the HttpClient\n */\nexport class ContextResolver<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(private app: AppServer<Shop>, private httpClientTokenCache: HttpClientTokenCacheInterface) {}\n\n\t/**\n\t * Create a context from a request body\n\t */\n\tpublic async fromAPI<Payload = unknown>(\n\t\treq: Request,\n\t): Promise<Context<Shop, Payload>> {\n\t\tconst webHookContent = await req.text();\n\t\tconst webHookBody = JSON.parse(webHookContent);\n\n\t\tif (\n\t\t\twebHookBody.source === undefined ||\n\t\t\twebHookBody.source.shopId === undefined\n\t\t) {\n\t\t\tthrow new Error(\"Invalid request\");\n\t\t}\n\n\t\tconst shop = await this.app.repository.getShopById(\n\t\t\twebHookBody.source.shopId,\n\t\t);\n\n\t\tif (shop === null) {\n\t\t\tthrow new Error(`Cannot find shop by id ${webHookBody.source.shopId}`);\n\t\t}\n\n\t\tawait this.app.requestVerifier.authenticatePostRequest(req, webHookContent, shop);\n\n\t\treturn new Context<Shop, Payload>(\n\t\t\tshop as Shop,\n\t\t\twebHookBody,\n\t\t\tnew HttpClient(shop, this.httpClientTokenCache),\n\t\t);\n\t}\n\n\t/**\n\t * Create a context from a request query parameters\n\t * This is usually a module request from the shopware admin\n\t */\n\tpublic async fromBrowser<Payload = unknown>(\n\t\treq: Request,\n\t): Promise<Context<Shop, Payload>> {\n\t\tconst url = new URL(req.url);\n\n\t\tconst shopId = url.searchParams.get(\"shop-id\");\n\n\t\tif (shopId === null) {\n\t\t\tthrow new Error(\"Missing shop-id query parameter\");\n\t\t}\n\n\t\tconst shop = await this.app.repository.getShopById(shopId);\n\n\t\tif (shop === null) {\n\t\t\tthrow new Error(`Cannot find shop by id ${shopId}`);\n\t\t}\n\n\t\tawait this.app.requestVerifier.authenticateGetRequest(req, shop);\n\n\t\tconst paramsObject: Record<string, string> = {};\n\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tparamsObject[key] = value;\n\t\t});\n\n\t\treturn new Context<Shop, Payload>(\n\t\t\tshop as Shop,\n\t\t\tparamsObject as Payload,\n\t\t\tnew HttpClient(shop, this.httpClientTokenCache),\n\t\t);\n\t}\n}\n\n/**\n * Context is the parsed data from the request\n */\nexport class Context<\n\tShop extends ShopInterface = ShopInterface,\n\tPayload = unknown,\n> {\n\tconstructor(\n\t\tpublic shop: Shop,\n\t\tpublic payload: Payload,\n\t\tpublic httpClient: HttpClient,\n\t) {}\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ShopInterface } from "./repository.js";
|
|
2
|
+
import { WebCryptoHmacSigner } from "./signer.js";
|
|
3
|
+
export interface DualSignatureConfiguration {
|
|
4
|
+
appSecret: string;
|
|
5
|
+
enforceDoubleSignature: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare class DualSignatureVerifier<Shop extends ShopInterface = ShopInterface> {
|
|
8
|
+
private readonly signer;
|
|
9
|
+
private readonly now;
|
|
10
|
+
constructor(signer: WebCryptoHmacSigner, now?: () => Date);
|
|
11
|
+
authenticateRegistrationRequest(req: Request, cfg: DualSignatureConfiguration, shop: Shop | null): Promise<void>;
|
|
12
|
+
authenticateRegistrationConfirmation(req: Request, body: string, shop: Shop, cfg: DualSignatureConfiguration): Promise<void>;
|
|
13
|
+
authenticatePostRequest(req: Request, body: string, shop: Shop): Promise<void>;
|
|
14
|
+
authenticateGetRequest(req: Request, shop: Shop): Promise<void>;
|
|
15
|
+
private verifyRegistrationAppSignature;
|
|
16
|
+
private verifyRegistrationShopSignature;
|
|
17
|
+
private verifyPostSignature;
|
|
18
|
+
private getRegistrationSignatureMessage;
|
|
19
|
+
private tryAuthenticateWithPreviousSecret;
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
22
|
+
*
|
|
23
|
+
* 1. If the shop has previously verified with a double signature, it must always do so
|
|
24
|
+
* 2. If the shop is sending a double signature, then we should also verify it
|
|
25
|
+
* 3. If the app is configured to enforce double signature, then we should force it
|
|
26
|
+
*/
|
|
27
|
+
private shouldEnforceDoubleSignature;
|
|
28
|
+
private shouldEnforceDoubleSignatureForRegister;
|
|
29
|
+
private shouldEnforceDoubleSignatureForRegisterConfirm;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=dual-signature-verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dual-signature-verifier.d.ts","sourceRoot":"","sources":["../../src/dual-signature-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAOlD,MAAM,WAAW,0BAA0B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,EAAE,OAAO,CAAC;CAChC;AAED,qBAAa,qBAAqB,CAAC,IAAI,SAAS,aAAa,GAAG,aAAa;IAE3E,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBADH,MAAM,EAAE,mBAAmB,EAC3B,GAAG,GAAE,MAAM,IAAuB;IAGvC,+BAA+B,CAC3C,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,0BAA0B,EAC/B,IAAI,EAAE,IAAI,GAAG,IAAI,GACf,OAAO,CAAC,IAAI,CAAC;IAgBH,oCAAoC,CAChD,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,0BAA0B,GAC7B,OAAO,CAAC,IAAI,CAAC;IAkBH,uBAAuB,CACnC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,GACR,OAAO,CAAC,IAAI,CAAC;IAcH,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAc9D,8BAA8B;YAe9B,+BAA+B;YAe/B,mBAAmB;IAmBjC,OAAO,CAAC,+BAA+B;YAazB,iCAAiC;IAqB/C;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;IAKpC,OAAO,CAAC,uCAAuC;IAK/C,OAAO,CAAC,8CAA8C;CAItD"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const SHOPWARE_SHOP_SIGNATURE_HEADER = "shopware-shop-signature";
|
|
2
|
+
const SHOPWARE_SHOP_SIGNATURE_PREVIOUS_HEADER = "shopware-shop-signature-previous";
|
|
3
|
+
const SHOPWARE_APP_SIGNATURE_HEADER = "shopware-app-signature";
|
|
4
|
+
const INFLIGHT_ALLOWANCE_MS = 60_000;
|
|
5
|
+
export class DualSignatureVerifier {
|
|
6
|
+
signer;
|
|
7
|
+
now;
|
|
8
|
+
constructor(signer, now = () => new Date()) {
|
|
9
|
+
this.signer = signer;
|
|
10
|
+
this.now = now;
|
|
11
|
+
}
|
|
12
|
+
async authenticateRegistrationRequest(req, cfg, shop) {
|
|
13
|
+
try {
|
|
14
|
+
await this.verifyRegistrationAppSignature(req, cfg.appSecret);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw new Error("invalid-app-signature", { cause: error });
|
|
18
|
+
}
|
|
19
|
+
if (shop?.isRegistrationConfirmed() && this.shouldEnforceDoubleSignatureForRegister(cfg, shop, req)) {
|
|
20
|
+
try {
|
|
21
|
+
await this.verifyRegistrationShopSignature(req, shop.getShopSecret());
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new Error("invalid-shop-registration-signature", { cause: error });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async authenticateRegistrationConfirmation(req, body, shop, cfg) {
|
|
29
|
+
const pendingSecret = shop.getPendingShopSecret();
|
|
30
|
+
if (pendingSecret === null) {
|
|
31
|
+
throw new Error("Signature could not be verified");
|
|
32
|
+
}
|
|
33
|
+
await this.verifyPostSignature(req, body, pendingSecret, SHOPWARE_SHOP_SIGNATURE_HEADER);
|
|
34
|
+
if (!shop.isRegistrationConfirmed()) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (this.shouldEnforceDoubleSignatureForRegisterConfirm(cfg, shop, req)) {
|
|
38
|
+
await this.verifyPostSignature(req, body, shop.getShopSecret(), SHOPWARE_SHOP_SIGNATURE_PREVIOUS_HEADER);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async authenticatePostRequest(req, body, shop) {
|
|
42
|
+
try {
|
|
43
|
+
await this.verifyPostSignature(req, body, shop.getShopSecret(), SHOPWARE_SHOP_SIGNATURE_HEADER);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
await this.tryAuthenticateWithPreviousSecret(shop, error, async (secret) => {
|
|
47
|
+
await this.verifyPostSignature(req, body, secret, SHOPWARE_SHOP_SIGNATURE_HEADER);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async authenticateGetRequest(req, shop) {
|
|
52
|
+
try {
|
|
53
|
+
await this.signer.verifyGetRequest(req, shop.getShopSecret());
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
await this.tryAuthenticateWithPreviousSecret(shop, error, async (secret) => {
|
|
57
|
+
await this.signer.verifyGetRequest(req, secret);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async verifyRegistrationAppSignature(req, secret) {
|
|
62
|
+
const signature = req.headers.get(SHOPWARE_APP_SIGNATURE_HEADER);
|
|
63
|
+
if (signature === null) {
|
|
64
|
+
throw new Error("Missing shopware-app-signature header");
|
|
65
|
+
}
|
|
66
|
+
const message = this.getRegistrationSignatureMessage(req);
|
|
67
|
+
const valid = await this.signer.verify(signature, message, secret);
|
|
68
|
+
if (!valid) {
|
|
69
|
+
throw new Error("Invalid app signature");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async verifyRegistrationShopSignature(req, secret) {
|
|
73
|
+
const signature = req.headers.get(SHOPWARE_SHOP_SIGNATURE_HEADER);
|
|
74
|
+
if (signature === null) {
|
|
75
|
+
throw new Error("Missing shopware-shop-signature header");
|
|
76
|
+
}
|
|
77
|
+
const message = this.getRegistrationSignatureMessage(req);
|
|
78
|
+
const valid = await this.signer.verify(signature, message, secret);
|
|
79
|
+
if (!valid) {
|
|
80
|
+
throw new Error("Invalid shop signature");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async verifyPostSignature(req, body, secret, headerName) {
|
|
84
|
+
const signature = req.headers.get(headerName);
|
|
85
|
+
if (signature === null) {
|
|
86
|
+
throw new Error(`Missing ${headerName} header`);
|
|
87
|
+
}
|
|
88
|
+
const valid = await this.signer.verify(signature, body, secret);
|
|
89
|
+
if (!valid) {
|
|
90
|
+
throw new Error("Invalid signature");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
getRegistrationSignatureMessage(req) {
|
|
94
|
+
const url = new URL(req.url);
|
|
95
|
+
const shopId = url.searchParams.get("shop-id");
|
|
96
|
+
const shopUrl = url.searchParams.get("shop-url");
|
|
97
|
+
const timestamp = url.searchParams.get("timestamp");
|
|
98
|
+
if (!shopId || !shopUrl || !timestamp) {
|
|
99
|
+
throw new Error("Missing required registration parameters");
|
|
100
|
+
}
|
|
101
|
+
return `shop-id=${shopId}&shop-url=${shopUrl}×tamp=${timestamp}`;
|
|
102
|
+
}
|
|
103
|
+
async tryAuthenticateWithPreviousSecret(shop, error, verify) {
|
|
104
|
+
const previousSecret = shop.getPreviousShopSecret();
|
|
105
|
+
const rotatedAt = shop.getSecretsRotatedAt();
|
|
106
|
+
if (previousSecret === null || rotatedAt === null) {
|
|
107
|
+
throw error instanceof Error ? error : new Error("Invalid signature");
|
|
108
|
+
}
|
|
109
|
+
const allowanceEnd = rotatedAt.getTime() + INFLIGHT_ALLOWANCE_MS;
|
|
110
|
+
if (this.now().getTime() >= allowanceEnd) {
|
|
111
|
+
throw error instanceof Error ? error : new Error("Invalid signature");
|
|
112
|
+
}
|
|
113
|
+
await verify(previousSecret);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.
|
|
117
|
+
*
|
|
118
|
+
* 1. If the shop has previously verified with a double signature, it must always do so
|
|
119
|
+
* 2. If the shop is sending a double signature, then we should also verify it
|
|
120
|
+
* 3. If the app is configured to enforce double signature, then we should force it
|
|
121
|
+
*/
|
|
122
|
+
shouldEnforceDoubleSignature(cfg, shop, req, header) {
|
|
123
|
+
return shop.hasVerifiedWithDoubleSignature() || req.headers.has(header) || cfg.enforceDoubleSignature;
|
|
124
|
+
}
|
|
125
|
+
shouldEnforceDoubleSignatureForRegister(cfg, shop, req) {
|
|
126
|
+
return this.shouldEnforceDoubleSignature(cfg, shop, req, SHOPWARE_SHOP_SIGNATURE_HEADER);
|
|
127
|
+
}
|
|
128
|
+
shouldEnforceDoubleSignatureForRegisterConfirm(cfg, shop, req) {
|
|
129
|
+
return this.shouldEnforceDoubleSignature(cfg, shop, req, SHOPWARE_SHOP_SIGNATURE_PREVIOUS_HEADER);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=dual-signature-verifier.js.map
|