From 0a888a72c8d07d1b904093ec042a4a259b7a6d5a Mon Sep 17 00:00:00 2001 From: Patrick Honkonen <1883101+SaintPatrck@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:18:04 -0500 Subject: [PATCH] [PM-14553] Make canManage property of collections optional (#4284) --- .../6.json | 256 ++++++++++++++++++ .../datasource/disk/database/VaultDatabase.kt | 2 +- .../disk/entity/CollectionEntity.kt | 2 +- .../network/model/SyncResponseJson.kt | 2 +- .../util/VaultSdkCollectionExtensions.kt | 2 +- .../util/VaultSdkCollectionExtensionsTest.kt | 25 ++ 6 files changed, 285 insertions(+), 4 deletions(-) create mode 100644 app/schemas/com.x8bit.bitwarden.data.vault.datasource.disk.database.VaultDatabase/6.json diff --git a/app/schemas/com.x8bit.bitwarden.data.vault.datasource.disk.database.VaultDatabase/6.json b/app/schemas/com.x8bit.bitwarden.data.vault.datasource.disk.database.VaultDatabase/6.json new file mode 100644 index 000000000..8d506a645 --- /dev/null +++ b/app/schemas/com.x8bit.bitwarden.data.vault.datasource.disk.database.VaultDatabase/6.json @@ -0,0 +1,256 @@ +{ + "formatVersion": 1, + "database": { + "version": 6, + "identityHash": "ee158c483edfe5102504670f3d9845d4", + "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, 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_ciphers_user_id", + "unique": false, + "columnNames": [ + "user_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_ciphers_user_id` ON `${TABLE_NAME}` (`user_id`)" + } + ], + "foreignKeys": [] + }, + { + "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, 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", + "notNull": false + }, + { + "fieldPath": "isReadOnly", + "columnName": "read_only", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "canManage", + "columnName": "manage", + "affinity": "INTEGER", + "notNull": false + } + ], + "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`)" + } + ], + "foreignKeys": [] + }, + { + "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", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "user_id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "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", + "notNull": false + }, + { + "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`)" + } + ], + "foreignKeys": [] + }, + { + "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`)" + } + ], + "foreignKeys": [] + } + ], + "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, 'ee158c483edfe5102504670f3d9845d4')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/database/VaultDatabase.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/database/VaultDatabase.kt index 19dcdc75d..8c7ca5cbf 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/database/VaultDatabase.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/database/VaultDatabase.kt @@ -26,7 +26,7 @@ import com.x8bit.bitwarden.data.vault.datasource.disk.entity.SendEntity FolderEntity::class, SendEntity::class, ], - version = 5, + version = 6, exportSchema = true, ) @TypeConverters(ZonedDateTimeTypeConverter::class) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/entity/CollectionEntity.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/entity/CollectionEntity.kt index 5370642f9..15aaf69dd 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/entity/CollectionEntity.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/disk/entity/CollectionEntity.kt @@ -32,5 +32,5 @@ data class CollectionEntity( val isReadOnly: Boolean, @ColumnInfo(name = "manage") - val canManage: Boolean, + val canManage: Boolean?, ) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/SyncResponseJson.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/SyncResponseJson.kt index a0a309fe1..046747407 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/SyncResponseJson.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/SyncResponseJson.kt @@ -976,6 +976,6 @@ data class SyncResponseJson( val id: String, @SerialName("manage") - val canManage: Boolean, + val canManage: Boolean?, ) } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensions.kt index 42d9e373e..1d2283f33 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensions.kt @@ -17,7 +17,7 @@ fun SyncResponseJson.Collection.toEncryptedSdkCollection(): Collection = externalId = this.externalId, hidePasswords = this.shouldHidePasswords, readOnly = this.isReadOnly, - manage = this.canManage, + manage = this.canManage ?: !this.isReadOnly, ) /** diff --git a/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensionsTest.kt index 490cab5f6..90d4796d5 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensionsTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/util/VaultSdkCollectionExtensionsTest.kt @@ -32,6 +32,31 @@ class VaultSdkCollectionExtensionsTest { ) } + @Test + fun `toEncryptedSdkCollection should default manage to !isReadOnly if canManage is null`() { + assertEquals( + Collection( + organizationId = "organizationId", + hidePasswords = true, + name = "name", + externalId = "externalId", + readOnly = false, + id = "id", + manage = true, + ), + SyncResponseJson.Collection( + organizationId = "organizationId", + shouldHidePasswords = true, + name = "name", + externalId = "externalId", + isReadOnly = false, + id = "id", + canManage = null, + ) + .toEncryptedSdkCollection(), + ) + } + @Suppress("MaxLineLength") @Test fun `toEncryptedSdkCollectionList should convert a list of network Collections to a list of SDK Collections`() {