Skip to content

Commit

Permalink
Merge pull request #857 from bcgov/utopia-769
Browse files Browse the repository at this point in the history
[Utopia 769] Updated pia-intake entity and associated JSONB classes and dtos
  • Loading branch information
kushal-arora-fw authored Feb 15, 2023
2 parents bbdce52 + 52a6188 commit 8fc8a0a
Show file tree
Hide file tree
Showing 40 changed files with 1,465 additions and 56 deletions.
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
}
37 changes: 37 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,37 @@
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>,
updatedValue: any,
storedValue: any,
userType: UserTypesEnum,
path: string,
) => {
if (!updatedValue) return; // if value not edited - no need to validate permissions

if (typeof updatedValue === 'string' && updatedValue === storedValue) return; // if value is not updated by the current user;

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
48 changes: 48 additions & 0 deletions src/backend/src/modules/pia-intake/entities/pia-intake.entity.ts
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

0 comments on commit 8fc8a0a

Please sign in to comment.