Skip to content

Commit

Permalink
MAP-305: Use HMPPS Manage Users API for user details (#650)
Browse files Browse the repository at this point in the history
This has been split out into a new API. It was once part of HMPPS Auth.
  • Loading branch information
jimbali authored Oct 6, 2023
1 parent f3d4fac commit 5c9a2ab
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 27 deletions.
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

0 comments on commit 5c9a2ab

Please sign in to comment.