Create sealed class for Organization Events (#3345)

This commit is contained in:
David Perez 2024-06-24 11:09:01 -05:00 committed by GitHub
parent 448ef1597f
commit 6bd628c346
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 128 additions and 19 deletions

View file

@ -1,6 +1,6 @@
package com.x8bit.bitwarden.data.platform.manager.event
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEventType
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEvent
/**
* A manager for tracking events.
@ -9,5 +9,5 @@ interface OrganizationEventManager {
/**
* Tracks a specific event to be uploaded at a different time.
*/
fun trackEvent(eventType: OrganizationEventType, cipherId: String? = null)
fun trackEvent(event: OrganizationEvent)
}

View file

@ -9,7 +9,7 @@ import com.x8bit.bitwarden.data.platform.datasource.disk.EventDiskSource
import com.x8bit.bitwarden.data.platform.datasource.network.model.OrganizationEventJson
import com.x8bit.bitwarden.data.platform.datasource.network.service.EventService
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEventType
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEvent
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@ -58,14 +58,14 @@ class OrganizationEventManagerImpl(
}
@Suppress("ReturnCount")
override fun trackEvent(eventType: OrganizationEventType, cipherId: String?) {
override fun trackEvent(event: OrganizationEvent) {
val userId = authRepository.activeUserId ?: return
if (authRepository.authStateFlow.value !is AuthState.Authenticated) return
val organizations = authRepository.organizations.filter { it.shouldUseEvents }
if (organizations.none()) return
ioScope.launch {
cipherId?.let { id ->
event.cipherId?.let { id ->
val cipherOrganizationId = vaultRepository
.getVaultItemStateFlow(itemId = id)
.first { it.data != null }
@ -77,8 +77,8 @@ class OrganizationEventManagerImpl(
eventDiskSource.addOrganizationEvent(
userId = userId,
event = OrganizationEventJson(
type = eventType,
cipherId = cipherId,
type = event.type,
cipherId = event.cipherId,
date = ZonedDateTime.now(clock),
),
)

View file

@ -0,0 +1,106 @@
package com.x8bit.bitwarden.data.platform.manager.model
/**
* A representation of events used for organization tracking.
*/
sealed class OrganizationEvent {
/**
* The type of event this model represents.
*/
abstract val type: OrganizationEventType
/**
* The optional cipher ID.
*/
abstract val cipherId: String?
/**
* Tracks when a value is successfully auto-filled
*/
data class CipherClientAutoFilled(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_AUTO_FILLED
}
/**
* Tracks when a card code is copied.
*/
data class CipherClientCopiedCardCode(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_COPIED_CARD_CODE
}
/**
* Tracks when a hidden field is copied.
*/
data class CipherClientCopiedHiddenField(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_COPIED_HIDDEN_FIELD
}
/**
* Tracks when a password is copied.
*/
data class CipherClientCopiedPassword(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_COPIED_PASSWORD
}
/**
* Tracks when a card code is made visible.
*/
data class CipherClientToggledCardCodeVisible(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_TOGGLED_CARD_CODE_VISIBLE
}
/**
* Tracks when a card number is made visible.
*/
data class CipherClientToggledCardNumberVisible(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_TOGGLED_CARD_NUMBER_VISIBLE
}
/**
* Tracks when a hidden field is made visible.
*/
data class CipherClientToggledHiddenFieldVisible(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_TOGGLED_HIDDEN_FIELD_VISIBLE
}
/**
* Tracks when a password is made visible.
*/
data class CipherClientToggledPasswordVisible(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_TOGGLED_PASSWORD_VISIBLE
}
/**
* Tracks when a cipher is viewed.
*/
data class CipherClientViewed(
override val cipherId: String,
) : OrganizationEvent() {
override val type: OrganizationEventType
get() = OrganizationEventType.CIPHER_CLIENT_VIEWED
}
}

View file

@ -7,6 +7,7 @@ import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager
import com.x8bit.bitwarden.data.platform.datasource.disk.EventDiskSource
import com.x8bit.bitwarden.data.platform.datasource.network.model.OrganizationEventJson
import com.x8bit.bitwarden.data.platform.datasource.network.service.EventService
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEvent
import com.x8bit.bitwarden.data.platform.manager.model.OrganizationEventType
import com.x8bit.bitwarden.data.platform.repository.model.DataState
import com.x8bit.bitwarden.data.platform.util.asSuccess
@ -125,8 +126,9 @@ class OrganizationEventManagerTest {
every { authRepository.activeUserId } returns null
organizationEventManager.trackEvent(
eventType = OrganizationEventType.CIPHER_UPDATED,
cipherId = CIPHER_ID,
event = OrganizationEvent.CipherClientAutoFilled(
cipherId = CIPHER_ID,
),
)
coVerify(exactly = 0) {
@ -137,8 +139,9 @@ class OrganizationEventManagerTest {
@Test
fun `trackEvent should do nothing if the active user is not authenticated`() {
organizationEventManager.trackEvent(
eventType = OrganizationEventType.CIPHER_UPDATED,
cipherId = CIPHER_ID,
event = OrganizationEvent.CipherClientAutoFilled(
cipherId = CIPHER_ID,
),
)
coVerify(exactly = 0) {
@ -153,8 +156,9 @@ class OrganizationEventManagerTest {
every { authRepository.organizations } returns listOf(organization)
organizationEventManager.trackEvent(
eventType = OrganizationEventType.CIPHER_UPDATED,
cipherId = CIPHER_ID,
event = OrganizationEvent.CipherClientAutoFilled(
cipherId = CIPHER_ID,
),
)
coVerify(exactly = 0) {
@ -172,8 +176,9 @@ class OrganizationEventManagerTest {
mutableVaultItemStateFlow.value = DataState.Loaded(data = cipherView)
organizationEventManager.trackEvent(
eventType = OrganizationEventType.CIPHER_UPDATED,
cipherId = CIPHER_ID,
event = OrganizationEvent.CipherClientAutoFilled(
cipherId = CIPHER_ID,
),
)
coVerify(exactly = 0) {
@ -191,11 +196,9 @@ class OrganizationEventManagerTest {
every { authRepository.organizations } returns listOf(organization)
val cipherView = createMockCipherView(number = 1)
mutableVaultItemStateFlow.value = DataState.Loaded(data = cipherView)
val eventType = OrganizationEventType.CIPHER_UPDATED
organizationEventManager.trackEvent(
eventType = eventType,
cipherId = CIPHER_ID,
event = OrganizationEvent.CipherClientAutoFilled(cipherId = CIPHER_ID),
)
dispatcher.scheduler.runCurrent()
@ -203,7 +206,7 @@ class OrganizationEventManagerTest {
eventDiskSource.addOrganizationEvent(
userId = USER_ID,
event = OrganizationEventJson(
type = eventType,
type = OrganizationEventType.CIPHER_CLIENT_AUTO_FILLED,
cipherId = CIPHER_ID,
date = ZonedDateTime.now(fixedClock),
),