UNPKG

@dynatrace/react-native-plugin

Version:

This plugin gives you the ability to use the Dynatrace Mobile agent in your react native application.

190 lines (189 loc) 8.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ModifyEventValidation = void 0; const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger"); const EventSpecContstants_1 = require("../spec/EventSpecContstants"); const EventLimitation_1 = require("./EventLimitation"); const EventModifierUtil_1 = require("./EventModifierUtil"); class ModifyEventValidation { constructor() { this.customEventModifierChain = []; this.logger = new ConsoleLogger_1.ConsoleLogger('ModifyEventValidation'); } addEventModifier(eventModifier) { this.customEventModifierChain.push(eventModifier); return eventModifier; } removeEventModifier(eventModifier) { const index = this.customEventModifierChain.indexOf(eventModifier); if (index !== -1) { this.customEventModifierChain.splice(index, 1); return true; } return false; } modifyEvent(event) { if (this.customEventModifierChain.length > 0) { const eventCopy = Object.assign({}, event); let exceptionOccured = false; this.customEventModifierChain.forEach((modifier) => { try { event = modifier.modifyEvent(event); } catch (error) { if (event != null) { exceptionOccured = true; } } }); event = this.sanitizeUserEnrichedEvent(eventCopy, event, exceptionOccured); } return event; } isPropertiesAllowed(key, hasSessionPropertyCharacteristics) { if (hasSessionPropertyCharacteristics) { if (key.startsWith(`${"event_properties"}.`)) { this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of event properties is not allowed!`); return true; } } else { if (key.startsWith(`${"session_properties"}.`)) { this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of session properties is not allowed!`); return true; } } return false; } isKeyNameForbidden(key) { for (const namespace of EventSpecContstants_1.MODIFY_EVENT_WHITELIST_NAMESPACE) { if (key.startsWith(`${namespace}.`)) { return false; } } if (EventSpecContstants_1.MODIFY_EVENT_WHITELIST_FIELDS.includes(key)) { return false; } this.logger.debug(`isKeyNameForbidden(): Filtering key ${key} as this field is reserved and must not be overridden!`); return true; } sanitizeUserEnrichedEvent(originalEvent, userEnrichedEvent, externalException) { if (!(0, EventModifierUtil_1.isObject)(userEnrichedEvent)) { this.logger.debug(`sanitizeUserEnrichedEvent(${originalEvent}, ${userEnrichedEvent}): Enriched event is not an object`); return originalEvent; } if (userEnrichedEvent === originalEvent) { this.logger.debug(`sanitizeUserEnrichedEvent(${originalEvent}, ${userEnrichedEvent}): Event has not been changed`); return originalEvent; } let overriddenKeys = originalEvent["dt.internal.api.overridden_keys"]; if (overriddenKeys == null) { overriddenKeys = []; } const userEnrichedEventEntries = Object.entries(userEnrichedEvent); const validEntries = this.determineValidEntries(userEnrichedEventEntries, originalEvent, overriddenKeys); const restoredEntries = this.restoreRemovedEntries(Object.entries(originalEvent), userEnrichedEvent, overriddenKeys); const validAndRestoredEntries = validEntries.concat(restoredEntries); const { baseEntries, addedEntries } = this.determineAddedEntries(originalEvent, validAndRestoredEntries); const limitedEntries = new EventLimitation_1.EventLimitation().limitEventEntries(addedEntries); if (originalEvent["characteristics.has_event_properties"] === undefined && (0, EventModifierUtil_1.containEventPropertiesInArray)(limitedEntries)) { limitedEntries.push([ "characteristics.has_event_properties", true, ]); } const finalEntries = baseEntries.concat(limitedEntries); const sizedEntries = new EventLimitation_1.EventLimitation().limitEventProperties(finalEntries); if (sizedEntries.length < userEnrichedEventEntries.length) { sizedEntries.push([ "dt.internal.api.has_dropped_custom_properties", true, ]); } if (Array.isArray(overriddenKeys) && overriddenKeys.length > 0) { sizedEntries.push([ "dt.internal.api.overridden_keys", overriddenKeys, ]); } if (externalException) { sizedEntries.push([ "dt.internal.api.has_enrich_exception", true, ]); } return Object.fromEntries(sizedEntries); } determineValidEntries(userEnrichedEntries, originalJSONEvent, overriddenKeys) { const newEntries = []; for (const [prop, value] of userEnrichedEntries) { const originalValue = originalJSONEvent[prop]; if (!this.isModified(originalValue, value)) { newEntries.push([prop, value]); continue; } if (this.isPropertiesAllowed(prop, originalJSONEvent["characteristics.has_session_properties"] === true)) { continue; } const isNewlyAdded = typeof originalValue === 'undefined'; const isForbiddenKey = this.isKeyNameForbidden(prop); if (isForbiddenKey) { if (!isNewlyAdded) { newEntries.push([prop, originalValue]); } continue; } if (!isNewlyAdded && !overriddenKeys.includes(prop)) { overriddenKeys.push(prop); } newEntries.push([prop, value]); } return newEntries; } isModified(oldValue, newValue) { if (Array.isArray(oldValue)) { return (!Array.isArray(newValue) || oldValue.length !== newValue.length || !oldValue.every((item, index) => !this.isModified(item, newValue[index]))); } if ((0, EventModifierUtil_1.isObject)(oldValue)) { const oldEntries = Object.entries(oldValue); return (!(0, EventModifierUtil_1.isObject)(newValue) || Object.entries(newValue).length !== oldEntries.length || !oldEntries.every(([prop, value]) => !this.isModified(value, newValue[prop]))); } return oldValue !== newValue; } restoreRemovedEntries(originalEntries, userEnrichedEvent, overriddenKeys) { const restoredEntries = []; for (const [prop, value] of originalEntries) { if (typeof userEnrichedEvent[prop] !== 'undefined') { continue; } if (this.isKeyNameForbidden(prop)) { restoredEntries.push([prop, value]); } else if (!overriddenKeys.includes(prop)) { overriddenKeys.push(prop); } } return restoredEntries; } determineAddedEntries(originalJSONEvent, userEnrichedEntries) { const resultEntries = { baseEntries: [], addedEntries: [], }; return userEnrichedEntries.reduce((entries, entry) => { if (Object.prototype.hasOwnProperty.call(originalJSONEvent, entry[0])) { entries.baseEntries.push(entry); } else { entries.addedEntries.push(entry); } return entries; }, resultEntries); } } exports.ModifyEventValidation = ModifyEventValidation;