UNPKG

@ahmedhegazee/nestjs-telescope

Version:

Advanced observability and monitoring solution for NestJS applications with ML-powered analytics, enterprise features, and production-ready scaling

210 lines 7.5 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var DataMaskingService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.DataMaskingService = void 0; const common_1 = require("@nestjs/common"); let DataMaskingService = DataMaskingService_1 = class DataMaskingService { constructor() { this.logger = new common_1.Logger(DataMaskingService_1.name); this.defaultPatterns = [ /\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g, /\b\d{3}-\d{2}-\d{4}\b/g, /\b\d{9}\b/g, /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, /Bearer\s+[A-Za-z0-9\-\._~\+\/]+=*/g, /\b\d{3}-?\d{3}-?\d{4}\b/g, /\b(?:\d{1,3}\.){3}\d{1,3}\b/g, /https?:\/\/[^\s]*(?:token|key|secret|password)=[^\s&]*/g, /['\"]?(?:api[_-]?key|access[_-]?token|secret[_-]?key)['\"]?\s*[:=]\s*['\"]?[A-Za-z0-9\-_]{8,}['\"]?/gi, /\b\d{8,17}\b/g, /\b[A-Z]{1,2}\d{6,9}\b/g ]; this.sensitiveKeyPatterns = [ /password/i, /passwd/i, /secret/i, /token/i, /key/i, /auth/i, /credential/i, /pin/i, /ssn/i, /social/i, /card/i, /account/i, /bank/i ]; } maskSensitiveData(data, config = {}) { const finalConfig = { enabled: true, preserveLength: true, maskingChar: '*', customPatterns: [], sensitiveKeys: [], ...config }; if (!finalConfig.enabled) { return data; } try { return this.maskData(data, finalConfig); } catch (error) { this.logger.error('Error masking sensitive data:', error); return data; } } detectSensitiveData(data, config = {}) { const finalConfig = { enabled: true, preserveLength: true, maskingChar: '*', customPatterns: [], sensitiveKeys: [], ...config }; if (!finalConfig.enabled || !data) { return false; } try { const dataStr = this.convertToString(data); const allPatterns = [...this.defaultPatterns, ...finalConfig.customPatterns]; for (const pattern of allPatterns) { if (pattern.test(dataStr)) { return true; } } if (typeof data === 'object' && data !== null) { return this.hasSensitiveKeys(data, finalConfig); } return false; } catch (error) { this.logger.error('Error detecting sensitive data:', error); return false; } } maskData(data, config) { if (data === null || data === undefined) { return data; } if (typeof data === 'string') { return this.maskString(data, config); } if (typeof data === 'number' || typeof data === 'boolean') { return data; } if (Array.isArray(data)) { return data.map(item => this.maskData(item, config)); } if (typeof data === 'object') { return this.maskObject(data, config); } return data; } maskString(str, config) { let maskedStr = str; const allPatterns = [...this.defaultPatterns, ...config.customPatterns]; for (const pattern of allPatterns) { maskedStr = maskedStr.replace(pattern, (match) => { return config.preserveLength ? config.maskingChar.repeat(match.length) : '***MASKED***'; }); } return maskedStr; } maskObject(obj, config) { const maskedObj = {}; for (const [key, value] of Object.entries(obj)) { const lowerKey = key.toLowerCase(); const isSensitiveKey = this.sensitiveKeyPatterns.some(pattern => pattern.test(lowerKey)) || config.sensitiveKeys.some(sensitiveKey => lowerKey.includes(sensitiveKey.toLowerCase())); if (isSensitiveKey) { maskedObj[key] = this.maskSensitiveValue(value, config); } else { maskedObj[key] = this.maskData(value, config); } } return maskedObj; } maskSensitiveValue(value, config) { if (typeof value === 'string') { return config.preserveLength ? config.maskingChar.repeat(value.length) : '***MASKED***'; } if (typeof value === 'number') { return config.preserveLength ? config.maskingChar.repeat(value.toString().length) : '***MASKED***'; } return '***MASKED***'; } hasSensitiveKeys(obj, config) { for (const key of Object.keys(obj)) { const lowerKey = key.toLowerCase(); if (this.sensitiveKeyPatterns.some(pattern => pattern.test(lowerKey))) { return true; } if (config.sensitiveKeys.some(sensitiveKey => lowerKey.includes(sensitiveKey.toLowerCase()))) { return true; } if (typeof obj[key] === 'object' && obj[key] !== null) { if (this.hasSensitiveKeys(obj[key], config)) { return true; } } } return false; } convertToString(data) { try { if (typeof data === 'string') { return data; } return JSON.stringify(data); } catch (error) { return String(data); } } createSafeSummary(data, config = {}) { const finalConfig = { enabled: true, preserveLength: false, maskingChar: '*', customPatterns: [], sensitiveKeys: [], ...config }; try { const maskedData = this.maskSensitiveData(data, finalConfig); const summary = JSON.stringify(maskedData); if (summary.length > 500) { return summary.substring(0, 497) + '...'; } return summary; } catch (error) { return '[Data masking failed]'; } } }; exports.DataMaskingService = DataMaskingService; exports.DataMaskingService = DataMaskingService = DataMaskingService_1 = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", []) ], DataMaskingService); //# sourceMappingURL=data-masking.service.js.map