{"version":3,"file":"index.cjs","sources":["../src/main/data/prisonApi/PrisonApiClient.ts","../src/main/types/permissions/PermissionCheckStatus.ts","../src/main/services/permissions/PermissionsLogger.ts","../src/main/types/permissions/prisoner/PrisonerPermissions.ts","../src/main/services/permissions/utils/PermissionUtils.ts","../src/main/types/user/Role.ts","../src/main/services/permissions/checks/baseCheck/RestrictedPatientCheck.ts","../src/main/services/permissions/checks/baseCheck/ReleasedPrisonerCheck.ts","../src/main/services/permissions/checks/baseCheck/TransferingPrisonerCheck.ts","../src/main/services/permissions/checks/baseCheck/BaseCheck.ts","../src/main/data/hmppsPrisonerSearch/PrisonerSearchClient.ts","../src/main/services/permissions/PermissionsService.ts","../src/main/types/errors/PrisonerPermissionError.ts","../src/main/middleware/PrisonerPermissionsGuard.ts"],"sourcesContent":["import { RestClient, ApiConfig, asUser } from '@ministryofjustice/hmpps-rest-client'\nimport type Logger from 'bunyan'\n\nexport default class PrisonApiClient extends RestClient {\n  constructor(logger: Logger | Console, config: ApiConfig) {\n    super('Prison API', config, logger)\n  }\n\n  isUserAKeyWorker(userToken: string, staffId: number, agencyId: string): Promise<boolean> {\n    return this.get<boolean>({ path: `/api/staff/${staffId}/${agencyId}/roles/KW` }, asUser(userToken))\n  }\n}\n","// eslint-disable-next-line import/prefer-default-export\nexport enum PermissionCheckStatus {\n  NOT_PERMITTED = 'NOT_PERMITTED', // Generic not permitted status - default\n  NOT_IN_CASELOAD = 'NOT_IN_CASELOAD',\n  RESTRICTED_PATIENT = 'RESTRICTED_PATIENT',\n  PRISONER_IS_RELEASED = 'PRISONER_IS_RELEASED',\n  PRISONER_IS_TRANSFERRING = 'PRISONER_IS_TRANSFERRING',\n  OK = 'OK',\n}\n","import { TelemetryClient } from 'applicationinsights'\nimport type Logger from 'bunyan'\nimport { PermissionCheckStatus } from '../../types/permissions/PermissionCheckStatus'\nimport { HmppsUser } from '../../types/user/HmppsUser'\nimport Prisoner from '../../data/hmppsPrisonerSearch/interfaces/Prisoner'\nimport { PrisonerPermission } from '../../types/permissions/prisoner/PrisonerPermissions'\n\nexport default class PermissionsLogger {\n  constructor(\n    private readonly logger: Logger | Console,\n    private readonly telemetryClient?: TelemetryClient,\n  ) {}\n\n  logPermissionCheckStatus(\n    user: HmppsUser,\n    prisoner: Prisoner,\n    permission: PrisonerPermission,\n    permissionCheckStatus: PermissionCheckStatus,\n  ) {\n    if (permissionCheckStatus === PermissionCheckStatus.OK) return\n\n    if (this.telemetryClient) {\n      this.telemetryClient.trackEvent({\n        name: 'prisoner-permission-check-failed',\n        properties: {\n          username: user.username,\n          prisonerNumber: prisoner.prisonerNumber,\n          activeCaseLoad: user.authSource === 'nomis' && user.activeCaseLoadId,\n          permissionChecked: permission,\n          status: permissionCheckStatus,\n        },\n      })\n    } else {\n      this.logger.info(\n        `Prisoner permission check failed: ${permission} (${permissionCheckStatus}) for user ${user.username}`,\n      )\n    }\n  }\n}\n","export enum PrisonerBasePermission {\n  read = 'prisoner:base-record:read',\n}\n\n/**\n * These permissions define what a HMPPS user can do with respect to data held about a prisoner.\n */\nexport interface PrisonerPermissions {\n  [PrisonerBasePermission.read]: boolean\n\n  // TODO:\n  // domainGroups: {\n  //   ...\n  // }\n}\n\nexport type PrisonerPermission = PrisonerBasePermission\n\nexport function checkPrisonerAccess(permission: PrisonerPermission, permissions: PrisonerPermissions): boolean {\n  if (permission === PrisonerBasePermission.read) {\n    return permissions[PrisonerBasePermission.read]\n  }\n\n  // TODO: Check each domain group for the permission\n\n  return false\n}\n","import { HmppsUser } from '../../../types/user/HmppsUser'\n\nexport const isInUsersCaseLoad = (prisonId: string | undefined, user: HmppsUser): boolean =>\n  user.authSource === 'nomis' && user.caseLoads?.some(caseLoad => caseLoad.caseLoadId === prisonId)\n\nexport const userHasRoles = (rolesToCheck: string[], userRoles: string[]): boolean => {\n  const normaliseRoleText = (role: string): string => role.replace(/ROLE_/, '')\n  return rolesToCheck.map(normaliseRoleText).some(role => userRoles.map(normaliseRoleText).includes(role))\n}\n","// eslint-disable-next-line import/prefer-default-export\nexport enum Role {\n  GlobalSearch = 'ROLE_GLOBAL_SEARCH',\n  InactiveBookings = 'ROLE_INACTIVE_BOOKINGS',\n  PomUser = 'ROLE_POM',\n  PrisonUser = 'ROLE_PRISON',\n}\n","import { HmppsUser } from '../../../../types/user/HmppsUser'\nimport Prisoner from '../../../../data/hmppsPrisonerSearch/interfaces/Prisoner'\nimport { isInUsersCaseLoad, userHasRoles } from '../../utils/PermissionUtils'\nimport { Role } from '../../../../types/user/Role'\nimport { PermissionCheckStatus } from '../../../../types/permissions/PermissionCheckStatus'\n\n/*\n * Restricted patients can be accessed in the following circumstances:\n * - The user has the \"Inactive Bookings\" role\n * - The user is a POM user and has the supporting prison ID in their caseloads\n */\nexport default function restrictedPatientCheck(user: HmppsUser, prisoner: Prisoner): PermissionCheckStatus {\n  const { userRoles } = user\n  const pomUser = userHasRoles([Role.PomUser], userRoles)\n  const inactiveBookingsUser = userHasRoles([Role.InactiveBookings], userRoles)\n\n  const userHasPrisonersSupportingPrisonInTheirCaseLoad = isInUsersCaseLoad(prisoner.supportingPrisonId, user)\n  const userIsPomUserWithSupportingPrisonInTheirCaseLoad = pomUser && userHasPrisonersSupportingPrisonInTheirCaseLoad\n\n  if (userIsPomUserWithSupportingPrisonInTheirCaseLoad) return PermissionCheckStatus.OK\n  if (inactiveBookingsUser) return PermissionCheckStatus.OK\n\n  return PermissionCheckStatus.RESTRICTED_PATIENT\n}\n","import { HmppsUser } from '../../../../types/user/HmppsUser'\nimport { userHasRoles } from '../../utils/PermissionUtils'\nimport { Role } from '../../../../types/user/Role'\nimport { PermissionCheckStatus } from '../../../../types/permissions/PermissionCheckStatus'\n\n/*\n * Released prisoners can be accessed in the following circumstances:\n * - The user has the \"Inactive Bookings\" role\n */\nexport default function releasedPrisonerCheck(user: HmppsUser): PermissionCheckStatus {\n  const { userRoles } = user\n  const inactiveBookingsUser = userHasRoles([Role.InactiveBookings], userRoles)\n\n  if (inactiveBookingsUser) return PermissionCheckStatus.OK\n\n  return PermissionCheckStatus.PRISONER_IS_RELEASED\n}\n","import { HmppsUser } from '../../../../types/user/HmppsUser'\nimport { userHasRoles } from '../../utils/PermissionUtils'\nimport { Role } from '../../../../types/user/Role'\nimport { PermissionCheckStatus } from '../../../../types/permissions/PermissionCheckStatus'\n\n/*\n * Transferring prisoners can be accessed in the following circumstances:\n * - The user has the \"Global search\" role\n * - The user has the \"Inactive Bookings\" role\n */\nexport default function transferringPrisonerCheck(user: HmppsUser): PermissionCheckStatus {\n  const { userRoles } = user\n  const inactiveBookingsUser = userHasRoles([Role.InactiveBookings], userRoles)\n  const globalSearchUser = userHasRoles([Role.GlobalSearch], userRoles)\n\n  if (globalSearchUser) return PermissionCheckStatus.OK\n  if (inactiveBookingsUser) return PermissionCheckStatus.OK\n\n  return PermissionCheckStatus.PRISONER_IS_TRANSFERRING\n}\n","/*\n * The \"default\" access checks for accessing information about a prisoner.\n *\n * This function can be used for checking what we consider the \"base checks\" for accessing a page on the prisoner profile\n * when no other special cases are given.\n *\n * It provides the following options for special circumstances:\n *\n * - allowGlobal (default: true): Does the page allow access to users outside the prisoners current case load\n */\nimport { HmppsUser } from '../../../../types/user/HmppsUser'\nimport Prisoner from '../../../../data/hmppsPrisonerSearch/interfaces/Prisoner'\nimport { isInUsersCaseLoad, userHasRoles } from '../../utils/PermissionUtils'\nimport { Role } from '../../../../types/user/Role'\nimport { PermissionCheckStatus } from '../../../../types/permissions/PermissionCheckStatus'\nimport restrictedPatientCheck from './RestrictedPatientCheck'\nimport releasedPrisonerCheck from './ReleasedPrisonerCheck'\nimport transferringPrisonerCheck from './TransferingPrisonerCheck'\n\nexport default function baseCheck(user: HmppsUser, prisoner: Prisoner): PermissionCheckStatus {\n  const inUsersCaseLoad = isInUsersCaseLoad(prisoner.prisonId, user)\n  const globalSearchUser = userHasRoles([Role.GlobalSearch], user.userRoles)\n\n  if (prisoner.restrictedPatient) return restrictedPatientCheck(user, prisoner)\n  if (prisoner.prisonId === 'OUT') return releasedPrisonerCheck(user)\n  if (prisoner.prisonId === 'TRN') return transferringPrisonerCheck(user)\n  if (inUsersCaseLoad || globalSearchUser) return PermissionCheckStatus.OK\n\n  return PermissionCheckStatus.NOT_IN_CASELOAD\n}\n","import { RestClient, ApiConfig, AuthenticationClient, asSystem } from '@ministryofjustice/hmpps-rest-client'\nimport type Logger from 'bunyan'\nimport Prisoner from './interfaces/Prisoner'\n\nexport default class PrisonerSearchClient extends RestClient {\n  constructor(logger: Logger | Console, config: ApiConfig, authenticationClient: AuthenticationClient) {\n    super('Prisoner Search', config, logger, authenticationClient)\n  }\n\n  getPrisonerDetails(prisonerNumber: string): Promise<Prisoner> {\n    return this.get<Prisoner>({ path: `/prisoner/${prisonerNumber}` }, asSystem())\n  }\n}\n","import type bunyan from 'bunyan'\nimport { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport { TelemetryClient } from 'applicationinsights'\nimport Prisoner from '../../data/hmppsPrisonerSearch/interfaces/Prisoner'\nimport PrisonApiClient from '../../data/prisonApi/PrisonApiClient'\nimport { HmppsUser } from '../../types/user/HmppsUser'\nimport PermissionsLogger from './PermissionsLogger'\nimport {\n  PrisonerBasePermission,\n  PrisonerPermission,\n  PrisonerPermissions,\n} from '../../types/permissions/prisoner/PrisonerPermissions'\nimport baseCheck from './checks/baseCheck/BaseCheck'\nimport { PermissionCheckStatus } from '../../types/permissions/PermissionCheckStatus'\nimport PrisonerSearchClient from '../../data/hmppsPrisonerSearch/PrisonerSearchClient'\n\nexport default class PermissionsService {\n  private readonly prisonApiClient: PrisonApiClient\n\n  private readonly prisonerSearchClient: PrisonerSearchClient\n\n  readonly permissionsLogger: PermissionsLogger\n\n  static create({\n    prisonApiConfig,\n    prisonerSearchConfig,\n    authenticationClient,\n    logger = console,\n    telemetryClient,\n  }: {\n    prisonApiConfig: ApiConfig\n    prisonerSearchConfig: ApiConfig\n    authenticationClient: AuthenticationClient\n    logger?: bunyan | typeof console\n    telemetryClient?: TelemetryClient\n  }): PermissionsService {\n    return new PermissionsService(\n      new PrisonApiClient(logger, prisonApiConfig),\n      new PrisonerSearchClient(logger, prisonerSearchConfig, authenticationClient),\n      new PermissionsLogger(logger, telemetryClient),\n    )\n  }\n\n  private constructor(\n    prisonApiClient: PrisonApiClient,\n    prisonerSearchClient: PrisonerSearchClient,\n    permissionsLogger: PermissionsLogger,\n  ) {\n    this.prisonApiClient = prisonApiClient\n    this.prisonerSearchClient = prisonerSearchClient\n    this.permissionsLogger = permissionsLogger\n  }\n\n  public getPrisonerPermissions({\n    user,\n    prisoner,\n    requestDependentOn,\n  }: {\n    user: HmppsUser\n    prisoner: Prisoner\n    requestDependentOn: PrisonerPermission[]\n  }): PrisonerPermissions {\n    const baseCheckStatus = baseCheck(user, prisoner)\n    const basePermission = PrisonerBasePermission.read\n\n    if (baseCheckStatus !== PermissionCheckStatus.OK && requestDependentOn.includes(basePermission)) {\n      this.permissionsLogger.logPermissionCheckStatus(user, prisoner, basePermission, baseCheckStatus)\n    }\n\n    return {\n      [PrisonerBasePermission.read]: baseCheckStatus === PermissionCheckStatus.OK,\n\n      // TODO:\n      // domainGroups: {\n      //    ...\n      // },\n    } as PrisonerPermissions\n  }\n\n  public async isUserAKeyWorkerAtPrison(token: string, user: HmppsUser, prison: string): Promise<boolean> {\n    if (user.authSource !== 'nomis') {\n      return Promise.resolve(false)\n    }\n    return this.prisonApiClient.isUserAKeyWorker(token, user.staffId, prison)\n  }\n\n  public getPrisonerDetails(prisonerNumber: string): Promise<Prisoner> {\n    return this.prisonerSearchClient.getPrisonerDetails(prisonerNumber)\n  }\n}\n","import { PrisonerPermission } from '../permissions/prisoner/PrisonerPermissions'\n\nexport default class PrisonerPermissionError extends Error {\n  public status = 403\n\n  public failedPermissionChecks: PrisonerPermission[]\n\n  constructor(message = 'Access not permitted', failedPermissionChecks: PrisonerPermission[] = []) {\n    super(message)\n    this.name = 'NotFoundError'\n    this.failedPermissionChecks = failedPermissionChecks\n  }\n}\n","import type { NextFunction, Request, Response } from 'express'\nimport { checkPrisonerAccess, PrisonerPermission } from '../types/permissions/prisoner/PrisonerPermissions'\nimport PermissionsService from '../services/permissions/PermissionsService'\nimport PrisonerPermissionError from '../types/errors/PrisonerPermissionError'\nimport Prisoner from '../data/hmppsPrisonerSearch/interfaces/Prisoner'\n\nexport default function prisonerPermissionsGuard(\n  permissionsService: PermissionsService,\n  options: {\n    requestDependentOn: PrisonerPermission[]\n    getPrisonerNumberFunction?: (req: Request) => string | undefined\n  },\n) {\n  const { requestDependentOn, getPrisonerNumberFunction = getPrisonerNumberFrom } = options\n\n  if (!requestDependentOn?.length) throw Error('Unprotected route, must provide at least one dependent permission')\n\n  return async (req: Request, res: Response, next: NextFunction) => {\n    const prisonerData = await getPrisonerData(req, permissionsService, getPrisonerNumberFunction)\n    if (!prisonerData) return next(Error('Could not retrieve prisoner data'))\n\n    await populateKeyWorkerData(req, res, prisonerData, permissionsService)\n\n    const prisonerPermissions = permissionsService.getPrisonerPermissions({\n      user: res.locals.user,\n      prisoner: prisonerData,\n      requestDependentOn,\n    })\n\n    const failedChecks = requestDependentOn.filter(permission => !checkPrisonerAccess(permission, prisonerPermissions))\n\n    if (failedChecks.length) return next(new PrisonerPermissionError('Failed permissions checks', failedChecks))\n\n    req.middleware = { ...req.middleware, prisonerData }\n    res.locals.prisonerPermissions = prisonerPermissions\n    return next()\n  }\n}\n\nfunction getPrisonerNumberFrom(req: Request): string | undefined {\n  if (req.params?.prisonerNumber) {\n    return req.params.prisonerNumber\n  }\n  if (req.query?.prisonerNumber) {\n    return req.query.prisonerNumber as string\n  }\n  return undefined\n}\n\nasync function getPrisonerData(\n  req: Request,\n  permissionsService: PermissionsService,\n  getPrisonerNumberFunction: (req: Request) => string | undefined,\n): Promise<Prisoner | undefined> {\n  if (req.middleware?.prisonerData) return req.middleware?.prisonerData\n  const prisonerNumber = getPrisonerNumberFunction(req)\n  return prisonerNumber ? permissionsService.getPrisonerDetails(prisonerNumber) : undefined\n}\n\nasync function populateKeyWorkerData(\n  req: Request,\n  res: Response,\n  prisoner: Prisoner,\n  permissionsService: PermissionsService,\n): Promise<void> {\n  if (res.locals.user?.authSource !== 'nomis') return\n\n  const userCaseLoads = res.locals.user?.caseLoads?.map(caseLoad => caseLoad.caseLoadId)\n\n  if (!req.session) throw new Error('User session required in order to cache key worker status')\n  const keyWorkerAtPrisons = req.session.keyWorkerAtPrisons ?? {}\n\n  if (\n    prisoner.prisonId &&\n    userCaseLoads?.includes(prisoner.prisonId) &&\n    keyWorkerAtPrisons[prisoner.prisonId] === undefined\n  ) {\n    req.session.keyWorkerAtPrisons = {\n      ...keyWorkerAtPrisons,\n      [prisoner.prisonId]: await permissionsService.isUserAKeyWorkerAtPrison(\n        res.locals.user.token!,\n        res.locals.user,\n        prisoner.prisonId,\n      ),\n    }\n  }\n\n  // This information is then provided to the user object on res.locals\n  res.locals.user.keyWorkerAtPrisons = req.session.keyWorkerAtPrisons || {}\n}\n"],"names":["RestClient","asUser","PrisonerBasePermission","asSystem"],"mappings":"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"}