Skip to content

Commit

Permalink
SDIT-2556 Additional config and ensure HPA_USER role set (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
karenmillermoj authored Nov 22, 2024
1 parent 797701e commit df84f74
Show file tree
Hide file tree
Showing 11 changed files with 324 additions and 4 deletions.
4 changes: 2 additions & 2 deletions integration_tests/e2e/signIn.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import AuthManageDetailsPage from '../pages/authManageDetails'
context('Sign In', () => {
beforeEach(() => {
cy.task('reset')
cy.task('stubSignIn')
cy.task('stubSignIn', { roles: ['ROLE_HPA_USER'] })
})

it('Unauthenticated user directed to auth', () => {
Expand Down Expand Up @@ -66,7 +66,7 @@ context('Sign In', () => {
Page.verifyOnPage(AuthSignInPage)

cy.task('stubVerifyToken', true)
cy.task('stubSignIn', { name: 'bobby brown' })
cy.task('stubSignIn', { name: 'bobby brown', roles: ['ROLE_HPA_USER'] })

cy.signIn()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { components } from './index'

export type Prisoner = components['schemas']['Prisoner']
export type PagedModelPrisoner = components['schemas']['PagedModelPrisoner']
2 changes: 1 addition & 1 deletion server/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function createApp(services: Services): express.Application {
app.use(setUpStaticResources())
nunjucksSetup(app)
app.use(setUpAuthentication())
app.use(authorisationMiddleware())
app.use(authorisationMiddleware(['ROLE_HPA_USER']))
app.use(setUpCsrf())
app.use(setUpCurrentUser())

Expand Down
42 changes: 42 additions & 0 deletions server/data/historicalPrisonerApiClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import nock from 'nock'

import config from '../config'
import HistoricalPrisonerApiClient from './historicalPrisonerApiClient'

jest.mock('./tokenStore/redisTokenStore')

const token = { access_token: 'token-1', expires_in: 300 }

describe('historicalPrisonerApiClient', () => {
let fakeHistoricalPrisonerApiClient: nock.Scope
let historicalPrisonerApiClient: HistoricalPrisonerApiClient

beforeEach(() => {
fakeHistoricalPrisonerApiClient = nock(config.apis.historicalPrisonerApi.url)
historicalPrisonerApiClient = new HistoricalPrisonerApiClient()
})

afterEach(() => {
jest.resetAllMocks()
nock.cleanAll()
})

describe('identifiers', () => {
it('should return data from api', async () => {
const response = { data: 'data' }

fakeHistoricalPrisonerApiClient
.get('/identifiers?prisonNumber=A1234BC&pnc=456&cro=789&page=1')
.matchHeader('authorization', `Bearer ${token.access_token}`)
.reply(200, response)

const output = await historicalPrisonerApiClient.findPrisonersWithIdentifiers(token.access_token, {
prisonerNumber: 'A1234BC',
pnc: '456',
cro: '789',
page: 1,
})
expect(output).toEqual(response)
})
})
})
30 changes: 30 additions & 0 deletions server/data/historicalPrisonerApiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import config from '../config'
import RestClient from './restClient'
import { PagedModelPrisoner } from '../@types/historical-prisoner/historicalPrisonerApiTypes'

export default class HistoricalPrisonerApiClient {
constructor() {}

private static restClient(token: string): RestClient {
return new RestClient('Historical Prisoner Api Client', config.apis.historicalPrisonerApi, token)
}

findPrisonersWithIdentifiers(
token: string,
{
prisonerNumber,
pnc,
cro,
page,
}: {
prisonerNumber?: string
pnc?: string
cro?: string
page: number
},
): Promise<PagedModelPrisoner> {
return HistoricalPrisonerApiClient.restClient(token).get<PagedModelPrisoner>({
path: `/identifiers?prisonNumber=${prisonerNumber}&pnc=${pnc}&cro=${cro}&page=${page}`,
})
}
}
2 changes: 2 additions & 0 deletions server/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import RedisTokenStore from './tokenStore/redisTokenStore'
import InMemoryTokenStore from './tokenStore/inMemoryTokenStore'
import config from '../config'
import HmppsAuditClient from './hmppsAuditClient'
import HistoricalPrisonerApiClient from './historicalPrisonerApiClient'

type RestClientBuilder<T> = (token: string) => T

Expand All @@ -25,6 +26,7 @@ export const dataAccess = () => ({
config.redis.enabled ? new RedisTokenStore(createRedisClient()) : new InMemoryTokenStore(),
),
hmppsAuditClient: new HmppsAuditClient(config.sqs.audit),
historicalPrisonerApiClient: new HistoricalPrisonerApiClient(),
})

export type DataAccess = ReturnType<typeof dataAccess>
Expand Down
6 changes: 6 additions & 0 deletions server/services/auditService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import HmppsAuditClient, { AuditEvent } from '../data/hmppsAuditClient'

export enum Page {
EXAMPLE_PAGE = 'EXAMPLE_PAGE',
COMPARISON = 'COMPARISON',
DISCLAIMER_ACCEPTED = 'DISCLAIMER_ACCEPTED',
LOG_IN = 'LOGIN',
PRINT = 'PRINT',
SEARCH = 'SEARCH',
VIEW = 'VIEW',
}

export interface PageViewEventDetails {
Expand Down
21 changes: 21 additions & 0 deletions server/services/historicalPrisonerService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import HistoricalPrisonerApiClient from '../data/historicalPrisonerApiClient'
import { PagedModelPrisoner } from '../@types/historical-prisoner/historicalPrisonerApiTypes'

export default class HistoricalPrisonerService {
constructor(private readonly historicalPrisonerApiClient: HistoricalPrisonerApiClient) {}

async findPrisonersWithIdentifiers(
token: string,
searchParams: {
prisonerNumber?: string
pnc?: string
cro?: string
sort: string
page: number
size: number
},
): Promise<PagedModelPrisoner> {
const { ...queryParams } = searchParams
return this.historicalPrisonerApiClient.findPrisonersWithIdentifiers(token, queryParams)
}
}
4 changes: 3 additions & 1 deletion server/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { dataAccess } from '../data'
import AuditService from './auditService'
import HistoricalPrisonerService from './historicalPrisonerService'

export const services = () => {
const { applicationInfo, hmppsAuditClient } = dataAccess()
const { applicationInfo, hmppsAuditClient, historicalPrisonerApiClient } = dataAccess()

const auditService = new AuditService(hmppsAuditClient)

return {
applicationInfo,
auditService,
historicalPrisonerService: new HistoricalPrisonerService(historicalPrisonerApiClient),
}
}

Expand Down
57 changes: 57 additions & 0 deletions server/views/pages/disclaimer.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %}
{% from "govuk/components/button/macro.njk" import govukButton %}

{% extends "../partials/layout.njk" %}

{% set pageTitle = "Usage" %}
{% set mainClasses = "app-container govuk-body" %}

{% block content %}

<div class="govuk-grid-row govuk-body">
<h1 class="govuk-heading-l">Usage</h1>
<form action="/disclaimer" method="post">
<input type="hidden" name="_csrf" value="{{ csrfToken }}"/>`
`
<div class="govuk-grid-column-two-thirds">
This information is Official Sensitive and should not be shared with anyone who
does not have a valid reason to use it. The Information in this application which was created
using the legacy application, LIDS, is accurate for that period of time entered and should be
used in conjunction with legislation and codes which applied at the time of entry. Information
in this application which was created using Prison NOMIS may not be accurate and should be
discounted. Any information which can be found on Prison NOMIS should be taken from Prison
NOMIS. Please note that MoJ/HMPPS will not accept any responsibility for errors on the system.

<div class="govuk-list">
{{ govukCheckboxes({
idPrefix: 'disclaimer',
name: 'disclaimer',
fieldset: {
legend: {
text: ' ',
isPageHeading: false,
classes: "govuk-label"
}
},
items: [
{
value: 'disclaimer',
text: 'I confirm that I understand'
}
],
errorMessage: errors | findError('disclaimer')
}) }}
</div>

{{ govukButton({
text: "Continue",
href: params.href,
preventDoubleClick: true,
attributes: { "data-qa": "continue" }
}) }}
</div>
</form>
</div>
</div>

{% endblock %}
156 changes: 156 additions & 0 deletions server/views/pages/search.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
{% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/date-input/macro.njk" import govukDateInput %}
{% from "govuk/components/input/macro.njk" import govukInput %}
{% from "govuk/components/radios/macro.njk" import govukRadios %}

{% extends "../partials/layout.njk" %}

{% set pageTitle = "Usage" %}
{% set mainClasses = "app-container govuk-body" %}

{% block content %}
<div class="govuk-grid-row govuk-body">
<h1 class="govuk-heading-l">Prisoner Search</h1>

<div class="govuk-grid-column-one-third">
<form action="/search" method="post">
<input type="hidden" name="_csrf" value="{{ csrfToken }}"/>

{% set nameHtml %}
{{ govukInput({
id: "first-name",
name: "firstName",
classes: "govuk-!-width-one-half",
label: {
text: "First name or initial"
},
errorMessage: validationErrors.firstName
}) }}
{{ govukInput({
id: "last-name",
name: "lastName",
classes: "govuk-!-width-one-half",
label: {
text: "Surname"
},
errorMessage: validationErrors.contactByEmail
}) }}
{{ govukDateInput({
id: "date-of-birth",
namePrefix: "date-of-birth",
fieldset: {
legend: {
text: "Date of birth",
isPageHeading: false
}
}
}) }}
{{ govukInput({
id: "age",
name: "age",
classes: "govuk-!-width-one-half",
label: {
text: "Or, enter an age or age range"
},
errorMessage: validationErrors.age,
hint: {
text: "For example, 32-34"
}
}) }}
{% endset -%}

{% set idHtml %}
{{ govukInput({
id: "prison-number",
name: "prisonNumber",
classes: "govuk-!-width-one-third",
label: {
text: "Prison number"
}
}) }}
{{ govukInput({
id: "pnc-number",
name: "pncNumber",
classes: "govuk-!-width-one-third",
label: {
text: "PNC number"
},
hint: {
text: "Previously known as CRN (Crime Reference Number)"
}
}) }}
{{ govukInput({
id: "cro-number",
name: "croNumber",
classes: "govuk-!-width-one-third",
label: {
text: "CRO number"
}
}) }}
{% endset -%}

{% set otherHtml %}
{{ govukInput({
id: "contact-by-text",
name: "contactByText",
classes: "govuk-!-width-one-third",
label: {
text: "Enter any combination of street, town, postcode, eg"
},
hint: {
text: "22b Baker Street W1"
}
}) }}
{% endset -%}

{{ govukRadios({
name: "contact",
fieldset: {
legend: {
text: "Search by",
isPageHeading: false,
classes: "govuk-fieldset__legend--l"
}
},
items: [
{
value: "name",
text: "Name/age",
checked: true,
conditional: {
html: nameHtml
}
},
{
value: "id",
text: "Unique identifier",
conditional: {
html: idHtml
}
},
{
value: "other",
text: "Other",
conditional: {
html: otherHtml
}
}
]
}) }}

{{ govukButton({
text: "Search",
href: params.href,
preventDoubleClick: true,
attributes: { "data-qa": "search" }
}) }}
</form>
</div>

<div class="govuk-grid-column-two-thirds">
ADD RESULTS HERE
</div>

</div>

{% endblock %}

0 comments on commit df84f74

Please sign in to comment.