Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
{
"formatVersion": 1,
"database": {
"version": 10,
"identityHash": "67e32a70f154b819751a225259e8222b",
"entities": [
{
"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, `organization_id` TEXT, 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
},
{
"fieldPath": "organizationId",
"columnName": "organization_id",
"affinity": "TEXT"
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_ciphers_user_id",
"unique": false,
"columnNames": [
"user_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_ciphers_user_id` ON `${TABLE_NAME}` (`user_id`)"
},
{
"name": "index_ciphers_user_id_organization_id",
"unique": false,
"columnNames": [
"user_id",
"organization_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_ciphers_user_id_organization_id` ON `${TABLE_NAME}` (`user_id`, `organization_id`)"
}
]
},
{
"tableName": "collections",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` TEXT NOT NULL, `organization_id` TEXT NOT NULL, `should_hide_passwords` INTEGER NOT NULL, `name` TEXT NOT NULL, `external_id` TEXT, `read_only` INTEGER NOT NULL, `manage` INTEGER, `default_user_collection_email` TEXT, `type` TEXT NOT NULL DEFAULT '0', PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "user_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "organizationId",
"columnName": "organization_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "shouldHidePasswords",
"columnName": "should_hide_passwords",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "externalId",
"columnName": "external_id",
"affinity": "TEXT"
},
{
"fieldPath": "isReadOnly",
"columnName": "read_only",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "canManage",
"columnName": "manage",
"affinity": "INTEGER"
},
{
"fieldPath": "defaultUserCollectionEmail",
"columnName": "default_user_collection_email",
"affinity": "TEXT"
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'0'"
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_collections_user_id",
"unique": false,
"columnNames": [
"user_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_collections_user_id` ON `${TABLE_NAME}` (`user_id`)"
}
]
},
{
"tableName": "domains",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_id` TEXT NOT NULL, `domains_json` TEXT, PRIMARY KEY(`user_id`))",
"fields": [
{
"fieldPath": "userId",
"columnName": "user_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "domainsJson",
"columnName": "domains_json",
"affinity": "TEXT"
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"user_id"
]
}
},
{
"tableName": "folders",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` TEXT NOT NULL, `name` TEXT, `revision_date` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "user_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT"
},
{
"fieldPath": "revisionDate",
"columnName": "revision_date",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_folders_user_id",
"unique": false,
"columnNames": [
"user_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_folders_user_id` ON `${TABLE_NAME}` (`user_id`)"
}
]
},
{
"tableName": "sends",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` TEXT NOT NULL, `send_type` TEXT NOT NULL, `send_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": "sendType",
"columnName": "send_type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sendJson",
"columnName": "send_json",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "index_sends_user_id",
"unique": false,
"columnNames": [
"user_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_sends_user_id` ON `${TABLE_NAME}` (`user_id`)"
}
]
}
],
"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, '67e32a70f154b819751a225259e8222b')"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class AuthenticatorBridgeRepositoryImpl(

// Vault is unlocked, query vault disk source for totp logins:
val cipherData = vaultDiskSource
.getTotpCiphers(userId = userId)
.getLoginCiphers(userId = userId)
// Filter out any deleted and archived ciphers.
.filter { it.deletedDate == null && it.archivedDate == null }
.mapNotNull {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ interface VaultDiskSource {
): List<SyncResponseJson.Cipher>

/**
* Retrieves all ciphers from the data source for a given [userId] that contain TOTP codes.
* Retrieves all login ciphers from the data source for a given [userId].
*/
suspend fun getTotpCiphers(userId: String): List<SyncResponseJson.Cipher>
suspend fun getLoginCiphers(userId: String): List<SyncResponseJson.Cipher>

/**
* Retrieves a cipher from the data source for a given [userId] and [cipherId].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.bitwarden.core.data.manager.dispatcher.DispatcherManager
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringWithErrorCallback
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.ui.platform.base.util.orNullIfBlank
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.DomainsDao
Expand Down Expand Up @@ -53,7 +52,6 @@ class VaultDiskSourceImpl(
CipherEntity(
id = cipher.id,
userId = userId,
hasTotp = cipher.login?.totp != null,
cipherType = json.encodeToString(cipher.type),
cipherJson = json.encodeToString(cipher),
organizationId = cipher.organizationId,
Expand Down Expand Up @@ -120,8 +118,8 @@ class VaultDiskSourceImpl(
}
}

override suspend fun getTotpCiphers(userId: String): List<SyncResponseJson.Cipher> {
val entities = ciphersDao.getAllTotpCiphers(userId = userId)
override suspend fun getLoginCiphers(userId: String): List<SyncResponseJson.Cipher> {
val entities = ciphersDao.getAllLoginCiphers(userId = userId)
return withContext(context = dispatcherManager.default) {
entities
.map { entity ->
Expand All @@ -132,11 +130,6 @@ class VaultDiskSourceImpl(
}
}
.awaitAll()
.filter {
// A safety-check since after the DB migration, we will temporarily think
// all ciphers contain a totp code
it.login?.totp.orNullIfBlank() != null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘ŒπŸΎ

}
}
}

Expand Down Expand Up @@ -167,7 +160,6 @@ class VaultDiskSourceImpl(
CipherEntity(
id = cipher.id,
userId = userId,
hasTotp = cipher.login?.totp.orNullIfBlank() != null,
cipherType = json.encodeToString(cipher.type),
cipherJson = json.encodeToString(cipher),
organizationId = cipher.organizationId,
Expand Down Expand Up @@ -369,7 +361,6 @@ class VaultDiskSourceImpl(
CipherEntity(
id = cipher.id,
userId = userId,
hasTotp = cipher.login?.totp != null,
cipherType = json.encodeToString(cipher.type),
cipherJson = json.encodeToString(cipher),
organizationId = cipher.organizationId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ interface CiphersDao {
): List<CipherEntity>

/**
* Retrieves all ciphers from the database for a given [userId].
* Retrieves all login type ciphers from the database for a given [userId].
*/
@Query("SELECT * FROM ciphers WHERE user_id = :userId AND has_totp = 1")
suspend fun getAllTotpCiphers(
@Query("SELECT * FROM ciphers WHERE user_id = :userId AND cipher_type = 1")
suspend fun getAllLoginCiphers(
userId: String,
): List<CipherEntity>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package com.x8bit.bitwarden.data.vault.datasource.disk.database

import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.DeleteColumn
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.AutoMigrationSpec
import com.x8bit.bitwarden.data.vault.datasource.disk.convertor.InstantTypeConverter
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CiphersDao
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
Expand All @@ -27,11 +29,13 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.entity.SendEntity
FolderEntity::class,
SendEntity::class,
],
version = 9,
version = 10,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 6, to = 7),
AutoMigration(from = 7, to = 8),
AutoMigration(from = 8, to = 9),
AutoMigration(from = 9, to = 10, RemoveTotpAutoMigration::class),
],
)
@TypeConverters(InstantTypeConverter::class)
Expand Down Expand Up @@ -62,3 +66,9 @@ abstract class VaultDatabase : RoomDatabase() {
*/
abstract fun sendsDao(): SendsDao
}

/**
* A defined migration to remove the `has_totp` field from the `cipher` table.
*/
@DeleteColumn.Entries(DeleteColumn(tableName = "ciphers", columnName = "has_totp"))
class RemoveTotpAutoMigration : AutoMigrationSpec
Loading
Loading