@microsoft/1ds-core-js
Version:
Microsoft Application Insights JavaScript SDK - 1ds-core-js
262 lines • 14.2 kB
JavaScript
/*
* 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