Merge pull request #8031 from vector-im/feature/bma/fixPosthog

Do not send any request to Posthog if no consent is provided.
This commit is contained in:
Benoit Marty 2023-01-30 17:11:30 +01:00 committed by GitHub
commit 156f4f71f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 4 deletions

1
changelog.d/8031.bugfix Normal file
View file

@ -0,0 +1 @@
Do not send any request to Posthog if no consent is provided.

View file

@ -31,6 +31,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.matrix.android.sdk.api.extensions.orFalse
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
@ -60,6 +61,9 @@ class DefaultVectorAnalytics @Inject constructor(
private var userConsent: Boolean? = null
private var analyticsId: String? = null
// Cache for the properties to send
private var pendingUserProperties: UserProperties? = null
override fun init() {
observeUserConsent()
observeAnalyticsId()
@ -112,6 +116,7 @@ class DefaultVectorAnalytics @Inject constructor(
private suspend fun identifyPostHog() {
val id = analyticsId ?: return
if (!userConsent.orFalse()) return
if (id.isEmpty()) {
Timber.tag(analyticsTag.value).d("reset")
posthog?.reset()
@ -126,7 +131,7 @@ class DefaultVectorAnalytics @Inject constructor(
.onEach { consent ->
Timber.tag(analyticsTag.value).d("User consent updated to $consent")
userConsent = consent
optOutPostHog()
initOrStopPostHog()
initOrStopSentry()
}
.launchIn(globalScope)
@ -141,8 +146,22 @@ class DefaultVectorAnalytics @Inject constructor(
}
}
private fun optOutPostHog() {
userConsent?.let { posthog?.optOut(!it) }
private suspend fun initOrStopPostHog() {
userConsent?.let { _userConsent ->
when (_userConsent) {
true -> {
posthog?.optOut(false)
identifyPostHog()
pendingUserProperties?.let { doUpdateUserProperties(it) }
pendingUserProperties = null
}
false -> {
// When opting out, ensure that the queue is flushed first, or it will be flushed later (after user has revoked consent)
posthog?.flush()
posthog?.optOut(true)
}
}
}
}
override fun capture(event: VectorAnalyticsEvent) {
@ -160,7 +179,17 @@ class DefaultVectorAnalytics @Inject constructor(
}
override fun updateUserProperties(userProperties: UserProperties) {
posthog?.identify(REUSE_EXISTING_ID, userProperties.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
if (userConsent == true) {
doUpdateUserProperties(userProperties)
} else {
pendingUserProperties = userProperties
}
}
private fun doUpdateUserProperties(userProperties: UserProperties) {
posthog
?.takeIf { userConsent == true }
?.identify(REUSE_EXISTING_ID, userProperties.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
}
private fun Map<String, Any?>?.toPostHogProperties(): Properties? {

View file

@ -97,6 +97,7 @@ class DefaultVectorAnalyticsTest {
@Test
fun `given lateinit user properties when valid analytics id updates then identify with lateinit properties`() = runTest {
fakeLateInitUserPropertiesFactory.givenCreatesProperties(A_LATE_INIT_USER_PROPERTIES)
fakeAnalyticsStore.givenUserContent(true)
fakeAnalyticsStore.givenAnalyticsId(AN_ANALYTICS_ID)
@ -106,6 +107,7 @@ class DefaultVectorAnalyticsTest {
@Test
fun `when signing out then resets posthog and closes Sentry`() = runTest {
fakeAnalyticsStore.allowSettingAnalyticsIdToCallBackingFlow()
fakeAnalyticsStore.givenUserContent(true)
defaultVectorAnalytics.onSignOut()