UNPKG

@microsoft/1ds-core-js

Version:

Microsoft Application Insights JavaScript SDK - 1ds-core-js

262 lines 14.2 kB
/* * 1DS JS SDK Core, 4.3.10 * Copyright (c) Microsoft and contributors. All rights reserved. * (Microsoft Internal Only) */ import { isNullOrUndefined, isString, objForEachKey } from "@microsoft/applicationinsights-core-js"; import { arrForEach, arrIncludes, arrIndexOf, getLength } from "@nevware21/ts-utils"; import { STR_EMPTY } from "./InternalConstants"; import { getFieldValueType, isValueAssigned, isValueKind } from "./Utils"; import { _DYN_CAN_HANDLE, _DYN_HANDLE_FIELD, _DYN_LENGTH, _DYN_RM_FIELD_SANITIZER, _DYN_RM_SANITIZER, _DYN_VALUE } from "./__DynamicConstants"; function _isSpecialName(name) { return (name == "__proto__" || name == "constructor" || name == "prototype"); } var ValueSanitizer = /** @class */ (function () { function ValueSanitizer(fieldSanitizerProvider) { var _self = this; // To aid with performance this is a lookup map to check if the field value sanitizer supports this field var _sanitizerMap = {}; var _sanitizers = []; var _fieldSanitizers = []; if (fieldSanitizerProvider) { _fieldSanitizers.push(fieldSanitizerProvider); } function _getFieldSanitizer(path, name) { var result; var fieldLookup = _sanitizerMap[path]; if (fieldLookup) { result = fieldLookup[name]; } if (!result && result !== null) { // Null is a valid result indicating that the value sanitizer does not support this field if (isString(path) && isString(name)) { if (_fieldSanitizers[_DYN_LENGTH /* @min:%2elength */] > 0) { for (var lp = 0; lp < _fieldSanitizers[_DYN_LENGTH /* @min:%2elength */]; lp++) { if (_fieldSanitizers[lp][_DYN_HANDLE_FIELD /* @min:%2ehandleField */](path, name)) { result = { canHandle: true, fieldHandler: _fieldSanitizers[lp] }; break; } } } else if (_sanitizers[_DYN_LENGTH /* @min:%2elength */] === 0) { // Special use-case where there is no sanitizer to pass on to, so just resolving the field // and returning the resulting value (same as sanitizeProperty()) result = { canHandle: true }; } } // We still don't have a handler so lets lookup the providers if (!result && result !== null) { // Setting the result to null -- which means we and any contained sanitizers can't handle this field result = null; for (var lp = 0; lp < _sanitizers[_DYN_LENGTH /* @min:%2elength */]; lp++) { if (_sanitizers[lp][_DYN_HANDLE_FIELD /* @min:%2ehandleField */](path, name)) { result = { canHandle: true, handler: _sanitizers[lp], fieldHandler: null }; break; } } } if (!fieldLookup) { // Handle edge case to avoid prototype pollution if (_isSpecialName(path)) { return null; } fieldLookup = _sanitizerMap[path] = {}; } // Handle edge case to avoid prototype pollution if (_isSpecialName(name)) { return null; } fieldLookup[name] = result; } return result; } _self.clearCache = function () { _sanitizerMap = {}; }; _self.addSanitizer = function (newSanitizer) { if (newSanitizer) { if (!arrIncludes(_sanitizers, newSanitizer)) { _sanitizers.push(newSanitizer); } // Invalidate any previously mapped fields _sanitizerMap = {}; } }; _self.addFieldSanitizer = function (fieldSanitizer) { if (fieldSanitizer) { if (!arrIncludes(_fieldSanitizers, fieldSanitizer)) { _fieldSanitizers.push(fieldSanitizer); } // Invalidate any previously mapped fields _sanitizerMap = {}; } }; _self[_DYN_RM_SANITIZER /* @min:%2ermSanitizer */] = function (theSanitizer) { if (theSanitizer) { var idx = arrIndexOf(_sanitizers, theSanitizer); if (idx !== -1) { _sanitizers.splice(idx, 1); // Invalidate any previously mapped fields _sanitizerMap = {}; } // Try and remove the sanitizer from any chained sanitizer as well arrForEach(_sanitizers, function (sanitizer) { sanitizer && sanitizer[_DYN_RM_SANITIZER /* @min:%2ermSanitizer */] && sanitizer[_DYN_RM_SANITIZER /* @min:%2ermSanitizer */](theSanitizer); }); } }; _self[_DYN_RM_FIELD_SANITIZER /* @min:%2ermFieldSanitizer */] = function (theFieldSanitizer) { if (theFieldSanitizer) { var idx = arrIndexOf(_fieldSanitizers, theFieldSanitizer); if (idx !== -1) { _fieldSanitizers.splice(idx, 1); // Invalidate any previously mapped fields _sanitizerMap = {}; } // Try and remove the field sanitizer from any chained sanitizer as well arrForEach(_sanitizers, function (sanitizer) { sanitizer && sanitizer[_DYN_RM_FIELD_SANITIZER /* @min:%2ermFieldSanitizer */] && sanitizer[_DYN_RM_FIELD_SANITIZER /* @min:%2ermFieldSanitizer */](theFieldSanitizer); }); } }; _self.isEmpty = function () { return (getLength(_sanitizers) + getLength(_fieldSanitizers)) === 0; }; _self[_DYN_HANDLE_FIELD /* @min:%2ehandleField */] = function (path, name) { var mapValue = _getFieldSanitizer(path, name); return mapValue ? mapValue[_DYN_CAN_HANDLE /* @min:%2ecanHandle */] : false; }; _self[_DYN_VALUE /* @min:%2evalue */] = function (path, name, value, stringifyObjects) { var mapValue = _getFieldSanitizer(path, name); if (mapValue && mapValue[_DYN_CAN_HANDLE /* @min:%2ecanHandle */]) { if (!mapValue[_DYN_CAN_HANDLE /* @min:%2ecanHandle */]) { return null; } if (mapValue.handler) { // This value sanitizer can't handle this field so pass it only the next one return mapValue.handler[_DYN_VALUE /* @min:%2evalue */](path, name, value, stringifyObjects); } // Check that property is valid if (!isString(name) || isNullOrUndefined(value) || value === STR_EMPTY) { return null; } var property = null; var fieldType = getFieldValueType(value); if ((fieldType & 8192 /* FieldValueSanitizerType.EventProperty */) === 8192 /* FieldValueSanitizerType.EventProperty */) { var subType = fieldType & ~8192 /* FieldValueSanitizerType.EventProperty */; property = value; if (!isValueAssigned(property[_DYN_VALUE /* @min:%2evalue */]) || (subType !== 1 /* FieldValueSanitizerType.String */ && subType !== 2 /* FieldValueSanitizerType.Number */ && subType !== 3 /* FieldValueSanitizerType.Boolean */ && (subType & 4096 /* FieldValueSanitizerType.Array */) !== 4096 /* FieldValueSanitizerType.Array */)) { // Not a supported IEventProperty type to be able to sanitize return null; } } else if (fieldType === 1 /* FieldValueSanitizerType.String */ || fieldType === 2 /* FieldValueSanitizerType.Number */ || fieldType === 3 /* FieldValueSanitizerType.Boolean */ || (fieldType & 4096 /* FieldValueSanitizerType.Array */) === 4096 /* FieldValueSanitizerType.Array */) { // If the property isn't IEventProperty (and is either string, number, boolean or array), convert it into one. property = _convertToProperty(path, name, value); } else if (fieldType === 4 /* FieldValueSanitizerType.Object */) { property = _convertToProperty(path, name, !!stringifyObjects ? JSON.stringify(value) : value); } if (property) { return _handleProperty(mapValue, path, name, fieldType, property, stringifyObjects); } } return null; }; _self.property = function (path, name, property, stringifyObjects) { var mapValue = _getFieldSanitizer(path, name); if (!mapValue || !mapValue[_DYN_CAN_HANDLE /* @min:%2ecanHandle */]) { return null; } // Check that property is valid if (!isString(name) || isNullOrUndefined(property) || !isValueAssigned(property[_DYN_VALUE /* @min:%2evalue */])) { return null; } var fieldType = getFieldValueType(property[_DYN_VALUE /* @min:%2evalue */]); if (fieldType === 0 /* FieldValueSanitizerType.NotSet */) { // Not a supported field that we can sanitize or serialize return null; } return _handleProperty(mapValue, path, name, fieldType, property, stringifyObjects); }; function _handleProperty(mapValue, path, name, fieldType, property, stringifyObjects) { if (mapValue.handler) { // This value sanitizer can't handle this field so pass it only the next one return mapValue.handler.property(path, name, property, stringifyObjects); } // If either pii or cc is set convert value to string (since only string pii/cc is allowed). // If the value is a complex type like an array that can't be converted to string we will drop // the property. if (!isNullOrUndefined(property.kind)) { if ((fieldType & 4096 /* FieldValueSanitizerType.Array */) === 4096 /* FieldValueSanitizerType.Array */ || !isValueKind(property.kind)) { return null; } // Convert the value to a string and assign back to the original value property[_DYN_VALUE /* @min:%2evalue */] = property[_DYN_VALUE /* @min:%2evalue */].toString(); } return _callFieldSanitizer(mapValue.fieldHandler, path, name, fieldType, property); } function _convertToProperty(path, name, value) { if (isValueAssigned(value)) { return { value: value }; } return null; } function _callFieldSanitizer(fieldProvider, path, name, theType, property) { if (property && fieldProvider) { var sanitizer = fieldProvider.getSanitizer(path, name, theType, property.kind, property.propertyType); if (sanitizer) { // This is where we the field will call the handler to "scrub" the value. This the primary hook for the ClientHashing Plugin to // be able to apply the hashFunc() / Sha256 conversion of the properties value if (theType === 4 /* FieldValueSanitizerType.Object */) { // Special case of an embedded object (ext.metadata, data.properties) var newValue_1 = {}; var propValue = property[_DYN_VALUE /* @min:%2evalue */]; objForEachKey(propValue, function (propKey, theValue) { var newPath = path + "." + name; if (isValueAssigned(theValue)) { var newProp = _convertToProperty(newPath, propKey, theValue); newProp = _callFieldSanitizer(fieldProvider, newPath, propKey, getFieldValueType(theValue), newProp); if (newProp) { newValue_1[propKey] = newProp[_DYN_VALUE /* @min:%2evalue */]; } } }); property[_DYN_VALUE /* @min:%2evalue */] = newValue_1; } else { var details = { path: path, name: name, type: theType, prop: property, sanitizer: _self }; property = sanitizer.call(_self, details); } } } return property; } } ValueSanitizer.getFieldType = getFieldValueType; return ValueSanitizer; }()); export { ValueSanitizer }; //# sourceMappingURL=ValueSanitizer.js.map