BIT-654: Adding generator disk source implementation (#245)

This commit is contained in:
joshua-livefront
2023-11-14 15:07:48 -05:00
committed by Álison Fernandes
parent f52f4befba
commit fa9401f2d2
10 changed files with 463 additions and 1 deletions

View File

@@ -0,0 +1,19 @@
package com.x8bit.bitwarden.data.generator.datasource.disk
import com.x8bit.bitwarden.data.generator.repository.model.PasswordGenerationOptions
/**
* Primary access point for disk information related to generation.
*/
interface GeneratorDiskSource {
/**
* Retrieves a user's password generation options using a [userId].
*/
fun getPasswordGenerationOptions(userId: String): PasswordGenerationOptions?
/**
* Stores a user's password generation options using a [userId].
*/
fun storePasswordGenerationOptions(userId: String, options: PasswordGenerationOptions?)
}

View File

@@ -0,0 +1,43 @@
package com.x8bit.bitwarden.data.generator.datasource.disk
import android.content.SharedPreferences
import com.x8bit.bitwarden.data.generator.repository.model.PasswordGenerationOptions
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseDiskSource
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
private const val PASSWORD_GENERATION_OPTIONS_KEY = "passwordGenerationOptions"
/**
* Primary implementation of [GeneratorDiskSource].
*/
class GeneratorDiskSourceImpl(
sharedPreferences: SharedPreferences,
private val json: Json,
) : BaseDiskSource(sharedPreferences),
GeneratorDiskSource {
override fun getPasswordGenerationOptions(userId: String): PasswordGenerationOptions? {
val key = getPasswordGenerationOptionsKey(userId)
return getString(key)?.let { json.decodeFromString(it) }
}
override fun storePasswordGenerationOptions(
userId: String,
options: PasswordGenerationOptions?,
) {
val key = getPasswordGenerationOptionsKey(userId)
putString(
key,
options?.let { json.encodeToString(options) },
)
}
override fun onSharedPreferenceChanged(
sharedPreferences: SharedPreferences?,
key: String?,
) = Unit
private fun getPasswordGenerationOptionsKey(userId: String): String =
"${BASE_KEY}_${PASSWORD_GENERATION_OPTIONS_KEY}_$userId"
}

View File

@@ -0,0 +1,30 @@
package com.x8bit.bitwarden.data.generator.datasource.disk.di
import android.content.SharedPreferences
import com.x8bit.bitwarden.data.generator.datasource.disk.GeneratorDiskSource
import com.x8bit.bitwarden.data.generator.datasource.disk.GeneratorDiskSourceImpl
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.json.Json
import javax.inject.Singleton
/**
* Provides persistence-related dependencies for the generator package.
*/
@Module
@InstallIn(SingletonComponent::class)
object GeneratorDiskModule {
@Provides
@Singleton
fun provideGeneratorDiskSource(
sharedPreferences: SharedPreferences,
json: Json,
): GeneratorDiskSource =
GeneratorDiskSourceImpl(
sharedPreferences = sharedPreferences,
json = json,
)
}

View File

@@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.generator.repository
import com.bitwarden.core.PasswordGeneratorRequest
import com.x8bit.bitwarden.data.generator.repository.model.GeneratedPasswordResult
import com.x8bit.bitwarden.data.generator.repository.model.PasswordGenerationOptions
/**
* Responsible for managing generator data.
@@ -14,4 +15,14 @@ interface GeneratorRepository {
suspend fun generatePassword(
passwordGeneratorRequest: PasswordGeneratorRequest,
): GeneratedPasswordResult
/**
* Get the [PasswordGenerationOptions] for the current user.
*/
fun getPasswordGenerationOptions(): PasswordGenerationOptions?
/**
* Save the [PasswordGenerationOptions] for the current user.
*/
fun savePasswordGenerationOptions(options: PasswordGenerationOptions)
}

View File

@@ -1,8 +1,11 @@
package com.x8bit.bitwarden.data.generator.repository
import com.bitwarden.core.PasswordGeneratorRequest
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.generator.datasource.disk.GeneratorDiskSource
import com.x8bit.bitwarden.data.generator.datasource.sdk.GeneratorSdkSource
import com.x8bit.bitwarden.data.generator.repository.model.GeneratedPasswordResult
import com.x8bit.bitwarden.data.generator.repository.model.PasswordGenerationOptions
import javax.inject.Singleton
/**
@@ -11,6 +14,8 @@ import javax.inject.Singleton
@Singleton
class GeneratorRepositoryImpl constructor(
private val generatorSdkSource: GeneratorSdkSource,
private val generatorDiskSource: GeneratorDiskSource,
private val authDiskSource: AuthDiskSource,
) : GeneratorRepository {
override suspend fun generatePassword(
@@ -22,4 +27,14 @@ class GeneratorRepositoryImpl constructor(
onSuccess = { GeneratedPasswordResult.Success(it) },
onFailure = { GeneratedPasswordResult.InvalidRequest },
)
override fun getPasswordGenerationOptions(): PasswordGenerationOptions? {
val userId = authDiskSource.userState?.activeUserId
return userId?.let { generatorDiskSource.getPasswordGenerationOptions(it) }
}
override fun savePasswordGenerationOptions(options: PasswordGenerationOptions) {
val userId = authDiskSource.userState?.activeUserId
userId?.let { generatorDiskSource.storePasswordGenerationOptions(it, options) }
}
}

View File

@@ -1,5 +1,7 @@
package com.x8bit.bitwarden.data.generator.repository.di
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.generator.datasource.disk.GeneratorDiskSource
import com.x8bit.bitwarden.data.generator.datasource.sdk.GeneratorSdkSource
import com.x8bit.bitwarden.data.generator.repository.GeneratorRepository
import com.x8bit.bitwarden.data.generator.repository.GeneratorRepositoryImpl
@@ -20,5 +22,11 @@ object GeneratorRepositoryModule {
@Singleton
fun provideGeneratorRepository(
generatorSdkSource: GeneratorSdkSource,
): GeneratorRepository = GeneratorRepositoryImpl(generatorSdkSource)
generatorDiskSource: GeneratorDiskSource,
authDiskSource: AuthDiskSource,
): GeneratorRepository = GeneratorRepositoryImpl(
generatorSdkSource = generatorSdkSource,
generatorDiskSource = generatorDiskSource,
authDiskSource = authDiskSource,
)
}

View File

@@ -0,0 +1,51 @@
package com.x8bit.bitwarden.data.generator.repository.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* A data class representing the configuration options for password generation.
*
* @property length The total length of the generated password.
* @property allowAmbiguousChar Indicates whether ambiguous characters are allowed in the password.
* @property hasNumbers Indicates whether the password should contain numbers.
* @property minNumber The minimum number of numeric characters required in the password.
* @property hasUppercase Indicates whether the password should contain uppercase characters.
* @property minUppercase The minimum number of uppercase characters required in the password.
* @property hasLowercase Indicates whether the password should contain lowercase characters.
* @property minLowercase The minimum number of lowercase characters required in the password.
* @property allowSpecial Indicates whether special characters are allowed in the password.
* @property minSpecial The minimum number of special characters required in the password.
*/
@Serializable
data class PasswordGenerationOptions(
@SerialName("length")
val length: Int,
@SerialName("allowAmbiguousChar")
val allowAmbiguousChar: Boolean,
@SerialName("number")
val hasNumbers: Boolean,
@SerialName("minNumber")
val minNumber: Int,
@SerialName("uppercase")
val hasUppercase: Boolean,
@SerialName("minUppercase")
val minUppercase: Int?,
@SerialName("lowercase")
val hasLowercase: Boolean,
@SerialName("minLowercase")
val minLowercase: Int?,
@SerialName("special")
val allowSpecial: Boolean,
@SerialName("minSpecial")
val minSpecial: Int,
)