Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Utopia 769] Updated pia-intake entity and associated JSONB classes and dtos #857

Merged
merged 18 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
81dcdf6
[UTOPIA-769] [Backend] [pia-intake.collectionUseAndDisclosure] Update…
kushal-arora-fw Feb 14, 2023
2e5b2b1
[UTOPIA-769] [Backend] [pia-intake] Update Sort type fix to fix break…
kushal-arora-fw Feb 14, 2023
76148b5
[Backend] [pia-intake.storingPersonalInformation] Updated pia-intake …
kushal-arora-fw Feb 14, 2023
94252aa
[UTOPIA-769] [BE] pia-intake validations update
kushal-arora-fw Feb 14, 2023
fe6ff4e
[UTOPIA-769] [BE] pia-intake - added entity column storingPersonalInf…
kushal-arora-fw Feb 14, 2023
c20f7f4
[UTOPIA-769] [Backend] [pia-intake.securityPersonalInformation] Updat…
kushal-arora-fw Feb 14, 2023
86fc576
[UTOPIA-769] [Backend] removed class suffix from jsonb-classes
kushal-arora-fw Feb 14, 2023
5f988a5
[UTOPIA-769] [Backend] [pia-intake.accuracyCorrectionAndRetention] Up…
kushal-arora-fw Feb 14, 2023
1beb238
[UTOPIA-769] [Backend] [pia-intake.personalInformationBanks] Updated …
kushal-arora-fw Feb 14, 2023
d9ef5b7
[UTOPIA-769] [Backend] [pia-intake.additionalRisks] Updated pia-intak…
kushal-arora-fw Feb 14, 2023
78434f8
[CodeClimate fix] [Backend] moved create-pia-mock to separate file
kushal-arora-fw Feb 14, 2023
cb2608b
[UTOPIA-769] [Backend] Migration to update pia-intake table with josn…
kushal-arora-fw Feb 14, 2023
4e45d84
[UTOPIA-769] [Backend] [Unit Test] Added Test Case for empty Jsonb va…
kushal-arora-fw Feb 14, 2023
8bef40f
[UTOPIA-769] [Backend] Added conditional operator to IsOptional fields
kushal-arora-fw Feb 14, 2023
73cfcf1
[UTOPIA-769] [Backend] applied pia jsonb fields role validations
kushal-arora-fw Feb 15, 2023
a4a28bc
[UTOPIA-769] [Backend] updated generic section names to specific
kushal-arora-fw Feb 15, 2023
42f0b93
[UTOPIA-769] [Backend] Updating jsonb classes to add IsOptional for a…
kushal-arora-fw Feb 15, 2023
52a6188
[UTOPIA-769] [Backend] [Bug fix] updated role validation logic when d…
kushal-arora-fw Feb 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/backend/src/common/enums/users.enum.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export enum UserTypesEnum {
DRAFTER = 'DRAFTER',
MPO = 'MPO',
}
4 changes: 4 additions & 0 deletions src/backend/src/common/enums/yes-no-input.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum YesNoInput {
YES = 'YES',
NO = 'NO',
}
8 changes: 8 additions & 0 deletions src/backend/src/common/interfaces/form-field.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { UserTypesEnum } from '../enums/users.enum';

export interface IFormField<T> {
key: keyof T;
type: 'text'; // add ORs for future support if needed
isRichText: boolean;
allowedUserTypesEdit: Array<UserTypesEnum>; // null if no role restrictions apply
}
34 changes: 34 additions & 0 deletions src/backend/src/common/validators/form-field-role.validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ForbiddenException } from '@nestjs/common';
import { UserTypesEnum } from '../enums/users.enum';
import { IFormField } from '../interfaces/form-field.interface';

/**
* @method validateRoleForFormField
*
* @description
* This method validates role access to Form Fields values
*/
export const validateRoleForFormField = <T>(
metadata: IFormField<T>,
value: any,
userType: UserTypesEnum,
path: string,
) => {
if (!value) return; // if value not edited - no need to validate permissions

if (!metadata?.allowedUserTypesEdit) return; // if allowedUserTypesEdit is null, all roles can edit this field/key

if (
metadata.allowedUserTypesEdit.includes(UserTypesEnum.MPO) &&
userType !== UserTypesEnum.MPO
) {
// if allowed user types is MPO and the user is not an MPO user, throw error
throw new ForbiddenException({
path: path,
message: `You do not have permissions to edit certain section of this document. Please reach out to your MPO to proceed.`,
});
}

// allow otherwise
return;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class PiaIntakeAddJsonbColumns1676414798877
implements MigrationInterface
{
name = 'piaIntakeAddJsonbColumns1676414798877';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "pia-intake" ADD "collection_use_and_disclosure" jsonb`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" ADD "storing_personal_information" jsonb`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" ADD "security_personal_information" jsonb`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" ADD "accuracy_correction_and_retention" jsonb`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" ADD "personal_information_banks" jsonb`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" ADD "additional_risks" jsonb`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "pia-intake" DROP COLUMN "additional_risks"`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" DROP COLUMN "personal_information_banks"`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" DROP COLUMN "accuracy_correction_and_retention"`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" DROP COLUMN "security_personal_information"`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" DROP COLUMN "storing_personal_information"`,
);
await queryRunner.query(
`ALTER TABLE "pia-intake" DROP COLUMN "collection_use_and_disclosure"`,
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PiaIntakeEntity } from '../entities/pia-intake.entity';
export type PiaIntakeAllowedSortFieldsType =
| 'drafterName'
| 'updatedAt'
| 'createdAt';

export const PiaIntakeAllowedSortFields: Array<keyof PiaIntakeEntity> = [
'drafterName',
'updatedAt',
];
export const PiaIntakeAllowedSortFields: Array<PiaIntakeAllowedSortFieldsType> =
['drafterName', 'updatedAt', 'createdAt'];
113 changes: 83 additions & 30 deletions src/backend/src/modules/pia-intake/dto/create-pia-intake.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,23 @@ import {
IsDateString,
IsEmail,
IsEnum,
IsNotEmptyObject,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from '@nestjs/class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { GovMinistriesEnum } from '../../../common/enums/gov-ministries.enum';
import { PiaIntakeStatusEnum } from '../enums/pia-intake-status.enum';

export const piaIntakeEntityMock = {
title: 'Test PIA for screening King Richard',
ministry: GovMinistriesEnum.TOURISM_ARTS_CULTURE_AND_SPORT,
branch: 'Entertainment',
status: PiaIntakeStatusEnum.INCOMPLETE,
drafterName: 'Will Smith',
drafterTitle: 'Actor',
drafterEmail: 'will@test.bc.gov.in',
leadName: 'King Richard',
leadTitle: 'Chief Guiding Officer',
leadEmail: 'king@test.bc.gov.in',
mpoName: 'Reinaldo Marcus Green',
mpoEmail: 'reinaldo@test.bc.gov.in',
initiativeDescription: `*King Richard* is a 2021 American biographical sports drama film directed by [Reinaldo Marcus Green](https://en.wikipedia.org/wiki/Reinaldo_Marcus_Green) and written by [Zach Baylin](https://en.wikipedia.org/wiki/Zach_Baylin). The film stars [Will Smith](https://en.wikipedia.org/wiki/Will_Smith) as Richard Williams, the father and coach of famed tennis players [Venus](https://en.wikipedia.org/wiki/Venus_Williams) and [Serena Williams](https://en.wikipedia.org/wiki/Serena_Williams) (both of whom served as executive producers on the film), with [Aunjanue Ellis](https://en.wikipedia.org/wiki/Aunjanue_Ellis), [Saniyya Sidney](https://en.wikipedia.org/wiki/Saniyya_Sidney), [Demi Singleton](https://en.wikipedia.org/wiki/Demi_Singleton), [Tony Goldwyn](https://en.wikipedia.org/wiki/Tony_Goldwyn), and [Jon Bernthal](https://en.wikipedia.org/wiki/Jon_Bernthal) in supporting roles.`,
initiativeScope: `Richard Williams lives in [Compton, California](https://en.wikipedia.org/wiki/Compton,_California), with his wife Brandy, his three step-daughters, and his two daughters, Venus and Serena. Richard aspires to turn Venus and Serena into professional tennis players; he has prepared a plan for success since before they were born. Richard and Brandy coach Venus and Serena on a daily basis, while also working as a security guard and a nurse, respectively. Richard works tirelessly to find a professional coach for the girls, creating brochures and videotapes to advertise their skills, but has not had success.`,
dataElementsInvolved: `Cast Involved:

1. Will Smith as Richard Williams
2. Aunjanue Ellis as Oracene "Brandy" Price
3. Saniyya Sidney as Venus Williams
4. Demi Singleton as Serena Williams
5. Jon Bernthal as Rick Macci
6. Tony Goldwyn as Paul Cohen
7. Mikayla LaShae Bartholomew as Tunde Price
`,
hasAddedPiToDataElements: false,
submittedAt: new Date(),
riskMitigation: `The film was released on [Blu-ray](https://en.wikipedia.org/wiki/Blu-ray) and [DVD](https://en.wikipedia.org/wiki/DVD) February 8, 2022 by [Warner Bros. Home Entertainment](https://en.wikipedia.org/wiki/Warner_Bros._Home_Entertainment), with the 4K Ultra HD release through [Warner Archive Collection](https://en.wikipedia.org/wiki/Warner_Archive_Collection) on the same date.`,
};
import { AccuracyCorrectionAndRetention } from '../jsonb-classes/accuracy-correction-and-retention';
import { AdditionalRisks } from '../jsonb-classes/additional-risks';
import { CollectionUseAndDisclosure } from '../jsonb-classes/collection-use-and-disclosure';
import { PersonalInformationBanks } from '../jsonb-classes/personal-information-banks';
import { SecurityPersonalInformation } from '../jsonb-classes/security-personal-information';
import { StoringPersonalInformation } from '../jsonb-classes/storing-personal-information';
import { piaIntakeEntityMock } from '../mocks/create-pia-intake.mock';

export class CreatePiaIntakeDto {
@IsString()
Expand Down Expand Up @@ -205,4 +186,76 @@ export class CreatePiaIntakeDto {
example: new Date(),
})
submittedAt: Date;

@IsObject()
@IsOptional()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => CollectionUseAndDisclosure)
@ApiProperty({
type: CollectionUseAndDisclosure,
required: false,
example: piaIntakeEntityMock.collectionUseAndDisclosure,
})
collectionUseAndDisclosure: CollectionUseAndDisclosure;

@IsObject()
@IsOptional()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => StoringPersonalInformation)
@ApiProperty({
type: StoringPersonalInformation,
required: false,
example: piaIntakeEntityMock.storingPersonalInformation,
})
storingPersonalInformation: StoringPersonalInformation;

@IsObject()
@IsOptional()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => SecurityPersonalInformation)
@ApiProperty({
type: SecurityPersonalInformation,
required: false,
example: piaIntakeEntityMock.securityPersonalInformation,
})
securityPersonalInformation: SecurityPersonalInformation;

@IsObject()
@IsOptional()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => AccuracyCorrectionAndRetention)
@ApiProperty({
type: AccuracyCorrectionAndRetention,
required: false,
example: piaIntakeEntityMock.accuracyCorrectionAndRetention,
})
accuracyCorrectionAndRetention: AccuracyCorrectionAndRetention;

@IsObject()
@IsOptional()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => PersonalInformationBanks)
@ApiProperty({
type: PersonalInformationBanks,
required: false,
example: piaIntakeEntityMock.personalInformationBanks,
})
personalInformationBanks: PersonalInformationBanks;

@IsObject()
@IsOptional()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => AdditionalRisks)
@ApiProperty({
type: AdditionalRisks,
required: false,
example: piaIntakeEntityMock.additionalRisks,
})
additionalRisks: AdditionalRisks;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { GovMinistriesEnum } from 'src/common/enums/gov-ministries.enum';
import { SortOrderEnum } from 'src/common/enums/sort-order.enum';
import { PiaIntakeAllowedSortFields } from '../constants/pia-intake-allowed-sort-fields';
import { PiaIntakeEntity } from '../entities/pia-intake.entity';
import {
PiaIntakeAllowedSortFields,
PiaIntakeAllowedSortFieldsType,
} from '../constants/pia-intake-allowed-sort-fields';
import { PiaFilterDrafterByCurrentUserEnum } from '../enums/pia-filter-drafter-by-current-user.enum';
import { PiaIntakeStatusEnum } from '../enums/pia-intake-status.enum';
import { piaIntakeEntityMock } from './create-pia-intake.dto';
import { piaIntakeEntityMock } from '../mocks/create-pia-intake.mock';

export class PiaIntakeFindQuery {
@ApiProperty({
Expand Down Expand Up @@ -86,7 +88,7 @@ export class PiaIntakeFindQuery {
@IsString()
@IsIn(PiaIntakeAllowedSortFields)
@IsOptional()
readonly sortBy?: keyof PiaIntakeEntity;
readonly sortBy?: PiaIntakeAllowedSortFieldsType;

@ApiProperty({
required: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { GovMinistriesEnum } from '../../../common/enums/gov-ministries.enum';
import { Column, Entity } from 'typeorm';
import { BaseEntity } from '../../../common/entities/base.entity';
import { PiaIntakeStatusEnum } from '../enums/pia-intake-status.enum';
import { CollectionUseAndDisclosure } from '../jsonb-classes/collection-use-and-disclosure';
import { StoringPersonalInformation } from '../jsonb-classes/storing-personal-information';
import { SecurityPersonalInformation } from '../jsonb-classes/security-personal-information';
import { AccuracyCorrectionAndRetention } from '../jsonb-classes/accuracy-correction-and-retention';
import { PersonalInformationBanks } from '../jsonb-classes/personal-information-banks';
import { AdditionalRisks } from '../jsonb-classes/additional-risks';

@Entity('pia-intake')
export class PiaIntakeEntity extends BaseEntity {
Expand Down Expand Up @@ -129,4 +135,46 @@ export class PiaIntakeEntity extends BaseEntity {
default: null,
})
submittedAt: Date;

@Column({
name: 'collection_use_and_disclosure',
type: 'jsonb',
nullable: true,
})
collectionUseAndDisclosure: CollectionUseAndDisclosure;

@Column({
name: 'storing_personal_information',
type: 'jsonb',
nullable: true,
})
storingPersonalInformation: StoringPersonalInformation;

@Column({
name: 'security_personal_information',
type: 'jsonb',
nullable: true,
})
securityPersonalInformation: SecurityPersonalInformation;

@Column({
name: 'accuracy_correction_and_retention',
type: 'jsonb',
nullable: true,
})
accuracyCorrectionAndRetention: AccuracyCorrectionAndRetention;

@Column({
name: 'personal_information_banks',
type: 'jsonb',
nullable: true,
})
personalInformationBanks: PersonalInformationBanks;

@Column({
name: 'additional_risks',
type: 'jsonb',
nullable: true,
})
additionalRisks: AdditionalRisks;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IsOptional, IsString } from '@nestjs/class-validator';

export class Accuracy {
@IsString()
@IsOptional()
description?: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IsEnum, IsOptional } from '@nestjs/class-validator';
import { YesNoInput } from 'src/common/enums/yes-no-input.enum';

export class Correction {
@IsEnum(YesNoInput)
@IsOptional()
haveProcessInPlace?: YesNoInput;

@IsEnum(YesNoInput)
@IsOptional()
willDocument?: YesNoInput;

@IsEnum(YesNoInput)
@IsOptional()
willConductNotifications?: YesNoInput;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
IsNotEmptyObject,
IsObject,
ValidateNested,
} from '@nestjs/class-validator';
import { Type } from 'class-transformer';
import { Accuracy } from './accuracy';
import { Correction } from './correction';
import { Retention } from './retention';

export class AccuracyCorrectionAndRetention {
@IsObject()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => Accuracy)
accuracy: Accuracy;

@IsObject()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => Correction)
correction: Correction;

@IsObject()
@IsNotEmptyObject()
@ValidateNested()
@Type(() => Retention)
retention: Retention;
}
Loading