UserAccountManagerImpl.java 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Nextcloud Android client application
  3. *
  4. * @author Chris Narkiewicz
  5. * Copyright (C) 2019 Chris Narkiewicz
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  9. * License as published by the Free Software Foundation; either
  10. * version 3 of the License, or any later version.
  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 AFFERO GENERAL PUBLIC LICENSE for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public
  18. * License along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. package com.nextcloud.client.account;
  21. import android.accounts.Account;
  22. import android.accounts.AccountManager;
  23. import android.content.Context;
  24. import android.net.Uri;
  25. import com.owncloud.android.MainApp;
  26. import com.owncloud.android.R;
  27. import com.owncloud.android.authentication.AccountUtils;
  28. import com.owncloud.android.lib.common.OwnCloudAccount;
  29. import com.owncloud.android.lib.common.OwnCloudClient;
  30. import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
  31. import com.owncloud.android.lib.common.UserInfo;
  32. import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  33. import com.owncloud.android.lib.common.utils.Log_OC;
  34. import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation;
  35. import javax.inject.Inject;
  36. import androidx.annotation.NonNull;
  37. import androidx.annotation.Nullable;
  38. public class UserAccountManagerImpl implements UserAccountManager {
  39. private static final String TAG = AccountUtils.class.getSimpleName();
  40. private static final String PREF_SELECT_OC_ACCOUNT = "select_oc_account";
  41. private Context context;
  42. private AccountManager accountManager;
  43. @Inject
  44. public UserAccountManagerImpl(
  45. Context context,
  46. AccountManager accountManager
  47. ) {
  48. this.context = context;
  49. this.accountManager = accountManager;
  50. }
  51. @Override
  52. @NonNull
  53. public Account[] getAccounts() {
  54. return accountManager.getAccountsByType(getAccountType());
  55. }
  56. @Nullable
  57. public Account getCurrentAccount() {
  58. return AccountUtils.getCurrentOwnCloudAccount(context);
  59. }
  60. public void updateAccountVersion() {
  61. Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(context);
  62. if (currentAccount == null) {
  63. return;
  64. }
  65. final String currentAccountVersion = accountManager.getUserData(currentAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_ACCOUNT_VERSION);
  66. final boolean needsUpdate = !String.valueOf(ACCOUNT_VERSION_WITH_PROPER_ID).equalsIgnoreCase(currentAccountVersion);
  67. if (!needsUpdate) {
  68. return;
  69. }
  70. Log_OC.i(TAG, "Upgrading accounts to account version #" + ACCOUNT_VERSION_WITH_PROPER_ID);
  71. Account[] ocAccounts = accountManager.getAccountsByType(MainApp.getAccountType(context));
  72. String serverUrl;
  73. String username;
  74. String displayName;
  75. String newAccountName;
  76. Account newAccount;
  77. GetRemoteUserInfoOperation remoteUserNameOperation = new GetRemoteUserInfoOperation();
  78. for (Account account : ocAccounts) {
  79. // build new account name
  80. serverUrl = accountManager.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_BASE_URL);
  81. // update user name
  82. try {
  83. OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
  84. OwnCloudClient client = OwnCloudClientManagerFactory.getDefaultSingleton()
  85. .getClientFor(ocAccount, context);
  86. RemoteOperationResult result = remoteUserNameOperation.execute(client);
  87. if (result.isSuccess()) {
  88. UserInfo userInfo = (UserInfo) result.getData().get(0);
  89. username = userInfo.id;
  90. displayName = userInfo.displayName;
  91. } else {
  92. // skip account, try it next time
  93. Log_OC.e(TAG, "Error while getting username for account: " + account.name);
  94. continue;
  95. }
  96. } catch (Exception e) {
  97. Log_OC.e(TAG, "Error while getting username: " + e.getMessage());
  98. continue;
  99. }
  100. newAccountName = com.owncloud.android.lib.common.accounts.AccountUtils.
  101. buildAccountName(Uri.parse(serverUrl), username);
  102. // migrate to a new account, if needed
  103. if (!newAccountName.equals(account.name)) {
  104. newAccount = migrateAccount(context, currentAccount, accountManager, serverUrl, newAccountName,
  105. account);
  106. } else {
  107. // servers which base URL is in the root of their domain need no change
  108. Log_OC.d(TAG, account.name + " needs no upgrade ");
  109. newAccount = account;
  110. }
  111. accountManager.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_DISPLAY_NAME, displayName);
  112. accountManager.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID, username);
  113. // at least, upgrade account version
  114. Log_OC.d(TAG, "Setting version " + ACCOUNT_VERSION_WITH_PROPER_ID + " to " + newAccountName);
  115. accountManager.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_ACCOUNT_VERSION,
  116. Integer.toString(ACCOUNT_VERSION_WITH_PROPER_ID));
  117. }
  118. }
  119. @NonNull
  120. private Account migrateAccount(Context context, Account currentAccount, AccountManager accountMgr,
  121. String serverUrl, String newAccountName, Account account) {
  122. Log_OC.d(TAG, "Upgrading " + account.name + " to " + newAccountName);
  123. // create the new account
  124. Account newAccount = new Account(newAccountName, MainApp.getAccountType(context));
  125. String password = accountMgr.getPassword(account);
  126. accountMgr.addAccountExplicitly(newAccount, (password != null) ? password : "", null);
  127. // copy base URL
  128. accountMgr.setUserData(newAccount, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_BASE_URL, serverUrl);
  129. // copy server version
  130. accountMgr.setUserData(
  131. newAccount,
  132. com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_VERSION,
  133. accountMgr.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_VERSION)
  134. );
  135. // copy cookies
  136. accountMgr.setUserData(
  137. newAccount,
  138. com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_COOKIES,
  139. accountMgr.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_COOKIES)
  140. );
  141. // don't forget the account saved in preferences as the current one
  142. if (currentAccount.name.equals(account.name)) {
  143. AccountUtils.setCurrentOwnCloudAccount(context, newAccountName);
  144. }
  145. // remove the old account
  146. accountMgr.removeAccount(account, null, null);
  147. // will assume it succeeds, not a big deal otherwise
  148. return newAccount;
  149. }
  150. private String getAccountType() {
  151. return context.getString(R.string.account_type);
  152. }
  153. }