Skip to content

Commit

Permalink
Refactor primary data model
Browse files Browse the repository at this point in the history
- **AuthenticatorItemEntity.kt:** Rename property `username` to `accountName`.
- **TotpCodeManagerImpl.kt:** Replace entity `username` references with `accountName`.
- **UpdateItemRequest.kt:**
  - Rename property `username` to `accountName` to reflect similar change in entity object.
  - Remove default property values
- **AuthenticatorRepository.kt:** Updated `createItem` signature to accept an `AuthenticatorItemEntity` parameter.
- **AuthenticatorRepositoryImpl.kt:** Updated `createItem` function to accommodate interface changes.
- **DataStateExtensions.kt:** Add ext function to observe a flow while it is loading.
- **ItemViewModel.kt:** Update references of entity property `username` to `accountName`.
- **ManualCodeEntryViewModel.kt:** Update references to `createItem` so that an `AuthenticatorItemEntity` instance is provided.
  • Loading branch information
SaintPatrck committed Apr 8, 2024
1 parent cd992a6 commit 7dcb41b
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "3cc9605b629947b2b4148a40ff0d955d",
"identityHash": "8724b95439edde85bd15e0bd2e02195e",
"entities": [
{
"tableName": "items",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` TEXT NOT NULL, `algorithm` TEXT NOT NULL, `period` INTEGER NOT NULL, `digits` INTEGER NOT NULL, `key` TEXT NOT NULL, `issuer` TEXT, `userId` TEXT, `username` TEXT, PRIMARY KEY(`id`))",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `key` TEXT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `algorithm` TEXT NOT NULL, `period` INTEGER NOT NULL, `digits` INTEGER NOT NULL, `issuer` TEXT, `userId` TEXT, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "accountName",
"columnName": "accountName",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
Expand All @@ -38,12 +50,6 @@
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "issuer",
"columnName": "issuer",
Expand All @@ -55,12 +61,6 @@
"columnName": "userId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
Expand All @@ -76,7 +76,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3cc9605b629947b2b4148a40ff0d955d')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8724b95439edde85bd15e0bd2e02195e')"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ data class AuthenticatorItemEntity(
@ColumnInfo(name = "id")
val id: String,

@ColumnInfo(name = "key")
val key: String,

@ColumnInfo(name = "accountName")
val accountName: String,

@ColumnInfo(name = "type")
val type: AuthenticatorItemType = AuthenticatorItemType.TOTP,

Expand All @@ -25,15 +31,9 @@ data class AuthenticatorItemEntity(
@ColumnInfo(name = "digits")
val digits: Int = 6,

@ColumnInfo(name = "key")
val key: String,

@ColumnInfo(name = "issuer")
val issuer: String?,
val issuer: String? = null,

@ColumnInfo(name = "userId")
val userId: String?,

@ColumnInfo(name = "username")
val username: String?,
val userId: String? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class TotpCodeManagerImpl @Inject constructor(
time % response.period.toInt(),
issueTime = clock.millis(),
id = cipherId,
username = itemEntity.username,
username = itemEntity.accountName,
issuer = itemEntity.issuer,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ interface AuthenticatorRepository {
/**
* Attempt to create a cipher.
*/
suspend fun createItem(code: String, issuer: String): CreateItemResult
suspend fun createItem(item: AuthenticatorItemEntity): CreateItemResult

/**
* Attempt to delete a cipher.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.x8bit.bitwarden.authenticator.data.authenticator.repository

import com.x8bit.bitwarden.authenticator.data.authenticator.datasource.disk.AuthenticatorDiskSource
import com.x8bit.bitwarden.authenticator.data.authenticator.datasource.disk.entity.AuthenticatorItemEntity
import com.x8bit.bitwarden.authenticator.data.authenticator.datasource.disk.entity.AuthenticatorItemType
import com.x8bit.bitwarden.authenticator.data.authenticator.manager.TotpCodeManager
import com.x8bit.bitwarden.authenticator.data.authenticator.manager.model.VerificationCodeItem
import com.x8bit.bitwarden.authenticator.data.authenticator.repository.model.AuthenticatorData
Expand Down Expand Up @@ -31,7 +30,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import java.util.UUID
import javax.inject.Inject

/**
Expand Down Expand Up @@ -179,20 +177,9 @@ class AuthenticatorRepositoryImpl @Inject constructor(
mutableTotpCodeResultFlow.tryEmit(totpCodeResult)
}

override suspend fun createItem(code: String, issuer: String): CreateItemResult {
override suspend fun createItem(item: AuthenticatorItemEntity): CreateItemResult {
return try {
authenticatorDiskSource.saveItem(
AuthenticatorItemEntity(
id = UUID.randomUUID().toString(),
type = AuthenticatorItemType.TOTP,
period = 30,
digits = 6,
key = code,
issuer = issuer,
userId = null,
username = null,
)
)
authenticatorDiskSource.saveItem(item)
CreateItemResult.Success
} catch (e: Exception) {
CreateItemResult.Error
Expand All @@ -216,13 +203,13 @@ class AuthenticatorRepositoryImpl @Inject constructor(
authenticatorDiskSource.saveItem(
AuthenticatorItemEntity(
id = itemId,
key = updateItemRequest.key,
accountName = updateItemRequest.accountName,
type = updateItemRequest.type,
period = updateItemRequest.period,
digits = updateItemRequest.digits,
key = updateItemRequest.key,
issuer = updateItemRequest.issuer,
userId = null,
username = null,
)
)
UpdateItemResult.Success
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,32 @@ import com.x8bit.bitwarden.authenticator.data.authenticator.datasource.disk.enti
/**
* Models a request to modify an existing authenticator item.
*
* @property key Key used to generate verification codes for the authenticator item.
* @property accountName Required account or username associated with the item.
* @property type Type of authenticator item.
* @property algorithm Hashing algorithm applied to the authenticator item verification code.
* @property period Time, in seconds, the authenticator item verification code is valid. Default is
* 30 seconds.
* @property period Time, in seconds, the authenticator item verification code is valid.
* @property digits Number of digits contained in the verification code for this authenticator item.
* Default is 6 digits.
* @property key Key used to generate verification codes for the authenticator item.
* @property issuer Entity that provided the authenticator item.
* @property username Optional username associated with .
*/
data class UpdateItemRequest(
val type: AuthenticatorItemType,
val algorithm: AuthenticatorItemAlgorithm = AuthenticatorItemAlgorithm.SHA1,
val period: Int = 30,
val digits: Int = 6,
val key: String,
val accountName: String,
val type: AuthenticatorItemType,
val algorithm: AuthenticatorItemAlgorithm,
val period: Int,
val digits: Int,
val issuer: String?,
val username: String?,
) {
/**
* The composite label of the authenticator item.
* The composite label of the authenticator item. Derived from combining [issuer] and [accountName]
* ```
* label = issuer (“:” / “%3A”) *”%20” username
* label = accountName /issuer (“:” / “%3A”) *”%20” accountName
* ```
*/
val label = if (issuer != null) {
issuer + username?.let { ":$it" }.orEmpty()
"$issuer:$accountName"
} else {
username.orEmpty()
accountName
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.x8bit.bitwarden.authenticator.data.platform.repository.util

import com.x8bit.bitwarden.authenticator.data.platform.repository.model.DataState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.transformWhile

/**
* Maps the data inside a [DataState] with the given [transform].
Expand All @@ -15,6 +17,14 @@ inline fun <T : Any?, R : Any?> DataState<T>.map(
is DataState.NoNetwork -> DataState.NoNetwork(data?.let(transform))
}

/**
* Emits all values of a [DataState] [Flow] until it emits a [DataState.Loaded].
*/
fun <T : Any?> Flow<DataState<T>>.takeUntilLoaded(): Flow<DataState<T>> = transformWhile {
emit(it)
it !is DataState.Loaded
}

/**
* Combines the [dataState1] and [dataState2] [DataState]s together using the provided [transform].
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ItemViewModel @Inject constructor(

TotpCodeItemData(
type = item.type,
username = item.username?.asText(),
username = item.accountName.asText(),
issuer = item.issuer.orEmpty().asText(),
periodSeconds = authCode.periodSeconds,
timeLeftSeconds = authCode.timeLeftSeconds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ package com.x8bit.bitwarden.authenticator.ui.authenticator.feature.manualcodeent
import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.x8bit.bitwarden.authenticator.data.authenticator.datasource.disk.entity.AuthenticatorItemAlgorithm
import com.x8bit.bitwarden.authenticator.data.authenticator.datasource.disk.entity.AuthenticatorItemEntity
import com.x8bit.bitwarden.authenticator.data.authenticator.datasource.disk.entity.AuthenticatorItemType
import com.x8bit.bitwarden.authenticator.data.authenticator.repository.AuthenticatorRepository
import com.x8bit.bitwarden.authenticator.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.authenticator.ui.platform.base.util.Text
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import java.util.UUID
import javax.inject.Inject

private const val KEY_STATE = "state"
Expand Down Expand Up @@ -55,7 +59,14 @@ class ManualCodeEntryViewModel @Inject constructor(

private fun handleCodeSubmit() {
viewModelScope.launch {
authenticatorRepository.createItem(state.code, state.issuer)
authenticatorRepository.createItem(
AuthenticatorItemEntity(
id = UUID.randomUUID().toString(),
key = state.code,
accountName = "",
issuer = state.issuer
)
)
}
sendEvent(ManualCodeEntryEvent.NavigateBack)
}
Expand Down

0 comments on commit 7dcb41b

Please sign in to comment.