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

Haar 2512 add service values #123

Merged
merged 5 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

NODE_ENV=dev && node_modules/.bin/lint-staged && npm run typecheck && npm test
4 changes: 2 additions & 2 deletions integration_tests/e2e/edit-base-client-deployment.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ context('Edit base client deployment: Auth', () => {
cy.task('stubSignIn')
cy.task('stubManageUser')
cy.task('stubListBaseClients')
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials })
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials, includeService: true })
cy.task('stubGetListClientInstancesList')
})

Expand All @@ -41,7 +41,7 @@ context('Edit base client deployment details page', () => {
cy.task('stubSignIn')
cy.task('stubManageUser')
cy.task('stubListBaseClients')
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials })
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials, includeService: true })
cy.task('stubGetListClientInstancesList')
editBaseClientDeploymentDetailsPage = visitEditBaseClientDeploymentDetailsPage()
})
Expand Down
61 changes: 48 additions & 13 deletions integration_tests/e2e/view-base-client.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ context('Base client page - Auth', () => {
beforeEach(() => {
cy.task('reset')
cy.task('stubSignIn')
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials })
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials, includeService: false })
cy.task('stubManageUser')
cy.task('stubGetListClientInstancesList')
cy.task('stubAddClientInstance')
Expand All @@ -42,7 +42,7 @@ context('Base client page - client credentials flow', () => {
beforeEach(() => {
cy.task('reset')
cy.task('stubSignIn')
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials })
cy.task('stubGetBaseClient', { grantType: GrantType.ClientCredentials, includeService: false })
cy.task('stubManageUser')
cy.task('stubGetListClientInstancesList')
cy.task('stubAddClientInstance')
Expand Down Expand Up @@ -112,18 +112,17 @@ context('Base client page - client credentials flow', () => {
context('Base client page - authorization-code flow', () => {
let baseClientsPage: ViewBaseClientPage

beforeEach(() => {
cy.task('reset')
cy.task('stubSignIn')
cy.task('stubGetBaseClient', { grantType: GrantType.AuthorizationCode })
cy.task('stubManageUser')
cy.task('stubGetListClientInstancesList')
cy.task('stubAddClientInstance')

baseClientsPage = visitBaseClientPage()
})
context('Base client details - response includes service details', () => {
beforeEach(() => {
cy.task('reset')
cy.task('stubSignIn')
cy.task('stubGetBaseClient', { grantType: GrantType.AuthorizationCode, includeService: true })
cy.task('stubManageUser')
cy.task('stubGetListClientInstancesList')
cy.task('stubAddClientInstance')
baseClientsPage = visitBaseClientPage()
})

context('Base client details', () => {
it('User can see base client details table', () => {
baseClientsPage.baseClientDetailsTable().should('be.visible')
})
Expand All @@ -148,4 +147,40 @@ context('Base client page - authorization-code flow', () => {
baseClientsPage.baseClientServiceDetailsTable().should('be.visible')
})
})

context('Base client details - response has null service details', () => {
beforeEach(() => {
cy.task('reset')
cy.task('stubSignIn')
cy.task('stubGetBaseClient', { grantType: GrantType.AuthorizationCode, includeService: false })
cy.task('stubManageUser')
cy.task('stubGetListClientInstancesList')
cy.task('stubAddClientInstance')
baseClientsPage = visitBaseClientPage()
})

it('User can see base client details table', () => {
baseClientsPage.baseClientDetailsTable().should('be.visible')
})

it('User can see audit trail table', () => {
baseClientsPage.baseClientAuditTable().should('be.visible')
})

it('User cannot see client credentials table', () => {
baseClientsPage.baseClientClientCredentialsTable().should('not.exist')
})

it('User can see authorization-code table', () => {
baseClientsPage.baseClientAuthorizationCodeTable().should('be.visible')
})

it('User can see config table', () => {
baseClientsPage.baseClientConfigTable().should('be.visible')
})

it('User cannot see service details panel', () => {
baseClientsPage.baseClientServiceDetailsTable().should('not.exist')
})
})
})
4 changes: 2 additions & 2 deletions integration_tests/mockApis/baseClientsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default {
})
},

stubGetBaseClient: (config: { grantType: GrantType }) => {
stubGetBaseClient: (config: { grantType: GrantType; includeService: boolean }) => {
return stubFor({
request: {
method: 'GET',
Expand All @@ -35,7 +35,7 @@ export default {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
jsonBody: getBaseClientResponseMock(config.grantType),
jsonBody: getBaseClientResponseMock(config.grantType, config.includeService),
},
})
},
Expand Down
6 changes: 4 additions & 2 deletions server/audit/baseClientAudit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ export const sendBaseClientEvent = async (
if (!config.apis.audit.enabled) {
logger.info(`${baseClientEvent} - ${baseClientId} - ${JSON.stringify(details)}`)
} else {
await auditService.sendAuditMessage({
const auditMessage = {
action: baseClientEvent,
who: username,
subjectId: baseClientId,
subjectType: BASE_CLIENT_SUBJECT_TYPE,
correlationId,
service: config.productId,
details: JSON.stringify(details),
})
}
await auditService.sendAuditMessage(auditMessage)
}
}

Expand Down
28 changes: 26 additions & 2 deletions server/controllers/baseClientController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,30 @@ describe('BaseClientController', () => {
expect(baseClientService.getBaseClient).toHaveBeenCalledWith(token, baseClient.baseClientId)
})

it('renders the main view of a base client with null service', async () => {
// GIVEN a base client with null service
const baseClient = baseClientFactory.build()
baseClient.service = null
const clients = clientFactory.buildList(3)
baseClientService.getBaseClient.mockResolvedValue(baseClient)
baseClientService.listClientInstances.mockResolvedValue(clients)

// WHEN the index page is requested
request = createMock<Request>({ params: { baseClientId: baseClient.baseClientId } })
await baseClientController.displayBaseClient()(request, response, next)

// THEN the view base client page is rendered
const presenter = viewBaseClientPresenter(baseClient, clients)
expect(response.render).toHaveBeenCalledWith('pages/base-client.njk', {
baseClient,
presenter,
...nunjucksUtils,
})

// AND the base client is retrieved from the base client service
expect(baseClientService.getBaseClient).toHaveBeenCalledWith(token, baseClient.baseClientId)
})

it('audits the view attempt', async () => {
// GIVEN a base client
const baseClient = baseClientFactory.build()
Expand Down Expand Up @@ -606,7 +630,7 @@ describe('BaseClientController', () => {
it.each([
['renders one client instance', 1, true],
['renders multiple client instances', 3, false],
])(`if %s renders the page with isLastClient %s`, async (_, clientCount, isLastClient) => {
])(`if %s renders the page with isLastClient %s`, async (_, clientCount: number, isLastClient: boolean) => {
// GIVEN a base client
const baseClient = baseClientFactory.build()
const clients = clientFactory.buildList(clientCount)
Expand Down Expand Up @@ -663,7 +687,7 @@ describe('BaseClientController', () => {
it.each([
['one client instance exists', '/', 1],
['multiple client instances', '/base-clients/abcd', 3],
])(`if delete successful and %s, redirects to %s`, async (_, redirectURL, clientCount) => {
])(`if delete successful and %s, redirects to %s`, async (_, redirectURL: string, clientCount: number) => {
// GIVEN a base client
const baseClient = baseClientFactory.build({ baseClientId: 'abcd' })
const clients = clientFactory.buildList(clientCount)
Expand Down
22 changes: 19 additions & 3 deletions server/data/localMockData/baseClientsResponseMock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export const listBaseClientsResponseMock: ListBaseClientsResponse = {
],
}

export const getBaseClientResponseMock: (grantType: GrantType) => GetBaseClientResponse = (grantType: GrantType) => {
export const getBaseClientResponseMock: (grantType: GrantType, includeService: boolean) => GetBaseClientResponse = (
grantType: GrantType,
includeService: boolean = true,
) => {
const response: GetBaseClientResponse = {
grantType: 'CLIENT_CREDENTIALS',
clientId: 'base_client_id_1',
Expand All @@ -45,7 +48,6 @@ export const getBaseClientResponseMock: (grantType: GrantType) => GetBaseClientR
jiraNumber: 'jiraNumber',
validDays: 1,
accessTokenValiditySeconds: 3600,
serviceAuthorities: ['ROLE_ONE', 'ROLE_TWO'],
deployment: {
clientType: 'service',
team: 'deployment team',
Expand All @@ -69,14 +71,28 @@ export const getBaseClientResponseMock: (grantType: GrantType) => GetBaseClientR
}
}

return {
const baseClient = {
...response,
grantType: 'AUTHORIZATION_CODE',
redirectUris: ['redirectUri1', 'redirectUri2'],
jwtFields: '+alpha,-beta',
mfa: MfaType.None,
mfaRememberMe: false,
}

return includeService
? {
...baseClient,
service: {
name: 'service name',
description: 'service description',
authorisedRoles: ['ROLE_ONE', 'ROLE_TWO'],
url: 'https://localhost:3000',
enabled: true,
contact: 'service contact',
},
}
: baseClient
}

export const getListClientInstancesResponseMock: ListClientInstancesResponse = {
Expand Down
6 changes: 3 additions & 3 deletions server/interfaces/baseClientApi/baseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface BaseClient {
expired: boolean
clientCredentials: ClientCredentialsDetails
authorisationCode: AuthorisationCodeDetails
service: ServiceDetails
service?: ServiceDetails
deployment: DeploymentDetails
config: ClientConfig
}
Expand All @@ -31,13 +31,13 @@ interface AuthorisationCodeDetails {
mfa: MfaType
}

interface ServiceDetails {
export interface ServiceDetails {
serviceName: string
description: string
serviceRoles: string[]
url: string
contact: string
status: string
status: boolean
}

export interface DeploymentDetails {
Expand Down
9 changes: 8 additions & 1 deletion server/interfaces/baseClientApi/baseClientResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,14 @@ export interface GetBaseClientResponse {
secretKey: string
deploymentInfo: string
}
serviceAuthorities?: string[]
service?: {
name: string
description: string
authorisedRoles: string[]
url: string
enabled: boolean
contact: string
}
}

export interface ClientSecretsResponse {
Expand Down
26 changes: 17 additions & 9 deletions server/mappers/baseClientApi/getBaseClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GetBaseClientResponse } from '../../interfaces/baseClientApi/baseClientResponse'
import { BaseClient, DeploymentDetails } from '../../interfaces/baseClientApi/baseClient'
import { BaseClient, DeploymentDetails, ServiceDetails } from '../../interfaces/baseClientApi/baseClient'
import { ClientType } from '../../data/enums/clientTypes'
import { HostingType } from '../../data/enums/hostingTypes'
import { snake, toBaseClientId } from '../../utils/utils'
Expand All @@ -23,14 +23,7 @@ export default (response: GetBaseClientResponse): BaseClient => {
mfaRememberMe: response.mfaRememberMe ? response.mfaRememberMe : false,
mfa: response.mfa ? response.mfa : '',
},
service: {
serviceName: '',
description: '',
serviceRoles: response.serviceAuthorities ? response.serviceAuthorities : [],
url: '',
contact: '',
status: '',
},
service: getService(response),
deployment: getDeployment(response),
config: {
allowedIPs: response.ips ? response.ips : [],
Expand Down Expand Up @@ -77,3 +70,18 @@ const getDeployment = (response: GetBaseClientResponse): DeploymentDetails => {

return deployment
}

const getService = (response: GetBaseClientResponse): ServiceDetails => {
if (!response.service) {
return null
}

return {
serviceName: response.service.name,
description: response.service.description,
serviceRoles: response.service.authorisedRoles ? response.service.authorisedRoles : [],
url: response.service.url,
contact: response.service.contact,
status: response.service.enabled,
}
}
7 changes: 6 additions & 1 deletion server/mappers/baseClientApi/listBaseClients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BaseClient, BaseClientListFilter } from '../../interfaces/baseClientApi
import { toClientType } from '../../data/enums/clientTypes'
import { toGrantType } from '../../data/enums/grantType'
import { kebab, multiSeparatorSplit, snake, toBaseClientId } from '../../utils/utils'
import { MfaType } from '../../data/enums/mfaTypes'

export const mapListBaseClientRequest = (request: Request): BaseClientListFilter => {
const asJson = JSON.stringify(request.query)
Expand Down Expand Up @@ -71,14 +72,16 @@ export default (response: ListBaseClientsResponse): BaseClient[] => {
registeredRedirectURIs: [],
jwtFields: '',
azureAdLoginFlow: false,
mfaRememberMe: false,
mfa: MfaType.None,
},
service: {
serviceName: client.teamName || '',
description: '',
serviceRoles: [],
url: '',
contact: '',
status: '',
status: false,
},
deployment: {
clientType: snake(client.clientType),
Expand All @@ -90,6 +93,8 @@ export default (response: ListBaseClientsResponse): BaseClient[] => {
deployment: '',
secretName: '',
clientIdKey: '',
secretKey: '',
deploymentInfo: '',
},
config: {
allowedIPs: [],
Expand Down
2 changes: 1 addition & 1 deletion server/mappers/forms/mapCreateBaseClientForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default (request: Request): BaseClient => {
serviceRoles: [],
url: '',
contact: '',
status: '',
status: false,
},
deployment: {
clientType: '',
Expand Down
Loading