UserAccountManagerImpl.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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.content.SharedPreferences;
  25. import android.preference.PreferenceManager;
  26. import android.text.TextUtils;
  27. import com.owncloud.android.MainApp;
  28. import com.owncloud.android.R;
  29. import com.owncloud.android.datamodel.ArbitraryDataProvider;
  30. import com.owncloud.android.datamodel.OCFile;
  31. import com.owncloud.android.lib.common.OwnCloudAccount;
  32. import com.owncloud.android.lib.common.OwnCloudClient;
  33. import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
  34. import com.owncloud.android.lib.common.UserInfo;
  35. import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  36. import com.owncloud.android.lib.common.utils.Log_OC;
  37. import com.owncloud.android.lib.resources.status.OwnCloudVersion;
  38. import com.owncloud.android.lib.resources.users.GetUserInfoRemoteOperation;
  39. import javax.inject.Inject;
  40. import androidx.annotation.NonNull;
  41. import androidx.annotation.Nullable;
  42. public class UserAccountManagerImpl implements UserAccountManager {
  43. private static final String TAG = UserAccountManagerImpl.class.getSimpleName();
  44. private static final String PREF_SELECT_OC_ACCOUNT = "select_oc_account";
  45. private Context context;
  46. private AccountManager accountManager;
  47. public static UserAccountManagerImpl fromContext(Context context) {
  48. AccountManager am = (AccountManager)context.getSystemService(Context.ACCOUNT_SERVICE);
  49. return new UserAccountManagerImpl(context, am);
  50. }
  51. @Inject
  52. public UserAccountManagerImpl(
  53. Context context,
  54. AccountManager accountManager
  55. ) {
  56. this.context = context;
  57. this.accountManager = accountManager;
  58. }
  59. @Override
  60. public void removeAllAccounts() {
  61. for (Account account : getAccounts()) {
  62. accountManager.removeAccount(account, null, null);
  63. }
  64. }
  65. @Override
  66. @NonNull
  67. public Account[] getAccounts() {
  68. return accountManager.getAccountsByType(getAccountType());
  69. }
  70. @Override
  71. public boolean exists(Account account) {
  72. Account[] nextcloudAccounts = getAccounts();
  73. if (account != null && account.name != null) {
  74. int lastAtPos = account.name.lastIndexOf('@');
  75. String hostAndPort = account.name.substring(lastAtPos + 1);
  76. String username = account.name.substring(0, lastAtPos);
  77. String otherHostAndPort;
  78. String otherUsername;
  79. for (Account otherAccount : nextcloudAccounts) {
  80. lastAtPos = otherAccount.name.lastIndexOf('@');
  81. otherHostAndPort = otherAccount.name.substring(lastAtPos + 1);
  82. otherUsername = otherAccount.name.substring(0, lastAtPos);
  83. if (otherHostAndPort.equals(hostAndPort) &&
  84. otherUsername.equalsIgnoreCase(username)) {
  85. return true;
  86. }
  87. }
  88. }
  89. return false;
  90. }
  91. @Nullable
  92. public Account getCurrentAccount() {
  93. Account[] ocAccounts = getAccounts();
  94. Account defaultAccount = null;
  95. ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver());
  96. SharedPreferences appPreferences = PreferenceManager.getDefaultSharedPreferences(context);
  97. String accountName = appPreferences.getString(PREF_SELECT_OC_ACCOUNT, null);
  98. // account validation: the saved account MUST be in the list of ownCloud Accounts known by the AccountManager
  99. if (accountName != null) {
  100. for (Account account : ocAccounts) {
  101. if (account.name.equals(accountName)) {
  102. defaultAccount = account;
  103. break;
  104. }
  105. }
  106. }
  107. if (defaultAccount == null && ocAccounts.length > 0) {
  108. // take first which is not pending for removal account as fallback
  109. for (Account account: ocAccounts) {
  110. boolean pendingForRemoval = arbitraryDataProvider.getBooleanValue(account,
  111. PENDING_FOR_REMOVAL);
  112. if (!pendingForRemoval) {
  113. defaultAccount = account;
  114. break;
  115. }
  116. }
  117. }
  118. return defaultAccount;
  119. }
  120. @Override
  121. @Nullable
  122. public OwnCloudAccount getCurrentOwnCloudAccount() {
  123. try {
  124. Account currentPlatformAccount = getCurrentAccount();
  125. return new OwnCloudAccount(currentPlatformAccount, context);
  126. } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException ex) {
  127. return null;
  128. }
  129. }
  130. @Override
  131. @Nullable
  132. public Account getAccountByName(String name) {
  133. for (Account account : getAccounts()) {
  134. if (account.name.equals(name)) {
  135. return account;
  136. }
  137. }
  138. return null;
  139. }
  140. @Override
  141. public boolean setCurrentOwnCloudAccount(String accountName) {
  142. boolean result = false;
  143. if (accountName != null) {
  144. for (final Account account : getAccounts()) {
  145. if (accountName.equals(account.name)) {
  146. SharedPreferences.Editor appPrefs = PreferenceManager.getDefaultSharedPreferences(context).edit();
  147. appPrefs.putString(PREF_SELECT_OC_ACCOUNT, accountName);
  148. appPrefs.apply();
  149. result = true;
  150. break;
  151. }
  152. }
  153. }
  154. return result;
  155. }
  156. @Override
  157. public boolean setCurrentOwnCloudAccount(int hashCode) {
  158. boolean result = false;
  159. if (hashCode != 0) {
  160. for (final Account account : getAccounts()) {
  161. if (hashCode == account.hashCode()) {
  162. SharedPreferences.Editor appPrefs = PreferenceManager.getDefaultSharedPreferences(context).edit();
  163. appPrefs.putString(PREF_SELECT_OC_ACCOUNT, account.name);
  164. appPrefs.apply();
  165. result = true;
  166. break;
  167. }
  168. }
  169. }
  170. return result;
  171. }
  172. @Override
  173. @NonNull
  174. public OwnCloudVersion getServerVersion(Account account) {
  175. OwnCloudVersion serverVersion = MainApp.MINIMUM_SUPPORTED_SERVER_VERSION;
  176. if (account != null) {
  177. AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());
  178. String serverVersionStr = accountMgr.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_OC_VERSION);
  179. if (serverVersionStr != null) {
  180. serverVersion = new OwnCloudVersion(serverVersionStr);
  181. }
  182. }
  183. return serverVersion;
  184. }
  185. @Override
  186. public boolean isSearchSupported(Account account) {
  187. return account != null && getServerVersion(account).isSearchSupported();
  188. }
  189. @Override
  190. public boolean isMediaStreamingSupported(Account account) {
  191. return account != null && getServerVersion(account).isMediaStreamingSupported();
  192. }
  193. @Override
  194. public void resetOwnCloudAccount() {
  195. SharedPreferences.Editor appPrefs = PreferenceManager.getDefaultSharedPreferences(context).edit();
  196. appPrefs.putString(PREF_SELECT_OC_ACCOUNT, null);
  197. appPrefs.apply();
  198. }
  199. @Override
  200. public boolean accountOwnsFile(OCFile file, Account account) {
  201. return !TextUtils.isEmpty(file.getOwnerId()) && account.name.split("@")[0].equals(file.getOwnerId());
  202. }
  203. public boolean migrateUserId() {
  204. boolean success = false;
  205. Account[] ocAccounts = accountManager.getAccountsByType(MainApp.getAccountType(context));
  206. String userId;
  207. String displayName;
  208. GetUserInfoRemoteOperation remoteUserNameOperation = new GetUserInfoRemoteOperation();
  209. for (Account account : ocAccounts) {
  210. String storedUserId = accountManager.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
  211. if (!TextUtils.isEmpty(storedUserId)) {
  212. continue;
  213. }
  214. // add userId
  215. try {
  216. OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
  217. OwnCloudClient client = OwnCloudClientManagerFactory.getDefaultSingleton()
  218. .getClientFor(ocAccount, context);
  219. RemoteOperationResult result = remoteUserNameOperation.execute(client);
  220. if (result.isSuccess()) {
  221. UserInfo userInfo = (UserInfo) result.getData().get(0);
  222. userId = userInfo.id;
  223. displayName = userInfo.displayName;
  224. } else {
  225. // skip account, try it next time
  226. Log_OC.e(TAG, "Error while getting username for account: " + account.name);
  227. continue;
  228. }
  229. } catch (Exception e) {
  230. Log_OC.e(TAG, "Error while getting username: " + e.getMessage());
  231. continue;
  232. }
  233. accountManager.setUserData(account,
  234. com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_DISPLAY_NAME,
  235. displayName);
  236. accountManager.setUserData(account,
  237. com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID,
  238. userId);
  239. success = true;
  240. }
  241. return success;
  242. }
  243. private String getAccountType() {
  244. return context.getString(R.string.account_type);
  245. }
  246. }