Skip to content

Commit cea3158

Browse files
Merge pull request #16781 from nextcloud/fix/oc-capability-entry-type
fix(oc-capability): uses correct room field types
2 parents 3b90fb1 + bb4c135 commit cea3158

8 files changed

Lines changed: 1522 additions & 6 deletions

File tree

app/schemas/com.nextcloud.client.database.NextcloudDatabase/100.json

Lines changed: 1308 additions & 0 deletions
Large diffs are not rendered by default.

app/src/main/java/com/nextcloud/client/database/NextcloudDatabase.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import com.nextcloud.client.core.Clock
1717
import com.nextcloud.client.core.ClockImpl
1818
import com.nextcloud.client.database.dao.ArbitraryDataDao
1919
import com.nextcloud.client.database.dao.AssistantDao
20+
import com.nextcloud.client.database.dao.CapabilityDao
2021
import com.nextcloud.client.database.dao.FileDao
2122
import com.nextcloud.client.database.dao.FileSystemDao
2223
import com.nextcloud.client.database.dao.OfflineOperationDao
@@ -39,6 +40,7 @@ import com.nextcloud.client.database.entity.VirtualEntity
3940
import com.nextcloud.client.database.migrations.DatabaseMigrationUtil
4041
import com.nextcloud.client.database.migrations.MIGRATION_88_89
4142
import com.nextcloud.client.database.migrations.MIGRATION_97_98
43+
import com.nextcloud.client.database.migrations.MIGRATION_99_100
4244
import com.nextcloud.client.database.migrations.Migration67to68
4345
import com.nextcloud.client.database.migrations.RoomMigration
4446
import com.nextcloud.client.database.migrations.addLegacyMigrations
@@ -95,7 +97,8 @@ import com.owncloud.android.db.ProviderMeta
9597
AutoMigration(from = 95, to = 96),
9698
AutoMigration(from = 96, to = 97, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class),
9799
// manual migration used for 97 to 98
98-
AutoMigration(from = 98, to = 99)
100+
AutoMigration(from = 98, to = 99),
101+
// manual migration used for 99 to 100
99102
],
100103
exportSchema = true
101104
)
@@ -112,6 +115,7 @@ abstract class NextcloudDatabase : RoomDatabase() {
112115
abstract fun syncedFolderDao(): SyncedFolderDao
113116
abstract fun assistantDao(): AssistantDao
114117
abstract fun shareDao(): ShareDao
118+
abstract fun capabilityDao(): CapabilityDao
115119

116120
companion object {
117121
const val FIRST_ROOM_DB_VERSION = 65
@@ -134,6 +138,7 @@ abstract class NextcloudDatabase : RoomDatabase() {
134138
.addMigrations(Migration67to68())
135139
.addMigrations(MIGRATION_88_89)
136140
.addMigrations(MIGRATION_97_98)
141+
.addMigrations(MIGRATION_99_100)
137142
.build()
138143
}
139144
return instance!!
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Nextcloud - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
package com.nextcloud.client.database.dao
9+
10+
import androidx.room.Dao
11+
import androidx.room.Query
12+
import com.nextcloud.client.database.entity.CapabilityEntity
13+
14+
@Dao
15+
interface CapabilityDao {
16+
17+
@Query("SELECT * FROM capabilities WHERE account = :accountName LIMIT 1")
18+
suspend fun getByAccountName(accountName: String): CapabilityEntity?
19+
}

app/src/main/java/com/nextcloud/client/database/entity/CapabilityEntity.kt

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import androidx.room.ColumnInfo
1111
import androidx.room.Entity
1212
import androidx.room.PrimaryKey
1313
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
14+
import com.owncloud.android.lib.resources.status.CapabilityBooleanType
15+
import com.owncloud.android.lib.resources.status.E2EVersion
16+
import com.owncloud.android.lib.resources.status.OCCapability
1417

1518
@Entity(tableName = ProviderTableMeta.CAPABILITIES_TABLE_NAME)
1619
data class CapabilityEntity(
@@ -124,13 +127,13 @@ data class CapabilityEntity(
124127
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SECURITY_GUARD)
125128
val securityGuard: Int?,
126129
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAME_CHARACTERS)
127-
val forbiddenFileNameCharacters: Int?,
130+
val forbiddenFileNameCharacters: String?,
128131
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAMES)
129-
val forbiddenFileNames: Int?,
132+
val forbiddenFileNames: String?,
130133
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_EXTENSIONS)
131-
val forbiddenFileNameExtensions: Int?,
134+
val forbiddenFileNameExtensions: String?,
132135
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_BASE_NAMES)
133-
val forbiddenFilenameBaseNames: Int?,
136+
val forbiddenFilenameBaseNames: String?,
134137
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_DOWNLOAD_LIMIT)
135138
val filesDownloadLimit: Int?,
136139
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_DOWNLOAD_LIMIT_DEFAULT)
@@ -150,3 +153,85 @@ data class CapabilityEntity(
150153
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_CLIENT_INTEGRATION_JSON)
151154
val clientIntegrationJson: String?
152155
)
156+
157+
@Suppress("LongMethod", "ReturnCount")
158+
fun CapabilityEntity?.toOCCapability(): OCCapability {
159+
val capability = OCCapability()
160+
if (this == null) return capability
161+
val id = this.id ?: return capability
162+
163+
fun intToBoolean(value: Int?): CapabilityBooleanType =
164+
value?.let { CapabilityBooleanType.fromValue(it) } ?: CapabilityBooleanType.UNKNOWN
165+
166+
capability.id = id.toLong()
167+
capability.accountName = this.accountName
168+
capability.versionMayor = this.versionMajor ?: 0
169+
capability.versionMinor = this.versionMinor ?: 0
170+
capability.versionMicro = this.versionMicro ?: 0
171+
capability.versionString = this.versionString
172+
capability.versionEdition = this.versionEditor
173+
capability.extendedSupport = intToBoolean(this.extendedSupport)
174+
capability.corePollInterval = this.corePollinterval ?: 0
175+
capability.filesSharingApiEnabled = intToBoolean(this.sharingApiEnabled)
176+
capability.filesSharingPublicEnabled = intToBoolean(this.sharingPublicEnabled)
177+
capability.filesSharingPublicPasswordEnforced = intToBoolean(this.sharingPublicPasswordEnforced)
178+
capability.filesSharingPublicAskForOptionalPassword = intToBoolean(this.sharingPublicAskForOptionalPassword)
179+
capability.filesSharingPublicExpireDateEnabled = intToBoolean(this.sharingPublicExpireDateEnabled)
180+
capability.filesSharingPublicExpireDateDays = this.sharingPublicExpireDateDays ?: 0
181+
capability.filesSharingPublicExpireDateEnforced = intToBoolean(this.sharingPublicExpireDateEnforced)
182+
capability.filesSharingPublicSendMail = intToBoolean(this.sharingPublicSendMail)
183+
capability.filesSharingPublicUpload = intToBoolean(this.sharingPublicUpload)
184+
capability.filesSharingUserSendMail = intToBoolean(this.sharingUserSendMail)
185+
capability.filesSharingResharing = intToBoolean(this.sharingResharing)
186+
capability.filesSharingFederationOutgoing = intToBoolean(this.sharingFederationOutgoing)
187+
capability.filesSharingFederationIncoming = intToBoolean(this.sharingFederationIncoming)
188+
capability.filesBigFileChunking = intToBoolean(this.filesBigfilechunking)
189+
capability.filesUndelete = intToBoolean(this.filesUndelete)
190+
capability.filesVersioning = intToBoolean(this.filesVersioning)
191+
capability.externalLinks = intToBoolean(this.externalLinks)
192+
capability.serverName = this.serverName
193+
capability.serverColor = this.serverColor
194+
capability.serverTextColor = this.serverTextColor
195+
capability.serverElementColor = this.serverElementColor
196+
capability.serverSlogan = this.serverSlogan
197+
capability.serverLogo = this.serverLogo
198+
capability.serverBackground = this.serverBackgroundUrl
199+
capability.endToEndEncryption = intToBoolean(this.endToEndEncryption)
200+
capability.endToEndEncryptionKeysExist = intToBoolean(this.endToEndEncryptionKeysExist)
201+
capability.endToEndEncryptionApiVersion = this.endToEndEncryptionApiVersion?.let {
202+
E2EVersion.fromValue(it)
203+
} ?: E2EVersion.UNKNOWN
204+
capability.serverBackgroundDefault = intToBoolean(this.serverBackgroundDefault)
205+
capability.serverBackgroundPlain = intToBoolean(this.serverBackgroundPlain)
206+
capability.activity = intToBoolean(this.activity)
207+
capability.richDocuments = intToBoolean(this.richdocument)
208+
capability.richDocumentsDirectEditing = intToBoolean(this.richdocumentDirectEditing)
209+
capability.richDocumentsTemplatesAvailable = intToBoolean(this.richdocumentTemplates)
210+
capability.richDocumentsMimeTypeList = this.richdocumentMimetypeList?.split(",") ?: emptyList()
211+
capability.richDocumentsOptionalMimeTypeList = this.richdocumentOptionalMimetypeList?.split(",") ?: emptyList()
212+
capability.richDocumentsProductName = this.richdocumentProductName
213+
capability.directEditingEtag = this.directEditingEtag
214+
capability.etag = this.etag
215+
capability.userStatus = intToBoolean(this.userStatus)
216+
capability.userStatusSupportsEmoji = intToBoolean(this.userStatusSupportsEmoji)
217+
capability.userStatusSupportsBusy = intToBoolean(this.userStatusSupportsBusy)
218+
capability.filesLockingVersion = this.filesLockingVersion
219+
capability.assistant = intToBoolean(this.assistant)
220+
capability.groupfolders = intToBoolean(this.groupfolders)
221+
capability.dropAccount = intToBoolean(this.dropAccount)
222+
capability.securityGuard = intToBoolean(this.securityGuard)
223+
capability.forbiddenFilenameCharactersJson = this.forbiddenFileNameCharacters
224+
capability.forbiddenFilenamesJson = this.forbiddenFileNames
225+
capability.forbiddenFilenameExtensionJson = this.forbiddenFileNameExtensions
226+
capability.forbiddenFilenameBaseNamesJson = this.forbiddenFilenameBaseNames
227+
capability.isWCFEnabled = intToBoolean(this.isWCFEnabled)
228+
capability.filesDownloadLimit = intToBoolean(this.filesDownloadLimit)
229+
capability.filesDownloadLimitDefault = this.filesDownloadLimitDefault ?: 0
230+
capability.recommendations = intToBoolean(this.recommendation)
231+
capability.notesFolderPath = this.notesFolderPath
232+
capability.defaultPermissions = this.defaultPermissions ?: 0
233+
capability.hasValidSubscription = intToBoolean(this.hasValidSubscription)
234+
capability.clientIntegrationJson = this.clientIntegrationJson
235+
236+
return capability
237+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Nextcloud - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
package com.nextcloud.client.database.migrations
9+
10+
import androidx.room.migration.Migration
11+
import androidx.sqlite.db.SupportSQLiteDatabase
12+
13+
@Suppress("MagicNumber", "LongMethod")
14+
val MIGRATION_99_100 = object : Migration(99, 100) {
15+
override fun migrate(db: SupportSQLiteDatabase) {
16+
db.execSQL("DROP TABLE IF EXISTS capabilities")
17+
18+
db.execSQL(
19+
"""
20+
CREATE TABLE IF NOT EXISTS capabilities (
21+
_id INTEGER PRIMARY KEY AUTOINCREMENT,
22+
account TEXT,
23+
version_mayor INTEGER,
24+
version_minor INTEGER,
25+
version_micro INTEGER,
26+
version_string TEXT,
27+
version_edition TEXT,
28+
extended_support INTEGER,
29+
core_pollinterval INTEGER,
30+
sharing_api_enabled INTEGER,
31+
sharing_public_enabled INTEGER,
32+
sharing_public_password_enforced INTEGER,
33+
sharing_public_ask_for_optional_password INTEGER,
34+
sharing_public_expire_date_enabled INTEGER,
35+
sharing_public_expire_date_days INTEGER,
36+
sharing_public_expire_date_enforced INTEGER,
37+
sharing_public_send_mail INTEGER,
38+
sharing_public_upload INTEGER,
39+
sharing_user_send_mail INTEGER,
40+
sharing_resharing INTEGER,
41+
sharing_federation_outgoing INTEGER,
42+
sharing_federation_incoming INTEGER,
43+
files_bigfilechunking INTEGER,
44+
files_undelete INTEGER,
45+
files_versioning INTEGER,
46+
files_locking_version TEXT,
47+
external_links INTEGER,
48+
server_name TEXT,
49+
server_color TEXT,
50+
server_text_color TEXT,
51+
server_element_color TEXT,
52+
background_url TEXT,
53+
server_slogan TEXT,
54+
server_logo TEXT,
55+
background_default INTEGER,
56+
background_plain INTEGER,
57+
end_to_end_encryption INTEGER,
58+
end_to_end_encryption_keys_exist INTEGER,
59+
end_to_end_encryption_api_version TEXT,
60+
activity INTEGER,
61+
richdocument INTEGER,
62+
recommendation INTEGER,
63+
richdocument_mimetype_list TEXT,
64+
richdocument_optional_mimetype_list TEXT,
65+
richdocument_direct_editing INTEGER,
66+
richdocument_direct_templates INTEGER,
67+
richdocument_product_name TEXT,
68+
direct_editing_etag TEXT,
69+
etag TEXT,
70+
user_status INTEGER,
71+
user_status_supports_emoji INTEGER,
72+
user_status_supports_busy INTEGER,
73+
assistant INTEGER,
74+
groupfolders INTEGER,
75+
drop_account INTEGER,
76+
security_guard INTEGER,
77+
forbidden_filename_characters TEXT,
78+
forbidden_filenames TEXT,
79+
forbidden_filename_extensions TEXT,
80+
forbidden_filename_basenames TEXT,
81+
windows_compatible_filenames INTEGER,
82+
files_download_limit INTEGER,
83+
files_download_limit_default INTEGER,
84+
notes_folder_path TEXT,
85+
default_permissions INTEGER,
86+
has_valid_subscription INTEGER,
87+
client_integration_json TEXT
88+
)
89+
""".trimIndent()
90+
)
91+
}
92+
}

app/src/main/java/com/nextcloud/utils/extensions/FileDataStorageManagerExtensions.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
package com.nextcloud.utils.extensions
99

10+
import com.nextcloud.client.database.entity.toOCCapability
1011
import com.owncloud.android.datamodel.FileDataStorageManager
1112
import com.owncloud.android.datamodel.OCFile
1213
import com.owncloud.android.lib.resources.shares.OCShare
14+
import com.owncloud.android.lib.resources.status.OCCapability
1315
import kotlinx.coroutines.Dispatchers
1416
import kotlinx.coroutines.withContext
1517

@@ -48,3 +50,6 @@ fun FileDataStorageManager.getNonEncryptedSubfolders(id: Long, accountName: Stri
4850
fileDao.getNonEncryptedSubfolders(id, accountName).map {
4951
createFileInstance(it)
5052
}
53+
54+
suspend fun FileDataStorageManager.getCapabilitiesByAccountName(accountName: String): OCCapability =
55+
capabilityDao.getByAccountName(accountName).toOCCapability()

app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.nextcloud.android.lib.resources.files.FileDownloadLimit;
3535
import com.nextcloud.client.account.User;
3636
import com.nextcloud.client.database.NextcloudDatabase;
37+
import com.nextcloud.client.database.dao.CapabilityDao;
3738
import com.nextcloud.client.database.dao.FileDao;
3839
import com.nextcloud.client.database.dao.OfflineOperationDao;
3940
import com.nextcloud.client.database.dao.RecommendedFileDao;
@@ -112,6 +113,7 @@ public class FileDataStorageManager {
112113
public final OfflineOperationDao offlineOperationDao = NextcloudDatabase.getInstance(MainApp.getAppContext()).offlineOperationDao();
113114
public final FileDao fileDao = NextcloudDatabase.getInstance(MainApp.getAppContext()).fileDao();
114115
public final ShareDao shareDao = NextcloudDatabase.getInstance(MainApp.getAppContext()).shareDao();
116+
public final CapabilityDao capabilityDao = NextcloudDatabase.instance().capabilityDao();
115117

116118
private final Gson gson = new Gson();
117119
public final OfflineOperationsRepositoryType offlineOperationsRepository;

app/src/main/java/com/owncloud/android/db/ProviderMeta.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
public class ProviderMeta {
2525
public static final String DB_NAME = "filelist";
26-
public static final int DB_VERSION = 99;
26+
public static final int DB_VERSION = 100;
2727

2828
private ProviderMeta() {
2929
// No instance

0 commit comments

Comments
 (0)