Skip to content
Open
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
1,303 changes: 1,303 additions & 0 deletions app/schemas/com.nextcloud.client.database.NextcloudDatabase/99.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.nextcloud.client.core.Clock
import com.nextcloud.client.core.ClockImpl
import com.nextcloud.client.database.dao.ArbitraryDataDao
import com.nextcloud.client.database.dao.AssistantDao
import com.nextcloud.client.database.dao.CapabilityDao
import com.nextcloud.client.database.dao.FileDao
import com.nextcloud.client.database.dao.FileSystemDao
import com.nextcloud.client.database.dao.OfflineOperationDao
Expand All @@ -39,6 +40,7 @@ import com.nextcloud.client.database.entity.VirtualEntity
import com.nextcloud.client.database.migrations.DatabaseMigrationUtil
import com.nextcloud.client.database.migrations.MIGRATION_88_89
import com.nextcloud.client.database.migrations.MIGRATION_97_98
import com.nextcloud.client.database.migrations.MIGRATION_98_99
import com.nextcloud.client.database.migrations.Migration67to68
import com.nextcloud.client.database.migrations.RoomMigration
import com.nextcloud.client.database.migrations.addLegacyMigrations
Expand Down Expand Up @@ -94,7 +96,8 @@ import com.owncloud.android.db.ProviderMeta
AutoMigration(from = 94, to = 95, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class),
AutoMigration(from = 95, to = 96),
AutoMigration(from = 96, to = 97, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class)
// manual migration used for 97 to 98
// manual migration used for 97 to 98,
// manual migration used for 98 to 99
],
exportSchema = true
)
Expand All @@ -111,6 +114,7 @@ abstract class NextcloudDatabase : RoomDatabase() {
abstract fun syncedFolderDao(): SyncedFolderDao
abstract fun assistantDao(): AssistantDao
abstract fun shareDao(): ShareDao
abstract fun capabilityDao(): CapabilityDao

companion object {
const val FIRST_ROOM_DB_VERSION = 65
Expand All @@ -133,6 +137,7 @@ abstract class NextcloudDatabase : RoomDatabase() {
.addMigrations(Migration67to68())
.addMigrations(MIGRATION_88_89)
.addMigrations(MIGRATION_97_98)
.addMigrations(MIGRATION_98_99)
.build()
}
return instance!!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.client.database.dao

import androidx.room.Dao
import androidx.room.Query
import com.nextcloud.client.database.entity.CapabilityEntity

@Dao
interface CapabilityDao {

@Query("SELECT * FROM capabilities WHERE account = :accountName LIMIT 1")
suspend fun getByAccountName(accountName: String): CapabilityEntity?
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
import com.owncloud.android.lib.resources.status.CapabilityBooleanType
import com.owncloud.android.lib.resources.status.E2EVersion
import com.owncloud.android.lib.resources.status.OCCapability

@Entity(tableName = ProviderTableMeta.CAPABILITIES_TABLE_NAME)
data class CapabilityEntity(
Expand Down Expand Up @@ -124,13 +127,13 @@ data class CapabilityEntity(
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SECURITY_GUARD)
val securityGuard: Int?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAME_CHARACTERS)
val forbiddenFileNameCharacters: Int?,
val forbiddenFileNameCharacters: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAMES)
val forbiddenFileNames: Int?,
val forbiddenFileNames: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_EXTENSIONS)
val forbiddenFileNameExtensions: Int?,
val forbiddenFileNameExtensions: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_BASE_NAMES)
val forbiddenFilenameBaseNames: Int?,
val forbiddenFilenameBaseNames: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_DOWNLOAD_LIMIT)
val filesDownloadLimit: Int?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_DOWNLOAD_LIMIT_DEFAULT)
Expand All @@ -150,3 +153,85 @@ data class CapabilityEntity(
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_CLIENT_INTEGRATION_JSON)
val clientIntegrationJson: String?
)

@Suppress("LongMethod", "ReturnCount")
fun CapabilityEntity?.toOCCapability(): OCCapability {
val capability = OCCapability()
if (this == null) return capability
val id = this.id ?: return capability

fun intToBoolean(value: Int?): CapabilityBooleanType =
value?.let { CapabilityBooleanType.fromValue(it) } ?: CapabilityBooleanType.UNKNOWN

capability.id = id.toLong()
capability.accountName = this.accountName
capability.versionMayor = this.versionMajor ?: 0
capability.versionMinor = this.versionMinor ?: 0
capability.versionMicro = this.versionMicro ?: 0
capability.versionString = this.versionString
capability.versionEdition = this.versionEditor
capability.extendedSupport = intToBoolean(this.extendedSupport)
capability.corePollInterval = this.corePollinterval ?: 0
capability.filesSharingApiEnabled = intToBoolean(this.sharingApiEnabled)
capability.filesSharingPublicEnabled = intToBoolean(this.sharingPublicEnabled)
capability.filesSharingPublicPasswordEnforced = intToBoolean(this.sharingPublicPasswordEnforced)
capability.filesSharingPublicAskForOptionalPassword = intToBoolean(this.sharingPublicAskForOptionalPassword)
capability.filesSharingPublicExpireDateEnabled = intToBoolean(this.sharingPublicExpireDateEnabled)
capability.filesSharingPublicExpireDateDays = this.sharingPublicExpireDateDays ?: 0
capability.filesSharingPublicExpireDateEnforced = intToBoolean(this.sharingPublicExpireDateEnforced)
capability.filesSharingPublicSendMail = intToBoolean(this.sharingPublicSendMail)
capability.filesSharingPublicUpload = intToBoolean(this.sharingPublicUpload)
capability.filesSharingUserSendMail = intToBoolean(this.sharingUserSendMail)
capability.filesSharingResharing = intToBoolean(this.sharingResharing)
capability.filesSharingFederationOutgoing = intToBoolean(this.sharingFederationOutgoing)
capability.filesSharingFederationIncoming = intToBoolean(this.sharingFederationIncoming)
capability.filesBigFileChunking = intToBoolean(this.filesBigfilechunking)
capability.filesUndelete = intToBoolean(this.filesUndelete)
capability.filesVersioning = intToBoolean(this.filesVersioning)
capability.externalLinks = intToBoolean(this.externalLinks)
capability.serverName = this.serverName
capability.serverColor = this.serverColor
capability.serverTextColor = this.serverTextColor
capability.serverElementColor = this.serverElementColor
capability.serverSlogan = this.serverSlogan
capability.serverLogo = this.serverLogo
capability.serverBackground = this.serverBackgroundUrl
capability.endToEndEncryption = intToBoolean(this.endToEndEncryption)
capability.endToEndEncryptionKeysExist = intToBoolean(this.endToEndEncryptionKeysExist)
capability.endToEndEncryptionApiVersion = this.endToEndEncryptionApiVersion?.let {
E2EVersion.fromValue(it)
} ?: E2EVersion.UNKNOWN
capability.serverBackgroundDefault = intToBoolean(this.serverBackgroundDefault)
capability.serverBackgroundPlain = intToBoolean(this.serverBackgroundPlain)
capability.activity = intToBoolean(this.activity)
capability.richDocuments = intToBoolean(this.richdocument)
capability.richDocumentsDirectEditing = intToBoolean(this.richdocumentDirectEditing)
capability.richDocumentsTemplatesAvailable = intToBoolean(this.richdocumentTemplates)
capability.richDocumentsMimeTypeList = this.richdocumentMimetypeList?.split(",") ?: emptyList()
capability.richDocumentsOptionalMimeTypeList = this.richdocumentOptionalMimetypeList?.split(",") ?: emptyList()
capability.richDocumentsProductName = this.richdocumentProductName
capability.directEditingEtag = this.directEditingEtag
capability.etag = this.etag
capability.userStatus = intToBoolean(this.userStatus)
capability.userStatusSupportsEmoji = intToBoolean(this.userStatusSupportsEmoji)
capability.userStatusSupportsBusy = intToBoolean(this.userStatusSupportsBusy)
capability.filesLockingVersion = this.filesLockingVersion
capability.assistant = intToBoolean(this.assistant)
capability.groupfolders = intToBoolean(this.groupfolders)
capability.dropAccount = intToBoolean(this.dropAccount)
capability.securityGuard = intToBoolean(this.securityGuard)
capability.forbiddenFilenameCharactersJson = this.forbiddenFileNameCharacters
capability.forbiddenFilenamesJson = this.forbiddenFileNames
capability.forbiddenFilenameExtensionJson = this.forbiddenFileNameExtensions
capability.forbiddenFilenameBaseNamesJson = this.forbiddenFilenameBaseNames
capability.isWCFEnabled = intToBoolean(this.isWCFEnabled)
capability.filesDownloadLimit = intToBoolean(this.filesDownloadLimit)
capability.filesDownloadLimitDefault = this.filesDownloadLimitDefault ?: 0
capability.recommendations = intToBoolean(this.recommendation)
capability.notesFolderPath = this.notesFolderPath
capability.defaultPermissions = this.defaultPermissions ?: 0
capability.hasValidSubscription = intToBoolean(this.hasValidSubscription)
capability.clientIntegrationJson = this.clientIntegrationJson

return capability
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.client.database.migrations

import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase

@Suppress("MagicNumber", "LongMethod")
val MIGRATION_98_99 = object : Migration(98, 99) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("DROP TABLE IF EXISTS capabilities")

db.execSQL(
"""
CREATE TABLE IF NOT EXISTS capabilities (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
account TEXT,
version_mayor INTEGER,
version_minor INTEGER,
version_micro INTEGER,
version_string TEXT,
version_edition TEXT,
extended_support INTEGER,
core_pollinterval INTEGER,
sharing_api_enabled INTEGER,
sharing_public_enabled INTEGER,
sharing_public_password_enforced INTEGER,
sharing_public_ask_for_optional_password INTEGER,
sharing_public_expire_date_enabled INTEGER,
sharing_public_expire_date_days INTEGER,
sharing_public_expire_date_enforced INTEGER,
sharing_public_send_mail INTEGER,
sharing_public_upload INTEGER,
sharing_user_send_mail INTEGER,
sharing_resharing INTEGER,
sharing_federation_outgoing INTEGER,
sharing_federation_incoming INTEGER,
files_bigfilechunking INTEGER,
files_undelete INTEGER,
files_versioning INTEGER,
files_locking_version TEXT,
external_links INTEGER,
server_name TEXT,
server_color TEXT,
server_text_color TEXT,
server_element_color TEXT,
background_url TEXT,
server_slogan TEXT,
server_logo TEXT,
background_default INTEGER,
background_plain INTEGER,
end_to_end_encryption INTEGER,
end_to_end_encryption_keys_exist INTEGER,
end_to_end_encryption_api_version TEXT,
activity INTEGER,
richdocument INTEGER,
recommendation INTEGER,
richdocument_mimetype_list TEXT,
richdocument_optional_mimetype_list TEXT,
richdocument_direct_editing INTEGER,
richdocument_direct_templates INTEGER,
richdocument_product_name TEXT,
direct_editing_etag TEXT,
etag TEXT,
user_status INTEGER,
user_status_supports_emoji INTEGER,
user_status_supports_busy INTEGER,
assistant INTEGER,
groupfolders INTEGER,
drop_account INTEGER,
security_guard INTEGER,
forbidden_filename_characters TEXT,
forbidden_filenames TEXT,
forbidden_filename_extensions TEXT,
forbidden_filename_basenames TEXT,
windows_compatible_filenames INTEGER,
files_download_limit INTEGER,
files_download_limit_default INTEGER,
notes_folder_path TEXT,
default_permissions INTEGER,
has_valid_subscription INTEGER,
client_integration_json TEXT
)
""".trimIndent()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

package com.nextcloud.utils.extensions

import com.nextcloud.client.database.entity.toOCCapability
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.resources.shares.OCShare
import com.owncloud.android.lib.resources.status.OCCapability
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

Expand Down Expand Up @@ -48,3 +50,6 @@ fun FileDataStorageManager.getNonEncryptedSubfolders(id: Long, accountName: Stri
fileDao.getNonEncryptedSubfolders(id, accountName).map {
createFileInstance(it)
}

suspend fun FileDataStorageManager.getCapabilitiesByAccountName(accountName: String): OCCapability =
capabilityDao.getByAccountName(accountName).toOCCapability()
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.nextcloud.android.lib.resources.files.FileDownloadLimit;
import com.nextcloud.client.account.User;
import com.nextcloud.client.database.NextcloudDatabase;
import com.nextcloud.client.database.dao.CapabilityDao;
import com.nextcloud.client.database.dao.FileDao;
import com.nextcloud.client.database.dao.OfflineOperationDao;
import com.nextcloud.client.database.dao.RecommendedFileDao;
Expand Down Expand Up @@ -110,6 +111,7 @@ public class FileDataStorageManager {
public final OfflineOperationDao offlineOperationDao = NextcloudDatabase.getInstance(MainApp.getAppContext()).offlineOperationDao();
public final FileDao fileDao = NextcloudDatabase.getInstance(MainApp.getAppContext()).fileDao();
public final ShareDao shareDao = NextcloudDatabase.getInstance(MainApp.getAppContext()).shareDao();
public final CapabilityDao capabilityDao = NextcloudDatabase.instance().capabilityDao();

private final Gson gson = new Gson();
public final OfflineOperationsRepositoryType offlineOperationsRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/
public class ProviderMeta {
public static final String DB_NAME = "filelist";
public static final int DB_VERSION = 98;
public static final int DB_VERSION = 99;

private ProviderMeta() {
// No instance
Expand Down
Loading