diff --git a/services/web/app/src/Features/Analytics/AnalyticsManager.js b/services/web/app/src/Features/Analytics/AnalyticsManager.js index 7d8cce9f12..55c9340289 100644 --- a/services/web/app/src/Features/Analytics/AnalyticsManager.js +++ b/services/web/app/src/Features/Analytics/AnalyticsManager.js @@ -193,7 +193,10 @@ function _recordEvent( } function _setUserProperty({ analyticsId, propertyName, propertyValue }) { - if (!_isAttributeValid(propertyName) || !_isAttributeValid(propertyValue)) { + if ( + !_isAttributeValid(propertyName) || + !_isAttributeValueValid(propertyValue) + ) { return } Metrics.analyticsQueue.inc({ @@ -246,15 +249,29 @@ function _isAttributeValid(attribute) { return !attribute || /^[a-zA-Z0-9-_.:;,/]+$/.test(attribute) } +function _isAttributeValueValid(attributeValue) { + return _isAttributeValid(attributeValue) || attributeValue instanceof Date +} + +function _isSegmentationValueValid(attributeValue) { + // spaces are allowed for segmentation values + return !attributeValue || /^[a-zA-Z0-9-_.:;,/ ]+$/.test(attributeValue) +} + function _isSegmentationValid(segmentation) { if (!segmentation) { return true } - const hasAnyInvalidAttribute = [ - ...Object.keys(segmentation), - ...Object.values(segmentation), - ].some(attribute => !_isAttributeValid(attribute)) - return !hasAnyInvalidAttribute + + const hasAnyInvalidKey = [...Object.keys(segmentation)].some( + key => !_isAttributeValid(key) + ) + + const hasAnyInvalidValue = [...Object.values(segmentation)].some( + value => !_isSegmentationValueValid(value) + ) + + return !hasAnyInvalidKey && !hasAnyInvalidValue } function getIdsFromSession(session) { diff --git a/services/web/test/unit/src/Analytics/AnalyticsManagerTests.js b/services/web/test/unit/src/Analytics/AnalyticsManagerTests.js index 72d3ff7544..2cb9de8562 100644 --- a/services/web/test/unit/src/Analytics/AnalyticsManagerTests.js +++ b/services/web/test/unit/src/Analytics/AnalyticsManagerTests.js @@ -225,6 +225,20 @@ describe('AnalyticsManager', function () { }) }) + it('empty space in event segmentation value', async function () { + await this.AnalyticsManager.recordEventForUser( + this.fakeUserId, + 'an_event', + { segment: 'a value with spaces' } + ) + sinon.assert.calledWithMatch(this.analyticsEventsQueue.add, 'event', { + analyticsId: this.analyticsId, + event: 'an_event', + segmentation: { segment: 'a value with spaces' }, + isLoggedIn: true, + }) + }) + it('boolean field in event segmentation', async function () { await this.AnalyticsManager.recordEventForUser( this.fakeUserId,