From d0cc2141a79fce5ae01f90be743a6ce42a3693b1 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Mon, 4 Mar 2024 19:19:47 +0600 Subject: [PATCH 1/4] feat: ignore @eeo.one userID modification similar to @e.email accounts, @eeo.one murenatest accounts have their email as their userID. So, we have to ignore the modification of the userID when it ends with either @e.email/@eeo.one. issue: https://gitlab.e.foundation/e/os/backlog/-/issues/1975 --- app/build.gradle | 2 +- .../main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e082e17c1..a2e14d695 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/kotlin/at/bitfire/davdroid/util/SsoUtils.kt b/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt index 8edee609e..2829f0086 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt @@ -18,7 +18,7 @@ package at.bitfire.davdroid.util object SsoUtils { - private const val EELO_EMAIL_DOMAIN = "@e.email" + private val SPECIAL_EMAIL_DOMAINS = arrayOf("@e.email", "@eeo.one") /** * Murena account's userId is set same as it's email address. @@ -28,14 +28,17 @@ object SsoUtils { */ fun sanitizeUserId(param: String): String { val userId = param.trim() - if (userId.endsWith(EELO_EMAIL_DOMAIN, ignoreCase = true)) { - return userId - } if (userId.lastIndexOf("@") < 0) { // not email address return userId } + SPECIAL_EMAIL_DOMAINS.forEach { + if (userId.endsWith(it, ignoreCase = true)) { + return userId + } + } + return userId.substringBefore("@") } } -- GitLab From 705d9316c22273b816b9d075b137e38ad5c0b225 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 5 Mar 2024 10:00:22 +0600 Subject: [PATCH 2/4] fix: refactor userId retrieval logic - update sanitize userId method. retrieve userId by substracting host part from the username - save email retrieve by CalDav propfind as email address of account issue: https://gitlab.e.foundation/e/os/backlog/-/issues/1975 --- .../at/bitfire/davdroid/util/SsoUtilsTest.kt | 26 ++++++----- .../activity/SsoGrantPermissionActivity.java | 10 ++++- .../davdroid/settings/AccountSettings.kt | 44 ++++++++++++++----- .../ui/setup/AccountDetailsFragment.kt | 2 +- .../at/bitfire/davdroid/util/SsoUtils.kt | 32 ++++++++------ 5 files changed, 75 insertions(+), 39 deletions(-) rename app/src/{test => androidTest}/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt (63%) diff --git a/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt similarity index 63% rename from app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt rename to app/src/androidTest/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt index 5a4f70cf5..949289c90 100644 --- a/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt @@ -16,41 +16,43 @@ 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 { @Test - fun `test sanitizeUserId with empty input`() { + 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" + fun test_sanitizeUserId_with_case_sensitivity() { + 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`() { + 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) } } 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 d74e50312..1c1d5db2c 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() { + AccountManager accountManager = AccountManager.get(this); + 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 5cda84f5d..e5574f1f5 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 ced0c5c1e..c6d17fb69 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 2829f0086..6b2dbb57f 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt @@ -16,29 +16,33 @@ package at.bitfire.davdroid.util -object SsoUtils { +import android.net.Uri - private val SPECIAL_EMAIL_DOMAINS = arrayOf("@e.email", "@eeo.one") +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() + fun sanitizeUserId(accountName: String, baseUrl: String?): String { + val userId = accountName.trim() + + val host = getHost(baseUrl) ?: return userId + val userNameEndPart = "@$host" - if (userId.lastIndexOf("@") < 0) { // not email address + if (!userId.endsWith(userNameEndPart, ignoreCase = true)) { return userId } - SPECIAL_EMAIL_DOMAINS.forEach { - if (userId.endsWith(it, ignoreCase = true)) { - 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.parse(baseUrl.trim()) + return uri.host } } -- GitLab From d2c0dee4890814a80a9fce7a1c3982ac1d46951e Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Tue, 5 Mar 2024 15:13:58 +0000 Subject: [PATCH 3/4] chore: update according to review --- .../android/ui/activity/SsoGrantPermissionActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 1c1d5db2c..8c1de631f 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 @@ -125,8 +125,8 @@ public class SsoGrantPermissionActivity extends AppCompatActivity { @NonNull private String getUserId() { - AccountManager accountManager = AccountManager.get(this); - String baseUrl = accountManager.getUserData(account, AccountUtils.Constants.KEY_OC_BASE_URL); + 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); } -- GitLab From 6dea3d9c3ecb7fc600376f9b691bf21359c15403 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Wed, 6 Mar 2024 13:52:39 +0600 Subject: [PATCH 4/4] chore: use java URI instead of android URI for sanitizeUserId method --- app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt | 4 ++-- .../kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) rename app/src/{androidTest => test}/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt (87%) 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 6b2dbb57f..7836933cd 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/util/SsoUtils.kt @@ -16,7 +16,7 @@ package at.bitfire.davdroid.util -import android.net.Uri +import java.net.URI object SsoUtils { @@ -42,7 +42,7 @@ object SsoUtils { return null } - val uri = Uri.parse(baseUrl.trim()) + val uri = URI.create(baseUrl.trim()) return uri.host } } diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt b/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt similarity index 87% rename from app/src/androidTest/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt rename to app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt index 949289c90..e14b20e9d 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt +++ b/app/src/test/kotlin/at/bitfire/davdroid/util/SsoUtilsTest.kt @@ -22,7 +22,7 @@ import org.junit.Test class SsoUtilsTest { @Test - fun test_sanitizeUserId_with_empty_input() { + fun `test sanitizeUserId with empty input`() { val userId = "" val expected = "" val actual = SsoUtils.sanitizeUserId(userId, null) @@ -30,7 +30,7 @@ class SsoUtilsTest { } @Test - fun test_sanitizeUserId_with_input_without_url_part() { + fun `test sanitizeUserId with input without url part`() { val userId = "username" val url = "https://murena.io" val expected = "username" @@ -39,7 +39,7 @@ class SsoUtilsTest { } @Test - fun test_sanitizeUserId_with_case_sensitivity() { + fun `test sanitizeUserId with case sensitivity`() { val userId = "User@E.EMAIL@MURENA.io" val baseUrl = "https://murena.io/" val expected = "User@E.EMAIL" @@ -48,7 +48,7 @@ class SsoUtilsTest { } @Test - fun test_sanitizeUserId_with_leading_or_trailing_spaces() { + fun `test sanitizeUserId with leading or trailing spaces`() { val userId = " user@domain.com " val url = " http://domain.com " val expected = "user" -- GitLab