Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(backend): do not store entire grant on context #911

Merged
merged 6 commits into from
Jan 11, 2023
Merged

Conversation

wilsonianb
Copy link
Contributor

@wilsonianb wilsonianb commented Dec 20, 2022

Changes proposed in this pull request

  • Make access limits specific to outgoing payment creation.

Context

Checklist

  • Related issues linked using fixes #number
  • Tests added/updated
  • Documentation added
  • Make sure that all checks pass

Make access limits specific to outgoing payment creation.
@github-actions github-actions bot added pkg: backend Changes in the backend package. type: source Changes business logic type: tests Testing related labels Dec 20, 2022
@wilsonianb wilsonianb marked this pull request as ready for review December 20, 2022 22:40
Copy link
Contributor

@mkurapov mkurapov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to come back to this tomorrow (getting late here), just a few minor comments for now

(!access['identifier'] ||
access['identifier'] === ctx.paymentPointer.url) &&
access.actions.find((tokenAction) => {
if (tokenAction == action) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (tokenAction == action) {
if (tokenAction === action) {

I don't think a triple-equals will cause issues here, it'll be just a string comparison at runtime

same below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I originally had this based on a branch using generated OpenAPI types where it was an issue.
I tripled the access type check but missed the actions.

Comment on lines 50 to 51
(!access['identifier'] ||
access['identifier'] === ctx.paymentPointer.url) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(!access['identifier'] ||
access['identifier'] === ctx.paymentPointer.url) &&
(access.identifier === ctx.paymentPointer.url) &&

if its optional

Comment on lines 54 to 55
// Unless the relevant grant action is ReadAll/ListAll add the
// clientId to ctx for Read/List filtering
Copy link
Contributor

@mkurapov mkurapov Dec 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I understand the comment fully, but it reads as though

return (
    (action === AccessAction.Read &&
      tokenAction == AccessAction.ReadAll) ||
     (action === AccessAction.List &&
       tokenAction == AccessAction.ListAll)
)

should be before

if (tokenAction == action) { ... }

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

action will never be ReadAll or ListAll

const toAction = ({
path,
method
}: {
path: string
method: HttpMethod
}): AccessAction | undefined => {
switch (method) {
case HttpMethod.GET:
return path.endsWith('{id}') ? AccessAction.Read : AccessAction.List
case HttpMethod.POST:
return path.endsWith('/complete')
? AccessAction.Complete
: AccessAction.Create
default:
return undefined
}
}

so this should be fine, but I'll update the types to make that explicit.

Copy link
Contributor Author

@wilsonianb wilsonianb Dec 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Actually this is still dependent on Read and ReadAll (and List/ListAll) being mutually exclusive, which is no longer the case (in OpenAPI)

@wilsonianb wilsonianb requested a review from mkurapov December 21, 2022 19:26
mkurapov
mkurapov previously approved these changes Dec 22, 2022
Copy link
Contributor

@mkurapov mkurapov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, non-blocking comments

return new TokenInfo(options, data.key)
return data.active ? data : undefined

return data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return data

@@ -282,7 +289,7 @@ export class App {
}: {
path: string
method: HttpMethod
}): AccessAction | undefined => {
}): RequestAction | undefined => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the RequestAction type 👍 . I propose we call the variable also that: action -> requestAction

import { HttpSigContext, PaymentPointerContext } from '../../app'

export type RequestAction = Exclude<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 I now appreciate Exclude after my types adventure

@@ -92,7 +98,7 @@ async function createOutgoingPayment(
deps: ServiceDependencies,
options: CreateOutgoingPaymentOptions
): Promise<OutgoingPayment | OutgoingPaymentError> {
const grantId = options.grant ? options.grant.grant : undefined
const grantId = options.grant?.id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this be required in the future? i.e. will this end up throwing if there is no grant on the ctx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think grant is mainly optional for creating outgoing payments via the admin api

createOutgoingPayment(
input: CreateOutgoingPaymentInput!
): OutgoingPaymentResponse!

@@ -32,6 +32,11 @@ import {
import { Interval } from 'luxon'
import { knex } from 'knex'

export interface Grant {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this interface first better in the auth/middleware.ts file?

expect(next).toHaveBeenCalled()
expect(ctx.grant).toEqual(tokenInfo)
if (identifierOption !== IdentifierOption.Conflicting) {
test('sets the context client info and calls next', async (): Promise<void> => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More for my own understanding, why are we ok to allow tokenInfo to not have an identifier?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then I'm not sure why it was subsequently re-required for outgoing payments 😬

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

identifier (string):
A string identifier indicating a specific resource at the RS. For example, a patient identifier for a medical API or a bank account number for a financial API.

Based on the description, this feels like it should be reference to specific sub resource, and not just a payment pointer (of how we are currently treating it). I'm ok with keeping it optional across the board, thoughts?

Copy link
Contributor Author

@wilsonianb wilsonianb Jan 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Our own descriptions also seem to suggest it would refer to a specific (sub)resource...
https://github.com/interledger/open-payments/blob/main/openapi/schemas.yaml#L56-L59

description: A string identifier indicating a specific resource at the RS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we do want to be able to refer to a payment pointer, especially for create and list action grants.
If/when we switch to Adrian's grant requests to the payment pointer itself, the client will no longer need to specify the payment pointer. And he's proposed just having a paymentPointer field in the token introspection response for the grant.

mkurapov
mkurapov previously approved these changes Jan 10, 2023
expect(next).toHaveBeenCalled()
expect(ctx.grant).toEqual(tokenInfo)
if (identifierOption !== IdentifierOption.Conflicting) {
test('sets the context client info and calls next', async (): Promise<void> => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

identifier (string):
A string identifier indicating a specific resource at the RS. For example, a patient identifier for a medical API or a bank account number for a financial API.

Based on the description, this feels like it should be reference to specific sub resource, and not just a payment pointer (of how we are currently treating it). I'm ok with keeping it optional across the board, thoughts?

@wilsonianb wilsonianb merged commit dc909a6 into main Jan 11, 2023
@wilsonianb wilsonianb deleted the bw-no-grant branch January 11, 2023 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: backend Changes in the backend package. type: source Changes business logic type: tests Testing related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Do not store entire grant on context
2 participants