UNPKG

typeorm-pii-compliance

Version:

TypeORM PII Compliance Service: Cascading Personally Identifiable Information Disposal

131 lines (130 loc) 6.43 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PiiComplianceService = void 0; const pii_metadata_1 = require("./pii-metadata"); const pii_type_1 = require("./types/pii.type"); class PiiComplianceService { constructor(options) { this.options = options; } entities() { if (!this._sorted) { this._sorted = [...pii_metadata_1.PiiMetadata.entities]; this._sorted.sort((a, b) => b.hierarchyPriority - a.hierarchyPriority); } return this._sorted; } process(groupOrEntityId, idOrCallback, callbackFunc) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { let [group, entityId, beforeDisposal] = [ undefined, [], undefined, ]; if (idOrCallback && callbackFunc) [group, entityId, beforeDisposal] = [ groupOrEntityId, idArrayize(idOrCallback), callbackFunc, ]; else if (idOrCallback) { if (typeof idOrCallback === 'function') [entityId, beforeDisposal] = [idArrayize(groupOrEntityId), idOrCallback]; else [group, entityId] = [groupOrEntityId, idArrayize(idOrCallback)]; } else entityId = idArrayize(groupOrEntityId); beforeDisposal = beforeDisposal || ((_a = this.options) === null || _a === void 0 ? void 0 : _a.beforeDisposal); const entityConfigs = this.entities().filter((item) => (!group && !item.group) || (group && item.group === group)); for (const { entity, columns, strategy } of entityConfigs) { const where = columns.reduce((result, item, idx) => { result[item] = entityId[idx]; return result; }, {}); let columnsMeta = []; if (strategy === pii_type_1.PiiDisposalStrategy.MASKING) { columnsMeta = pii_metadata_1.PiiMetadata.columns.filter((item) => item.entity === entity); if (columnsMeta.length <= 0) { console.warn(`PiiComplianceService: [${entity.constructor.name}] entity does not have a column referenced by @PiiColumn decorator.`); continue; } } if (beforeDisposal || strategy === pii_type_1.PiiDisposalStrategy.MASKING) { const records = yield entity.find({ where }); for (const record of records) { if (beforeDisposal) yield beforeDisposal(entity, record); if (strategy === pii_type_1.PiiDisposalStrategy.MASKING) { for (let column of columnsMeta) record[column.name] = yield PiiComplianceService.transform(record[column.name], column.maskingMethod, (_b = this.options) === null || _b === void 0 ? void 0 : _b.replaceChar); yield record.save(); } } } if (strategy === pii_type_1.PiiDisposalStrategy.DELETE) yield entity.delete(where); } }); } static transform(value, maskingMethod, replaceChar = '*') { return __awaiter(this, void 0, void 0, function* () { if (typeof maskingMethod === 'function') return yield maskingMethod(value); switch (maskingMethod) { case 'null': return null; case 'zero': return 0; case 'blank': return ''; } replaceChar = replaceChar || '*'; if (value === null || typeof value === 'undefined') value = ''; value = value.toString(); switch (maskingMethod) { case 'email': return value.replace(/(.{0,5})@(.{0,5})/g, (...args) => replaceChar.repeat(args[1].length) + '@' + replaceChar.repeat(args[2].length)); default: const method = maskingMethod; switch (method.substr(0, method.length - 1)) { case 'edge': { const maskLen = Number(method.substr(-1)); return value.replace(new RegExp(`(^.{0,${maskLen}})|(.{0,${maskLen}}$)`, 'g'), replacer(replaceChar)); } case 'center': { const maskLen = Number(method.substr(-1)); const len = value.length; if (len <= maskLen) return replaceChar.repeat(len); const center = Math.ceil(len / 2); const left = value.substr(0, center); const right = value.substr(center); return (left.replace(new RegExp(`.{0,${Math.ceil(maskLen / 2)}}$`), replacer(replaceChar)) + (maskLen > 1 ? right.replace(new RegExp(`^.{0,${Math.floor(maskLen / 2)}}`), replacer(replaceChar)) : right)); } } } }); } } exports.PiiComplianceService = PiiComplianceService; function replacer(replaceChar) { return (substring, ...args) => { return replaceChar.repeat(substring.length); }; } function idArrayize(id) { return Array.isArray(id) ? id : [id]; }