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

MAP-305: Use HMPPS Manage Users API for user details #650

Merged
merged 1 commit into from
Oct 6, 2023
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
1 change: 1 addition & 0 deletions feature.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ PRISON_API_URL=http://localhost:9091
PRISONER_SEARCH_API_URL=http://localhost:9091/search
TOKENVERIFICATION_API_URL=http://localhost:9091/token-verification-api
TOKENVERIFICATION_API_ENABLED=true
HMPPS_MANAGE_USERS_API_URL=http://localhost:9091

DB_NAME=use-of-force-int
DB_PORT=5432
Expand Down
3 changes: 3 additions & 0 deletions helm_deploy/use-of-force/templates/_envs.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ env:
- name: NOMIS_AUTH_URL
value: {{ .Values.env.NOMIS_AUTH_URL | quote }}

- name: HMPPS_MANAGE_USERS_API_URL
value: {{ .Values.env.HMPPS_MANAGE_USERS_API_URL | quote }}

- name: PRISON_API_URL
value: {{ .Values.env.PRISON_API_URL | quote }}

Expand Down
1 change: 1 addition & 0 deletions helm_deploy/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ env:
DPS_URL: https://digital-dev.prison.service.justice.gov.uk/
COMPONENT_API_URL: "https://frontend-components-dev.hmpps.service.justice.gov.uk"
ENVIRONMENT_NAME: 'DEV'
HMPPS_MANAGE_USERS_API_URL: https://manage-users-api-dev.hmpps.service.justice.gov.uk
1 change: 1 addition & 0 deletions helm_deploy/values-preprod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ env:
DPS_URL: https://digital-preprod.prison.service.justice.gov.uk/
COMPONENT_API_URL: "https://frontend-components-preprod.hmpps.service.justice.gov.uk"
ENVIRONMENT_NAME: 'PRE-PRODUCTION'
HMPPS_MANAGE_USERS_API_URL: https://manage-users-api-preprod.hmpps.service.justice.gov.uk

allow_list:
office: "217.33.148.210/32"
Expand Down
1 change: 1 addition & 0 deletions helm_deploy/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ env:
DPS_URL: https://digital.prison.service.justice.gov.uk/
COMPONENT_API_URL: "https://frontend-components.hmpps.service.justice.gov.uk"
ENVIRONMENT_NAME: ''
HMPPS_MANAGE_USERS_API_URL: https://manage-users-api.hmpps.service.justice.gov.uk

allow_list:
office: "217.33.148.210/32"
Expand Down
8 changes: 4 additions & 4 deletions integration-tests/mockApis/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const stubUser = username =>
stubFor({
request: {
method: 'GET',
urlPattern: `/auth/api/user/${encodeURI(username)}`,
urlPattern: `/users/${encodeURI(username)}`,
},
response: {
status: 200,
Expand All @@ -175,7 +175,7 @@ const stubFindUser = (firstName, lastName, results) =>
stubFor({
request: {
method: 'GET',
urlPattern: `/auth/api/prisonuser\\?firstName=${encodeURI(firstName)}&lastName=${encodeURI(lastName)}`,
urlPattern: `/prisonusers\\?firstName=${encodeURI(firstName)}&lastName=${encodeURI(lastName)}`,
},
response: {
status: 200,
Expand All @@ -198,7 +198,7 @@ const stubEmail = username =>
stubFor({
request: {
method: 'GET',
urlPattern: `/auth/api/user/${encodeURI(username)}/email`,
urlPattern: `/users/${encodeURI(username)}/email`,
},
response: {
status: 200,
Expand All @@ -216,7 +216,7 @@ const stubUnverifiedEmail = username =>
stubFor({
request: {
method: 'GET',
urlPattern: `/auth/api/user/${encodeURI(username)}/email`,
urlPattern: `/users/${encodeURI(username)}/email`,
},
response: {
status: 204,
Expand Down
7 changes: 7 additions & 0 deletions server/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ module.exports = {
systemClientId: get('SYSTEM_CLIENT_ID', get('API_CLIENT_ID', 'use-of-force-system'), requiredInProduction),
systemClientSecret: get('SYSTEM_CLIENT_SECRET', get('API_CLIENT_SECRET', 'clientsecret'), requiredInProduction),
},
hmppsManageUsersApi: {
url: get('HMPPS_MANAGE_USERS_API_URL', 'http://localhost:8081', requiredInProduction),
timeout: {
response: get('HMPPS_MANAGE_USERS_API_TIMEOUT_RESPONSE', 10000),
deadline: get('HMPPS_MANAGE_USERS_API_TIMEOUT_DEADLINE', 10000),
},
},
prison: {
url: get('PRISON_API_URL', 'http://localhost:8080', requiredInProduction),
timeout: {
Expand Down
45 changes: 28 additions & 17 deletions server/data/authClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ const redisClient = {

describe('authClient', () => {
let systemToken
let fakeApi
let fakeHmppsAuthApi
let fakeHmppsManageUsersApi
let client: AuthClient

const token = 'token-1'

beforeEach(() => {
systemToken = systemTokenBuilder(new TokenStore(redisClient as RedisClient))
fakeApi = nock(config.apis.oauth2.url)
fakeHmppsAuthApi = nock(config.apis.oauth2.url)
fakeHmppsManageUsersApi = nock(config.apis.hmppsManageUsersApi.url)
client = new AuthClient(token)
})

Expand All @@ -34,8 +36,8 @@ describe('authClient', () => {
const userResponse = { username: 'BOB', email: '[email protected]' }

it('email exists', async () => {
fakeApi
.get(`/api/user/${userName}/email`)
fakeHmppsManageUsersApi
.get(`/users/${userName}/email`)
.matchHeader('authorization', `Bearer ${token}`)
.reply(200, userResponse)

Expand All @@ -44,27 +46,27 @@ describe('authClient', () => {
})

it('no verified email exists', async () => {
fakeApi.get(`/api/user/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(204)
fakeHmppsManageUsersApi.get(`/users/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(204)

const output = await client.getEmail(userName)
expect(output).toEqual({ username: 'Bob', exists: true, verified: false })
})

it('user doesnt exist', async () => {
fakeApi.get(`/api/user/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(404)
fakeHmppsManageUsersApi.get(`/users/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(404)

const output = await client.getEmail(userName)
expect(output).toEqual({ username: 'Bob', exists: false, verified: false })
})

it('username offends the auth service', async () => {
fakeApi.get(`/api/user/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(400)
fakeHmppsManageUsersApi.get(`/users/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(400)

expect(client.getEmail(userName)).rejects.toThrow('Bad Request')
})

it('not authorised error', async () => {
fakeApi.get(`/api/user/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(401)
fakeHmppsManageUsersApi.get(`/users/${userName}/email`).matchHeader('authorization', `Bearer ${token}`).reply(401)

expect(client.getEmail(userName)).rejects.toThrow('Unauthorized')
})
Expand All @@ -75,7 +77,10 @@ describe('authClient', () => {
const userResponse = { username: 'Bob', email: '[email protected]' }

it('user exists', async () => {
fakeApi.get(`/api/user/${userName}`).matchHeader('authorization', `Bearer ${token}`).reply(200, userResponse)
fakeHmppsManageUsersApi
.get(`/users/${userName}`)
.matchHeader('authorization', `Bearer ${token}`)
.reply(200, userResponse)

const output = await client.getUser(userName)
expect(output).toEqual(userResponse)
Expand All @@ -87,8 +92,14 @@ describe('authClient', () => {
const user2 = { username: 'Jo', email: '[email protected]' }

it('getUsers', async () => {
fakeApi.get(`/api/user/${user1.username}`).matchHeader('authorization', `Bearer ${token}`).reply(200, user1)
fakeApi.get(`/api/user/${user2.username}`).matchHeader('authorization', `Bearer ${token}`).reply(200, user2)
fakeHmppsManageUsersApi
.get(`/users/${user1.username}`)
.matchHeader('authorization', `Bearer ${token}`)
.reply(200, user1)
fakeHmppsManageUsersApi
.get(`/users/${user2.username}`)
.matchHeader('authorization', `Bearer ${token}`)
.reply(200, user2)

const output = await client.getUsers([user1.username, user2.username])
expect(output).toEqual(expect.arrayContaining([user1, user2]))
Expand All @@ -99,8 +110,8 @@ describe('authClient', () => {
const userResponse = { username: 'Bob', email: '[email protected]' }

it('user exists', async () => {
fakeApi
.get(`/api/prisonuser?firstName=bob&lastName=smith`)
fakeHmppsManageUsersApi
.get(`/prisonusers?firstName=bob&lastName=smith`)
.matchHeader('authorization', `Bearer ${token}`)
.reply(200, userResponse)

Expand All @@ -109,8 +120,8 @@ describe('authClient', () => {
})

it('it trims names', async () => {
fakeApi
.get(`/api/prisonuser?firstName=bob&lastName=smith`)
fakeHmppsManageUsersApi
.get(`/prisonusers?firstName=bob&lastName=smith`)
.matchHeader('authorization', `Bearer ${token}`)
.reply(200, userResponse)

Expand All @@ -123,7 +134,7 @@ describe('authClient', () => {
const tokenObject = { access_token: 'token-1' }
it('with username', async () => {
const userName = 'Bob'
fakeApi
fakeHmppsAuthApi
.post(`/oauth/token`, 'grant_type=client_credentials&username=Bob')
.basicAuth({ user: config.apis.oauth2.systemClientId, pass: config.apis.oauth2.systemClientSecret })
.matchHeader('Content-Type', 'application/x-www-form-urlencoded')
Expand All @@ -134,7 +145,7 @@ describe('authClient', () => {
})

it('without username', async () => {
fakeApi
fakeHmppsAuthApi
.post(`/oauth/token`, 'grant_type=client_credentials')
.basicAuth({ user: config.apis.oauth2.systemClientId, pass: config.apis.oauth2.systemClientSecret })
.matchHeader('Content-Type', 'application/x-www-form-urlencoded')
Expand Down
13 changes: 7 additions & 6 deletions server/data/authClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ const timeoutSpec = {
response: config.apis.oauth2.timeout.response,
deadline: config.apis.oauth2.timeout.deadline,
}
const apiUrl = config.apis.oauth2.url
const hmppsAuthUrl = config.apis.oauth2.url
const hmppsManageUsersApiUrl = config.apis.hmppsManageUsersApi.url

const agentOptions = {
maxSockets: config.apis.oauth2.agent.maxSockets,
maxFreeSockets: config.apis.oauth2.agent.maxFreeSockets,
freeSocketTimeout: config.apis.oauth2.agent.freeSocketTimeout,
}

const keepaliveAgent = apiUrl.startsWith('https') ? new HttpsAgent(agentOptions) : new Agent(agentOptions)
const keepaliveAgent = hmppsAuthUrl.startsWith('https') ? new HttpsAgent(agentOptions) : new Agent(agentOptions)

async function getSystemClientToken(tokenStore: TokenStore, username?: string) {
const key = username || '%ANONYMOUS%'
Expand Down Expand Up @@ -56,7 +57,7 @@ const getOauthToken = (oauthClientToken, requestSpec) => {
const oauthRequest = querystring.stringify(requestSpec)

return superagent
.post(`${apiUrl}/oauth/token`)
.post(`${hmppsAuthUrl}/oauth/token`)
.set('Authorization', oauthClientToken)
.set('content-type', 'application/x-www-form-urlencoded')
.send(oauthRequest)
Expand Down Expand Up @@ -126,7 +127,7 @@ export class AuthClient {
}

async getEmail(username: string): Promise<EmailResult> {
const path = `${apiUrl}/api/user/${username}/email`
const path = `${hmppsManageUsersApiUrl}/users/${username}/email`
const { status, body } = await this.get({ path, raw: true })
return {
email: body.email,
Expand All @@ -137,7 +138,7 @@ export class AuthClient {
}

async getUser(username: string): Promise<UserResult> {
const path = `${apiUrl}/api/user/${username}`
const path = `${hmppsManageUsersApiUrl}/users/${username}`
const body = await this.get({ path })
return body
}
Expand All @@ -147,7 +148,7 @@ export class AuthClient {
}

async findUsers(firstName: string, lastName: string): Promise<FoundUserResult[]> {
const path = `${apiUrl}/api/prisonuser`
const path = `${hmppsManageUsersApiUrl}/prisonusers`
const body = await this.get({
path,
query: querystring.stringify({ firstName: firstName?.trim(), lastName: lastName?.trim() }),
Expand Down