mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 15:15:34 +03:00
Introduce OfflineCiphersDao/Entity
This commit is contained in:
parent
c7d7ed6cb9
commit
9cb8f414ba
8 changed files with 153 additions and 6 deletions
|
@ -2,8 +2,56 @@
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"identityHash": "64bb48a6bc6a544d168b0b4f4862cbcd",
|
"identityHash": "67b7550b79460fd815162804f4a00c2e",
|
||||||
"entities": [
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "offline_ciphers",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` TEXT NOT NULL, `cipher_type` TEXT NOT NULL, `cipher_json` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userId",
|
||||||
|
"columnName": "user_id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "cipherType",
|
||||||
|
"columnName": "cipher_type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "cipherJson",
|
||||||
|
"columnName": "cipher_json",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_offline_ciphers_user_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_offline_ciphers_user_id` ON `${TABLE_NAME}` (`user_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"tableName": "ciphers",
|
"tableName": "ciphers",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` TEXT NOT NULL, `cipher_type` TEXT NOT NULL, `cipher_json` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` TEXT NOT NULL, `cipher_type` TEXT NOT NULL, `cipher_json` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
@ -244,7 +292,7 @@
|
||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"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, '64bb48a6bc6a544d168b0b4f4862cbcd')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '67b7550b79460fd815162804f4a00c2e')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.disk
|
package com.x8bit.bitwarden.data.vault.datasource.disk
|
||||||
|
|
||||||
|
import com.bitwarden.vault.Cipher
|
||||||
import com.bitwarden.vault.CipherView
|
import com.bitwarden.vault.CipherView
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
@ -13,7 +14,7 @@ interface VaultDiskSource {
|
||||||
/**
|
/**
|
||||||
* Saves a cipher to the offline data source for the given [userId].
|
* Saves a cipher to the offline data source for the given [userId].
|
||||||
*/
|
*/
|
||||||
suspend fun saveOfflineCipher(userId: String, cipher: CipherView)
|
suspend fun saveOfflineCipher(userId: String, cipher: Cipher)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a cipher to the data source for the given [userId].
|
* Saves a cipher to the data source for the given [userId].
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.disk
|
package com.x8bit.bitwarden.data.vault.datasource.disk
|
||||||
|
|
||||||
|
import com.bitwarden.vault.Cipher
|
||||||
import com.bitwarden.vault.CipherView
|
import com.bitwarden.vault.CipherView
|
||||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||||
|
@ -7,6 +8,7 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CiphersDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FoldersDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FoldersDao
|
||||||
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.OfflineCiphersDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.SendsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.SendsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CipherEntity
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CipherEntity
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CollectionEntity
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CollectionEntity
|
||||||
|
@ -31,7 +33,7 @@ import kotlinx.serialization.json.Json
|
||||||
*/
|
*/
|
||||||
@Suppress("TooManyFunctions", "LongParameterList")
|
@Suppress("TooManyFunctions", "LongParameterList")
|
||||||
class VaultDiskSourceImpl(
|
class VaultDiskSourceImpl(
|
||||||
private val offlineCiphersDao: CiphersDao,
|
private val offlineCiphersDao: OfflineCiphersDao,
|
||||||
private val ciphersDao: CiphersDao,
|
private val ciphersDao: CiphersDao,
|
||||||
private val collectionsDao: CollectionsDao,
|
private val collectionsDao: CollectionsDao,
|
||||||
private val domainsDao: DomainsDao,
|
private val domainsDao: DomainsDao,
|
||||||
|
@ -47,7 +49,7 @@ class VaultDiskSourceImpl(
|
||||||
private val forceFolderFlow = bufferedMutableSharedFlow<List<SyncResponseJson.Folder>>()
|
private val forceFolderFlow = bufferedMutableSharedFlow<List<SyncResponseJson.Folder>>()
|
||||||
private val forceSendFlow = bufferedMutableSharedFlow<List<SyncResponseJson.Send>>()
|
private val forceSendFlow = bufferedMutableSharedFlow<List<SyncResponseJson.Send>>()
|
||||||
|
|
||||||
override suspend fun saveOfflineCipher(userId: String, cipher: CipherView) {
|
override suspend fun saveOfflineCipher(userId: String, cipher: Cipher) {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.x8bit.bitwarden.data.vault.datasource.disk.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Transaction
|
||||||
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.OfflineCipherEntity
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides methods for inserting, retrieving, and deleting ciphers from the database using the
|
||||||
|
* [OfflineCipherEntity].
|
||||||
|
*/
|
||||||
|
@Dao
|
||||||
|
interface OfflineCiphersDao {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts multiple ciphers into the database.
|
||||||
|
*/
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insertCiphers(ciphers: List<OfflineCipherEntity>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all ciphers from the database for a given [userId].
|
||||||
|
*/
|
||||||
|
@Query("SELECT * FROM offline_ciphers WHERE user_id = :userId")
|
||||||
|
fun getAllCiphers(
|
||||||
|
userId: String,
|
||||||
|
): Flow<List<OfflineCipherEntity>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all the stored ciphers associated with the given [userId]. This will return the
|
||||||
|
* number of rows deleted by this query.
|
||||||
|
*/
|
||||||
|
@Query("DELETE FROM offline_ciphers WHERE user_id = :userId")
|
||||||
|
suspend fun deleteAllCiphers(userId: String): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the specified cipher associated with the given [userId] and [cipherId]. This will
|
||||||
|
* return the number of rows deleted by this query.
|
||||||
|
*/
|
||||||
|
@Query("DELETE FROM offline_ciphers WHERE user_id = :userId AND id = :cipherId")
|
||||||
|
suspend fun deleteCipher(userId: String, cipherId: String): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all the stored ciphers associated with the given [userId] and then add all new
|
||||||
|
* [ciphers] to the database. This will return `true` if any changes were made to the database
|
||||||
|
* and `false` otherwise.
|
||||||
|
*/
|
||||||
|
@Transaction
|
||||||
|
suspend fun replaceAllCiphers(userId: String, ciphers: List<OfflineCipherEntity>): Boolean {
|
||||||
|
val deletedCiphersCount = deleteAllCiphers(userId)
|
||||||
|
insertCiphers(ciphers)
|
||||||
|
return deletedCiphersCount > 0 || ciphers.isNotEmpty()
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,11 +8,13 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CiphersDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FoldersDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FoldersDao
|
||||||
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.OfflineCiphersDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.SendsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.SendsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CipherEntity
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CipherEntity
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CollectionEntity
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.CollectionEntity
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.DomainsEntity
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.DomainsEntity
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.FolderEntity
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.FolderEntity
|
||||||
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.OfflineCipherEntity
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.SendEntity
|
import com.x8bit.bitwarden.data.vault.datasource.disk.entity.SendEntity
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +22,7 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.entity.SendEntity
|
||||||
*/
|
*/
|
||||||
@Database(
|
@Database(
|
||||||
entities = [
|
entities = [
|
||||||
|
OfflineCipherEntity::class,
|
||||||
CipherEntity::class,
|
CipherEntity::class,
|
||||||
CollectionEntity::class,
|
CollectionEntity::class,
|
||||||
DomainsEntity::class,
|
DomainsEntity::class,
|
||||||
|
@ -32,6 +35,11 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.entity.SendEntity
|
||||||
@TypeConverters(ZonedDateTimeTypeConverter::class)
|
@TypeConverters(ZonedDateTimeTypeConverter::class)
|
||||||
abstract class VaultDatabase : RoomDatabase() {
|
abstract class VaultDatabase : RoomDatabase() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the DAO for accessing cipher data.
|
||||||
|
*/
|
||||||
|
abstract fun offlineCipherDao(): OfflineCiphersDao
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the DAO for accessing cipher data.
|
* Provides the DAO for accessing cipher data.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CiphersDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FoldersDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.FoldersDao
|
||||||
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.OfflineCiphersDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.SendsDao
|
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.SendsDao
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.disk.database.VaultDatabase
|
import com.x8bit.bitwarden.data.vault.datasource.disk.database.VaultDatabase
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
@ -39,6 +40,10 @@ class VaultDiskModule {
|
||||||
.addTypeConverter(ZonedDateTimeTypeConverter())
|
.addTypeConverter(ZonedDateTimeTypeConverter())
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideOfflineCipherDao(database: VaultDatabase): OfflineCiphersDao = database.offlineCipherDao()
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideCipherDao(database: VaultDatabase): CiphersDao = database.cipherDao()
|
fun provideCipherDao(database: VaultDatabase): CiphersDao = database.cipherDao()
|
||||||
|
@ -62,6 +67,7 @@ class VaultDiskModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideVaultDiskSource(
|
fun provideVaultDiskSource(
|
||||||
|
offlineCiphersDao: OfflineCiphersDao,
|
||||||
ciphersDao: CiphersDao,
|
ciphersDao: CiphersDao,
|
||||||
collectionsDao: CollectionsDao,
|
collectionsDao: CollectionsDao,
|
||||||
domainsDao: DomainsDao,
|
domainsDao: DomainsDao,
|
||||||
|
@ -70,6 +76,7 @@ class VaultDiskModule {
|
||||||
json: Json,
|
json: Json,
|
||||||
dispatcherManager: DispatcherManager,
|
dispatcherManager: DispatcherManager,
|
||||||
): VaultDiskSource = VaultDiskSourceImpl(
|
): VaultDiskSource = VaultDiskSourceImpl(
|
||||||
|
offlineCiphersDao = offlineCiphersDao,
|
||||||
ciphersDao = ciphersDao,
|
ciphersDao = ciphersDao,
|
||||||
collectionsDao = collectionsDao,
|
collectionsDao = collectionsDao,
|
||||||
domainsDao = domainsDao,
|
domainsDao = domainsDao,
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.x8bit.bitwarden.data.vault.datasource.disk.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity representing a cipher in the database.
|
||||||
|
*/
|
||||||
|
@Entity(tableName = "offline_ciphers")
|
||||||
|
data class OfflineCipherEntity(
|
||||||
|
@PrimaryKey(autoGenerate = false)
|
||||||
|
@ColumnInfo(name = "id")
|
||||||
|
val id: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "user_id", index = true)
|
||||||
|
val userId: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "cipher_type")
|
||||||
|
val cipherType: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "cipher_json")
|
||||||
|
val cipherJson: String,
|
||||||
|
)
|
|
@ -53,7 +53,7 @@ class CipherManagerImpl(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
cipherView = cipherView
|
cipherView = cipherView
|
||||||
)
|
)
|
||||||
.flatMap { vaultDiskSource.saveOfflineCipher(userId = userId, cipher = it) }
|
.map { vaultDiskSource.saveOfflineCipher(userId = userId, cipher = it) }
|
||||||
.fold(
|
.fold(
|
||||||
onFailure = { CreateCipherResult.Error },
|
onFailure = { CreateCipherResult.Error },
|
||||||
onSuccess = { CreateCipherResult.Success }
|
onSuccess = { CreateCipherResult.Success }
|
||||||
|
|
Loading…
Reference in a new issue