From bdeea4fb785523794b5a11e6e0d705c86768f6d8 Mon Sep 17 00:00:00 2001 From: unakb Date: Wed, 27 Nov 2024 11:09:26 +0000 Subject: [PATCH] feat(j-s): Connect case files to defendant or civil claimant --- .../app/modules/backend/backend.service.ts | 24 +++++- .../app/modules/file/dto/createFile.input.ts | 10 +++ .../api/src/app/modules/file/file.resolver.ts | 9 ++- .../file/limitedAccessFile.resolver.ts | 8 +- .../20241122091513-update-case-file.js | 44 +++++++++++ .../src/app/modules/file/file.controller.ts | 73 ++++++++++++++++++- .../src/app/modules/file/file.service.ts | 5 ++ .../limitedAccessWriteCaseFileGuard.spec.ts | 10 +-- .../file/guards/writeCaseFile.guard.ts | 55 ++++++++++++++ .../file/limitedAccessFile.controller.ts | 38 ++++++++++ .../src/app/modules/file/models/file.model.ts | 11 +++ .../createCaseFileGuards.spec.ts | 15 +++- .../SendToPrisonAdmin/SendToPrisonAdmin.tsx | 30 ++++---- .../utils/hooks/useS3Upload/useS3Upload.ts | 17 ++++- 14 files changed, 318 insertions(+), 31 deletions(-) create mode 100644 apps/judicial-system/backend/migrations/20241122091513-update-case-file.js create mode 100644 apps/judicial-system/backend/src/app/modules/file/guards/writeCaseFile.guard.ts diff --git a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts index 099c3bf98b10..2a8571b7c250 100644 --- a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts +++ b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts @@ -266,8 +266,19 @@ export class BackendService extends DataSource<{ req: Request }> { return this.post(`case/${id}/file/url`, createPresignedPost) } - createCaseFile(id: string, createFile: unknown): Promise { - return this.post(`case/${id}/file`, createFile) + createCaseFile( + id: string, + createFile: unknown, + defendantId?: string, + civilClaimantId?: string, + ): Promise { + const connectionInjection = defendantId + ? `/defendant/${defendantId}` + : civilClaimantId + ? `/civilClaimant/${civilClaimantId}` + : '' + + return this.post(`case/${id}${connectionInjection}/file`, createFile) } getCaseFileSignedUrl( @@ -435,8 +446,15 @@ export class BackendService extends DataSource<{ req: Request }> { limitedAccessCreateCaseFile( id: string, createFile: unknown, + civilClaimantId?: string, ): Promise { - return this.post(`case/${id}/limitedAccess/file`, createFile) + const connectionInjection = civilClaimantId + ? `/civilClaimant/${civilClaimantId}` + : '' + return this.post( + `case/${id}/limitedAccess${connectionInjection}/file`, + createFile, + ) } limitedAccessGetCaseFileSignedUrl( diff --git a/apps/judicial-system/api/src/app/modules/file/dto/createFile.input.ts b/apps/judicial-system/api/src/app/modules/file/dto/createFile.input.ts index 51137a3310e5..bd66872d061f 100644 --- a/apps/judicial-system/api/src/app/modules/file/dto/createFile.input.ts +++ b/apps/judicial-system/api/src/app/modules/file/dto/createFile.input.ts @@ -70,4 +70,14 @@ export class CreateFileInput { @IsOptional() @Field(() => String, { nullable: true }) readonly userGeneratedFilename?: string + + @Allow() + @IsOptional() + @Field(() => ID, { nullable: true }) + readonly defendantId?: string + + @Allow() + @IsOptional() + @Field(() => ID, { nullable: true }) + readonly civilClaimantId?: string } diff --git a/apps/judicial-system/api/src/app/modules/file/file.resolver.ts b/apps/judicial-system/api/src/app/modules/file/file.resolver.ts index 45990fbb7dc2..3a50398c9070 100644 --- a/apps/judicial-system/api/src/app/modules/file/file.resolver.ts +++ b/apps/judicial-system/api/src/app/modules/file/file.resolver.ts @@ -65,14 +65,19 @@ export class FileResolver { @Context('dataSources') { backendService }: { backendService: BackendService }, ): Promise { - const { caseId, ...createFile } = input + const { caseId, defendantId, civilClaimantId, ...createFile } = input this.logger.debug(`Creating a file for case ${caseId}`) return this.auditTrailService.audit( user.id, AuditedAction.CREATE_FILE, - backendService.createCaseFile(caseId, createFile), + backendService.createCaseFile( + caseId, + createFile, + defendantId, + civilClaimantId, + ), (file) => file.id, ) } diff --git a/apps/judicial-system/api/src/app/modules/file/limitedAccessFile.resolver.ts b/apps/judicial-system/api/src/app/modules/file/limitedAccessFile.resolver.ts index ecd4c88ec4bf..75c597e3ebea 100644 --- a/apps/judicial-system/api/src/app/modules/file/limitedAccessFile.resolver.ts +++ b/apps/judicial-system/api/src/app/modules/file/limitedAccessFile.resolver.ts @@ -64,14 +64,18 @@ export class LimitedAccessFileResolver { @Context('dataSources') { backendService }: { backendService: BackendService }, ): Promise { - const { caseId, ...createFile } = input + const { caseId, civilClaimantId, ...createFile } = input this.logger.debug(`Creating a file for case ${caseId}`) return this.auditTrailService.audit( user.id, AuditedAction.CREATE_FILE, - backendService.limitedAccessCreateCaseFile(caseId, createFile), + backendService.limitedAccessCreateCaseFile( + caseId, + createFile, + civilClaimantId, + ), (file) => file.id, ) } diff --git a/apps/judicial-system/backend/migrations/20241122091513-update-case-file.js b/apps/judicial-system/backend/migrations/20241122091513-update-case-file.js new file mode 100644 index 000000000000..46ff67fc695a --- /dev/null +++ b/apps/judicial-system/backend/migrations/20241122091513-update-case-file.js @@ -0,0 +1,44 @@ +'use strict' + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.sequelize.transaction(async (t) => { + await queryInterface.addColumn( + 'case_file', + 'defendant_id', + { + type: Sequelize.UUID, + references: { + model: 'defendant', + key: 'id', + }, + allowNull: true, + }, + { transaction: t }, + ) + await queryInterface.addColumn( + 'case_file', + 'civil_claimant_id', + { + type: Sequelize.UUID, + references: { + model: 'civil_claimant', + key: 'id', + }, + allowNull: true, + }, + { transaction: t }, + ) + }) + }, + down: (queryInterface) => { + return queryInterface.sequelize.transaction(async (t) => { + await queryInterface.removeColumn('case_file', 'civil_claimant_id', { + transaction: t, + }) + await queryInterface.removeColumn('case_file', 'defendant_id', { + transaction: t, + }) + }) + }, +} diff --git a/apps/judicial-system/backend/src/app/modules/file/file.controller.ts b/apps/judicial-system/backend/src/app/modules/file/file.controller.ts index 54626a9f5700..bbd4846faa97 100644 --- a/apps/judicial-system/backend/src/app/modules/file/file.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/file/file.controller.ts @@ -49,12 +49,21 @@ import { CurrentCase, } from '../case' import { MergedCaseExistsGuard } from '../case/guards/mergedCaseExists.guard' +import { + CivilClaimant, + CivilClaimantExistsGuard, + CurrentCivilClaimant, + CurrentDefendant, + Defendant, + DefendantExistsGuard, +} from '../defendant' import { CreateFileDto } from './dto/createFile.dto' import { CreatePresignedPostDto } from './dto/createPresignedPost.dto' import { UpdateFilesDto } from './dto/updateFile.dto' import { CurrentCaseFile } from './guards/caseFile.decorator' import { CaseFileExistsGuard } from './guards/caseFileExists.guard' import { ViewCaseFileGuard } from './guards/viewCaseFile.guard' +import { WriteCaseFileGuard } from './guards/writeCaseFile.guard' import { DeleteFileResponse } from './models/deleteFile.response' import { CaseFile } from './models/file.model' import { PresignedPost } from './models/presignedPost.model' @@ -98,7 +107,7 @@ export class FileController { return this.fileService.createPresignedPost(theCase, createPresignedPost) } - @UseGuards(RolesGuard, CaseExistsGuard, CaseWriteGuard) + @UseGuards(RolesGuard, CaseExistsGuard, CaseWriteGuard, WriteCaseFileGuard) @RolesRules( prosecutorRule, prosecutorRepresentativeRule, @@ -126,6 +135,68 @@ export class FileController { return this.fileService.createCaseFile(theCase, createFile, user) } + @UseGuards( + RolesGuard, + CaseExistsGuard, + DefendantExistsGuard, + CaseWriteGuard, + WriteCaseFileGuard, + ) + @RolesRules(publicProsecutorStaffRule) + @Post('defendant/:defendantId/file') + @ApiCreatedResponse({ + type: CaseFile, + description: 'Creates a new case file connected to a defendant', + }) + async createDefendantCaseFile( + @Param('caseId') caseId: string, + @Param('defendantId') defendantId: string, + @CurrentHttpUser() user: User, + @CurrentCase() theCase: Case, + @CurrentDefendant() defendant: Defendant, + @Body() createFile: CreateFileDto, + ): Promise { + this.logger.debug( + `Creating a file for case ${caseId} for defendant ${defendantId}`, + ) + + return this.fileService.createCaseFile(theCase, createFile, user, defendant) + } + + @UseGuards( + RolesGuard, + CaseExistsGuard, + CivilClaimantExistsGuard, + CaseWriteGuard, + WriteCaseFileGuard, + ) + @RolesRules(publicProsecutorStaffRule) + @Post('defendant/:defendantId/file') + @ApiCreatedResponse({ + type: CaseFile, + description: 'Creates a new case file connected to a defendant', + }) + async createCivilClaimantCaseFile( + @Param('caseId') caseId: string, + @Param('civilClaimantId') civilClaimantId: string, + @CurrentHttpUser() user: User, + @CurrentCase() theCase: Case, + @CurrentCivilClaimant() civilClaimant: CivilClaimant, + @Body() createFile: CreateFileDto, + ): Promise { + this.logger.debug( + `Creating a file for case ${caseId} for civil claimant ${civilClaimantId}`, + ) + + return this.fileService.createCaseFile( + theCase, + createFile, + user, + undefined, + civilClaimant, + ) + } + @UseGuards( RolesGuard, CaseExistsGuard, diff --git a/apps/judicial-system/backend/src/app/modules/file/file.service.ts b/apps/judicial-system/backend/src/app/modules/file/file.service.ts index 3aa552b87baf..e92185cfd733 100644 --- a/apps/judicial-system/backend/src/app/modules/file/file.service.ts +++ b/apps/judicial-system/backend/src/app/modules/file/file.service.ts @@ -31,6 +31,7 @@ import { createConfirmedPdf } from '../../formatters' import { AwsS3Service } from '../aws-s3' import { Case } from '../case' import { CourtDocumentFolder, CourtService } from '../court' +import { CivilClaimant, Defendant } from '../defendant' import { UserService } from '../user' import { CreateFileDto } from './dto/createFile.dto' import { CreatePresignedPostDto } from './dto/createPresignedPost.dto' @@ -339,6 +340,8 @@ export class FileService { theCase: Case, createFile: CreateFileDto, user: User, + defendant?: Defendant, + civilClaimant?: CivilClaimant, ): Promise { const { key } = createFile @@ -360,6 +363,8 @@ export class FileService { userGeneratedFilename: createFile.userGeneratedFilename ?? fileName.replace(/\.pdf$/, ''), submittedBy: user.name, + defendantId: defendant?.id, + civilClaimantId: civilClaimant?.id, }) if ( diff --git a/apps/judicial-system/backend/src/app/modules/file/guards/test/limitedAccessWriteCaseFileGuard.spec.ts b/apps/judicial-system/backend/src/app/modules/file/guards/test/limitedAccessWriteCaseFileGuard.spec.ts index 5b5854214b6f..a0f37051c36b 100644 --- a/apps/judicial-system/backend/src/app/modules/file/guards/test/limitedAccessWriteCaseFileGuard.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/file/guards/test/limitedAccessWriteCaseFileGuard.spec.ts @@ -48,7 +48,7 @@ describe('LimitedAccess Write Case File Guard', () => { }) describe.each(allowedCaseFileCategories)( - 'a defender can view %s', + 'a defender can access %s', (category) => { describe('when creating a case file', () => { let then: Then @@ -93,7 +93,7 @@ describe('LimitedAccess Write Case File Guard', () => { (category) => !allowedCaseFileCategories.includes(category as CaseFileCategory), ), - )('a defender can not view %s', (category) => { + )('a defender can not access %s', (category) => { describe('when creating a case file', () => { let then: Then @@ -137,7 +137,7 @@ describe('LimitedAccess Write Case File Guard', () => { Object.keys(UserRole).filter((role) => role !== UserRole.DEFENDER), )('role %s', (role) => { describe.each(Object.keys(CaseFileCategory))( - 'can not view %s', + 'can not access %s', (category) => { describe('when creating a case file', () => { let then: Then @@ -225,7 +225,7 @@ describe('LimitedAccess Write Case File Guard', () => { }) }) - describe('a defender can view DEFENDANT_CASE_FILE in indictment cases', () => { + describe('a defender can access DEFENDANT_CASE_FILE in indictment cases', () => { describe('when creating a case file', () => { let then: Then @@ -265,7 +265,7 @@ describe('LimitedAccess Write Case File Guard', () => { describe.each( Object.keys(CaseType).filter((ct) => ct !== CaseType.INDICTMENT), - )('a defender can not view DEFENDANT_CASE_FILE in %s cases', (caseType) => { + )('a defender can not access DEFENDANT_CASE_FILE in %s cases', (caseType) => { describe('when creating a case file', () => { let then: Then diff --git a/apps/judicial-system/backend/src/app/modules/file/guards/writeCaseFile.guard.ts b/apps/judicial-system/backend/src/app/modules/file/guards/writeCaseFile.guard.ts new file mode 100644 index 000000000000..da409be6a1fa --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/file/guards/writeCaseFile.guard.ts @@ -0,0 +1,55 @@ +import { + BadRequestException, + CanActivate, + ExecutionContext, + Injectable, + InternalServerErrorException, +} from '@nestjs/common' + +import { CaseFileCategory, User } from '@island.is/judicial-system/types' + +import { Case } from '../../case' + +@Injectable() +export class WriteCaseFileGuard implements CanActivate { + canActivate(context: ExecutionContext): boolean { + const request = context.switchToHttp().getRequest() + + const user: User = request.user + const theCase: Case = request.case + const defendant = request.defendant + const civilClaimant = request.civilClaimant + + if (!theCase) { + throw new InternalServerErrorException('Missing case') + } + + if (!user) { + throw new InternalServerErrorException('Missing user') + } + + // The case file category is either in the request body (creating case file) + // or in the case file (deleting case file) + const caseFileCategory: CaseFileCategory = + request.body?.category ?? request.caseFile?.category + + if (!caseFileCategory) { + throw new InternalServerErrorException('Missing case file category') + } + + if ( + caseFileCategory === CaseFileCategory.SENT_TO_PRISON_ADMIN_FILE && + !defendant + ) { + throw new BadRequestException('Missing defendant for case file category') + } + + if (caseFileCategory === CaseFileCategory.CIVIL_CLAIM && !civilClaimant) { + throw new BadRequestException( + 'Missing civil claimant for case file category', + ) + } + + return true + } +} diff --git a/apps/judicial-system/backend/src/app/modules/file/limitedAccessFile.controller.ts b/apps/judicial-system/backend/src/app/modules/file/limitedAccessFile.controller.ts index 3c1605da9c12..eef4db21b81b 100644 --- a/apps/judicial-system/backend/src/app/modules/file/limitedAccessFile.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/file/limitedAccessFile.controller.ts @@ -37,6 +37,11 @@ import { LimitedAccessCaseExistsGuard, } from '../case' import { MergedCaseExistsGuard } from '../case/guards/mergedCaseExists.guard' +import { + CivilClaimant, + CivilClaimantExistsGuard, + CurrentCivilClaimant, +} from '../defendant' import { CreateFileDto } from './dto/createFile.dto' import { CreatePresignedPostDto } from './dto/createPresignedPost.dto' import { CurrentCaseFile } from './guards/caseFile.decorator' @@ -108,6 +113,39 @@ export class LimitedAccessFileController { return this.fileService.createCaseFile(theCase, createFile, user) } + @UseGuards( + new CaseTypeGuard([...indictmentCases]), + CivilClaimantExistsGuard, + CaseWriteGuard, + LimitedAccessWriteCaseFileGuard, + ) + @RolesRules(defenderRule) + @Post('civilClaimant/:civilClaimantId/file') + @ApiCreatedResponse({ + type: CaseFile, + description: 'Creates a new case file for a civil claimant', + }) + createCivilClaimantCaseFile( + @Param('caseId') caseId: string, + @Param('civilClaimantId') civilClaimantId: string, + @CurrentHttpUser() user: User, + @CurrentCase() theCase: Case, + @CurrentCivilClaimant() civilClaimant: CivilClaimant, + @Body() createFile: CreateFileDto, + ): Promise { + this.logger.debug( + `Creating a file for case ${caseId} and civil claimant ${civilClaimantId}`, + ) + + return this.fileService.createCaseFile( + theCase, + createFile, + user, + undefined, + civilClaimant, + ) + } + @UseGuards( CaseReadGuard, MergedCaseExistsGuard, diff --git a/apps/judicial-system/backend/src/app/modules/file/models/file.model.ts b/apps/judicial-system/backend/src/app/modules/file/models/file.model.ts index b07a262aa8fa..9d3a68677b33 100644 --- a/apps/judicial-system/backend/src/app/modules/file/models/file.model.ts +++ b/apps/judicial-system/backend/src/app/modules/file/models/file.model.ts @@ -17,6 +17,7 @@ import { // TODO Find a way to import from an index file import { Case } from '../../case/models/case.model' +import { CivilClaimant, Defendant } from '../../defendant' @Table({ tableName: 'case_file', @@ -45,6 +46,16 @@ export class CaseFile extends Model { @ApiProperty({ type: String }) caseId!: string + @ForeignKey(() => Defendant) + @Column({ type: DataType.UUID, allowNull: true }) + @ApiProperty({ type: String }) + defendantId?: string + + @ForeignKey(() => CivilClaimant) + @Column({ type: DataType.UUID, allowNull: true }) + @ApiProperty({ type: String }) + civilClaimantId?: string + @Column({ type: DataType.STRING, allowNull: false }) @ApiProperty({ type: String }) name!: string diff --git a/apps/judicial-system/backend/src/app/modules/file/test/fileController/createCaseFileGuards.spec.ts b/apps/judicial-system/backend/src/app/modules/file/test/fileController/createCaseFileGuards.spec.ts index 1823dd2f2884..46e9f341c6c5 100644 --- a/apps/judicial-system/backend/src/app/modules/file/test/fileController/createCaseFileGuards.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/file/test/fileController/createCaseFileGuards.spec.ts @@ -4,6 +4,7 @@ import { RolesGuard } from '@island.is/judicial-system/auth' import { CaseExistsGuard, CaseWriteGuard } from '../../../case' import { FileController } from '../../file.controller' +import { WriteCaseFileGuard } from '../../guards/writeCaseFile.guard' describe('FileController - Create case file guards', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -17,7 +18,7 @@ describe('FileController - Create case file guards', () => { }) it('should have three guards', () => { - expect(guards).toHaveLength(3) + expect(guards).toHaveLength(4) }) describe('RolesGuard', () => { @@ -55,4 +56,16 @@ describe('FileController - Create case file guards', () => { expect(guard).toBeInstanceOf(CaseWriteGuard) }) }) + + describe('CaseWriteGuard', () => { + let guard: CanActivate + + beforeEach(() => { + guard = new guards[3]() + }) + + it('should have CaseWriteGuard as guard 4', () => { + expect(guard).toBeInstanceOf(WriteCaseFileGuard) + }) + }) }) diff --git a/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/SendToPrisonAdmin/SendToPrisonAdmin.tsx b/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/SendToPrisonAdmin/SendToPrisonAdmin.tsx index 84ba3f0e18ad..4b2962c7c8fc 100644 --- a/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/SendToPrisonAdmin/SendToPrisonAdmin.tsx +++ b/apps/judicial-system/web/src/routes/PublicProsecutor/Indictments/SendToPrisonAdmin/SendToPrisonAdmin.tsx @@ -2,9 +2,9 @@ import { FC, useCallback, useContext, useState } from 'react' import { useIntl } from 'react-intl' import { useParams, useRouter } from 'next/navigation' -import { Box, UploadFile } from '@island.is/island-ui/core' +import { Box, InputFileUpload, UploadFile } from '@island.is/island-ui/core' import { PUBLIC_PROSECUTOR_STAFF_INDICTMENT_OVERVIEW_ROUTE } from '@island.is/judicial-system/consts' -import { core } from '@island.is/judicial-system-web/messages' +import { core, errors } from '@island.is/judicial-system-web/messages' import { CourtCaseInfo, FormContentContainer, @@ -37,7 +37,10 @@ const SendToPrisonAdmin: FC = () => { const [uploadFileError, setUploadFileError] = useState() const router = useRouter() const { defendantId } = useParams<{ caseId: string; defendantId: string }>() - const { handleUpload, handleRemove } = useS3Upload(workingCase.id) + const { handleUpload, handleRemove } = useS3Upload( + workingCase.id, + defendantId, + ) const { updateDefendant, isUpdatingDefendant } = useDefendants() const { uploadFiles, removeUploadFile, addUploadFiles, updateUploadFile } = useUploadFiles() @@ -65,16 +68,15 @@ const SendToPrisonAdmin: FC = () => { isSentToPrisonAdmin: true, }) - // TODO: UNCOMMENT WHEN THIS FEATURE IS READY - // const uploadResult = await handleUpload( - // uploadFiles.filter((file) => file.percent === 0), - // updateUploadFile, - // ) + const uploadResult = await handleUpload( + uploadFiles.filter((file) => file.percent === 0), + updateUploadFile, + ) - // if (uploadResult !== 'ALL_SUCCEEDED') { - // setUploadFileError(formatMessage(errors.uploadFailed)) - // return - // } + if (uploadResult !== 'ALL_SUCCEEDED') { + setUploadFileError(formatMessage(errors.uploadFailed)) + return + } router.push( `${PUBLIC_PROSECUTOR_STAFF_INDICTMENT_OVERVIEW_ROUTE}/${workingCase.id}`, @@ -119,8 +121,6 @@ const SendToPrisonAdmin: FC = () => { description={formatMessage(strings.fileUploadDescription)} /> - {/* NOTE: This is temporarily disabled while we work on this - upload feature. @@ -134,7 +134,7 @@ const SendToPrisonAdmin: FC = () => { buttonLabel={formatMessage(core.uploadBoxButtonLabel)} onChange={handleFileUpload} onRemove={handleRemoveFile} - /> */} + /> diff --git a/apps/judicial-system/web/src/utils/hooks/useS3Upload/useS3Upload.ts b/apps/judicial-system/web/src/utils/hooks/useS3Upload/useS3Upload.ts index d47a6ad001f6..271b094b12b9 100644 --- a/apps/judicial-system/web/src/utils/hooks/useS3Upload/useS3Upload.ts +++ b/apps/judicial-system/web/src/utils/hooks/useS3Upload/useS3Upload.ts @@ -189,7 +189,11 @@ const uploadToS3 = ( return promise } -const useS3Upload = (caseId: string) => { +const useS3Upload = ( + caseId: string, + defendantId?: string, + civilClaimantId?: string, +) => { const { limitedAccess } = useContext(UserContext) const { formatMessage } = useIntl() @@ -255,6 +259,8 @@ const useS3Upload = (caseId: string) => { displayDate: file.displayDate, policeFileId: file.policeFileId, userGeneratedFilename: file.userGeneratedFilename, + defendantId, + civilClaimantId, }, }, }) @@ -269,7 +275,14 @@ const useS3Upload = (caseId: string) => { return createdFile.id }, - [limitedAccess, limitedAccessCreateFile, createFile, caseId], + [ + limitedAccess, + limitedAccessCreateFile, + createFile, + caseId, + defendantId, + civilClaimantId, + ], ) const handleUpload = useCallback(