diff --git a/CHANGELOG.md b/CHANGELOG.md index 22f06a805..b4dc06338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,31 @@ # Change log +**May 10th 2024** – Derive user details from the `authorization_code` "user" token instead of making an API call to `hmpps-manage-users-api`, thereby removing an unnecessary dependency. + +PR: [#352](https://github.com/ministryofjustice/hmpps-template-typescript/pull/352) + +--- + **February 29th 2024** – Use same node version for outdated check and security scan. This currently defaults to node 16 PR: [#321](https://github.com/ministryofjustice/hmpps-template-typescript/pull/321) +--- + **February 15th 2024** – Move over to use Debian 12 based image (bookworm) PR: [#316](https://github.com/ministryofjustice/hmpps-template-typescript/pull/316) +--- + **January 9th 2024** – Move over to Gov UK Frontend 5.0 and MoJ Frontend 2.0 Note, this removed support for IE8,9,10 etc. PR: [#297](https://github.com/ministryofjustice/hmpps-template-typescript/pull/297) +--- + **November 29th 2023** – Remove getUserRoles as an api call and add as decoded from the token #274 This is to encourage services not to make additional calls to retrieve a user's role information. diff --git a/cypress.config.ts b/cypress.config.ts index a34c06cfb..7f8802ab0 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,7 +1,6 @@ import { defineConfig } from 'cypress' import { resetStubs } from './integration_tests/mockApis/wiremock' import auth from './integration_tests/mockApis/auth' -import manageUsersApi from './integration_tests/mockApis/manageUsersApi' import tokenVerification from './integration_tests/mockApis/tokenVerification' export default defineConfig({ @@ -19,7 +18,6 @@ export default defineConfig({ on('task', { reset: resetStubs, ...auth, - ...manageUsersApi, ...tokenVerification, }) }, diff --git a/feature.env b/feature.env index 80994b415..d3a56a947 100644 --- a/feature.env +++ b/feature.env @@ -1,6 +1,5 @@ PORT=3007 HMPPS_AUTH_URL=http://localhost:9091/auth -MANAGE_USERS_API_URL=http://localhost:9091/manage-users-api TOKEN_VERIFICATION_API_URL=http://localhost:9091/verification TOKEN_VERIFICATION_ENABLED=true REDIS_ENABLED=false diff --git a/helm_deploy/values-dev.yaml b/helm_deploy/values-dev.yaml index fcfd3538d..f78d9e919 100644 --- a/helm_deploy/values-dev.yaml +++ b/helm_deploy/values-dev.yaml @@ -10,7 +10,6 @@ generic-service: env: INGRESS_URL: "https://hmpps-template-typescript-dev.hmpps.service.justice.gov.uk" HMPPS_AUTH_URL: "https://sign-in-dev.hmpps.service.justice.gov.uk/auth" - MANAGE_USERS_API_URL: "https://manage-users-api-dev.hmpps.service.justice.gov.uk" TOKEN_VERIFICATION_API_URL: "https://token-verification-api-dev.prison.service.justice.gov.uk" ENVIRONMENT_NAME: DEV AUDIT_ENABLED: "false" diff --git a/helm_deploy/values-preprod.yaml b/helm_deploy/values-preprod.yaml index 58884b12e..f374d64c4 100644 --- a/helm_deploy/values-preprod.yaml +++ b/helm_deploy/values-preprod.yaml @@ -10,7 +10,6 @@ generic-service: env: INGRESS_URL: "https://hmpps-template-typescript-preprod.hmpps.service.justice.gov.uk" HMPPS_AUTH_URL: "https://sign-in-preprod.hmpps.service.justice.gov.uk/auth" - MANAGE_USERS_API_URL: "https://manage-users-api-preprod.hmpps.service.justice.gov.uk" TOKEN_VERIFICATION_API_URL: "https://token-verification-api-preprod.prison.service.justice.gov.uk" ENVIRONMENT_NAME: PRE-PRODUCTION AUDIT_ENABLED: "false" diff --git a/helm_deploy/values-prod.yaml b/helm_deploy/values-prod.yaml index de360cdbc..7c8e488c1 100644 --- a/helm_deploy/values-prod.yaml +++ b/helm_deploy/values-prod.yaml @@ -8,7 +8,6 @@ generic-service: env: INGRESS_URL: "https://hmpps-template-typescript.hmpps.service.justice.gov.uk" HMPPS_AUTH_URL: "https://sign-in.hmpps.service.justice.gov.uk/auth" - MANAGE_USERS_API_URL: "https://manage-users-api.hmpps.service.justice.gov.uk" TOKEN_VERIFICATION_API_URL: "https://token-verification-api.prison.service.justice.gov.uk" AUDIT_ENABLED: "false" diff --git a/integration_tests/e2e/health.cy.ts b/integration_tests/e2e/health.cy.ts index 1a7775dac..7c36be5e4 100644 --- a/integration_tests/e2e/health.cy.ts +++ b/integration_tests/e2e/health.cy.ts @@ -3,7 +3,6 @@ context('Healthcheck', () => { beforeEach(() => { cy.task('reset') cy.task('stubAuthPing') - cy.task('stubManageUsersPing') cy.task('stubTokenVerificationPing') }) @@ -24,14 +23,12 @@ context('Healthcheck', () => { beforeEach(() => { cy.task('reset') cy.task('stubAuthPing') - cy.task('stubManageUsersPing') cy.task('stubTokenVerificationPing', 500) }) it('Reports correctly when token verification down', () => { cy.request({ url: '/health', method: 'GET', failOnStatusCode: false }).then(response => { expect(response.body.components.hmppsAuth.status).to.equal('UP') - expect(response.body.components.manageUsersApi.status).to.equal('UP') expect(response.body.components.tokenVerification.status).to.equal('DOWN') expect(response.body.components.tokenVerification.details).to.contain({ status: 500, retries: 2 }) }) diff --git a/integration_tests/e2e/signIn.cy.ts b/integration_tests/e2e/signIn.cy.ts index 8312414c4..459661a03 100644 --- a/integration_tests/e2e/signIn.cy.ts +++ b/integration_tests/e2e/signIn.cy.ts @@ -7,7 +7,6 @@ context('Sign In', () => { beforeEach(() => { cy.task('reset') cy.task('stubSignIn') - cy.task('stubManageUser') }) it('Unauthenticated user directed to auth', () => { @@ -67,7 +66,8 @@ context('Sign In', () => { cy.request('/').its('body').should('contain', 'Sign in') cy.task('stubVerifyToken', true) - cy.task('stubManageUser', 'bobby brown') + cy.task('stubSignIn', { name: 'bobby brown' }) + cy.signIn() indexPage.headerUserName().contains('B. Brown') diff --git a/integration_tests/mockApis/auth.ts b/integration_tests/mockApis/auth.ts index 0ba104b6c..602598dd6 100644 --- a/integration_tests/mockApis/auth.ts +++ b/integration_tests/mockApis/auth.ts @@ -4,10 +4,16 @@ import { Response } from 'superagent' import { stubFor, getMatchingRequests } from './wiremock' import tokenVerification from './tokenVerification' -const createToken = (roles: string[] = []) => { +interface UserToken { + name?: string + roles?: string[] +} + +const createToken = (userToken: UserToken) => { // authorities in the session are always prefixed by ROLE. - const authorities = roles.map(role => (role.startsWith('ROLE_') ? role : `ROLE_${role}`)) + const authorities = userToken.roles?.map(role => (role.startsWith('ROLE_') ? role : `ROLE_${role}`)) || [] const payload = { + name: userToken.name || 'john smith', user_name: 'USER1', scope: ['read'], auth_source: 'nomis', @@ -97,7 +103,7 @@ const manageDetails = () => }, }) -const token = (roles: string[] = []) => +const token = (userToken: UserToken) => stubFor({ request: { method: 'POST', @@ -110,7 +116,7 @@ const token = (roles: string[] = []) => Location: 'http://localhost:3007/sign-in/callback?code=codexxxx&state=stateyyyy', }, jsonBody: { - access_token: createToken(roles), + access_token: createToken(userToken), token_type: 'bearer', user_name: 'USER1', expires_in: 599, @@ -119,10 +125,11 @@ const token = (roles: string[] = []) => }, }, }) + export default { getSignInUrl, stubAuthPing: ping, stubAuthManageDetails: manageDetails, - stubSignIn: (roles: string[]): Promise<[Response, Response, Response, Response, Response]> => - Promise.all([favicon(), redirect(), signOut(), token(roles), tokenVerification.stubVerifyToken()]), + stubSignIn: (userToken: UserToken = {}): Promise<[Response, Response, Response, Response, Response]> => + Promise.all([favicon(), redirect(), signOut(), token(userToken), tokenVerification.stubVerifyToken()]), } diff --git a/integration_tests/mockApis/manageUsersApi.ts b/integration_tests/mockApis/manageUsersApi.ts deleted file mode 100644 index 02dd86d01..000000000 --- a/integration_tests/mockApis/manageUsersApi.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { stubFor } from './wiremock' - -const stubUser = (name: string = 'john smith') => - stubFor({ - request: { - method: 'GET', - urlPattern: '/manage-users-api/users/me', - }, - response: { - status: 200, - headers: { - 'Content-Type': 'application/json;charset=UTF-8', - }, - jsonBody: { - username: 'USER1', - active: true, - name, - }, - }, - }) - -const ping = () => - stubFor({ - request: { - method: 'GET', - urlPattern: '/manage-users-api/health/ping', - }, - response: { - status: 200, - }, - }) - -export default { - stubManageUser: stubUser, - stubManageUsersPing: ping, -} diff --git a/server/@types/express/index.d.ts b/server/@types/express/index.d.ts index 93a37d8dd..ebd11d0ab 100644 --- a/server/@types/express/index.d.ts +++ b/server/@types/express/index.d.ts @@ -1,8 +1,6 @@ -import type { UserDetails } from '../../services/userService' +import { HmppsUser } from '../../interfaces/hmppsUser' -export default {} - -declare module 'express-session' { +export declare module 'express-session' { // Declare that the session will potentially contain these additional fields interface SessionData { returnTo: string @@ -12,7 +10,8 @@ declare module 'express-session' { export declare global { namespace Express { - interface User extends Partial { + interface User { + username: string token: string authSource: string } @@ -24,7 +23,7 @@ export declare global { } interface Locals { - user: Express.User + user: HmppsUser } } } diff --git a/server/app.ts b/server/app.ts index 8049860da..5ae45383e 100755 --- a/server/app.ts +++ b/server/app.ts @@ -38,7 +38,7 @@ export default function createApp(services: Services): express.Application { app.use(setUpAuthentication()) app.use(authorisationMiddleware()) app.use(setUpCsrf()) - app.use(setUpCurrentUser(services)) + app.use(setUpCurrentUser()) app.use(routes(services)) diff --git a/server/config.ts b/server/config.ts index e23ce3d6a..5ed20be49 100755 --- a/server/config.ts +++ b/server/config.ts @@ -81,14 +81,6 @@ export default { systemClientId: get('SYSTEM_CLIENT_ID', 'clientid', requiredInProduction), systemClientSecret: get('SYSTEM_CLIENT_SECRET', 'clientsecret', requiredInProduction), }, - manageUsersApi: { - url: get('MANAGE_USERS_API_URL', 'http://localhost:9091', requiredInProduction), - timeout: { - response: Number(get('MANAGE_USERS_API_TIMEOUT_RESPONSE', 10000)), - deadline: Number(get('MANAGE_USERS_API_TIMEOUT_DEADLINE', 10000)), - }, - agent: new AgentConfig(Number(get('MANAGE_USERS_API_TIMEOUT_RESPONSE', 10000))), - }, tokenVerification: { url: get('TOKEN_VERIFICATION_API_URL', 'http://localhost:8100', requiredInProduction), timeout: { diff --git a/server/data/index.ts b/server/data/index.ts index e5c1e97bb..5d09df6b4 100644 --- a/server/data/index.ts +++ b/server/data/index.ts @@ -11,7 +11,6 @@ initialiseAppInsights() buildAppInsightsClient(applicationInfo) import HmppsAuthClient from './hmppsAuthClient' -import ManageUsersApiClient from './manageUsersApiClient' import { createRedisClient } from './redisClient' import RedisTokenStore from './tokenStore/redisTokenStore' import InMemoryTokenStore from './tokenStore/inMemoryTokenStore' @@ -25,10 +24,9 @@ export const dataAccess = () => ({ hmppsAuthClient: new HmppsAuthClient( config.redis.enabled ? new RedisTokenStore(createRedisClient()) : new InMemoryTokenStore(), ), - manageUsersApiClient: new ManageUsersApiClient(), hmppsAuditClient: new HmppsAuditClient(config.sqs.audit), }) export type DataAccess = ReturnType -export { HmppsAuthClient, RestClientBuilder, ManageUsersApiClient, HmppsAuditClient } +export { HmppsAuthClient, RestClientBuilder, HmppsAuditClient } diff --git a/server/data/manageUsersApiClient.test.ts b/server/data/manageUsersApiClient.test.ts deleted file mode 100644 index a4a07daaf..000000000 --- a/server/data/manageUsersApiClient.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import nock from 'nock' - -import config from '../config' -import ManageUsersApiClient from './manageUsersApiClient' - -jest.mock('./tokenStore/redisTokenStore') - -const token = { access_token: 'token-1', expires_in: 300 } - -describe('manageUsersApiClient', () => { - let fakeManageUsersApiClient: nock.Scope - let manageUsersApiClient: ManageUsersApiClient - - beforeEach(() => { - fakeManageUsersApiClient = nock(config.apis.manageUsersApi.url) - manageUsersApiClient = new ManageUsersApiClient() - }) - - afterEach(() => { - jest.resetAllMocks() - nock.cleanAll() - }) - - describe('getUser', () => { - it('should return data from api', async () => { - const response = { data: 'data' } - - fakeManageUsersApiClient - .get('/users/me') - .matchHeader('authorization', `Bearer ${token.access_token}`) - .reply(200, response) - - const output = await manageUsersApiClient.getUser(token.access_token) - expect(output).toEqual(response) - }) - }) -}) diff --git a/server/data/manageUsersApiClient.ts b/server/data/manageUsersApiClient.ts deleted file mode 100644 index 5d8f2d733..000000000 --- a/server/data/manageUsersApiClient.ts +++ /dev/null @@ -1,30 +0,0 @@ -import logger from '../../logger' -import config from '../config' -import RestClient from './restClient' - -export interface User { - username: string - name?: string - active?: boolean - authSource?: string - uuid?: string - userId?: string - activeCaseLoadId?: string // Will be removed from User. For now, use 'me/caseloads' endpoint in 'nomis-user-roles-api' -} - -export interface UserRole { - roleCode: string -} - -export default class ManageUsersApiClient { - constructor() {} - - private static restClient(token: string): RestClient { - return new RestClient('Manage Users Api Client', config.apis.manageUsersApi, token) - } - - getUser(token: string): Promise { - logger.info('Getting user details: calling HMPPS Manage Users Api') - return ManageUsersApiClient.restClient(token).get({ path: '/users/me' }) - } -} diff --git a/server/interfaces/hmppsUser.ts b/server/interfaces/hmppsUser.ts new file mode 100644 index 000000000..e0e0c591a --- /dev/null +++ b/server/interfaces/hmppsUser.ts @@ -0,0 +1,59 @@ +export type AuthSource = 'nomis' | 'delius' | 'external' | 'azuread' + +/** + * These are the details that all user types share. + */ +export interface BaseUser { + authSource: AuthSource + username: string + userId: string + name: string + displayName: string + userRoles: string[] + token: string +} + +/** + * Prison users are those that have a user account in NOMIS. + * HMPPS Auth automatically grants these users a `ROLE_PRISON` role. + * Prison users have an additional numerical staffId. The userId is + * a stringified version of the staffId. Some teams may need to separately + * retrieve the user case load (which prisons that a prison user has access + * to) and store it here, an example can be found in `hmpps-prisoner-profile`. + */ +export interface PrisonUser extends BaseUser { + authSource: 'nomis' + staffId: number +} + +/** + * Probation users are those that have a user account in nDelius. + * HMPPS Auth automatically grants these users a `ROLE_PROBATION` role. + */ +export interface ProbationUser extends BaseUser { + authSource: 'delius' +} + +/** + * External users are those that have a user account in our External Users + * database. These accounts are created for users that need access to HMPPS + * services but have neither NOMIS nor nDelius access. + */ +export interface ExternalUser extends BaseUser { + authSource: 'external' +} + +/** + * AzureAD users are those that have a justice.gov.uk email address and + * an account in MoJ's Azure AD (now called Entra ID) tenant. HMPPS Auth + * will normally check to see if there is a Prison/Probation/External + * user with the same email address and request that the user to pick one + * to use to access the service, however if there is no match, it is + * possible that a user of this type could attempt to access the service, + * and would have no user roles associated. + */ +export interface AzureADUser extends BaseUser { + authSource: 'azuread' +} + +export type HmppsUser = PrisonUser | ProbationUser | ExternalUser | AzureADUser diff --git a/server/middleware/populateCurrentUser.ts b/server/middleware/populateCurrentUser.ts index 508772bfa..60bb2418e 100644 --- a/server/middleware/populateCurrentUser.ts +++ b/server/middleware/populateCurrentUser.ts @@ -1,21 +1,36 @@ import { RequestHandler } from 'express' +import { jwtDecode } from 'jwt-decode' import logger from '../../logger' -import UserService from '../services/userService' +import { convertToTitleCase } from '../utils/utils' -export default function populateCurrentUser(userService: UserService): RequestHandler { +export default function populateCurrentUser(): RequestHandler { return async (req, res, next) => { try { - if (res.locals.user) { - const user = res.locals.user && (await userService.getUser(res.locals.user.token)) - if (user) { - res.locals.user = { ...user, ...res.locals.user } - } else { - logger.info('No user available') - } + const { + name, + user_id: userId, + authorities: roles = [], + } = jwtDecode(res.locals.user.token) as { + name?: string + user_id?: string + authorities?: string[] } + + res.locals.user = { + ...res.locals.user, + userId, + name, + displayName: convertToTitleCase(name), + userRoles: roles.map(role => role.substring(role.indexOf('_') + 1)), + } + + if (res.locals.user.authSource === 'nomis') { + res.locals.user.staffId = parseInt(userId, 10) || undefined + } + next() } catch (error) { - logger.error(error, `Failed to retrieve user for: ${res.locals.user && res.locals.user.username}`) + logger.error(error, `Failed to populate user details for: ${res.locals.user && res.locals.user.username}`) next(error) } } diff --git a/server/middleware/setUpAuthentication.ts b/server/middleware/setUpAuthentication.ts index 8de0b1277..22d34b642 100644 --- a/server/middleware/setUpAuthentication.ts +++ b/server/middleware/setUpAuthentication.ts @@ -4,6 +4,7 @@ import passport from 'passport' import flash from 'connect-flash' import config from '../config' import auth from '../authentication/auth' +import { HmppsUser } from '../interfaces/hmppsUser' const router = express.Router() @@ -46,7 +47,7 @@ export default function setUpAuth(): Router { }) router.use((req, res, next) => { - res.locals.user = req.user + res.locals.user = req.user as HmppsUser next() }) diff --git a/server/middleware/setUpCurrentUser.ts b/server/middleware/setUpCurrentUser.ts index 0fdde0979..6cc7fd973 100644 --- a/server/middleware/setUpCurrentUser.ts +++ b/server/middleware/setUpCurrentUser.ts @@ -2,11 +2,10 @@ import { Router } from 'express' import auth from '../authentication/auth' import tokenVerifier from '../data/tokenVerification' import populateCurrentUser from './populateCurrentUser' -import type { Services } from '../services' -export default function setUpCurrentUser({ userService }: Services): Router { +export default function setUpCurrentUser(): Router { const router = Router({ mergeParams: true }) router.use(auth.authenticationMiddleware(tokenVerifier)) - router.use(populateCurrentUser(userService)) + router.use(populateCurrentUser()) return router } diff --git a/server/routes/testutils/appSetup.ts b/server/routes/testutils/appSetup.ts index 5b27087ae..36a94dd58 100644 --- a/server/routes/testutils/appSetup.ts +++ b/server/routes/testutils/appSetup.ts @@ -10,6 +10,7 @@ import * as auth from '../../authentication/auth' import type { Services } from '../../services' import type { ApplicationInfo } from '../../applicationInfo' import AuditService from '../../services/auditService' +import { HmppsUser } from '../../interfaces/hmppsUser' jest.mock('../../services/auditService') @@ -21,20 +22,20 @@ const testAppInfo: ApplicationInfo = { branchName: 'main', } -export const user: Express.User = { +export const user: HmppsUser = { name: 'FIRST LAST', userId: 'id', token: 'token', username: 'user1', displayName: 'First Last', - active: true, - activeCaseLoadId: 'MDI', - authSource: 'NOMIS', + authSource: 'nomis', + staffId: 1234, + userRoles: [], } export const flashProvider = jest.fn() -function appSetup(services: Services, production: boolean, userSupplier: () => Express.User): Express { +function appSetup(services: Services, production: boolean, userSupplier: () => HmppsUser): Express { const app = express() app.set('view engine', 'njk') @@ -42,10 +43,10 @@ function appSetup(services: Services, production: boolean, userSupplier: () => E nunjucksSetup(app, testAppInfo) app.use(cookieSession({ keys: [''] })) app.use((req, res, next) => { - req.user = userSupplier() + req.user = userSupplier() as Express.User req.flash = flashProvider res.locals = { - user: { ...req.user }, + user: { ...req.user } as HmppsUser, } next() }) @@ -71,7 +72,7 @@ export function appWithAllRoutes({ }: { production?: boolean services?: Partial - userSupplier?: () => Express.User + userSupplier?: () => HmppsUser }): Express { auth.default.authenticationMiddleware = () => (req, res, next) => next() return appSetup(services as Services, production, userSupplier) diff --git a/server/services/healthCheck.ts b/server/services/healthCheck.ts index 3be783658..e937d8a54 100644 --- a/server/services/healthCheck.ts +++ b/server/services/healthCheck.ts @@ -51,7 +51,6 @@ function gatherCheckInfo(aggregateStatus: Record, currentStatus const apiChecks = [ service('hmppsAuth', `${config.apis.hmppsAuth.url}/health/ping`, config.apis.hmppsAuth.agent), - service('manageUsersApi', `${config.apis.manageUsersApi.url}/health/ping`, config.apis.manageUsersApi.agent), ...(config.apis.tokenVerification.enabled ? [ service( diff --git a/server/services/index.ts b/server/services/index.ts index bb7d5e86c..0f97910b8 100644 --- a/server/services/index.ts +++ b/server/services/index.ts @@ -1,20 +1,15 @@ import { dataAccess } from '../data' import AuditService from './auditService' -import UserService from './userService' export const services = () => { - const { applicationInfo, manageUsersApiClient, hmppsAuditClient } = dataAccess() + const { applicationInfo, hmppsAuditClient } = dataAccess() - const userService = new UserService(manageUsersApiClient) const auditService = new AuditService(hmppsAuditClient) return { applicationInfo, - userService, auditService, } } export type Services = ReturnType - -export { UserService } diff --git a/server/services/userService.test.ts b/server/services/userService.test.ts deleted file mode 100644 index e4bde2025..000000000 --- a/server/services/userService.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import UserService from './userService' -import ManageUsersApiClient, { type User } from '../data/manageUsersApiClient' -import createUserToken from '../testutils/createUserToken' - -jest.mock('../data/manageUsersApiClient') - -describe('User service', () => { - let manageUsersApiClient: jest.Mocked - let userService: UserService - - describe('getUser', () => { - beforeEach(() => { - manageUsersApiClient = new ManageUsersApiClient() as jest.Mocked - userService = new UserService(manageUsersApiClient) - }) - - it('Retrieves and formats user name', async () => { - const token = createUserToken([]) - manageUsersApiClient.getUser.mockResolvedValue({ name: 'john smith' } as User) - - const result = await userService.getUser(token) - - expect(result.displayName).toEqual('John Smith') - }) - - it('Retrieves and formats roles', async () => { - const token = createUserToken(['ROLE_ONE', 'ROLE_TWO']) - manageUsersApiClient.getUser.mockResolvedValue({ name: 'john smith' } as User) - - const result = await userService.getUser(token) - - expect(result.roles).toEqual(['ONE', 'TWO']) - }) - - it('Propagates error', async () => { - const token = createUserToken([]) - manageUsersApiClient.getUser.mockRejectedValue(new Error('some error')) - - await expect(userService.getUser(token)).rejects.toEqual(new Error('some error')) - }) - }) -}) diff --git a/server/services/userService.ts b/server/services/userService.ts deleted file mode 100644 index bdd902fe9..000000000 --- a/server/services/userService.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { jwtDecode } from 'jwt-decode' -import { convertToTitleCase } from '../utils/utils' -import type { User } from '../data/manageUsersApiClient' -import ManageUsersApiClient from '../data/manageUsersApiClient' - -export interface UserDetails extends User { - displayName: string - roles: string[] -} - -export default class UserService { - constructor(private readonly manageUsersApiClient: ManageUsersApiClient) {} - - async getUser(token: string): Promise { - const user = await this.manageUsersApiClient.getUser(token) - return { ...user, roles: this.getUserRoles(token), displayName: convertToTitleCase(user.name) } - } - - getUserRoles(token: string): string[] { - const { authorities: roles = [] } = jwtDecode(token) as { authorities?: string[] } - return roles.map(role => role.substring(role.indexOf('_') + 1)) - } -}