Skip to content

Commit

Permalink
chore(j-s): Prison users access to appeal case files (#15844)
Browse files Browse the repository at this point in the history
* Create CaseFileInterceptor

* Filter case files in interceptor

* Only send appeal ruling for completed appeals

* Refactor

* Remove unused code

* Refactor

* Allow defence users to see all files

* Refactor

* Fix tests

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and jonnigs committed Sep 12, 2024
1 parent 81af6a1 commit f67a713
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ import {
prosecutorUpdateRule,
publicProsecutorStaffUpdateRule,
} from './guards/rolesRules'
import { CaseInterceptor } from './interceptors/case.interceptor'
import { CaseListInterceptor } from './interceptors/caseList.interceptor'
import { CompletedAppealAccessedInterceptor } from './interceptors/completedAppealAccessed.interceptor'
import { Case } from './models/case.model'
import { SignatureConfirmationResponse } from './models/signatureConfirmation.response'
import { transitionCase } from './state/case.state'
Expand Down Expand Up @@ -465,7 +465,7 @@ export class CaseController {
)
@Get('case/:caseId')
@ApiOkResponse({ type: Case, description: 'Gets an existing case' })
@UseInterceptors(CaseInterceptor)
@UseInterceptors(CompletedAppealAccessedInterceptor)
getById(@Param('caseId') caseId: string, @CurrentCase() theCase: Case): Case {
this.logger.debug(`Getting case ${caseId} by id`)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class LimitedAccessCaseExistsGuard implements CanActivate {
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest()

const caseId = request.params.caseId
const caseId: string = request.params.caseId

if (!caseId) {
throw new BadRequestException('Missing case id')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'

import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common'

import {
CaseAppealState,
CaseFileCategory,
isDefenceUser,
isPrisonStaffUser,
isPrisonSystemUser,
User,
} from '@island.is/judicial-system/types'

import { Case } from '../models/case.model'

@Injectable()
export class CaseFileInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<Case> {
const request = context.switchToHttp().getRequest()
const user: User = request.user

return next.handle().pipe(
map((data: Case) => {
if (isDefenceUser(user)) {
return data
}

if (
isPrisonStaffUser(user) ||
data.appealState !== CaseAppealState.COMPLETED
) {
data.caseFiles?.splice(0, data.caseFiles.length)
} else if (isPrisonSystemUser(user)) {
data.caseFiles?.splice(
0,
data.caseFiles.length,
...data.caseFiles.filter(
(cf) => cf.category === CaseFileCategory.APPEAL_RULING,
),
)
}

return data
}),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { EventLogService } from '../../event-log'
import { Case } from '../models/case.model'

@Injectable()
export class CaseInterceptor implements NestInterceptor {
export class CompletedAppealAccessedInterceptor implements NestInterceptor {
constructor(private readonly eventLogService: EventLogService) {}

intercept(context: ExecutionContext, next: CallHandler): Observable<Case> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ import { CaseWriteGuard } from './guards/caseWrite.guard'
import { LimitedAccessCaseExistsGuard } from './guards/limitedAccessCaseExists.guard'
import { RequestSharedWithDefenderGuard } from './guards/requestSharedWithDefender.guard'
import { defenderTransitionRule, defenderUpdateRule } from './guards/rolesRules'
import { CaseInterceptor } from './interceptors/case.interceptor'
import { CaseFileInterceptor } from './interceptors/caseFile.interceptor'
import { CompletedAppealAccessedInterceptor } from './interceptors/completedAppealAccessed.interceptor'
import { Case } from './models/case.model'
import { transitionCase } from './state/case.state'
import {
Expand Down Expand Up @@ -85,7 +86,7 @@ export class LimitedAccessCaseController {
type: Case,
description: 'Gets a limited set of properties of an existing case',
})
@UseInterceptors(CaseInterceptor)
@UseInterceptors(CompletedAppealAccessedInterceptor, CaseFileInterceptor)
async getById(
@Param('caseId') caseId: string,
@CurrentCase() theCase: Case,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ export const defenderCaseFileCategoriesForIndictmentCases = [
CaseFileCategory.PROSECUTOR_CASE_FILE,
CaseFileCategory.DEFENDANT_CASE_FILE,
]

export const prisonAdminCaseFileCategories = [CaseFileCategory.APPEAL_RULING]
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import {
} from '@nestjs/common'

import {
CaseFileCategory,
isCompletedCase,
isDefenceUser,
isIndictmentCase,
isPrisonSystemUser,
isPrisonAdminUser,
isRequestCase,
User,
} from '@island.is/judicial-system/types'
Expand All @@ -21,6 +20,7 @@ import { CaseFile } from '../models/file.model'
import {
defenderCaseFileCategoriesForIndictmentCases,
defenderCaseFileCategoriesForRestrictionAndInvestigationCases,
prisonAdminCaseFileCategories,
} from './caseFileCategory'

@Injectable()
Expand Down Expand Up @@ -65,14 +65,13 @@ export class LimitedAccessViewCaseFileGuard implements CanActivate {
}
}

if (isPrisonSystemUser(user)) {
if (
isCompletedCase(theCase.state) &&
caseFile.category &&
caseFile.category === CaseFileCategory.APPEAL_RULING
) {
return true
}
if (
caseFile.category &&
isCompletedCase(theCase.state) &&
isPrisonAdminUser(user) &&
prisonAdminCaseFileCategories.includes(caseFile.category)
) {
return true
}

throw new ForbiddenException(`Forbidden for ${user.role}`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,27 +229,19 @@ describe('Limited Access View Case File Guard', () => {
describe.each(allowedCaseFileCategories)(
'prison system users can view %s',
(category) => {
let thenPrison: Then
let thenPrisonAdmin: Then

beforeEach(() => {
mockRequest.mockImplementationOnce(() => ({
user: prisonUser,
case: { type, state },
caseFile: { category },
}))
mockRequest.mockImplementationOnce(() => ({
user: prisonAdminUser,
case: { type, state },
caseFile: { category },
}))

thenPrison = givenWhenThen()
thenPrisonAdmin = givenWhenThen()
})

it('should activate', () => {
expect(thenPrison.result).toBe(true)
expect(thenPrisonAdmin.result).toBe(true)
})
},
Expand Down
2 changes: 2 additions & 0 deletions libs/judicial-system/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ export {
isCourtOfAppealsUser,
prisonSystemRoles,
isPrisonSystemUser,
isPrisonStaffUser,
defenceRoles,
isDefenceUser,
isAdminUser,
isCoreUser,
isPrisonAdminUser,
isPublicProsecutor,
} from './lib/user'
export type { User } from './lib/user'
Expand Down
20 changes: 10 additions & 10 deletions libs/judicial-system/types/src/lib/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ export enum CaseFileCategory {
CASE_FILE_RECORD = 'CASE_FILE_RECORD',
PROSECUTOR_CASE_FILE = 'PROSECUTOR_CASE_FILE',
DEFENDANT_CASE_FILE = 'DEFENDANT_CASE_FILE',
PROSECUTOR_APPEAL_BRIEF = 'PROSECUTOR_APPEAL_BRIEF',
DEFENDANT_APPEAL_BRIEF = 'DEFENDANT_APPEAL_BRIEF',
PROSECUTOR_APPEAL_BRIEF_CASE_FILE = 'PROSECUTOR_APPEAL_BRIEF_CASE_FILE',
DEFENDANT_APPEAL_BRIEF_CASE_FILE = 'DEFENDANT_APPEAL_BRIEF_CASE_FILE',
PROSECUTOR_APPEAL_STATEMENT = 'PROSECUTOR_APPEAL_STATEMENT',
DEFENDANT_APPEAL_STATEMENT = 'DEFENDANT_APPEAL_STATEMENT',
PROSECUTOR_APPEAL_STATEMENT_CASE_FILE = 'PROSECUTOR_APPEAL_STATEMENT_CASE_FILE',
DEFENDANT_APPEAL_STATEMENT_CASE_FILE = 'DEFENDANT_APPEAL_STATEMENT_CASE_FILE',
PROSECUTOR_APPEAL_CASE_FILE = 'PROSECUTOR_APPEAL_CASE_FILE',
DEFENDANT_APPEAL_CASE_FILE = 'DEFENDANT_APPEAL_CASE_FILE',
PROSECUTOR_APPEAL_BRIEF = 'PROSECUTOR_APPEAL_BRIEF', // Sækjandi: Kæruskjal til Landsréttar
DEFENDANT_APPEAL_BRIEF = 'DEFENDANT_APPEAL_BRIEF', // Verjandi: Kæruskjal til Landsréttar
PROSECUTOR_APPEAL_BRIEF_CASE_FILE = 'PROSECUTOR_APPEAL_BRIEF_CASE_FILE', // Sækjandi: Fylgigögn kæruskjals til Landsréttar
DEFENDANT_APPEAL_BRIEF_CASE_FILE = 'DEFENDANT_APPEAL_BRIEF_CASE_FILE', // Verjandi: Fylgigögn kæruskjals til Landsréttar
PROSECUTOR_APPEAL_STATEMENT = 'PROSECUTOR_APPEAL_STATEMENT', // Sækjandi: Greinargerð
DEFENDANT_APPEAL_STATEMENT = 'DEFENDANT_APPEAL_STATEMENT', // Verjandi: Greinargerð
PROSECUTOR_APPEAL_STATEMENT_CASE_FILE = 'PROSECUTOR_APPEAL_STATEMENT_CASE_FILE', // Sækjandi: Fylgigögn greinargerðar
DEFENDANT_APPEAL_STATEMENT_CASE_FILE = 'DEFENDANT_APPEAL_STATEMENT_CASE_FILE', // Verjandi: Fylgigögn greinargerðar
PROSECUTOR_APPEAL_CASE_FILE = 'PROSECUTOR_APPEAL_CASE_FILE', // Sækjandi: Viðbótargögn við kæru til Landsréttar
DEFENDANT_APPEAL_CASE_FILE = 'DEFENDANT_APPEAL_CASE_FILE', // Verjandi: Viðbótargögn við kæru til Landsréttar
APPEAL_COURT_RECORD = 'APPEAL_COURT_RECORD',
APPEAL_RULING = 'APPEAL_RULING',
}
14 changes: 14 additions & 0 deletions libs/judicial-system/types/src/lib/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ export const isPrisonSystemUser = (user?: InstitutionUser): boolean => {
)
}

export const isPrisonAdminUser = (user: InstitutionUser): boolean =>
Boolean(
user.role &&
prisonSystemRoles.includes(user.role) &&
user.institution?.type === InstitutionType.PRISON_ADMIN,
)

export const isPrisonStaffUser = (user: InstitutionUser): boolean =>
Boolean(
user.role &&
prisonSystemRoles.includes(user.role) &&
user.institution?.type === InstitutionType.PRISON,
)

export const defenceRoles: string[] = [UserRole.DEFENDER]

export const isDefenceUser = (user?: InstitutionUser): boolean => {
Expand Down

0 comments on commit f67a713

Please sign in to comment.