Skip to content

Commit 83be8df

Browse files
authored
Merge pull request #4661 from owncloud/feature/add_account_id_to_user
[FEATURE REQUEST] Add account id to the user
2 parents 32e2509 + 1a13e63 commit 83be8df

File tree

20 files changed

+291
-12
lines changed

20 files changed

+291
-12
lines changed

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Table of Contents
22

3+
* [Changelog for unreleased](#changelog-for-owncloud-android-client-unreleased-unreleased)
34
* [Changelog for 4.6.2](#changelog-for-owncloud-android-client-462-2025-08-13)
45
* [Changelog for 4.6.1](#changelog-for-owncloud-android-client-461-2025-08-01)
56
* [Changelog for 4.6.0](#changelog-for-owncloud-android-client-460-2025-07-22)
@@ -29,6 +30,28 @@
2930
* [Changelog for 2.18.1](#changelog-for-owncloud-android-client-2181-2021-07-20)
3031
* [Changelog for 2.18.0](#changelog-for-owncloud-android-client-2180-2021-05-24)
3132
* [Changelog for 2.17 versions and below](#changelog-for-217-versions-and-below)
33+
# Changelog for ownCloud Android Client [unreleased] (UNRELEASED)
34+
35+
The following sections list the changes in ownCloud Android Client unreleased relevant to
36+
ownCloud admins and users.
37+
38+
[unreleased]: https://github.com/owncloud/android/compare/v4.6.2...master
39+
40+
## Summary
41+
42+
* Enhancement - Add account ID to the user information: [#4605](https://github.com/owncloud/android/issues/4605)
43+
44+
## Details
45+
46+
* Enhancement - Add account ID to the user information: [#4605](https://github.com/owncloud/android/issues/4605)
47+
48+
The account ID has been added to the Account Manager only for Infinite Scale
49+
users. This information will be used to fetch all permissions related to space
50+
management.
51+
52+
https://github.com/owncloud/android/issues/4605
53+
https://github.com/owncloud/android/pull/4661
54+
3255
# Changelog for ownCloud Android Client [4.6.2] (2025-08-13)
3356

3457
The following sections list the changes in ownCloud Android Client 4.6.2 relevant to

changelog/unreleased/4661

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Enhancement: Add account ID to the user information
2+
3+
The account ID has been added to the Account Manager only for Infinite Scale users.
4+
This information will be used to fetch all permissions related to space management.
5+
6+
https://github.com/owncloud/android/issues/4605
7+
https://github.com/owncloud/android/pull/4661

owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @author Aitor Ballesteros Pavón
88
* @author Jorge Aguado Recio
99
*
10-
* Copyright (C) 2024 ownCloud GmbH.
10+
* Copyright (C) 2025 ownCloud GmbH.
1111
*
1212
* This program is free software: you can redistribute it and/or modify
1313
* it under the terms of the GNU General Public License version 2,
@@ -109,6 +109,7 @@ import com.owncloud.android.domain.user.usecases.GetUserInfoAsyncUseCase
109109
import com.owncloud.android.domain.user.usecases.GetUserQuotasUseCase
110110
import com.owncloud.android.domain.user.usecases.GetUserQuotasAsStreamUseCase
111111
import com.owncloud.android.domain.user.usecases.RefreshUserQuotaFromServerAsyncUseCase
112+
import com.owncloud.android.domain.user.usecases.GetUserIdAsyncUseCase
112113
import com.owncloud.android.domain.webfinger.usecases.GetOwnCloudInstanceFromWebFingerUseCase
113114
import com.owncloud.android.domain.webfinger.usecases.GetOwnCloudInstancesFromAuthenticatedWebFingerUseCase
114115
import com.owncloud.android.usecases.accounts.RemoveAccountUseCase
@@ -259,6 +260,7 @@ val useCaseModule = module {
259260
factoryOf(::GetStoredQuotaAsStreamUseCase)
260261
factoryOf(::GetStoredQuotaUseCase)
261262
factoryOf(::GetUserAvatarAsyncUseCase)
263+
factoryOf(::GetUserIdAsyncUseCase)
262264
factoryOf(::GetUserInfoAsyncUseCase)
263265
factoryOf(::GetUserQuotasAsStreamUseCase)
264266
factoryOf(::GetUserQuotasUseCase)

owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
* @author Abel García de Prada
66
* @author Juan Carlos Garrote Gascón
77
* @author David Crespo Ríos
8+
* @author Jorge Aguado Recio
89
*
9-
* Copyright (C) 2024 ownCloud GmbH.
10+
* Copyright (C) 2025 ownCloud GmbH.
1011
*
1112
* This program is free software: you can redistribute it and/or modify
1213
* it under the terms of the GNU General Public License version 2,
@@ -101,6 +102,6 @@ val viewModelModule = module {
101102
get()) }
102103
viewModel { ReceiveExternalFilesViewModel(get(), get(), get(), get()) }
103104
viewModel { (accountName: String, showPersonalSpace: Boolean) ->
104-
SpacesListViewModel(get(), get(), get(), get(), get(), get(), get(), accountName, showPersonalSpace)
105+
SpacesListViewModel(get(), get(), get(), get(), get(), get(), get(), get(), accountName, showPersonalSpace)
105106
}
106107
}

owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListFragment.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @author Jorge Aguado Recio
66
* @author Aitor Ballesteros Pavón
77
*
8-
* Copyright (C) 2024 ownCloud GmbH.
8+
* Copyright (C) 2025 ownCloud GmbH.
99
*
1010
* This program is free software: you can redistribute it and/or modify
1111
* it under the terms of the GNU General Public License version 2,
@@ -44,8 +44,10 @@ import com.owncloud.android.extensions.toDrawableRes
4444
import com.owncloud.android.extensions.toSubtitleStringRes
4545
import com.owncloud.android.extensions.toTitleStringRes
4646
import com.owncloud.android.presentation.capabilities.CapabilityViewModel
47+
import com.owncloud.android.presentation.common.UIResult
4748
import org.koin.androidx.viewmodel.ext.android.viewModel
4849
import org.koin.core.parameter.parametersOf
50+
import timber.log.Timber
4951

5052
class SpacesListFragment : SpacesListAdapter.SpacesListAdapterListener, Fragment(), SearchView.OnQueryTextListener {
5153
private var _binding: SpacesListFragmentBinding? = null
@@ -120,6 +122,22 @@ class SpacesListFragment : SpacesListAdapter.SpacesListAdapterListener, Fragment
120122
setFragmentResult(REQUEST_KEY_CLICK_SPACE, bundleOf(BUNDLE_KEY_CLICK_SPACE to it))
121123
}
122124
}
125+
126+
collectLatestLifecycleFlow(spacesListViewModel.userId) { event ->
127+
event?.let {
128+
val accountName = requireArguments().getString(BUNDLE_ACCOUNT_NAME)
129+
when (val uiResult = event.peekContent()) {
130+
is UIResult.Success -> {
131+
Timber.d ("The account id for $accountName is: ${uiResult.data}")
132+
}
133+
is UIResult.Loading -> { }
134+
is UIResult.Error -> {
135+
Timber.e(uiResult.error, "Failed to retrieve user id for account $accountName")
136+
}
137+
}
138+
}
139+
}
140+
123141
}
124142

125143
private fun showOrHideEmptyView(spacesList: List<OCSpace>) {

owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @author Juan Carlos Garrote Gascón
55
* @author Jorge Aguado Recio
66
*
7-
* Copyright (C) 2024 ownCloud GmbH.
7+
* Copyright (C) 2025 ownCloud GmbH.
88
*
99
* This program is free software: you can redistribute it and/or modify
1010
* it under the terms of the GNU General Public License version 2,
@@ -33,6 +33,10 @@ import com.owncloud.android.domain.spaces.usecases.GetPersonalAndProjectSpacesWi
3333
import com.owncloud.android.domain.spaces.usecases.GetPersonalSpacesWithSpecialsForAccountAsStreamUseCase
3434
import com.owncloud.android.domain.spaces.usecases.GetProjectSpacesWithSpecialsForAccountAsStreamUseCase
3535
import com.owncloud.android.domain.spaces.usecases.RefreshSpacesFromServerAsyncUseCase
36+
import com.owncloud.android.domain.user.usecases.GetUserIdAsyncUseCase
37+
import com.owncloud.android.domain.utils.Event
38+
import com.owncloud.android.extensions.ViewModelExt.runUseCaseWithResult
39+
import com.owncloud.android.presentation.common.UIResult
3640
import com.owncloud.android.providers.CoroutinesDispatcherProvider
3741
import kotlinx.coroutines.flow.MutableStateFlow
3842
import kotlinx.coroutines.flow.StateFlow
@@ -46,6 +50,7 @@ class SpacesListViewModel(
4650
private val getProjectSpacesWithSpecialsForAccountAsStreamUseCase: GetProjectSpacesWithSpecialsForAccountAsStreamUseCase,
4751
private val getFileByRemotePathUseCase: GetFileByRemotePathUseCase,
4852
private val getStoredCapabilitiesUseCase: GetStoredCapabilitiesUseCase,
53+
private val getUserIdAsyncUseCase: GetUserIdAsyncUseCase,
4954
private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider,
5055
private val accountName: String,
5156
private val showPersonalSpace: Boolean,
@@ -55,10 +60,16 @@ class SpacesListViewModel(
5560
MutableStateFlow(SpacesListUiState(spaces = emptyList(), refreshing = false, error = null, searchFilter = ""))
5661
val spacesList: StateFlow<SpacesListUiState> = _spacesList
5762

63+
private val _userId = MutableStateFlow<Event<UIResult<String>>?>(null)
64+
val userId: StateFlow<Event<UIResult<String>>?> = _userId
65+
5866
init {
5967
viewModelScope.launch(coroutinesDispatcherProvider.io) {
6068
refreshSpacesFromServer()
6169
val capabilities = getStoredCapabilitiesUseCase(GetStoredCapabilitiesUseCase.Params(accountName))
70+
if (capabilities?.isSpacesAllowed() == true) {
71+
getUserId(accountName)
72+
}
6273
val isMultiPersonal = capabilities?.spaces?.hasMultiplePersonalSpaces
6374
val spacesListFlow = if (isMultiPersonal == true) getPersonalSpacesWithSpecialsForAccountAsStreamUseCase(
6475
GetPersonalSpacesWithSpecialsForAccountAsStreamUseCase.Params(accountName = accountName)
@@ -102,6 +113,16 @@ class SpacesListViewModel(
102113
_spacesList.update { it.copy(searchFilter = newSearchFilter) }
103114
}
104115

116+
private fun getUserId(
117+
accountName: String
118+
) = runUseCaseWithResult(
119+
coroutineDispatcher = coroutinesDispatcherProvider.io,
120+
showLoading = false,
121+
flow = _userId,
122+
useCase = getUserIdAsyncUseCase,
123+
useCaseParams = GetUserIdAsyncUseCase.Params(accountName = accountName)
124+
)
125+
105126
data class SpacesListUiState(
106127
val spaces: List<OCSpace>,
107128
val rootFolderFromSelectedSpace: OCFile? = null,

owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/accounts/AccountUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ public static class Constants {
225225

226226
public static final String KEY_IS_KITEWORKS_SERVER = "is_kiteworks_server";
227227

228+
public static final String KEY_ACCOUNT_UUID = "oc_uuid";
229+
228230
public static final int ACCOUNT_VERSION = 1;
229231
}
230232
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* ownCloud Android client application
3+
*
4+
* @author Jorge Aguado Recio
5+
*
6+
* Copyright (C) 2025 ownCloud GmbH.
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2,
10+
* as published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.owncloud.android.lib.resources.users
22+
23+
import com.owncloud.android.lib.common.OwnCloudClient
24+
import com.owncloud.android.lib.common.http.HttpConstants
25+
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod
26+
import com.owncloud.android.lib.common.operations.RemoteOperation
27+
import com.owncloud.android.lib.common.operations.RemoteOperationResult
28+
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode
29+
import com.squareup.moshi.JsonAdapter
30+
import com.squareup.moshi.JsonClass
31+
import com.squareup.moshi.Moshi
32+
import timber.log.Timber
33+
import java.net.URL
34+
35+
class GetRemoteUserIdOperation: RemoteOperation<String>() {
36+
override fun run(client: OwnCloudClient): RemoteOperationResult<String> {
37+
var result: RemoteOperationResult<String>
38+
try {
39+
val getMethod = GetMethod(URL(client.baseUri.toString() + GRAPH_ME_ENDPOINT))
40+
41+
val status = client.executeHttpMethod(getMethod)
42+
43+
val response = getMethod.getResponseBodyAsString()
44+
45+
if (status == HttpConstants.HTTP_OK) {
46+
Timber.d("Successful response: $response")
47+
48+
val moshi: Moshi = Moshi.Builder().build()
49+
val adapter: JsonAdapter<GraphMeResponse> = moshi.adapter(GraphMeResponse::class.java)
50+
51+
result = RemoteOperationResult(ResultCode.OK)
52+
result.data = getMethod.getResponseBodyAsString().let { adapter.fromJson(it)!!.id }
53+
54+
Timber.d("Get user id completed and parsed to ${result.data}")
55+
} else {
56+
result = RemoteOperationResult(getMethod)
57+
Timber.e("Failed response while getting user id; status code: $status, response: $response")
58+
}
59+
} catch (e: Exception) {
60+
result = RemoteOperationResult(e)
61+
Timber.e(e, "Exception while getting oCIS user id")
62+
}
63+
return result
64+
}
65+
66+
@JsonClass(generateAdapter = true)
67+
data class GraphMeResponse(val id: String)
68+
69+
companion object {
70+
private const val GRAPH_ME_ENDPOINT = "/graph/v1.0/me"
71+
}
72+
73+
}

owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/UserService.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ interface UserService : Service {
3434
fun getUserInfo(): RemoteOperationResult<RemoteUserInfo>
3535
fun getUserQuota(): RemoteOperationResult<GetRemoteUserQuotaOperation.RemoteQuota>
3636
fun getUserAvatar(avatarDimension: Int): RemoteOperationResult<RemoteAvatarData>
37+
fun getUserId(): RemoteOperationResult<String>
3738
}

owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/users/services/implementation/OCUserService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ package com.owncloud.android.lib.resources.users.services.implementation
2929
import com.owncloud.android.lib.common.OwnCloudClient
3030
import com.owncloud.android.lib.common.operations.RemoteOperationResult
3131
import com.owncloud.android.lib.resources.users.GetRemoteUserAvatarOperation
32+
import com.owncloud.android.lib.resources.users.GetRemoteUserIdOperation
3233
import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation
3334
import com.owncloud.android.lib.resources.users.GetRemoteUserQuotaOperation
3435
import com.owncloud.android.lib.resources.users.RemoteAvatarData
@@ -45,4 +46,7 @@ class OCUserService(override val client: OwnCloudClient) : UserService {
4546
override fun getUserAvatar(avatarDimension: Int): RemoteOperationResult<RemoteAvatarData> =
4647
GetRemoteUserAvatarOperation(avatarDimension).execute(client)
4748

49+
override fun getUserId(): RemoteOperationResult<String> =
50+
GetRemoteUserIdOperation().execute(client)
51+
4852
}

0 commit comments

Comments
 (0)