From e10f06930d8e0be3a961aa49e6d5cbe90dcffc07 Mon Sep 17 00:00:00 2001 From: Blair Currey <12960453+BlairCurrey@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:16:43 -0500 Subject: [PATCH 1/6] feat: update receiver regex validation --- openapi/auth-server.yaml | 2 +- openapi/schemas.yaml | 5 +-- packages/openapi/src/middleware.test.ts | 43 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/openapi/auth-server.yaml b/openapi/auth-server.yaml index 66129f2f..a237dd5e 100644 --- a/openapi/auth-server.yaml +++ b/openapi/auth-server.yaml @@ -110,7 +110,7 @@ paths: - read identifier: 'https://ilp.rafiki.money/alice' limits: - receiver: 'https://ilp.rafiki.money/connections/45a0d0ee-26dc-4c66-89e0-01fbf93156f7' + receiver: 'https://ilp.rafiki.money/incoming-payment/45a0d0ee-26dc-4c66-89e0-01fbf93156f7' interval: 'R12/2019-08-24T14:15:22Z/P1M' debitAmount: value: '500' diff --git a/openapi/schemas.yaml b/openapi/schemas.yaml index fc0bce44..f93637f6 100644 --- a/openapi/schemas.yaml +++ b/openapi/schemas.yaml @@ -42,10 +42,11 @@ components: type: string description: The URL of the incoming payment or ILP STREAM connection that is being paid. format: uri - pattern: '^https://(.+)/(incoming-payments|connections)/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' + pattern: '^(https|http)://(.+)/incoming-payments/(.+)$' examples: - 'https://ilp.rafiki.money/incoming-payments/08394f02-7b7b-45e2-b645-51d04e7c330c' - - 'https://ilp.rafiki.money/connections/016da9d5-c9a4-4c80-a354-86b915a04ff8' + - 'http://ilp.rafiki.money/incoming-payments/08394f02-7b7b-45e2-b645-51d04e7c330c' + - 'https://ilp.rafiki.money/incoming-payments/1' walletAddress: title: Wallet Address type: string diff --git a/packages/openapi/src/middleware.test.ts b/packages/openapi/src/middleware.test.ts index 7aa14187..3aa35b8e 100644 --- a/packages/openapi/src/middleware.test.ts +++ b/packages/openapi/src/middleware.test.ts @@ -256,6 +256,49 @@ describe('OpenAPI Validator', (): void => { expect(next).toHaveBeenCalled() } ) + + describe('Quote', (): void => { + test.each` + body | message | description + ${{ receiver: 'ht999tp://something.com/incoming-payments' }} | ${'body.receiver must match pattern "^(https|http):..(.+).incoming-payments.(.+)$"'} | ${'invalid receiver, unknown protocol'} + ${{ receiver: 'http://something.com/incoming-payments' }} | ${'body.receiver must match pattern "^(https|http):..(.+).incoming-payments.(.+)$"'} | ${'invalid receiver, missing incoming payment id'} + ${{ receiver: 'http://something.com/connections/c3a0d182-b221-4612-a500-07ad106b5f5d' }} | ${'body.receiver must match pattern "^(https|http):..(.+).incoming-payments.(.+)$"'} | ${'invalid receiver, wrong path'} + `( + 'returns 400 on invalid quote body ($description)', + async ({ body, message }): Promise => { + const validateQuotePostMiddleware = createValidatorMiddleware( + openApi, + { + path: '/quotes', + method: HttpMethod.POST + } + ) + + const ctx = createContext( + { + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json' + } + }, + {} + ) + addTestSignatureHeaders(ctx) + ctx.request.body = { + ...body, + walletAddress: WALLET_ADDRESS, + method: 'ilp' + } + await expect( + validateQuotePostMiddleware(ctx, next) + ).rejects.toMatchObject({ + status: 400, + message + }) + expect(next).not.toHaveBeenCalled() + } + ) + }) }) }) From b6e7dcd94134b36733afda9c0d46abb27cb1e9f7 Mon Sep 17 00:00:00 2001 From: Blair Currey <12960453+BlairCurrey@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:28:44 -0500 Subject: [PATCH 2/6] fix: example url typo --- openapi/auth-server.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi/auth-server.yaml b/openapi/auth-server.yaml index a237dd5e..1f868fce 100644 --- a/openapi/auth-server.yaml +++ b/openapi/auth-server.yaml @@ -110,7 +110,7 @@ paths: - read identifier: 'https://ilp.rafiki.money/alice' limits: - receiver: 'https://ilp.rafiki.money/incoming-payment/45a0d0ee-26dc-4c66-89e0-01fbf93156f7' + receiver: 'https://ilp.rafiki.money/incoming-payments/45a0d0ee-26dc-4c66-89e0-01fbf93156f7' interval: 'R12/2019-08-24T14:15:22Z/P1M' debitAmount: value: '500' From d881a37917a29b6af1c343d1459c71e97395ad47 Mon Sep 17 00:00:00 2001 From: Blair Currey <12960453+BlairCurrey@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:12:27 -0500 Subject: [PATCH 3/6] Update openapi/schemas.yaml Co-authored-by: Max Kurapov --- openapi/schemas.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi/schemas.yaml b/openapi/schemas.yaml index f93637f6..c08ff832 100644 --- a/openapi/schemas.yaml +++ b/openapi/schemas.yaml @@ -40,7 +40,7 @@ components: receiver: title: Receiver type: string - description: The URL of the incoming payment or ILP STREAM connection that is being paid. + description: The URL of the incoming payment that is being paid. format: uri pattern: '^(https|http)://(.+)/incoming-payments/(.+)$' examples: From e48673ccc1940ce6a7f668e76ffdcd0d4a454967 Mon Sep 17 00:00:00 2001 From: Blair Currey <12960453+BlairCurrey@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:17:49 -0500 Subject: [PATCH 4/6] chore: add changeset --- .changeset/fuzzy-rivers-jog.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fuzzy-rivers-jog.md diff --git a/.changeset/fuzzy-rivers-jog.md b/.changeset/fuzzy-rivers-jog.md new file mode 100644 index 00000000..a0c1c360 --- /dev/null +++ b/.changeset/fuzzy-rivers-jog.md @@ -0,0 +1,5 @@ +--- +'@interledger/open-payments': minor +--- + +Widened receiver regex to accept http and any id format. Removed previously deprecated 'connections' path. From 78626fb810b5ac6e219f6a39e71a8bc8ca75a719 Mon Sep 17 00:00:00 2001 From: Blair Currey <12960453+BlairCurrey@users.noreply.github.com> Date: Wed, 28 Feb 2024 13:01:56 -0500 Subject: [PATCH 5/6] test(openapi): add quote validation tests --- packages/openapi/src/middleware.test.ts | 83 ++++++++++++++++++++----- 1 file changed, 69 insertions(+), 14 deletions(-) diff --git a/packages/openapi/src/middleware.test.ts b/packages/openapi/src/middleware.test.ts index 3aa35b8e..29e08e2a 100644 --- a/packages/openapi/src/middleware.test.ts +++ b/packages/openapi/src/middleware.test.ts @@ -258,22 +258,23 @@ describe('OpenAPI Validator', (): void => { ) describe('Quote', (): void => { + let validateQuotePostMiddleware: AppMiddleware + + beforeAll((): void => { + validateQuotePostMiddleware = createValidatorMiddleware(openApi, { + path: '/quotes', + method: HttpMethod.POST + }) + }) + test.each` - body | message | description - ${{ receiver: 'ht999tp://something.com/incoming-payments' }} | ${'body.receiver must match pattern "^(https|http):..(.+).incoming-payments.(.+)$"'} | ${'invalid receiver, unknown protocol'} - ${{ receiver: 'http://something.com/incoming-payments' }} | ${'body.receiver must match pattern "^(https|http):..(.+).incoming-payments.(.+)$"'} | ${'invalid receiver, missing incoming payment id'} - ${{ receiver: 'http://something.com/connections/c3a0d182-b221-4612-a500-07ad106b5f5d' }} | ${'body.receiver must match pattern "^(https|http):..(.+).incoming-payments.(.+)$"'} | ${'invalid receiver, wrong path'} + body | description + ${{ receiver: 'ht999tp://something.com/incoming-payments' }} | ${'invalid receiver, unknown protocol'} + ${{ receiver: 'http://something.com/incoming-payments' }} | ${'invalid receiver, missing incoming payment id'} + ${{ receiver: 'http://something.com/connections/c3a0d182-b221-4612-a500-07ad106b5f5d' }} | ${'invalid receiver, wrong path'} `( 'returns 400 on invalid quote body ($description)', - async ({ body, message }): Promise => { - const validateQuotePostMiddleware = createValidatorMiddleware( - openApi, - { - path: '/quotes', - method: HttpMethod.POST - } - ) - + async ({ body }): Promise => { const ctx = createContext( { headers: { @@ -293,11 +294,65 @@ describe('OpenAPI Validator', (): void => { validateQuotePostMiddleware(ctx, next) ).rejects.toMatchObject({ status: 400, - message + message: + 'body.receiver must match pattern "^(https|http):..(.+).incoming-payments.(.+)$"' }) expect(next).not.toHaveBeenCalled() } ) + test.each` + receiver | description + ${'http://something.com/incoming-payments/c3a0d182-b221-4612-a500-07ad106b5f5d'} | ${'accepts http and uuid'} + ${'https://something.com/incoming-payments/123'} | ${'accepts http and non uuid id format'} + `( + 'calls next on valid request: ($description)', + async ({ receiver }): Promise => { + const ctx = createContext( + { + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json' + }, + url: '/quotes' + }, + {} + ) + addTestSignatureHeaders(ctx) + ctx.request.body = { + receiver, + walletAddress: WALLET_ADDRESS, + method: 'ilp' + } + const next = jest.fn().mockImplementation(() => { + expect(ctx.request.body.receiver).toEqual(receiver) + ctx.status = 201 + ctx.response.body = { + id: 'https://something-else/quotes/3b461206-daae-4d97-88b0-abffbcaa6f96', + walletAddress: 'https://something-else/accounts/someone', + receiveAmount: { + value: '100', + assetCode: 'USD', + assetScale: 2 + }, + debitAmount: { + value: '205', + assetCode: 'USD', + assetScale: 2 + }, + receiver, + expiresAt: '2024-02-28T16:26:32.444Z', + createdAt: '2024-02-28T16:21:32.444Z', + method: 'ilp' + } + }) + + await expect( + validateQuotePostMiddleware(ctx, next) + ).resolves.toBeUndefined() + + expect(next).toHaveBeenCalled() + } + ) }) }) }) From a4b56ecba7765c31e805417c1651a557211174ae Mon Sep 17 00:00:00 2001 From: Blair Currey <12960453+BlairCurrey@users.noreply.github.com> Date: Wed, 28 Feb 2024 13:10:53 -0500 Subject: [PATCH 6/6] chore: generate new types --- .../open-payments/src/openapi/generated/auth-server-types.ts | 2 +- .../src/openapi/generated/resource-server-types.ts | 2 +- .../src/openapi/generated/wallet-address-server-types.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/open-payments/src/openapi/generated/auth-server-types.ts b/packages/open-payments/src/openapi/generated/auth-server-types.ts index 3a2e6c65..2f8f4943 100644 --- a/packages/open-payments/src/openapi/generated/auth-server-types.ts +++ b/packages/open-payments/src/openapi/generated/auth-server-types.ts @@ -337,7 +337,7 @@ export interface external { /** * Receiver * Format: uri - * @description The URL of the incoming payment or ILP STREAM connection that is being paid. + * @description The URL of the incoming payment that is being paid. */ receiver: string; /** diff --git a/packages/open-payments/src/openapi/generated/resource-server-types.ts b/packages/open-payments/src/openapi/generated/resource-server-types.ts index 7320e577..641e229c 100644 --- a/packages/open-payments/src/openapi/generated/resource-server-types.ts +++ b/packages/open-payments/src/openapi/generated/resource-server-types.ts @@ -629,7 +629,7 @@ export interface external { /** * Receiver * Format: uri - * @description The URL of the incoming payment or ILP STREAM connection that is being paid. + * @description The URL of the incoming payment that is being paid. */ receiver: string; /** diff --git a/packages/open-payments/src/openapi/generated/wallet-address-server-types.ts b/packages/open-payments/src/openapi/generated/wallet-address-server-types.ts index 12d1082c..3e4d0c6d 100644 --- a/packages/open-payments/src/openapi/generated/wallet-address-server-types.ts +++ b/packages/open-payments/src/openapi/generated/wallet-address-server-types.ts @@ -156,7 +156,7 @@ export interface external { /** * Receiver * Format: uri - * @description The URL of the incoming payment or ILP STREAM connection that is being paid. + * @description The URL of the incoming payment that is being paid. */ receiver: string; /**