Skip to content

Commit

Permalink
Filter out integrations in consent (#912)
Browse files Browse the repository at this point in the history
  • Loading branch information
silesky authored Jul 31, 2023
1 parent a9a923a commit 70cc6e6
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 50 deletions.
5 changes: 5 additions & 0 deletions .changeset/rude-wombats-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@segment/analytics-consent-tools': patch
---

Support classic destinations and locally installed action destinations by removing integrations.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { CDNSettings } from '../../../types'

/**
* Assert integrations/remote plugins contain only the given integrations
*/
export const assertIntegrationsContainOnly = (
/**
* integration creation names
*/
creationNames: string[],
/**
* mock CDN settings
*/
originalCDNSettings: CDNSettings,
/**
* updated CDN settings
*/
updatedCDNSettings: CDNSettings
) => {
expect(updatedCDNSettings.remotePlugins).toEqual(
originalCDNSettings.remotePlugins?.filter((p) =>
// enabled consent
creationNames.includes(p.creationName)
)
)

// integrations should also be filtered
const integrations = Object.fromEntries(
Object.entries(originalCDNSettings.integrations).filter(
([creationName]) => {
return [...creationNames, 'Segment.io'].includes(creationName)
}
)
)

expect(updatedCDNSettings.integrations).toEqual(integrations)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
AnalyticsBrowserSettings,
} from '../../types'
import { CDNSettingsBuilder } from '@internal/test-helpers'
import { assertIntegrationsContainOnly } from './assertions/integrations-assertions'

const DEFAULT_LOAD_SETTINGS = {
writeKey: 'foo',
Expand Down Expand Up @@ -353,19 +354,12 @@ describe(createWrapper, () => {
const { updatedCDNSettings } = getAnalyticsLoadLastCall()

expect(typeof updatedCDNSettings.remotePlugins).toBe('object')
// remote plugins should be filtered based on consent settings
expect(updatedCDNSettings.remotePlugins).toEqual(
mockCdnSettings.remotePlugins?.filter((p) =>
// enabled consent
[creationNameNoConsentData, creationNameWithConsentMatch].includes(
p.creationName
)
)
)

// integrations should be untouched
expect(updatedCDNSettings.integrations).toEqual(
mockCdnSettings.integrations
// remote plugins should be filtered based on consent settings
assertIntegrationsContainOnly(
[creationNameNoConsentData, creationNameWithConsentMatch],
mockCdnSettings,
updatedCDNSettings
)
})

Expand All @@ -387,10 +381,10 @@ describe(createWrapper, () => {
expect(analyticsLoadSpy).toBeCalled()
const { updatedCDNSettings } = getAnalyticsLoadLastCall()
// remote plugins should be filtered based on consent settings
expect(updatedCDNSettings.remotePlugins).toContainEqual(
mockCdnSettings.remotePlugins?.find(
(p) => p.creationName === 'mockIntegration'
)
assertIntegrationsContainOnly(
['mockIntegration'],
mockCdnSettings,
updatedCDNSettings
)
})

Expand All @@ -412,10 +406,10 @@ describe(createWrapper, () => {
expect(analyticsLoadSpy).toBeCalled()
const { updatedCDNSettings } = getAnalyticsLoadLastCall()
// remote plugins should be filtered based on consent settings
expect(updatedCDNSettings.remotePlugins).toContainEqual(
mockCdnSettings.remotePlugins?.find(
(p) => p.creationName === 'mockIntegration'
)
assertIntegrationsContainOnly(
['mockIntegration'],
mockCdnSettings,
updatedCDNSettings
)
})

Expand All @@ -436,10 +430,10 @@ describe(createWrapper, () => {
})

const { updatedCDNSettings } = getAnalyticsLoadLastCall()
expect(updatedCDNSettings.remotePlugins).not.toContainEqual(
mockCdnSettings.remotePlugins?.find(
(p) => p.creationName === 'mockIntegration'
)
assertIntegrationsContainOnly(
['mockIntegation'],
mockCdnSettings,
updatedCDNSettings
)
})
})
Expand Down Expand Up @@ -558,14 +552,11 @@ describe(createWrapper, () => {
cdnSettings: mockCdnSettings,
})
const { updatedCDNSettings } = getAnalyticsLoadLastCall()
const foundIntg = updatedCDNSettings.remotePlugins?.find(
(el) => el.creationName === 'ENABLED'
)
expect(foundIntg).toBeTruthy()
const disabledIntg = updatedCDNSettings.remotePlugins?.find(
(el) => el.creationName === disabledDestinationCreationName
assertIntegrationsContainOnly(
['ENABLED'],
mockCdnSettings,
updatedCDNSettings
)
expect(disabledIntg).toBeFalsy()
})
})

Expand Down
45 changes: 30 additions & 15 deletions packages/consent/consent-tools/src/domain/create-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import {
Categories,
CreateWrapper,
AnyAnalytics,
CDNSettingsIntegrations,
CDNSettingsRemotePlugin,
InitOptions,
CreateWrapperSettings,
CDNSettings,
Expand Down Expand Up @@ -113,15 +111,12 @@ export const createWrapper: CreateWrapper = (createWrapperOptions) => {
return cdnSettings
}

const remotePlugins = omitDisabledRemotePlugins(
cdnSettings.remotePlugins,
cdnSettings.integrations,
return disableIntegrations(
cdnSettings,
initialCategories,
integrationCategoryMappings,
shouldEnableIntegration
)

return { ...cdnSettings, remotePlugins }
}

return ogLoad.call(analytics, settings, {
Expand Down Expand Up @@ -157,15 +152,15 @@ const getConsentCategories = (integration: unknown): string[] | undefined => {
return undefined
}

const omitDisabledRemotePlugins = (
remotePlugins: CDNSettingsRemotePlugin[],
integrations: CDNSettingsIntegrations,
const disableIntegrations = (
cdnSettings: CDNSettings,
consentedCategories: Categories,
integrationCategoryMappings: CreateWrapperSettings['integrationCategoryMappings'],
shouldEnableIntegration: CreateWrapperSettings['shouldEnableIntegration']
): CDNSettingsRemotePlugin[] =>
remotePlugins.filter((plugin) => {
const { creationName, libraryName } = plugin
): CDNSettings => {
const { remotePlugins, integrations } = cdnSettings

const isPluginEnabled = (creationName: string) => {
const categories = integrationCategoryMappings
? // allow hardcoding of consent category mappings for testing (or other reasons)
integrationCategoryMappings[creationName]
Expand All @@ -175,7 +170,6 @@ const omitDisabledRemotePlugins = (
if (shouldEnableIntegration) {
return shouldEnableIntegration(categories || [], consentedCategories, {
creationName,
libraryName,
})
}

Expand All @@ -189,4 +183,25 @@ const omitDisabledRemotePlugins = (
// Enable if all of its consent categories are consented to
const hasUserConsent = categories.every((c) => consentedCategories[c])
return hasUserConsent
})
}

const results = Object.keys(integrations).reduce<CDNSettings>(
(acc, creationName) => {
if (!isPluginEnabled(creationName)) {
// remote disabled action destinations
acc.remotePlugins =
acc.remotePlugins &&
acc.remotePlugins.filter((el) => el.creationName !== creationName)
// remove disabled classic destinations and locally-installed action destinations
delete acc.integrations[creationName]
}
return acc
},
{
...cdnSettings,
remotePlugins,
integrations: { ...integrations }, // make shallow copy to avoid mutating original
}
)
return results
}
5 changes: 1 addition & 4 deletions packages/consent/consent-tools/src/types/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@ export interface CreateWrapperSettings {
shouldEnableIntegration?: (
integrationCategories: string[],
categories: Categories,
integrationInfo: Pick<
CDNSettingsRemotePlugin,
'creationName' | 'libraryName'
>
integrationInfo: Pick<CDNSettingsRemotePlugin, 'creationName'>
) => boolean
}

0 comments on commit 70cc6e6

Please sign in to comment.