- Cascading Personally Identifiable Information Disposal
- NPM
$ npm install typeorm-pii-compliance --save
- Yarn
$ yarn add typeorm-pii-compliance
Constructor(options?: PiiComplianceServiceOptions)
replaceChar
(optional) : Character to be replaced when masking'*' | '-' | string
beforeDisposal
(optional) : Callback function called before disposal(type: EntityType, entity: any) => Promise<void> | void
- Options
hierarchyLevel
(enum, required) : Sets the level of the information hierarchy to adjust processing priorities.PiiHierarchyLevel.TOP
: The top-level entity. Usually defined in User or Member entities. It will be processed last.PiiHierarchyLevel.HIGHER
,PiiHierarchyLevel.HIGH
,PiiHierarchyLevel.MIDDLE
,PiiHierarchyLevel.LOW
,PiiHierarchyLevel.LOWER
PiiHierarchyLevel.LEAF
: It is an entity at the lowest level, such as data in the history records. It is processed first.
strategy
(enum, optional) : Disposal strategyPiiDisposalStrategy.MASKING
(default) :@PiiColumn()
Mask the set column.PiiDisposalStrategy.DELETE
: Delete entity from data source.
group
(string, optional) : Group- If there are multiple ID systems that recognize users, you can separate the processing contexts using the group.
- Options
maskingMethod
(required) : Masking methodnull
: Change the data to null. Check if the column type is nullable.zero
: Change the data to 0(Number)blank
: Change the data to ""(blank string)edge1
~edge8
: Masks 1 to 8 characters back and forth.center1
~center8
: Masks 1 to 8 characters from the center.email
: Masks up to 5 characters before and after centered at @.(<T>(value: T) => Promise<T> | T)
: Custom transform callback.
- To delete entities with PII, set the
@PiiId
decorator in the user ID column to be used for filtering.
// Top level user entity
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
@PiiId({ strategy: PiiDisposalStrategy.DELETE, hierarchyLevel: PiiHierarchyLevel.TOP })
id!: number;
// ... other columns
}
// Examples of tables includes PII that depend on users
@Entity()
export class OrderHistory extends BaseEntity {
@PrimaryGeneratedColumn()
seq!: number;
@Index()
@ManyToOne((type) => User, (parent) => parent.id)
@PiiId({ strategy: PiiDisposalStrategy.DELETE, hierarchyLevel: PiiHierarchyLevel.LEAF })
user!: User;
// ... other columns
}
const service = new PiiComplianceService();
/*
* If a user with User.id of 9999 withdrew, the deletion proceeds in the order of OrderHistory -> User entity when called as follows.
*/
await service.process(
// User ID
9999,
// Callback
async (type, entity) => {
console.log(type, entity);
}
);
- Use the
@PiiColumn
decorator to mask some PII instead of deleting the Entity.
// Top level user entity
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
@PiiId({ strategy: PiiDisposalStrategy.MASKING, hierarchyLevel: PiiHierarchyLevel.TOP })
id!: number;
@Column()
@PiiColumn({ maskingMethod: 'edge2' })
firstName!: string;
@Column()
@PiiColumn({ maskingMethod: 'edge2' })
lastName!: string;
@Column()
@PiiColumn({ maskingMethod: 'email' })
email!: string;
// ... other columns
}
// Examples of tables includes PII that depend on users
@Entity()
export class OrderHistory extends BaseEntity {
@PrimaryGeneratedColumn()
seq!: number;
@Index()
@ManyToOne((type) => User, (parent) => parent.id)
@PiiId({ strategy: PiiDisposalStrategy.DELETE, hierarchyLevel: PiiHierarchyLevel.LEAF })
user!: User;
// ... other columns
}
const service = new PiiComplianceService();
await service.process(
// User ID
9999,
// Callback
async (type, entity) => {
console.log(type, entity);
}
);