Просмотр исходного кода

Merge pull request #8620 from overleaf/ta-analytics-attributes-validate

Ignore Invalid Analytics Attributes

GitOrigin-RevId: 6e3ffc1dcc6088966480ad0704a988174e4fd3fb
Timothée Alby 4 лет назад
Родитель
Сommit
8f41431719

+ 27 - 0
services/web/app/src/Features/Analytics/AnalyticsManager.js

@@ -131,6 +131,9 @@ function updateEditingSession(userId, projectId, countryCode, segmentation) {
   if (_isAnalyticsDisabled() || _isSmokeTestUser(userId)) {
     return
   }
+  if (!_isSegmentationValid(segmentation)) {
+    return
+  }
   Metrics.analyticsQueue.inc({
     status: 'adding',
     event_type: 'editing-session',
@@ -161,6 +164,12 @@ function _recordEvent(
   { analyticsId, userId, event, segmentation, isLoggedIn },
   { delay } = {}
 ) {
+  if (!_isAttributeValid(event)) {
+    return
+  }
+  if (!_isSegmentationValid(segmentation)) {
+    return
+  }
   Metrics.analyticsQueue.inc({ status: 'adding', event_type: 'event' })
   analyticsEventsQueue
     .add(
@@ -184,6 +193,9 @@ function _recordEvent(
 }
 
 function _setUserProperty({ analyticsId, propertyName, propertyValue }) {
+  if (!_isAttributeValid(propertyName) || !_isAttributeValid(propertyValue)) {
+    return
+  }
   Metrics.analyticsQueue.inc({
     status: 'adding',
     event_type: 'user-property',
@@ -230,6 +242,21 @@ function _checkPropertyValue(propertyValue) {
   }
 }
 
+function _isAttributeValid(attribute) {
+  return attribute && /^[a-zA-Z0-9-_.:;,/]+$/.test(attribute)
+}
+
+function _isSegmentationValid(segmentation) {
+  if (!segmentation) {
+    return true
+  }
+  const hasAnyInvalidAttribute = [
+    ...Object.keys(segmentation),
+    ...Object.values(segmentation),
+  ].some(attribute => !_isAttributeValid(attribute))
+  return !hasAnyInvalidAttribute
+}
+
 function getIdsFromSession(session) {
   const analyticsId = _.get(session, ['analyticsId'])
   const userId = SessionManager.getLoggedInUserId(session)

+ 45 - 0
services/web/test/unit/src/Analytics/AnalyticsManagerTests.js

@@ -106,6 +106,51 @@ describe('AnalyticsManager', function () {
       )
       sinon.assert.notCalled(this.Queues.createScheduledJob)
     })
+
+    it('editing session segmentation is not valid', function () {
+      this.AnalyticsManager.updateEditingSession(
+        this.fakeUserId,
+        '789ghi',
+        'fr',
+        { key: '<alert>' }
+      )
+      sinon.assert.notCalled(this.analyticsEditingSessionQueue.add)
+    })
+
+    it('event is not valid', async function () {
+      await this.AnalyticsManager.recordEventForUser(
+        this.fakeUserId,
+        'not an event!'
+      )
+      sinon.assert.notCalled(this.analyticsEventsQueue.add)
+    })
+
+    it('event segmentation is not valid', async function () {
+      await this.AnalyticsManager.recordEventForUser(
+        this.fakeUserId,
+        'an_event',
+        { not_a: 'Valid Segmentation!' }
+      )
+      sinon.assert.notCalled(this.analyticsEventsQueue.add)
+    })
+
+    it('user property name is not valid', async function () {
+      await this.AnalyticsManager.setUserPropertyForUser(
+        this.fakeUserId,
+        'an invalid property',
+        'a_value'
+      )
+      sinon.assert.notCalled(this.analyticsUserPropertiesQueue.add)
+    })
+
+    it('user property value is not valid', async function () {
+      await this.AnalyticsManager.setUserPropertyForUser(
+        this.fakeUserId,
+        'a_property',
+        'an invalid value'
+      )
+      sinon.assert.notCalled(this.analyticsUserPropertiesQueue.add)
+    })
   })
 
   describe('queues the appropriate message for', function () {