mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-09 17:06:18 +00:00
commit
c36096d08c
@ -1,6 +1,6 @@
|
||||
buildscript {
|
||||
ext {
|
||||
kotlinVersion = '1.3.72'
|
||||
kotlinVersion = '1.4.20'
|
||||
moshiVersion = "1.9.2"
|
||||
}
|
||||
|
||||
@ -9,9 +9,8 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,20 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'kotlin-allopen'
|
||||
|
||||
dependencies {
|
||||
api 'com.squareup.okhttp3:okhttp:4.6.0'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
||||
api 'com.gitlab.ownclouders:dav4android:oc_support_2.1.5'
|
||||
api 'com.github.AppDevNext.Logcat:LogcatCore:2.1.1'
|
||||
api 'net.openid:appauth:0.7.1'
|
||||
api 'com.github.AppDevNext.Logcat:LogcatCore:2.2.2'
|
||||
|
||||
// Moshi
|
||||
implementation ("com.squareup.moshi:moshi-kotlin:$moshiVersion") {
|
||||
exclude module: "kotlin-reflect"
|
||||
}
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion"
|
||||
}
|
||||
|
||||
allOpen {
|
||||
// allows mocking for classes w/o directly opening them for release builds
|
||||
annotation 'com.owncloud.android.lib.testing.OpenClass'
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
}
|
||||
|
||||
android {
|
||||
@ -29,12 +24,8 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
|
||||
versionCode = 10000800
|
||||
versionName = "1.0.8"
|
||||
|
||||
// This is pretty ugly but manifest placeholders don't seem to work very well when using different modules
|
||||
// See https://github.com/openid/AppAuth-Android/issues/325
|
||||
manifestPlaceholders = [appAuthRedirectScheme: '']
|
||||
versionCode = 10000900
|
||||
versionName = "1.0.9"
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
|
@ -57,6 +57,7 @@ public class HttpClient {
|
||||
private static OkHttpClient sOkHttpClient;
|
||||
private static Context sContext;
|
||||
private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>();
|
||||
private static LogInterceptor sLogInterceptor;
|
||||
|
||||
public static OkHttpClient getOkHttpClient() {
|
||||
if (sOkHttpClient == null) {
|
||||
@ -110,6 +111,7 @@ public class HttpClient {
|
||||
};
|
||||
|
||||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
|
||||
.addNetworkInterceptor(getLogInterceptor())
|
||||
.protocols(Arrays.asList(Protocol.HTTP_1_1))
|
||||
.readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||
.writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||
@ -120,6 +122,7 @@ public class HttpClient {
|
||||
.cookieJar(cookieJar);
|
||||
// TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok.
|
||||
//.hostnameVerifier(new BrowserCompatHostnameVerifier());
|
||||
|
||||
sOkHttpClient = clientBuilder.build();
|
||||
|
||||
} catch (Exception e) {
|
||||
@ -137,6 +140,13 @@ public class HttpClient {
|
||||
sContext = context;
|
||||
}
|
||||
|
||||
public static LogInterceptor getLogInterceptor() {
|
||||
if (sLogInterceptor == null) {
|
||||
sLogInterceptor = new LogInterceptor();
|
||||
}
|
||||
return sLogInterceptor;
|
||||
}
|
||||
|
||||
public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) {
|
||||
return sCookieStore.get(httpUrl.host());
|
||||
}
|
||||
|
@ -51,6 +51,14 @@ public class HttpConstants {
|
||||
public static final String ACCEPT_ENCODING_IDENTITY = "identity";
|
||||
public static final String OC_FILE_REMOTE_ID = "OC-FileId";
|
||||
|
||||
/***********************************************************************************************************
|
||||
************************************************ CONTENT TYPES ********************************************
|
||||
***********************************************************************************************************/
|
||||
|
||||
public static final String CONTENT_TYPE_XML = "application/xml";
|
||||
public static final String CONTENT_TYPE_JSON = "application/json";
|
||||
public static final String CONTENT_TYPE_WWW_FORM = "application/x-www-form-urlencoded";
|
||||
|
||||
/***********************************************************************************************************
|
||||
************************************************ STATUS CODES *********************************************
|
||||
***********************************************************************************************************/
|
||||
|
@ -0,0 +1,65 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2020 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.owncloud.android.lib.common.http
|
||||
|
||||
import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_JSON
|
||||
import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_WWW_FORM
|
||||
import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_XML
|
||||
import okhttp3.MediaType
|
||||
import timber.log.Timber
|
||||
import java.util.Locale
|
||||
|
||||
object LogBuilder {
|
||||
fun logHttp(
|
||||
networkPetition: NetworkPetition,
|
||||
networkNode: NetworkNode,
|
||||
requestId: String? = "",
|
||||
description: String
|
||||
) = Timber.d("[Network, $networkPetition] [$networkNode] [$requestId] $description")
|
||||
}
|
||||
|
||||
enum class NetworkPetition {
|
||||
REQUEST, RESPONSE;
|
||||
|
||||
override fun toString(): String = super.toString().toLowerCase(Locale.ROOT)
|
||||
}
|
||||
|
||||
enum class NetworkNode {
|
||||
INFO, HEADER, BODY;
|
||||
|
||||
override fun toString(): String = super.toString().toLowerCase(Locale.ROOT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a media type is loggable.
|
||||
*
|
||||
* @return true if its type is text, xml, json, or x-www-form-urlencoded.
|
||||
*/
|
||||
fun MediaType?.isLoggable(): Boolean =
|
||||
this?.let { mediaType ->
|
||||
val mediaTypeString = mediaType.toString()
|
||||
(mediaType.type == "text" ||
|
||||
mediaTypeString.contains(CONTENT_TYPE_XML) ||
|
||||
mediaTypeString.contains(CONTENT_TYPE_JSON) ||
|
||||
mediaTypeString.contains(CONTENT_TYPE_WWW_FORM))
|
||||
} ?: false
|
@ -0,0 +1,179 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2020 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.common.http
|
||||
|
||||
import com.owncloud.android.lib.common.http.HttpConstants.AUTHORIZATION_HEADER
|
||||
import com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID
|
||||
import com.owncloud.android.lib.common.http.LogBuilder.logHttp
|
||||
import com.owncloud.android.lib.common.http.NetworkNode.BODY
|
||||
import com.owncloud.android.lib.common.http.NetworkNode.HEADER
|
||||
import com.owncloud.android.lib.common.http.NetworkNode.INFO
|
||||
import com.owncloud.android.lib.common.http.NetworkPetition.REQUEST
|
||||
import com.owncloud.android.lib.common.http.NetworkPetition.RESPONSE
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody
|
||||
import okio.Buffer
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.charset.StandardCharsets
|
||||
import kotlin.math.max
|
||||
|
||||
class LogInterceptor : Interceptor {
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
|
||||
if (!httpLogsEnabled) {
|
||||
return chain.proceed(chain.request())
|
||||
}
|
||||
|
||||
val request = chain.request().also {
|
||||
val requestId = it.headers[OC_X_REQUEST_ID]
|
||||
logHttp(REQUEST, INFO, requestId, "Type: ${it.method} URL: ${it.url}")
|
||||
logHeaders(requestId, it.headers, REQUEST)
|
||||
logRequestBody(requestId, it.body)
|
||||
}
|
||||
|
||||
val response = chain.proceed(request)
|
||||
|
||||
return response.also {
|
||||
val requestId = it.request.headers[OC_X_REQUEST_ID]
|
||||
logHttp(
|
||||
RESPONSE,
|
||||
INFO,
|
||||
requestId,
|
||||
"Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}"
|
||||
)
|
||||
logHeaders(requestId, it.headers, RESPONSE)
|
||||
logResponseBody(requestId, it.body)
|
||||
}
|
||||
}
|
||||
|
||||
private fun logHeaders(requestId: String?, headers: Headers, networkPetition: NetworkPetition) {
|
||||
headers.forEach { header ->
|
||||
val headerValue: String = if (header.first.equals(AUTHORIZATION_HEADER, true)) {
|
||||
"[redacted]"
|
||||
} else {
|
||||
header.second
|
||||
}
|
||||
logHttp(networkPetition, HEADER, requestId, "${header.first}: $headerValue")
|
||||
}
|
||||
}
|
||||
|
||||
private fun logRequestBody(requestId: String?, requestBodyParam: RequestBody?) {
|
||||
requestBodyParam?.let { requestBody ->
|
||||
|
||||
if (requestBody.isOneShot()) {
|
||||
logHttp(REQUEST, BODY, requestId, "One shot body -- Omitted")
|
||||
return@let
|
||||
}
|
||||
|
||||
if (requestBody.isDuplex()) {
|
||||
logHttp(REQUEST, BODY, requestId, "Duplex body -- Omitted")
|
||||
return@let
|
||||
}
|
||||
|
||||
val buffer = Buffer()
|
||||
requestBody.writeTo(buffer)
|
||||
|
||||
val contentType = requestBody.contentType()
|
||||
val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8
|
||||
|
||||
logHttp(REQUEST, BODY, requestId, "Length: ${requestBody.contentLength()} byte body")
|
||||
logHttp(REQUEST, BODY, requestId, "Type: ${requestBody.contentType()}")
|
||||
logHttp(REQUEST, BODY, requestId, "--> Body start for request")
|
||||
|
||||
if (contentType.isLoggable()) {
|
||||
if (requestBody.contentLength() < LIMIT_BODY_LOG) {
|
||||
logHttp(REQUEST, BODY, requestId, buffer.readString(charset))
|
||||
} else {
|
||||
logHttp(REQUEST, BODY, requestId, buffer.readString(LIMIT_BODY_LOG, charset))
|
||||
}
|
||||
logHttp(
|
||||
REQUEST,
|
||||
BODY,
|
||||
requestId,
|
||||
"<-- Body end for request -- Omitted: ${max(0, requestBody.contentLength() - LIMIT_BODY_LOG)} bytes"
|
||||
)
|
||||
} else {
|
||||
logHttp(
|
||||
REQUEST,
|
||||
BODY,
|
||||
requestId,
|
||||
"<-- Body end for request -- Binary -- Omitted: ${requestBody.contentLength()} bytes"
|
||||
)
|
||||
}
|
||||
|
||||
} ?: logHttp(REQUEST, BODY, requestId, "Empty body")
|
||||
}
|
||||
|
||||
private fun logResponseBody(requestId: String?, responseBodyParam: ResponseBody?) {
|
||||
responseBodyParam?.let { responseBody ->
|
||||
|
||||
val contentType = responseBody.contentType()
|
||||
val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8
|
||||
|
||||
logHttp(RESPONSE, BODY, requestId, "Length: ${responseBody.contentLength()} byte body")
|
||||
logHttp(RESPONSE, BODY, requestId, "Type: ${responseBody.contentType()}")
|
||||
logHttp(RESPONSE, BODY, requestId, "--> Body start for response")
|
||||
|
||||
val source = responseBody.source()
|
||||
source.request(LIMIT_BODY_LOG)
|
||||
val buffer = source.buffer
|
||||
|
||||
if (contentType.isLoggable()) {
|
||||
|
||||
if (responseBody.contentLength() < LIMIT_BODY_LOG) {
|
||||
logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(charset))
|
||||
} else {
|
||||
logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset))
|
||||
}
|
||||
logHttp(
|
||||
RESPONSE,
|
||||
BODY,
|
||||
requestId,
|
||||
"<-- Body end for response -- Omitted: ${
|
||||
max(
|
||||
0,
|
||||
responseBody.contentLength() - LIMIT_BODY_LOG
|
||||
)
|
||||
} bytes"
|
||||
)
|
||||
} else {
|
||||
logHttp(
|
||||
RESPONSE,
|
||||
BODY,
|
||||
requestId,
|
||||
"<-- Body end for response -- Binary -- Omitted: ${responseBody.contentLength()} bytes"
|
||||
)
|
||||
}
|
||||
} ?: logHttp(RESPONSE, BODY, requestId, "Empty body")
|
||||
}
|
||||
|
||||
companion object {
|
||||
var httpLogsEnabled: Boolean = false
|
||||
private const val LIMIT_BODY_LOG: Long = 1024
|
||||
}
|
||||
}
|
@ -84,18 +84,12 @@ public class ChunkFromFileRequestBody extends FileRequestBody {
|
||||
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
|
||||
while (mChannel.position() < maxCount) {
|
||||
|
||||
Timber.v("Sink buffer size: %s", sink.buffer().size());
|
||||
|
||||
readCount = mChannel.read(mBuffer);
|
||||
|
||||
Timber.v("Read " + readCount + " bytes from file channel to " + mBuffer.toString());
|
||||
|
||||
sink.buffer().write(mBuffer.array(), 0, readCount);
|
||||
sink.getBuffer().write(mBuffer.array(), 0, readCount);
|
||||
|
||||
sink.flush();
|
||||
|
||||
Timber.v("Write " + readCount + " bytes to sink buffer with size " + sink.buffer().size());
|
||||
|
||||
mBuffer.clear();
|
||||
if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks
|
||||
mTransferred += readCount;
|
||||
|
@ -53,6 +53,11 @@ public class FileRequestBody extends RequestBody implements ProgressiveDataTrans
|
||||
mContentType = contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOneShot() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType contentType() {
|
||||
return mContentType;
|
||||
|
@ -21,8 +21,9 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.response
|
||||
package com.owncloud.android.lib.resources
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
// Response retrieved by OCS Rest API, used to obtain capabilities, shares and user info among others.
|
||||
@ -41,6 +42,11 @@ data class OCSResponse<T>(
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class MetaData(
|
||||
val status: String,
|
||||
val statuscode: Int,
|
||||
val message: String?
|
||||
@Json(name = "statuscode")
|
||||
val statusCode: Int,
|
||||
val message: String?,
|
||||
@Json(name = "itemsperpage")
|
||||
val itemsPerPage: String?,
|
||||
@Json(name = "totalitems")
|
||||
val totalItems: String?
|
||||
)
|
@ -30,6 +30,8 @@ import java.io.File;
|
||||
|
||||
public class FileUtils {
|
||||
public static final String FINAL_CHUNKS_FILE = ".file";
|
||||
public static final String MIME_DIR = "DIR";
|
||||
public static final String MIME_DIR_UNIX = "httpd/unix-directory";
|
||||
|
||||
static String getParentPath(String remotePath) {
|
||||
String parentPath = new File(remotePath).getParent();
|
||||
|
@ -29,7 +29,17 @@ import android.os.Parcelable;
|
||||
|
||||
import at.bitfire.dav4jvm.Property;
|
||||
import at.bitfire.dav4jvm.Response;
|
||||
import at.bitfire.dav4jvm.property.*;
|
||||
import at.bitfire.dav4jvm.property.CreationDate;
|
||||
import at.bitfire.dav4jvm.property.GetContentLength;
|
||||
import at.bitfire.dav4jvm.property.GetContentType;
|
||||
import at.bitfire.dav4jvm.property.GetETag;
|
||||
import at.bitfire.dav4jvm.property.GetLastModified;
|
||||
import at.bitfire.dav4jvm.property.OCId;
|
||||
import at.bitfire.dav4jvm.property.OCPermissions;
|
||||
import at.bitfire.dav4jvm.property.OCPrivatelink;
|
||||
import at.bitfire.dav4jvm.property.OCSize;
|
||||
import at.bitfire.dav4jvm.property.QuotaAvailableBytes;
|
||||
import at.bitfire.dav4jvm.property.QuotaUsedBytes;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
@ -83,7 +93,8 @@ public class RemoteFile implements Parcelable, Serializable {
|
||||
/**
|
||||
* Create new {@link RemoteFile} with given path.
|
||||
* <p>
|
||||
* The path received must be URL-decoded. Path separator must be File.separator, and it must be the first character in 'path'.
|
||||
* The path received must be URL-decoded. Path separator must be File.separator, and it must be the first
|
||||
* character in 'path'.
|
||||
*
|
||||
* @param path The remote path of the file.
|
||||
*/
|
||||
@ -95,7 +106,7 @@ public class RemoteFile implements Parcelable, Serializable {
|
||||
mRemotePath = path;
|
||||
mCreationTimestamp = 0;
|
||||
mLength = 0;
|
||||
mMimeType = "DIR";
|
||||
mMimeType = FileUtils.MIME_DIR;
|
||||
mQuotaUsedBytes = BigDecimal.ZERO;
|
||||
mQuotaAvailableBytes = BigDecimal.ZERO;
|
||||
mPrivateLink = null;
|
||||
@ -154,6 +165,14 @@ public class RemoteFile implements Parcelable, Serializable {
|
||||
readFromParcel(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to find out if this file is a folder.
|
||||
*
|
||||
* @return true if it is a folder
|
||||
*/
|
||||
public boolean isFolder() {
|
||||
return mMimeType != null && (mMimeType.equals(FileUtils.MIME_DIR) || mMimeType.equals(FileUtils.MIME_DIR_UNIX));
|
||||
}
|
||||
|
||||
/**
|
||||
* Getters and Setters
|
||||
|
@ -46,9 +46,9 @@ import java.net.URL;
|
||||
|
||||
public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
||||
|
||||
private long mRemoteId;
|
||||
private String mRemoteId;
|
||||
|
||||
public GetRemoteShareOperation(long remoteId) {
|
||||
public GetRemoteShareOperation(String remoteId) {
|
||||
mRemoteId = remoteId;
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult>
|
||||
Uri requestUri = client.getBaseUri();
|
||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||
uriBuilder.appendEncodedPath(Long.toString(mRemoteId));
|
||||
uriBuilder.appendEncodedPath(mRemoteId);
|
||||
|
||||
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author Christian Schabesberger
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
@ -28,16 +29,21 @@
|
||||
|
||||
package com.owncloud.android.lib.resources.shares
|
||||
|
||||
import android.net.Uri
|
||||
import com.owncloud.android.lib.common.OwnCloudClient
|
||||
import com.owncloud.android.lib.common.http.HttpConstants
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK
|
||||
import org.json.JSONObject
|
||||
import com.owncloud.android.lib.resources.CommonOcsResponse
|
||||
import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import timber.log.Timber
|
||||
import java.lang.reflect.Type
|
||||
import java.net.URL
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* Created by masensio on 08/10/2015.
|
||||
@ -65,6 +71,7 @@ import java.util.ArrayList
|
||||
* Status codes:
|
||||
* 100 - successful
|
||||
*
|
||||
* @author Christian Schabesberger
|
||||
* @author masensio
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
@ -78,82 +85,68 @@ class GetRemoteShareesOperation
|
||||
* @param perPage maximum number of results in a single page
|
||||
*/
|
||||
(private val searchString: String, private val page: Int, private val perPage: Int) :
|
||||
RemoteOperation<ArrayList<JSONObject>>() {
|
||||
RemoteOperation<ShareeOcsResponse>() {
|
||||
|
||||
override fun run(client: OwnCloudClient): RemoteOperationResult<ArrayList<JSONObject>> {
|
||||
var result: RemoteOperationResult<ArrayList<JSONObject>>
|
||||
|
||||
try {
|
||||
val requestUri = client.baseUri
|
||||
val uriBuilder = requestUri.buildUpon()
|
||||
private fun buildRequestUri(baseUri: Uri) =
|
||||
baseUri.buildUpon()
|
||||
.appendEncodedPath(OCS_ROUTE)
|
||||
.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT)
|
||||
.appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE)
|
||||
.appendQueryParameter(PARAM_SEARCH, searchString)
|
||||
.appendQueryParameter(PARAM_PAGE, page.toString())
|
||||
.appendQueryParameter(PARAM_PER_PAGE, perPage.toString())
|
||||
.build()
|
||||
|
||||
val getMethod = GetMethod(URL(uriBuilder.build().toString()))
|
||||
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
|
||||
|
||||
val status = client.executeHttpMethod(getMethod)
|
||||
val response = getMethod.getResponseBodyAsString()
|
||||
|
||||
if (isSuccess(status)) {
|
||||
Timber.d("Successful response: $response")
|
||||
|
||||
// Parse the response
|
||||
val respJSON = JSONObject(response)
|
||||
val respOCS = respJSON.getJSONObject(NODE_OCS)
|
||||
val respData = respOCS.getJSONObject(NODE_DATA)
|
||||
val respExact = respData.getJSONObject(NODE_EXACT)
|
||||
val respExactUsers = respExact.getJSONArray(NODE_USERS)
|
||||
val respExactGroups = respExact.getJSONArray(NODE_GROUPS)
|
||||
val respExactRemotes = respExact.getJSONArray(NODE_REMOTES)
|
||||
val respPartialUsers = respData.getJSONArray(NODE_USERS)
|
||||
val respPartialGroups = respData.getJSONArray(NODE_GROUPS)
|
||||
val respPartialRemotes = respData.getJSONArray(NODE_REMOTES)
|
||||
val jsonResults = arrayOf(
|
||||
respExactUsers,
|
||||
respExactGroups,
|
||||
respExactRemotes,
|
||||
respPartialUsers,
|
||||
respPartialGroups,
|
||||
respPartialRemotes
|
||||
)
|
||||
|
||||
val data = ArrayList<JSONObject>() // For result data
|
||||
for (i in 0..5) {
|
||||
for (j in 0 until jsonResults[i].length()) {
|
||||
val jsonResult = jsonResults[i].getJSONObject(j)
|
||||
data.add(jsonResult)
|
||||
Timber.d("*** Added item: ${jsonResult.getString(PROPERTY_LABEL)}")
|
||||
}
|
||||
private fun parseResponse(response: String): ShareeOcsResponse? {
|
||||
val moshi = Moshi.Builder().build()
|
||||
val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java)
|
||||
val adapter: JsonAdapter<CommonOcsResponse<ShareeOcsResponse>> = moshi.adapter(type)
|
||||
return adapter.fromJson(response)!!.ocs.data
|
||||
}
|
||||
|
||||
result = RemoteOperationResult(OK)
|
||||
result.data = data
|
||||
|
||||
Timber.d("*** Get Users or groups completed ")
|
||||
|
||||
} else {
|
||||
result = RemoteOperationResult(getMethod)
|
||||
private fun onResultUnsuccessful(
|
||||
method: GetMethod,
|
||||
response: String?,
|
||||
status: Int
|
||||
): RemoteOperationResult<ShareeOcsResponse> {
|
||||
Timber.e("Failed response while getting users/groups from the server ")
|
||||
if (response != null) {
|
||||
Timber.e("*** status code: $status; response message: $response")
|
||||
} else {
|
||||
Timber.e("*** status code: $status")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
result = RemoteOperationResult(e)
|
||||
Timber.e(e, "Exception while getting users/groups")
|
||||
return RemoteOperationResult(method)
|
||||
}
|
||||
|
||||
private fun onRequestSuccessful(response: String?): RemoteOperationResult<ShareeOcsResponse> {
|
||||
val result = RemoteOperationResult<ShareeOcsResponse>(OK)
|
||||
Timber.d("Successful response: $response")
|
||||
result.data = parseResponse(response!!)
|
||||
Timber.d("*** Get Users or groups completed ")
|
||||
return result
|
||||
}
|
||||
|
||||
override fun run(client: OwnCloudClient): RemoteOperationResult<ShareeOcsResponse> {
|
||||
val requestUri = buildRequestUri(client.baseUri)
|
||||
|
||||
val getMethod = GetMethod(URL(requestUri.toString()))
|
||||
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE)
|
||||
|
||||
return try {
|
||||
val status = client.executeHttpMethod(getMethod)
|
||||
val response = getMethod.getResponseBodyAsString()
|
||||
|
||||
if (!isSuccess(status)) {
|
||||
onResultUnsuccessful(getMethod, response, status)
|
||||
} else {
|
||||
onRequestSuccessful(response)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Exception while getting users/groups")
|
||||
RemoteOperationResult(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSuccess(status: Int) = status == HttpConstants.HTTP_OK
|
||||
|
||||
companion object {
|
||||
@ -171,18 +164,5 @@ class GetRemoteShareesOperation
|
||||
// Arguments - constant values
|
||||
private const val VALUE_FORMAT = "json"
|
||||
private const val VALUE_ITEM_TYPE = "file" // to get the server search for users / groups
|
||||
|
||||
// JSON Node names
|
||||
private const val NODE_OCS = "ocs"
|
||||
private const val NODE_DATA = "data"
|
||||
private const val NODE_EXACT = "exact"
|
||||
private const val NODE_USERS = "users"
|
||||
private const val NODE_GROUPS = "groups"
|
||||
private const val NODE_REMOTES = "remotes"
|
||||
const val NODE_VALUE = "value"
|
||||
const val PROPERTY_LABEL = "label"
|
||||
const val PROPERTY_SHARE_TYPE = "shareType"
|
||||
const val PROPERTY_SHARE_WITH = "shareWith"
|
||||
const val PROPERTY_SHARE_WITH_ADDITIONAL_INFO = "shareWithAdditionalInfo"
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
package com.owncloud.android.lib.resources.shares
|
||||
|
||||
import com.owncloud.android.lib.resources.files.FileUtils
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@ -35,7 +34,7 @@ import java.io.File
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
data class RemoteShare(
|
||||
var id: Long = 0,
|
||||
var id: String = "0",
|
||||
var shareWith: String = "",
|
||||
var path: String = "",
|
||||
var token: String = "",
|
||||
@ -43,15 +42,11 @@ data class RemoteShare(
|
||||
var sharedWithAdditionalInfo: String = "",
|
||||
var name: String = "",
|
||||
var shareLink: String = "",
|
||||
var fileSource: String = "0",
|
||||
var itemSource: String = "0",
|
||||
var shareType: ShareType? = ShareType.UNKNOWN,
|
||||
var permissions: Int = DEFAULT_PERMISSION,
|
||||
var sharedDate: Long = INIT_SHARED_DATE,
|
||||
var expirationDate: Long = INIT_EXPIRATION_DATE_IN_MILLIS,
|
||||
var isFolder: Boolean = path.endsWith(File.separator),
|
||||
var userId: Long = 0,
|
||||
val isValid: Boolean = id > -1
|
||||
var isFolder: Boolean = path.endsWith(File.separator)
|
||||
) {
|
||||
|
||||
companion object {
|
||||
@ -106,17 +101,6 @@ enum class ShareType constructor(val value: Int) {
|
||||
FEDERATED(6);
|
||||
|
||||
companion object {
|
||||
fun fromValue(value: Int): ShareType? {
|
||||
return when (value) {
|
||||
-1 -> UNKNOWN
|
||||
0 -> USER
|
||||
1 -> GROUP
|
||||
3 -> PUBLIC_LINK
|
||||
4 -> EMAIL
|
||||
5 -> CONTACT
|
||||
6 -> FEDERATED
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
fun fromValue(value: Int) = values().firstOrNull { it.value == value }
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ import java.net.URL
|
||||
*
|
||||
* @param remoteShareId Share ID
|
||||
*/
|
||||
class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperation<ShareParserResult>() {
|
||||
class RemoveRemoteShareOperation(private val remoteShareId: String) : RemoteOperation<ShareParserResult>() {
|
||||
|
||||
override fun run(client: OwnCloudClient): RemoteOperationResult<ShareParserResult> {
|
||||
var result: RemoteOperationResult<ShareParserResult>
|
||||
@ -57,7 +57,7 @@ class RemoveRemoteShareOperation(private val remoteShareId: Long) : RemoteOperat
|
||||
val requestUri = client.baseUri
|
||||
val uriBuilder = requestUri.buildUpon()
|
||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH)
|
||||
uriBuilder.appendEncodedPath(remoteShareId.toString())
|
||||
uriBuilder.appendEncodedPath(remoteShareId)
|
||||
|
||||
val deleteMethod = DeleteMethod(
|
||||
URL(uriBuilder.build().toString())
|
||||
|
@ -179,7 +179,7 @@ class ShareXMLParser {
|
||||
name.equals(NODE_ID, ignoreCase = true) -> {// Parse Create XML Response
|
||||
share = RemoteShare()
|
||||
val value = readNode(parser, NODE_ID)
|
||||
share.id = Integer.parseInt(value).toLong()
|
||||
share.id = value
|
||||
}
|
||||
name.equals(NODE_URL, ignoreCase = true) -> {
|
||||
// NOTE: this field is received in all the public shares from OC 9.0.0
|
||||
@ -236,7 +236,7 @@ class ShareXMLParser {
|
||||
}
|
||||
|
||||
name.equals(NODE_ID, ignoreCase = true) -> {
|
||||
remoteShare.id = Integer.parseInt(readNode(parser, NODE_ID)).toLong()
|
||||
remoteShare.id = readNode(parser, NODE_ID)
|
||||
}
|
||||
|
||||
name.equals(NODE_ITEM_TYPE, ignoreCase = true) -> {
|
||||
@ -244,10 +244,6 @@ class ShareXMLParser {
|
||||
fixPathForFolder(remoteShare)
|
||||
}
|
||||
|
||||
name.equals(NODE_ITEM_SOURCE, ignoreCase = true) -> {
|
||||
remoteShare.itemSource = readNode(parser, NODE_ITEM_SOURCE)
|
||||
}
|
||||
|
||||
name.equals(NODE_PARENT, ignoreCase = true) -> {
|
||||
readNode(parser, NODE_PARENT)
|
||||
}
|
||||
@ -261,10 +257,6 @@ class ShareXMLParser {
|
||||
remoteShare.shareWith = readNode(parser, NODE_SHARE_WITH)
|
||||
}
|
||||
|
||||
name.equals(NODE_FILE_SOURCE, ignoreCase = true) -> {
|
||||
remoteShare.fileSource = readNode(parser, NODE_FILE_SOURCE)
|
||||
}
|
||||
|
||||
name.equals(NODE_PATH, ignoreCase = true) -> {
|
||||
remoteShare.path = readNode(parser, NODE_PATH)
|
||||
fixPathForFolder(remoteShare)
|
||||
@ -320,10 +312,8 @@ class ShareXMLParser {
|
||||
}
|
||||
}
|
||||
|
||||
if (remoteShare.isValid) {
|
||||
shares.add(remoteShare)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fixPathForFolder(share: RemoteShare) {
|
||||
if (share.isFolder && share.path.isNotEmpty() &&
|
||||
@ -403,11 +393,9 @@ class ShareXMLParser {
|
||||
private const val NODE_ELEMENT = "element"
|
||||
private const val NODE_ID = "id"
|
||||
private const val NODE_ITEM_TYPE = "item_type"
|
||||
private const val NODE_ITEM_SOURCE = "item_source"
|
||||
private const val NODE_PARENT = "parent"
|
||||
private const val NODE_SHARE_TYPE = "share_type"
|
||||
private const val NODE_SHARE_WITH = "share_with"
|
||||
private const val NODE_FILE_SOURCE = "file_source"
|
||||
private const val NODE_PATH = "path"
|
||||
private const val NODE_PERMISSIONS = "permissions"
|
||||
private const val NODE_STIME = "stime"
|
||||
|
@ -55,7 +55,7 @@ class UpdateRemoteShareOperation
|
||||
/**
|
||||
* @param remoteId Identifier of the share to update.
|
||||
*/
|
||||
private val remoteId: Long
|
||||
private val remoteId: String
|
||||
|
||||
) : RemoteOperation<ShareParserResult>() {
|
||||
/**
|
||||
|
@ -0,0 +1,72 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* Copyright (C) 2020 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.shares.responses
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* This was modeled according to the documentation:
|
||||
* https://doc.owncloud.com/server/developer_manual/core/apis/ocs-recipient-api.html#get-shares-recipients
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ShareeOcsResponse(
|
||||
val exact: ExactSharees?,
|
||||
val groups: List<ShareeItem>,
|
||||
val remotes: List<ShareeItem>,
|
||||
val users: List<ShareeItem>
|
||||
) {
|
||||
fun getFlatRepresentationWithoutExact() = ArrayList<ShareeItem>().apply {
|
||||
addAll(users)
|
||||
addAll(remotes)
|
||||
addAll(groups)
|
||||
}
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ExactSharees(
|
||||
val groups: List<ShareeItem>,
|
||||
val remotes: List<ShareeItem>,
|
||||
val users: List<ShareeItem>
|
||||
) {
|
||||
fun getFlatRepresentation() = ArrayList<ShareeItem>().apply {
|
||||
addAll(users)
|
||||
addAll(remotes)
|
||||
addAll(groups)
|
||||
}
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ShareeItem(
|
||||
val label: String,
|
||||
val value: ShareeValue
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ShareeValue(
|
||||
val shareType: Int,
|
||||
val shareWith: String,
|
||||
@Json(name = "shareWithAdditionalInfo")
|
||||
val additionalInfo: String?
|
||||
)
|
@ -44,7 +44,7 @@ interface ShareService : Service {
|
||||
): RemoteOperationResult<ShareParserResult>
|
||||
|
||||
fun updateShare(
|
||||
remoteId: Long,
|
||||
remoteId: String,
|
||||
name: String,
|
||||
password: String?,
|
||||
expirationDate: Long,
|
||||
@ -52,5 +52,5 @@ interface ShareService : Service {
|
||||
publicUpload: Boolean
|
||||
): RemoteOperationResult<ShareParserResult>
|
||||
|
||||
fun deleteShare(remoteId: Long): RemoteOperationResult<ShareParserResult>
|
||||
fun deleteShare(remoteId: String): RemoteOperationResult<ShareParserResult>
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author Christian Schabesberger
|
||||
* @author David González Verdugo
|
||||
*
|
||||
* Copyright (C) 2020 ownCloud GmbH.
|
||||
@ -22,13 +23,12 @@ package com.owncloud.android.lib.resources.shares.services
|
||||
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.resources.Service
|
||||
import org.json.JSONObject
|
||||
import java.util.ArrayList
|
||||
import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse
|
||||
|
||||
interface ShareeService : Service {
|
||||
fun getSharees(
|
||||
searchString: String,
|
||||
page: Int,
|
||||
perPage: Int
|
||||
): RemoteOperationResult<ArrayList<JSONObject>>
|
||||
): RemoteOperationResult<ShareeOcsResponse>
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class OCShareService(override val client: OwnCloudClient) :
|
||||
}.execute(client)
|
||||
|
||||
override fun updateShare(
|
||||
remoteId: Long,
|
||||
remoteId: String,
|
||||
name: String,
|
||||
password: String?,
|
||||
expirationDate: Long,
|
||||
@ -84,7 +84,7 @@ class OCShareService(override val client: OwnCloudClient) :
|
||||
this.retrieveShareDetails = true
|
||||
}.execute(client)
|
||||
|
||||
override fun deleteShare(remoteId: Long): RemoteOperationResult<ShareParserResult> =
|
||||
override fun deleteShare(remoteId: String): RemoteOperationResult<ShareParserResult> =
|
||||
RemoveRemoteShareOperation(
|
||||
remoteId
|
||||
).execute(client)
|
||||
|
@ -23,9 +23,8 @@ package com.owncloud.android.lib.resources.shares.services.implementation
|
||||
import com.owncloud.android.lib.common.OwnCloudClient
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation
|
||||
import com.owncloud.android.lib.resources.shares.responses.ShareeOcsResponse
|
||||
import com.owncloud.android.lib.resources.shares.services.ShareeService
|
||||
import org.json.JSONObject
|
||||
import java.util.ArrayList
|
||||
|
||||
class OCShareeService(override val client: OwnCloudClient) :
|
||||
ShareeService {
|
||||
@ -33,7 +32,7 @@ class OCShareeService(override val client: OwnCloudClient) :
|
||||
searchString: String,
|
||||
page: Int,
|
||||
perPage: Int
|
||||
): RemoteOperationResult<ArrayList<JSONObject>> =
|
||||
): RemoteOperationResult<ShareeOcsResponse> =
|
||||
GetRemoteShareesOperation(
|
||||
searchString,
|
||||
page,
|
||||
|
@ -34,8 +34,8 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK
|
||||
import com.owncloud.android.lib.resources.response.CapabilityResponse
|
||||
import com.owncloud.android.lib.resources.response.CommonOcsResponse
|
||||
import com.owncloud.android.lib.resources.status.responses.CapabilityResponse
|
||||
import com.owncloud.android.lib.resources.CommonOcsResponse
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
|
@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.response
|
||||
package com.owncloud.android.lib.resources.status.responses
|
||||
|
||||
import com.owncloud.android.lib.resources.status.RemoteCapability
|
||||
import com.owncloud.android.lib.resources.status.RemoteCapability.CapabilityBooleanType
|
@ -29,8 +29,8 @@ import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode
|
||||
import com.owncloud.android.lib.resources.response.CommonOcsResponse
|
||||
import com.owncloud.android.lib.resources.response.UserInfoResponse
|
||||
import com.owncloud.android.lib.resources.CommonOcsResponse
|
||||
import com.owncloud.android.lib.resources.users.responses.UserInfoResponse
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
|
@ -21,7 +21,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.owncloud.android.lib.resources.response
|
||||
package com.owncloud.android.lib.resources.users.responses
|
||||
|
||||
import com.owncloud.android.lib.resources.users.RemoteUserInfo
|
||||
import com.squareup.moshi.Json
|
@ -0,0 +1,93 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2020 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.resources.shares.responses
|
||||
|
||||
import com.owncloud.android.lib.resources.CommonOcsResponse
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.lang.reflect.Type
|
||||
|
||||
class ShareeResponseTest {
|
||||
|
||||
lateinit var adapter: JsonAdapter<CommonOcsResponse<ShareeOcsResponse>>
|
||||
|
||||
private fun loadResponses(fileName: String) =
|
||||
adapter.fromJson(File(fileName).readText())
|
||||
|
||||
@Before
|
||||
fun prepare() {
|
||||
val moshi = Moshi.Builder().build()
|
||||
val type: Type = Types.newParameterizedType(CommonOcsResponse::class.java, ShareeOcsResponse::class.java)
|
||||
adapter = moshi.adapter(type)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check structure - ok - contains meta`() {
|
||||
val response = loadResponses(EXAMPLE_RESPONSE_JSON)!!
|
||||
assertEquals("OK", response.ocs.meta.message!!)
|
||||
assertEquals(200, response.ocs.meta.statusCode)
|
||||
assertEquals("ok", response.ocs.meta.status)
|
||||
assertTrue(response.ocs.meta.itemsPerPage?.isEmpty()!!)
|
||||
assertTrue(response.ocs.meta.totalItems?.isEmpty()!!)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `example response - ok - correct sturcture`() {
|
||||
val response = loadResponses(EXAMPLE_RESPONSE_JSON)!!
|
||||
assertEquals(2, response.ocs.data.groups.size)
|
||||
assertEquals(0, response.ocs.data.remotes.size)
|
||||
assertEquals(2, response.ocs.data.users.size)
|
||||
assertEquals(0, response.ocs.data.exact?.groups?.size)
|
||||
assertEquals(0, response.ocs.data.exact?.remotes?.size)
|
||||
assertEquals(1, response.ocs.data.exact?.users?.size)
|
||||
assertEquals("user1@user1.com", response.ocs.data.users.get(0).value.additionalInfo)
|
||||
assertNull(response.ocs.data.users[1].value.additionalInfo)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check empty response - ok - parsing ok`() {
|
||||
val response = loadResponses(EMPTY_RESPONSE_JSON)!!
|
||||
assertTrue(response.ocs.data.exact?.groups?.isEmpty()!!)
|
||||
assertTrue(response.ocs.data.exact?.remotes?.isEmpty()!!)
|
||||
assertTrue(response.ocs.data.exact?.users?.isEmpty()!!)
|
||||
assertTrue(response.ocs.data.groups.isEmpty())
|
||||
assertTrue(response.ocs.data.remotes.isEmpty())
|
||||
assertTrue(response.ocs.data.users.isEmpty())
|
||||
}
|
||||
|
||||
companion object {
|
||||
val RESOURCES_PATH =
|
||||
"src/test/responses/com.owncloud.android.lib.resources.sharees.responses"
|
||||
val EXAMPLE_RESPONSE_JSON = "$RESOURCES_PATH/example_sharee_response.json"
|
||||
val EMPTY_RESPONSE_JSON = "$RESOURCES_PATH/empty_sharee_response.json"
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"ocs": {
|
||||
"meta": {
|
||||
"status": "ok",
|
||||
"statuscode": 100,
|
||||
"message": "OK",
|
||||
"totalitems": "",
|
||||
"itemsperpage": ""
|
||||
},
|
||||
"data": {
|
||||
"exact": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"remotes": []
|
||||
},
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"remotes": []
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
{
|
||||
"ocs": {
|
||||
"data": {
|
||||
"exact": {
|
||||
"groups": [],
|
||||
"remotes": [],
|
||||
"users": [
|
||||
{
|
||||
"label": "admin",
|
||||
"value": {
|
||||
"shareType": 0,
|
||||
"shareWith": "admin"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"label": "group1",
|
||||
"value": {
|
||||
"shareType": 1,
|
||||
"shareWith": "group1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "group2",
|
||||
"value": {
|
||||
"shareType": 1,
|
||||
"shareWith": "group2"
|
||||
}
|
||||
}
|
||||
],
|
||||
"remotes": [],
|
||||
"users": [
|
||||
{
|
||||
"label": "user1",
|
||||
"value": {
|
||||
"shareType": 0,
|
||||
"shareWith": "user1",
|
||||
"shareWithAdditionalInfo": "user1@user1.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "user2",
|
||||
"value": {
|
||||
"shareType": 0,
|
||||
"shareWith": "user2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"meta": {
|
||||
"itemsperpage": "",
|
||||
"message": "OK",
|
||||
"status": "ok",
|
||||
"statuscode": 200,
|
||||
"totalitems": ""
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user