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

refactor(backend): add getOrCreate method for grantReferenceService #787

Closed
wants to merge 12 commits into from
Closed

refactor(backend): add getOrCreate method for grantReferenceService #787

wants to merge 12 commits into from

Conversation

raducristianpopa
Copy link
Member

@raducristianpopa raducristianpopa commented Nov 24, 2022

Changes proposed in this pull request

  • Add getOrCreate method for grantReferenceService

Context

Checklist

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

@github-actions github-actions bot added pkg: backend Changes in the backend package. type: source Changes business logic type: tests Testing related labels Nov 24, 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.

Looks solid, just a few small comments. Would test this by

Comment on lines 289 to 292
await grantReferenceService.create({
id: grant.grant,
clientId: uuid()
})
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you need this create

@@ -79,4 +80,60 @@ describe('Grant Reference Service', (): void => {
)
})
})

describe('Get or Create Grant Reference', (): void => {
test('cannot fetch a non-existing grant reference', 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.

Suggested change
test('cannot fetch a non-existing grant reference', async (): Promise<void> => {
test('returns undefined for a non-existing grant reference', async (): Promise<void> => {

expect(retrievedRef).toEqual(existingRef)
})

test('create a grant reference', 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.

Suggested change
test('create a grant reference', async (): Promise<void> => {
test('creates a grant reference', async (): Promise<void> => {

nitpick, generally naming the test as though it's doing the action: the test creates, returns, throws etc

@@ -263,6 +263,42 @@ describe('Auth Middleware', (): void => {
scope.done()
})

test('if getOrCreateGrantReference throws, return 500', 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.

Suggested change
test('if getOrCreateGrantReference throws, return 500', async (): Promise<void> => {
test('returns 500 if getOrCreateGrantReference throws', async (): Promise<void> => {

the same as comments below

Comment on lines 62 to 64
} catch (e) {
const errInfo = e && typeof e === 'object' && e.stack ? e.stack : e
logger.debug(errInfo)
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
} catch (e) {
const errInfo = e && typeof e === 'object' && e.stack ? e.stack : e
logger.debug(errInfo)
} catch (error) {
const errorMessage = error?.message ?? 'Failed to get or create grant reference'
logger.error({ error }, errorMessage)

would prefer something like this, without needing to check the type etc

{ id, clientId: uuid() },
AccessAction.List
)
).rejects.toThrowError('does not match internal reference clientId')
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought we would have needed a RegEx here, but it seems to work?

Suggested change
).rejects.toThrowError('does not match internal reference clientId')
).rejects.toThrowError(/does not match internal reference clientId/)

Copy link
Member Author

Choose a reason for hiding this comment

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

I was thinking the same, but based on Jest docs, RegEx and strings are equivalent in this case.

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.

Looks great!
In order to properly test this we need to:

  • Create or seed an initial grant in the auth server
  • Make a request (e.g. get incoming payment) with the token related to the created grant, and verify that the grant reference was created in backend's database during token introspection
  • Make another request (e.g. duplicate get incoming payment) with the token related to the created grant, and this time verify the grant reference was fetched correctly from backend's database.

Easiest way would be to test this with the Create Incoming Payment request in the Postman P2P payment transfer example collection, after my PR is merged in. Once that is merged, I can walk you through the flow

}

return grantRef
} else if (action === AccessAction.Create) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this check should be moved out to the caller.

Comment on lines +58 to +61
await grantReferenceService.getOrCreate(
{ id: grant.grant, clientId: grant.clientId },
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
await grantReferenceService.getOrCreate(
{ id: grant.grant, clientId: grant.clientId },
action
)
if (action === AccessAction.Create) {
await grantReferenceService.getOrCreate({
id: grant.grant,
clientId: grant.clientId
})
} else {
await grantReferenceService.get(grant.grant)
}

Copy link
Member Author

Choose a reason for hiding this comment

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

By moving the action check to the caller, the clientId check

if (grantRef) {
if (grantRef.clientId !== options.clientId) {
throw new Error(
`clientID ${options.clientId} for grant ${options.id} does not match internal reference clientId ${grantRef.clientId}.`
)
}

will probably need to be moved to the getGrantRerefence method
async function getGrantReference(grantId: string, trx: Transaction) {
return await GrantReference.query(trx).findById(grantId)
}

and will have to take both arguments (id and clientId)

async function getGrantReference(
  options: CreateGrantReferenceOptions,
  trx: Transaction
) {
// ...
}

otherwise there will be no validation for the clientId when calling grantReferenceService.get

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm leaning towards not passing clientId to grantReferenceService.get (even though this is currently the only place calling it).
What if we moved the clientId check out here?

Suggested change
await grantReferenceService.getOrCreate(
{ id: grant.grant, clientId: grant.clientId },
action
)
if (action === AccessAction.Create) {
await grantReferenceService.getOrCreate({
id: grant.grant,
clientId: grant.clientId
})
} else {
const grantRef = await grantReferenceService.get(grant.grant)
if (grantRef && grantRef.clientId !== grant.clientId) {
throw new Error(
`clientID ${grant.clientId} for grant ${grant.id} does not match internal reference clientId ${grantRef.clientId}.`
}
}
}

🤔 that looks a lot like how it was before...

Is there an argument for not actually using getOrCreate?
It looks like the AccessAction.Create check was added after this issue was opened:

@wilsonianb
Copy link
Contributor

This will completely remove grantReferenceService (if we decide we want to):

@raducristianpopa
Copy link
Member Author

Closing this PR since #800 got merged in.

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.

Add grantReferenceService.getOrCreate
3 participants