Skip to content
Draft
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,55 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.externalstorage

import com.nextcloud.android.lib.resources.externalstorage.model.ExternalStorageMount
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.GetMethod
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.ocs.OcsKotlinResponse
import com.owncloud.android.lib.ocs.ocsJson
import com.owncloud.android.lib.resources.OCSRemoteOperation
import kotlinx.serialization.SerializationException
import org.apache.commons.httpclient.HttpStatus
import java.io.IOException

class ExternalStorageListMountsRemoteOperation : OCSRemoteOperation<List<ExternalStorageMount>>() {
override fun run(client: NextcloudClient): RemoteOperationResult<List<ExternalStorageMount>> {
val getMethod = GetMethod(client.baseUri.toString() + ENDPOINT + JSON_FORMAT, true)
return try {
val status = client.execute(getMethod)
if (status != HttpStatus.SC_OK) {
Log_OC.e(TAG, "Get external storage mounts failed with status code: $status")
return RemoteOperationResult(false, getMethod)
}
val response =
ocsJson.decodeFromString<OcsKotlinResponse<List<ExternalStorageMount>>>(
getMethod.getResponseBodyAsString()
)
val data = response.ocs.data
RemoteOperationResult<List<ExternalStorageMount>>(true, getMethod).apply { resultData = data }
} catch (e: IOException) {
failure(e)
} catch (e: SerializationException) {
failure(e)
} finally {
getMethod.releaseConnection()
}
}

private fun failure(e: Exception): RemoteOperationResult<List<ExternalStorageMount>> =
RemoteOperationResult<List<ExternalStorageMount>>(e).also {
Log_OC.e(TAG, "Get external storage mounts failed: $e")
}

companion object {
private val TAG = ExternalStorageListMountsRemoteOperation::class.java.simpleName
private const val ENDPOINT = "/ocs/v2.php/apps/files_external/api/v1/mounts"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.externalstorage.model

/**
* Auth mechanisms registered by External Storage app.
* Represents the way an external storage mount is authenticated.
*
* I.e.:
* PasswordUserProvided --> User has to provide its credentials the first time the share is opened
* PasswordGlobal --> The admin provides the credentials and the user finds the share already mounted
* etc...
*/
enum class AuthMechanism(
val identifier: String
) {
Null("null::null"),
Builtin("builtin::builtin"),
Password("password::password"),
PasswordSessionCredentials("password::sessioncredentials"),
PasswordLoginCredentials("password::logincredentials"),
PasswordUserProvided("password::userprovided"),
PasswordGlobal("password::global"),
PasswordGlobalUser("password::global::user"),
PublicKeyRsa("publickey::rsa"),
PublicKeyRsaPrivate("publickey::rsa_private"),
AmazonS3AccessKey("amazons3::accesskey"),
OpenStack("openstack::openstack"),
OpenStackV3("openstack::openstackv3"),
OpenStackRackspace("openstack::rackspace"),
SmbKerberos("smb::kerberos"),
SmbKerberosApache("smb::kerberosapache"),
Unknown("");

companion object {
fun fromIdentifier(identifier: String): AuthMechanism =
entries.firstOrNull { it != Unknown && it.identifier == identifier } ?: Unknown
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.externalstorage.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Subset of the mount's `config` object.
*/
@Serializable
data class ExternalStorageConfig(
// kept raw: identifiers from apps registering their own mechanisms map to Unknown instead of failing
@SerialName("authMechanism")
private val authMechanismIdentifier: String
) {
val authMechanism: AuthMechanism
get() = AuthMechanism.fromIdentifier(authMechanismIdentifier)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.externalstorage.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* A mount returned by `files_external`: [name] is the mount folder, [path] its parent folder
* relative to the user's root (empty when mounted at the root), [backend] the human-readable backend
* name and [backendClass] its identifier (e.g. `smb`, `sftp`). [config] is null on servers that
* don't send it.
*/
@Serializable
data class ExternalStorageMount(
val id: Long,
val name: String,
val path: String,
val type: String,
val backend: String,
@SerialName("class")
val backendClass: String,
val scope: MountScope,
val permissions: Int,
val config: ExternalStorageConfig? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.externalstorage.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
enum class MountScope {
@SerialName("system")
SYSTEM,

@SerialName("personal")
PERSONAL
}
Loading