Skip to content

Commit

Permalink
PP-12395: Revoke key functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
oswaldquek committed Jan 3, 2025
1 parent ebdea77 commit 08c4dba
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ async function get (req, res) {
return {
...activeKey,
changeNameLink: formatSimplifiedAccountPathsFor(paths.simplifiedAccount.settings.apiKeys.changeName,
req.service.externalId, req.account.type, activeKey.tokenLink),
revokeKeyLink: formatSimplifiedAccountPathsFor(paths.simplifiedAccount.settings.apiKeys.revoke,
req.service.externalId, req.account.type, activeKey.tokenLink)
}
}),
Expand All @@ -23,3 +25,4 @@ async function get (req, res) {
module.exports = { get }
module.exports.createApiKey = require('./create/create-api-key.controller')
module.exports.changeName = require('./change-name/change-name.controller')
module.exports.revoke = require('./revoke/revoke.controller')
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ describe('Controller: settings/api-keys', () => {
apiKeys.map(apiKey => {
return {
...apiKey,
changeNameLink: `/simplified/service/${SERVICE_ID}/account/${ACCOUNT_TYPE}/settings/api-keys/change-name/${apiKeys[0].tokenLink}`
changeNameLink: `/simplified/service/${SERVICE_ID}/account/${ACCOUNT_TYPE}/settings/api-keys/change-name/${apiKeys[0].tokenLink}`,
revokeKeyLink: `/simplified/service/${SERVICE_ID}/account/${ACCOUNT_TYPE}/settings/api-keys/revoke/${apiKeys[0].tokenLink}`
}
}))
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const paths = require('@root/paths')
const formatSimplifiedAccountPathsFor = require('@utils/simplified-account/format/format-simplified-account-paths-for')
const { response } = require('@utils/response')
const { getKeyByTokenLink } = require('@services/api-keys.service')

async function get (req, res) {
const tokenLink = req.params.tokenLink
const apiKey = await getKeyByTokenLink(req.account.id, tokenLink)
return response(req, res, 'simplified-account/settings/api-keys/revoke', {
description: apiKey.description,
backLink: formatSimplifiedAccountPathsFor(paths.simplifiedAccount.settings.apiKeys.index, req.service.externalId, req.account.type)
})
}

module.exports = { get }
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const ControllerTestBuilder = require('@test/test-helpers/simplified-account/controllers/ControllerTestBuilder.class')
const sinon = require('sinon')
const { expect } = require('chai')
const formatSimplifiedAccountPathsFor = require('@utils/simplified-account/format/format-simplified-account-paths-for')
const paths = require('@root/paths')

const ACCOUNT_TYPE = 'live'
const SERVICE_ID = 'service-id-123abc'
const mockResponse = sinon.spy()
const TOKEN_LINK = '550e8400-e29b-41d4-a716-446655440000'
const token = {
description: 'token description',
token_link: TOKEN_LINK
}
const apiKeysService = {
getKeyByTokenLink: sinon.stub().resolves(token)
}

const {
req,
res,
nextRequest,
call
} = new ControllerTestBuilder('@controllers/simplified-account/settings/api-keys/revoke/revoke.controller')
.withServiceExternalId(SERVICE_ID)
.withAccountType(ACCOUNT_TYPE)
.withStubs({
'@utils/response': { response: mockResponse },
'@services/api-keys.service': apiKeysService
})
.build()

describe('Controller: settings/api-keys/revoke', () => {
describe('get', () => {
before(() => {
nextRequest({
params: {
tokenLink: TOKEN_LINK
}
})
call('get')
})

it('should call the response method', () => {
expect(mockResponse).to.have.been.calledOnce // eslint-disable-line
})

it('should pass req, res, template path and context to the response method', () => {
expect(mockResponse).to.have.been.calledWith(
{ ...req, params: { tokenLink: TOKEN_LINK } },
res,
'simplified-account/settings/api-keys/revoke',
{
description: token.description,
backLink: formatSimplifiedAccountPathsFor(paths.simplifiedAccount.settings.apiKeys.index, SERVICE_ID, ACCOUNT_TYPE)
})
})
})
})
3 changes: 2 additions & 1 deletion app/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ module.exports = {
apiKeys: {
index: '/settings/api-keys',
create: '/settings/api-keys/create',
changeName: '/settings/api-keys/change-name/:tokenLink'
changeName: '/settings/api-keys/change-name/:tokenLink',
revoke: '/settings/api-keys/revoke/:tokenLink'
},
webhooks: {
index: '/settings/webhooks'
Expand Down
10 changes: 10 additions & 0 deletions app/services/api-keys.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,19 @@ const changeApiKeyName = async (tokenLink, name) => {
await publicAuthClient.updateToken({ payload: { token_link: tokenLink, description: name } })
}

/**
* @param {string} gatewayAccountId
* @param {string} tokenLink
* @return {Promise<*>}
*/
const getKeyByTokenLink = async (gatewayAccountId, tokenLink) => {
return await publicAuthClient.getKeyByTokenLink(gatewayAccountId, tokenLink)
}

module.exports = {
changeApiKeyName,
createApiKey,
getActiveKeys,
getKeyByTokenLink,
TOKEN_SOURCE
}
14 changes: 14 additions & 0 deletions app/services/clients/public-auth.client.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,22 @@ async function revokeTokensForAccount (accountId) {
await this.client.delete(url, 'revoke all tokens for gateway account')
}

/**
* @param {string} accountId
* @param {string} tokenLink
* @return {Promise<*>}
*/
async function getKeyByTokenLink (accountId, tokenLink) {
this.client = new Client(SERVICE_NAME)
const url = `${process.env.PUBLIC_AUTH_URL}/${accountId}/${tokenLink}`
configureClient(this.client, url)
const response = await this.client.get(url, 'get token by token link and account id')
return response.data
}

module.exports = {
getActiveTokensForAccount,
getKeyByTokenLink,
getRevokedTokensForAccount,
createTokenForAccount,
updateToken,
Expand Down
2 changes: 2 additions & 0 deletions app/simplified-account-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ simplifiedAccount.get(paths.simplifiedAccount.settings.apiKeys.create, permissio
simplifiedAccount.post(paths.simplifiedAccount.settings.apiKeys.create, permission('tokens:create'), serviceSettingsController.apiKeys.createApiKey.post)
simplifiedAccount.get(paths.simplifiedAccount.settings.apiKeys.changeName, permission('tokens:update'), serviceSettingsController.apiKeys.changeName.get)
simplifiedAccount.post(paths.simplifiedAccount.settings.apiKeys.changeName, permission('tokens:update'), serviceSettingsController.apiKeys.changeName.post)
simplifiedAccount.get(paths.simplifiedAccount.settings.apiKeys.revoke, permission('tokens:delete'), serviceSettingsController.apiKeys.revoke.get)
simplifiedAccount.post(paths.simplifiedAccount.settings.apiKeys.revoke, permission('tokens:delete'), serviceSettingsController.apiKeys.revoke.post)

// stripe details
const stripeDetailsPath = paths.simplifiedAccount.settings.stripeDetails
Expand Down
2 changes: 1 addition & 1 deletion app/views/simplified-account/settings/api-keys/index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
text: 'Change name'
},
{
href: '#',
href: key.revokeKeyLink,
text: 'Revoke'
}
]
Expand Down
38 changes: 38 additions & 0 deletions app/views/simplified-account/settings/api-keys/revoke.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends "../settings-layout.njk" %}

{% block settingsPageTitle %}
API keys - revoke key
{% endblock %}

{% block settingsContent %}
<form id="revoke-api-key" method="post" novalidate>
<input id="csrf" name="csrfToken" type="hidden" value="{{ csrf }}"/>

{{ govukRadios({
name: 'revokeApiKey',
fieldset: {
legend: {
text: 'Are you sure you want to revoke ' + description,
isPageHeading: true,
classes: 'govuk-fieldset__legend--l govuk-!-font-weight-bold'
}
},
hint: {
text: 'The key will stop working immediately. Any integration you’ve created will no longer work.'
},
items: [
{
value: 'Yes',
text: 'Yes'
},
{
value: 'No',
text: 'No'
}
]
}) }}
{{ govukButton({
text: 'Save changes'
}) }}
</form>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ describe('Settings - API keys', () => {
.within(() => {
cy.get('a')
.should('contain.text', 'Revoke')
.and('have.attr', 'href', '#')
.and('have.attr', 'href', formatSimplifiedAccountPathsFor(paths.simplifiedAccount.settings.apiKeys.revoke,
SERVICE_EXTERNAL_ID, ACCOUNT_TYPE, token.tokenLink))
})

cy.get('.govuk-summary-list__row').eq(0)
Expand Down

0 comments on commit 08c4dba

Please sign in to comment.