Merge pull request #12128 from nextcloud/refactor/convert-Authenticator-to-kt

Convert Authenticator to Kotlin
This commit is contained in:
Alper Öztürk 2024-03-19 12:59:20 +01:00 committed by GitHub
commit 1a35df4b39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 207 additions and 245 deletions

View File

@ -494,7 +494,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (accountSetupBinding != null) {
accountSetupBinding.hostUrlInput.setText("");
}
mServerInfo.mBaseUrl = AuthenticatorUrlUtils.normalizeUrlSuffix(loginUrlInfo.serverAddress);
mServerInfo.mBaseUrl = AuthenticatorUrlUtils.INSTANCE.normalizeUrlSuffix(loginUrlInfo.serverAddress);
webViewUser = loginUrlInfo.username;
webViewPassword = loginUrlInfo.password;
} catch (Exception e) {
@ -783,12 +783,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
if (uri.length() != 0) {
if (accountSetupBinding != null) {
uri = AuthenticatorUrlUtils.stripIndexPhpOrAppsFiles(uri);
uri = AuthenticatorUrlUtils.INSTANCE.stripIndexPhpOrAppsFiles(uri);
accountSetupBinding.hostUrlInput.setText(uri);
}
try {
uri = AuthenticatorUrlUtils.normalizeScheme(uri);
uri = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(uri);
} catch (IllegalArgumentException ex) {
// Let the Nextcloud library check the error of the malformed URI
Log_OC.e(TAG, "Invalid URL", ex);
@ -812,7 +812,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
Intent getServerInfoIntent = new Intent();
getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);
getServerInfoIntent.putExtra(OperationsService.EXTRA_SERVER_URL,
AuthenticatorUrlUtils.normalizeUrlSuffix(uri));
AuthenticatorUrlUtils.INSTANCE.normalizeUrlSuffix(uri));
if (mOperationsServiceBinder != null) {
mWaitingForOpId = mOperationsServiceBinder.queueNewOperation(getServerInfoIntent);
@ -1291,7 +1291,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
// create and save new ownCloud account
String lastPermanentLocation = authResult.getLastPermanentLocation();
if (lastPermanentLocation != null) {
mServerInfo.mBaseUrl = AuthenticatorUrlUtils.trimWebdavSuffix(lastPermanentLocation);
mServerInfo.mBaseUrl = AuthenticatorUrlUtils.INSTANCE.trimWebdavSuffix(lastPermanentLocation);
}
Uri uri = Uri.parse(mServerInfo.mBaseUrl);
@ -1488,7 +1488,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
String prefix = getString(R.string.login_data_own_scheme) + PROTOCOL_SUFFIX + "login/";
LoginUrlInfo loginUrlInfo = parseLoginDataUrl(prefix, data.toString());
mServerInfo.mBaseUrl = AuthenticatorUrlUtils.normalizeUrlSuffix(loginUrlInfo.serverAddress);
mServerInfo.mBaseUrl = AuthenticatorUrlUtils.INSTANCE.normalizeUrlSuffix(loginUrlInfo.serverAddress);
webViewUser = loginUrlInfo.username;
webViewPassword = loginUrlInfo.password;
doOnResumeAndBound();

View File

@ -1,121 +0,0 @@
/*
* ownCloud Android client application
*
* @author masensio on 09/02/2015.
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.authentication;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import com.nextcloud.common.NextcloudClient;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.OwnCloudCredentials;
import com.owncloud.android.lib.common.UserInfo;
import com.owncloud.android.lib.common.network.RedirectionPath;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
import com.owncloud.android.lib.resources.users.GetUserInfoRemoteOperation;
import java.lang.ref.WeakReference;
import static com.owncloud.android.datamodel.OCFile.ROOT_PATH;
/**
* Async Task to verify the credentials of a user
*/
public class AuthenticatorAsyncTask extends AsyncTask<Object, Void, RemoteOperationResult<UserInfo>> {
private static final boolean SUCCESS_IF_ABSENT = false;
private final WeakReference<Context> mWeakContext;
private final WeakReference<OnAuthenticatorTaskListener> mListener;
public AuthenticatorAsyncTask(Activity activity) {
mWeakContext = new WeakReference<>(activity.getApplicationContext());
mListener = new WeakReference<>((OnAuthenticatorTaskListener) activity);
}
@Override
protected RemoteOperationResult<UserInfo> doInBackground(Object... params) {
RemoteOperationResult<UserInfo> result;
if (params != null && params.length == 2 && mWeakContext.get() != null) {
String url = (String) params[0];
Context context = mWeakContext.get();
OwnCloudCredentials credentials = (OwnCloudCredentials) params[1];
// Client
Uri uri = Uri.parse(url);
NextcloudClient nextcloudClient = OwnCloudClientFactory.createNextcloudClient(uri,
credentials.getUsername(),
credentials.toOkHttpCredentials(),
context,
true);
// Operation - get display name
RemoteOperationResult<UserInfo> userInfoResult = new GetUserInfoRemoteOperation().execute(nextcloudClient);
// Operation - try credentials
if (userInfoResult.isSuccess()) {
OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(uri, context, true);
client.setUserId(userInfoResult.getResultData().getId());
client.setCredentials(credentials);
ExistenceCheckRemoteOperation operation = new ExistenceCheckRemoteOperation(ROOT_PATH, SUCCESS_IF_ABSENT);
result = operation.execute(client);
if (operation.wasRedirected()) {
RedirectionPath redirectionPath = operation.getRedirectionPath();
String permanentLocation = redirectionPath.getLastPermanentLocation();
result.setLastPermanentLocation(permanentLocation);
}
result.setResultData(userInfoResult.getResultData());
} else {
result = userInfoResult;
}
} else {
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR);
}
return result;
}
@Override
protected void onPostExecute(RemoteOperationResult<UserInfo> result) {
if (result != null) {
OnAuthenticatorTaskListener listener = mListener.get();
if (listener != null) {
listener.onAuthenticatorTaskCallback(result);
}
}
}
/*
* Interface to retrieve data from recognition task
*/
public interface OnAuthenticatorTaskListener{
void onAuthenticatorTaskCallback(RemoteOperationResult<UserInfo> result);
}
}

View File

@ -0,0 +1,115 @@
/*
* ownCloud Android client application
*
* @author masensio on 09/02/2015.
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@file:Suppress("DEPRECATION")
package com.owncloud.android.authentication
import android.app.Activity
import android.content.Context
import android.net.Uri
import android.os.AsyncTask
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.OwnCloudClientFactory
import com.owncloud.android.lib.common.OwnCloudCredentials
import com.owncloud.android.lib.common.UserInfo
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation
import com.owncloud.android.lib.resources.users.GetUserInfoRemoteOperation
import java.lang.ref.WeakReference
/**
* Async Task to verify the credentials of a user
*/
class AuthenticatorAsyncTask(activity: Activity) : AsyncTask<Any?, Void?, RemoteOperationResult<UserInfo?>?>() {
private val mWeakContext: WeakReference<Context?>
private val mListener: WeakReference<OnAuthenticatorTaskListener>
init {
mWeakContext = WeakReference(activity.applicationContext)
mListener = WeakReference(activity as OnAuthenticatorTaskListener)
}
@Deprecated("Deprecated in Java")
override fun doInBackground(vararg params: Any?): RemoteOperationResult<UserInfo?> {
val result: RemoteOperationResult<UserInfo?>
if (params.size == 2 && mWeakContext.get() != null) {
val url = params[0] as String
val credentials = params[1] as OwnCloudCredentials
val context = mWeakContext.get()
// Client
val uri = Uri.parse(url)
val nextcloudClient = OwnCloudClientFactory.createNextcloudClient(
uri,
credentials.username,
credentials.toOkHttpCredentials(),
context,
true
)
// Operation - get display name
val userInfoResult = GetUserInfoRemoteOperation().execute(nextcloudClient)
// Operation - try credentials
if (userInfoResult.isSuccess) {
val client = OwnCloudClientFactory.createOwnCloudClient(uri, context, true)
client.userId = userInfoResult.resultData?.id
client.credentials = credentials
val operation = ExistenceCheckRemoteOperation(OCFile.ROOT_PATH, SUCCESS_IF_ABSENT)
@Suppress("UNCHECKED_CAST")
result = operation.execute(client) as RemoteOperationResult<UserInfo?>
if (operation.wasRedirected()) {
val redirectionPath = operation.redirectionPath
val permanentLocation = redirectionPath.lastPermanentLocation
result.lastPermanentLocation = permanentLocation
}
result.setResultData(userInfoResult.resultData)
} else {
result = userInfoResult
}
} else {
result = RemoteOperationResult<UserInfo?>(RemoteOperationResult.ResultCode.UNKNOWN_ERROR)
}
return result
}
@Deprecated("Deprecated in Java")
override fun onPostExecute(result: RemoteOperationResult<UserInfo?>?) {
result?.let {
val listener = mListener.get()
listener?.onAuthenticatorTaskCallback(it)
}
}
/*
* Interface to retrieve data from recognition task
*/
interface OnAuthenticatorTaskListener {
fun onAuthenticatorTaskCallback(result: RemoteOperationResult<UserInfo?>?)
}
companion object {
private const val SUCCESS_IF_ABSENT = false
}
}

View File

@ -1,111 +0,0 @@
/*
* Nextcloud Android client application
*
* @author Andy Scherzinger
* Copyright (C) 2017 Andy Scherzinger
* Copyright (C) 2012 Bartek Przybylski
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.authentication;
import android.text.TextUtils;
import java.net.URI;
import java.util.Locale;
/**
* Helper class for authenticator-URL related logic.
*/
public final class AuthenticatorUrlUtils {
public static final String WEBDAV_PATH_4_0_AND_LATER = "/remote.php/webdav";
private static final String HTTPS_PROTOCOL = "https://";
private static final String HTTP_PROTOCOL = "http://";
private AuthenticatorUrlUtils() {
}
public static String normalizeUrlSuffix(String url) {
String normalizedUrl = url;
if (normalizedUrl.endsWith("/")) {
normalizedUrl = normalizedUrl.substring(0, normalizedUrl.length() - 1);
}
return trimUrlWebdav(normalizedUrl);
}
public static String normalizeUrl(String url, boolean sslWhenUnprefixed) {
String normalizedUrl = url;
if (!TextUtils.isEmpty(normalizedUrl)) {
normalizedUrl = normalizedUrl.trim();
if (!normalizedUrl.toLowerCase(Locale.ROOT).startsWith(HTTP_PROTOCOL) &&
!normalizedUrl.toLowerCase(Locale.ROOT).startsWith(HTTPS_PROTOCOL)) {
if (sslWhenUnprefixed) {
normalizedUrl = HTTPS_PROTOCOL + normalizedUrl;
} else {
normalizedUrl = HTTP_PROTOCOL + normalizedUrl;
}
}
normalizedUrl = normalizeUrlSuffix(normalizedUrl);
}
return normalizedUrl != null ? normalizedUrl : "";
}
public static String trimWebdavSuffix(String url) {
String trimmedUrl = url;
while (trimmedUrl.endsWith("/")) {
trimmedUrl = trimmedUrl.substring(0, url.length() - 1);
}
int pos = trimmedUrl.lastIndexOf(WEBDAV_PATH_4_0_AND_LATER);
if (pos >= 0) {
trimmedUrl = trimmedUrl.substring(0, pos);
}
return trimmedUrl;
}
private static String trimUrlWebdav(String url) {
if (url.toLowerCase(Locale.ROOT).endsWith(WEBDAV_PATH_4_0_AND_LATER)) {
return url.substring(0, url.length() - WEBDAV_PATH_4_0_AND_LATER.length());
}
return url;
}
public static String stripIndexPhpOrAppsFiles(String url) {
String strippedUrl = url;
if (strippedUrl.endsWith("/index.php")) {
strippedUrl = strippedUrl.substring(0, strippedUrl.lastIndexOf("/index.php"));
} else if (strippedUrl.contains("/index.php/apps/")) {
strippedUrl = strippedUrl.substring(0, strippedUrl.lastIndexOf("/index.php/apps/"));
}
return strippedUrl;
}
public static String normalizeScheme(String url) {
if (url.matches("[a-zA-Z][a-zA-Z0-9+.-]+://.+")) {
URI uri = URI.create(url);
String lcScheme = uri.getScheme().toLowerCase(Locale.ROOT);
return String.format("%s:%s", lcScheme, uri.getRawSchemeSpecificPart());
} else {
return url;
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Nextcloud Android client application
*
* @author Andy Scherzinger
* Copyright (C) 2017 Andy Scherzinger
* Copyright (C) 2012 Bartek Przybylski
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.authentication
import java.net.URI
/**
* Helper class for authenticator-URL related logic.
*/
object AuthenticatorUrlUtils {
const val WEBDAV_PATH_4_0_AND_LATER = "/remote.php/webdav"
fun normalizeUrlSuffix(url: String): String {
var normalizedUrl = url
if (normalizedUrl.endsWith("/")) {
normalizedUrl = normalizedUrl.substring(0, normalizedUrl.length - 1)
}
return trimUrlWebdav(normalizedUrl)
}
fun trimWebdavSuffix(url: String): String {
var trimmedUrl = url
while (trimmedUrl.endsWith("/")) {
trimmedUrl = trimmedUrl.substring(0, url.length - 1)
}
val pos = trimmedUrl.lastIndexOf(WEBDAV_PATH_4_0_AND_LATER)
if (pos >= 0) {
trimmedUrl = trimmedUrl.substring(0, pos)
}
return trimmedUrl
}
private fun trimUrlWebdav(url: String): String {
return if (url.lowercase().endsWith(WEBDAV_PATH_4_0_AND_LATER)) {
url.substring(0, url.length - WEBDAV_PATH_4_0_AND_LATER.length)
} else {
url
}
}
fun stripIndexPhpOrAppsFiles(url: String): String {
var strippedUrl = url
if (strippedUrl.endsWith("/index.php")) {
strippedUrl = strippedUrl.substring(0, strippedUrl.lastIndexOf("/index.php"))
} else if (strippedUrl.contains("/index.php/apps/")) {
strippedUrl = strippedUrl.substring(0, strippedUrl.lastIndexOf("/index.php/apps/"))
}
return strippedUrl
}
fun normalizeScheme(url: String): String {
return if (url.matches("[a-zA-Z][a-zA-Z0-9+.-]+://.+".toRegex())) {
val uri = URI.create(url)
val lcScheme = uri.scheme.lowercase()
String.format("%s:%s", lcScheme, uri.rawSchemeSpecificPart)
} else {
url
}
}
}

View File

@ -38,7 +38,7 @@ public class AuthenticatorUrlUtilsTest {
// WHEN
// scheme is normalized
String normalized = AuthenticatorUrlUtils.normalizeScheme(url);
String normalized = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(url);
// THEN
// input is returned unchanged
@ -54,7 +54,7 @@ public class AuthenticatorUrlUtilsTest {
// WHEN
// scheme is normalized
String normalized = AuthenticatorUrlUtils.normalizeScheme(url);
String normalized = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(url);
// THEN
// output is equal
@ -70,7 +70,7 @@ public class AuthenticatorUrlUtilsTest {
// WHEN
// scheme is normalized
String normalized = AuthenticatorUrlUtils.normalizeScheme(mixedCaseUrl);
String normalized = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(mixedCaseUrl);
// THEN
// scheme has been lower-cased
@ -87,7 +87,7 @@ public class AuthenticatorUrlUtilsTest {
// WHEN
// scheme is normalized
String normalized = AuthenticatorUrlUtils.normalizeScheme(emptyUrl);
String normalized = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(emptyUrl);
// THEN
// output is empty
@ -103,7 +103,7 @@ public class AuthenticatorUrlUtilsTest {
// WHEN
// scheme is normalized
String normalized = AuthenticatorUrlUtils.normalizeScheme(url);
String normalized = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(url);
// THEN
// output is equal
@ -119,7 +119,7 @@ public class AuthenticatorUrlUtilsTest {
// WHEN
// scheme is normalized
String normalized = AuthenticatorUrlUtils.normalizeScheme(url);
String normalized = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(url);
// THEN
// output is equal
@ -136,7 +136,7 @@ public class AuthenticatorUrlUtilsTest {
// WHEN
// scheme is normalized
String normalized = AuthenticatorUrlUtils.normalizeScheme(url);
String normalized = AuthenticatorUrlUtils.INSTANCE.normalizeScheme(url);
// THEN
// output is equal