diff --git a/app/build.gradle b/app/build.gradle index e082e17c190b28733bbd2a46a5966feb4bfa7753..a2e14d695c52cd273d60259a933ab60b4e3be0f0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -219,7 +219,7 @@ dependencies { implementation "commons-httpclient:commons-httpclient:3.1@jar" // remove after entire switch to lib v2 implementation 'org.apache.jackrabbit:jackrabbit-webdav:2.13.5' // remove after entire switch to lib v2 implementation 'com.google.code.gson:gson:2.10.1' - implementation("foundation.e:Nextcloud-Android-Library:1.0.5-release") { + implementation("foundation.e:Nextcloud-Android-Library:1.0.6-release") { exclude group: 'com.gitlab.bitfireAT', module: 'dav4jvm' exclude group: 'org.ogce', module: 'xpp3' // unused in Android and brings wrong Junit version exclude group: 'com.squareup.okhttp3' diff --git a/app/src/main/java/com/owncloud/android/ui/activity/SsoGrantPermissionActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/SsoGrantPermissionActivity.java index d74e50312a5149bf3c3b1b455a7eb40e604d99b9..8c1de631f7f88cee2a67d118e7c2a2c540493c43 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/SsoGrantPermissionActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/SsoGrantPermissionActivity.java @@ -35,6 +35,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -115,13 +116,20 @@ public class SsoGrantPermissionActivity extends AppCompatActivity { // create token String token = UUID.randomUUID().toString().replaceAll("-", ""); - String userId = SsoUtils.INSTANCE.sanitizeUserId(account.name); + String userId = getUserId(); saveToken(token, account.name); setResultData(token, userId, serverUrl); finish(); } + @NonNull + private String getUserId() { + final AccountManager accountManager = AccountManager.get(this); + final String baseUrl = accountManager.getUserData(account, AccountUtils.Constants.KEY_OC_BASE_URL); + return SsoUtils.INSTANCE.sanitizeUserId(account.name, baseUrl); + } + private void setResultData(String token, String userId, String serverUrl) { final Bundle result = new Bundle(); result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); diff --git a/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt b/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt index 5cda84f5d989f1381d0ae45792135a2db2f3c6ab..e5574f1f5315607350d001c8ee1ab4a9caca1686 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt @@ -126,21 +126,18 @@ class AccountSettings( @Volatile var currentlyUpdating = false - fun initialUserData(credentials: Credentials?, baseURL: String? = null, cookies: String? = null): Bundle { + fun initialUserData(credentials: Credentials?, url: String? = null, cookies: String? = null, email: String? = null): Bundle { val bundle = Bundle() bundle.putString(KEY_SETTINGS_VERSION, CURRENT_VERSION.toString()) + var userName: String? = null + if (credentials != null) { if (credentials.userName != null) { bundle.putString(KEY_USERNAME, credentials.userName) bundle.putString(NCAccountUtils.Constants.KEY_DISPLAY_NAME, credentials.userName) - if (credentials.userName.contains("@")) { - bundle.putString(KEY_EMAIL_ADDRESS, credentials.userName) - } - - val userId = SsoUtils.sanitizeUserId(credentials.userName) - bundle.putString(NCAccountUtils.Constants.KEY_USER_ID, userId) + userName = credentials.userName } if (credentials.certificateAlias != null) { @@ -156,17 +153,42 @@ class AccountSettings( } } - if (!baseURL.isNullOrEmpty()) { - bundle.putString(NCAccountUtils.Constants.KEY_OC_BASE_URL, AccountUtils.getOwnCloudBaseUrl(baseURL)) - } - if (!cookies.isNullOrEmpty()) { bundle.putString(COOKIE_KEY, cookies) } + var baseUrl : String? = null + if (!url.isNullOrEmpty()) { + baseUrl = AccountUtils.getOwnCloudBaseUrl(url) + bundle.putString(NCAccountUtils.Constants.KEY_OC_BASE_URL, baseUrl) + } + + addUserIdToBundle(bundle, userName, baseUrl) + addEmailToBundle(bundle, email, userName) + return bundle } + private fun addUserIdToBundle(bundle: Bundle, userName: String?, baseUrl: String?) { + userName?.let { + val userId = SsoUtils.sanitizeUserId(it, baseUrl) + bundle.putString(NCAccountUtils.Constants.KEY_USER_ID, userId) + } + } + + private fun addEmailToBundle(bundle: Bundle, email: String?, userName: String?) { + if (email != null) { + bundle.putString(KEY_EMAIL_ADDRESS, email) + return + } + + userName?.let { + if (it.contains("@")) { + bundle.putString(KEY_EMAIL_ADDRESS, it) + } + } + } + } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt index ced0c5c1e75fe4c20a5b53ad4f14842473a35bd4..c6d17fb691d33be99edda9fcdde8febb81931ecc 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt @@ -299,7 +299,7 @@ class AccountDetailsFragment : Fragment() { val account = Account(name, accountType) // create Android account - val userData = AccountSettings.initialUserData(credentials, baseURL, config.cookies) + val userData = AccountSettings.initialUserData(credentials, baseURL, config.cookies, config.calDAV?.emails?.firstOrNull()) Logger.log.log(Level.INFO, "Creating Android account with initial config", arrayOf(account, userData)) val accountManager = AccountManager.get(context) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt b/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt index 8edee609ef8c0ee019930caeb7b1a776e119bfc2..7836933cd3ac308d7cd2bacb19ff7e71b1fe1a07 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt @@ -16,26 +16,33 @@ package at.bitfire.davdroid.util -object SsoUtils { +import java.net.URI - private const val EELO_EMAIL_DOMAIN = "@e.email" +object SsoUtils { /** - * Murena account's userId is set same as it's email address. - * For old accounts (@e.email) userId = email. - * For new accounts (@murena.io) & other NC accounts userId is first part of email (ex: for email abc@murena.io, userId is abc). - * For api requests, we needed to pass the actual userId. This method remove the unwanted part (ex: @murena.io) from the userId + * This method removes the baseUrl's host part from the accountName to retrieve userId + * for ex: accountName: abc@murena.io; baseUrl: https://murena.io; so userID: abc */ - fun sanitizeUserId(param: String): String { - val userId = param.trim() - if (userId.endsWith(EELO_EMAIL_DOMAIN, ignoreCase = true)) { + fun sanitizeUserId(accountName: String, baseUrl: String?): String { + val userId = accountName.trim() + + val host = getHost(baseUrl) ?: return userId + val userNameEndPart = "@$host" + + if (!userId.endsWith(userNameEndPart, ignoreCase = true)) { return userId } - if (userId.lastIndexOf("@") < 0) { // not email address - return userId + return userId.substring(0, userId.lastIndexOf(userNameEndPart, ignoreCase = true)) + } + + private fun getHost(baseUrl: String?): String? { + if (baseUrl == null) { + return null } - return userId.substringBefore("@") + val uri = URI.create(baseUrl.trim()) + return uri.host } } diff --git a/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt b/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt index 5a4f70cf513b27c54fb1c84f88cafca7c4c9fdea..e14b20e9d833216ec27f4f388ed84ff6258ea650 100644 --- a/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt +++ b/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt @@ -16,9 +16,8 @@ package at.bitfire.davdroid.util -import org.junit.jupiter.api.Assertions.* - -import org.junit.jupiter.api.Test +import org.junit.Assert.assertEquals +import org.junit.Test class SsoUtilsTest { @@ -26,31 +25,34 @@ class SsoUtilsTest { fun `test sanitizeUserId with empty input`() { val userId = "" val expected = "" - val actual = SsoUtils.sanitizeUserId(userId) + val actual = SsoUtils.sanitizeUserId(userId, null) assertEquals(expected, actual) } @Test - fun `test sanitizeUserId with input without '@'`() { + fun `test sanitizeUserId with input without url part`() { val userId = "username" + val url = "https://murena.io" val expected = "username" - val actual = SsoUtils.sanitizeUserId(userId) + val actual = SsoUtils.sanitizeUserId(userId, url) assertEquals(expected, actual) } @Test fun `test sanitizeUserId with case sensitivity`() { - val userId = "User@E.EMAIL" + val userId = "User@E.EMAIL@MURENA.io" + val baseUrl = "https://murena.io/" val expected = "User@E.EMAIL" - val actual = SsoUtils.sanitizeUserId(userId) + val actual = SsoUtils.sanitizeUserId(userId, baseUrl) assertEquals(expected, actual) } @Test fun `test sanitizeUserId with leading or trailing spaces`() { val userId = " user@domain.com " + val url = " http://domain.com " val expected = "user" - val actual = SsoUtils.sanitizeUserId(userId) + val actual = SsoUtils.sanitizeUserId(userId, url) assertEquals(expected, actual) } }