Skip to content

Commit 063ad24

Browse files
committed
Require deleteMetadata to metadata manager
1 parent 8dc8d4a commit 063ad24

File tree

5 files changed

+32
-10
lines changed

5 files changed

+32
-10
lines changed

.changeset/tangy-rings-retire.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@saleor/app-sdk": major
3+
---
4+
5+
MetadataManager now requires deleteMetadata to be defined

src/auth/verify-signature.test.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { describe, expect, it } from "vitest";
2+
3+
import { verifySignatureWithJwks } from "@/auth/verify-signature";
4+
5+
/**
6+
* Actual signature copied from testing webhook payload.
7+
*/
8+
const testSignature =
9+
"eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il0sImlzcyI6Imh0dHBzOi8vaGFja2F0aG9uLXNoaXBwaW5nLmV1LnNhbGVvci5jbG91ZC9ncmFwaHFsLyIsImtpZCI6InlLdzlYeUVmOHgyYnd5SkdCWVlTckhzeXpHaHhKaktLdlpkb2tOZTlGSWMiLCJ0eXAiOiJKV1QifQ..ShPbfvYc_A5Aq3hiT6sisDclKikDkhxOvGXT2ZWgdsGRjZpg9ukiHRZym0kbfMfDqU5C3Pfo6n7am0ExwbnFWBfOil3pfe3uJOcOn_UGRj76Fy-59TB0JdS_WuTgNQcYM8Yjvlq2sNK4jdAfJVRTTx8FVgEpFrHBKmcMPfD7zuDozswIDMZOkklYqBcyQ76DJYIRVhl3QsktYPPrxDoqf-GJ--e9FuNqtqNDksP1weiDSraqXCF4-Ie7UWZsMIFxkPF8jdKjF_s1UmNS8Xel8soFQQ9L6Gps-NEv7xcHicGt5lgohH4mqhz1YIxCR7v_NTQgWImu_GQ6ELBiBSIZ2Q";
10+
11+
const rawContent = "{\"__typename\": \"OrderCreated\"}";
12+
13+
const jwks =
14+
"{\"keys\": [{\"kty\": \"RSA\", \"key_ops\": [\"verify\"], \"n\": \"uDhbbpspufsQiqHsmC4kvmFQ5l2mGZsGcWhKVSQKQubSdXMedPpLnPD3Z3DsY76DILTm6WfOtSp5rr4KzF5wjurlOEhuFsB1HUfK9ZZB2nEDCQbweoIv3SOdclaNB__pYvQ0nmQHwsAeqH1QUuFUIvOL3t31rhjvzX6wvS49fGNb7rDlqQjufCvaX_n-ADJTgEAg6y1Mzn5NhgoTV1KTBeviyZqCdwvD6bk1ghN2XXWpNcARTzu3WHrmzIzkTwQeIMG8efwIddjfCaMGiOzAfzdQlqHlHPL1Xb5kV9AVX3kiSy-9shaQY23HdWwwiodrb4k2w34Z9ZZN-MHp8i6JdQ\", \"e\": \"AQAB\", \"use\": \"sig\", \"kid\": \"yKw9XyEf8x2bwyJGBYYSrHsyzGhxJjKKvZdokNe9FIc\"}]}";
15+
16+
describe("verifySignatureWithJwks", () => {
17+
it("Returns empty promise if signature is valid", () =>
18+
expect(verifySignatureWithJwks(jwks, testSignature, rawContent)).resolves.not.toThrow());
19+
20+
it("Throws if signature is invalid", () =>
21+
expect(
22+
verifySignatureWithJwks(jwks, testSignature, "{\"forged\": \"payload\"}"),
23+
).rejects.toThrow());
24+
});

src/auth/verify-signature.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ const debug = createDebug("verify-signature");
77
/**
88
* Verify the Webhook payload signature from provided JWKS string.
99
* JWKS can be cached to avoid unnecessary calls.
10-
*
11-
* TODO: Add test
1210
*/
1311
export const verifySignatureWithJwks = async (jwks: string, signature: string, rawBody: string) => {
1412
const [header, , jwsSignature] = signature.split(".");
@@ -22,14 +20,14 @@ export const verifySignatureWithJwks = async (jwks: string, signature: string, r
2220

2321
try {
2422
const parsedJWKS = JSON.parse(jwks);
23+
2524
localJwks = jose.createLocalJWKSet(parsedJWKS) as jose.FlattenedVerifyGetKey;
2625
} catch {
2726
debug("Could not create local JWKSSet from given data: %s", jwks);
27+
2828
throw new Error("JWKS verification failed - could not parse given JWKS");
2929
}
3030

31-
debug("Created remote JWKS");
32-
3331
try {
3432
await jose.flattenedVerify(jws, localJwks);
3533
debug("JWKS verified");

src/handlers/shared/saleor-webhook-validator.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ describe("SaleorWebhookValidator", () => {
230230
});
231231
});
232232

233-
// TODO: This should be required
234233
it("Fallbacks to null if version is missing in payload", async () => {
235234
vi.spyOn(adapter, "getRawBody").mockResolvedValue(JSON.stringify({}));
236235
vi.spyOn(requestProcessor, "getSaleorHeaders").mockReturnValue(validHeaders);

src/settings-manager/metadata-manager.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ const serializeSettingsToMetadata = ({ key, value, domain }: SettingsValue): Met
4141
export interface MetadataManagerConfig {
4242
fetchMetadata: FetchMetadataCallback;
4343
mutateMetadata: MutateMetadataCallback;
44-
/**
45-
* Keep it optional, to avoid breaking changes. If not provided, delete will throw.
46-
* TODO: Make it required in next major version
47-
*/
4844
deleteMetadata?: DeleteMetadataCallback;
4945
}
5046

@@ -98,7 +94,7 @@ export class MetadataManager implements SettingsManager {
9894
async delete(args: DeleteSettingsValue | DeleteSettingsValue[] | string | string[]) {
9995
if (!this.deleteMetadata) {
10096
throw new Error(
101-
"Delete not implemented. Ensure MetadataManager is configured with deleteMetadata param in constructor"
97+
"Delete not implemented. Ensure MetadataManager is configured with deleteMetadata param in constructor",
10298
);
10399
}
104100

0 commit comments

Comments
 (0)