1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "app_account_info.h"
17 
18 #include "account_log_wrapper.h"
19 #ifdef HAS_ASSET_PART
20 #include <iomanip>
21 #include <sstream>
22 #include "mbedtls/sha256.h"
23 #endif
24 #include "nlohmann/json.hpp"
25 
26 namespace OHOS {
27 namespace AccountSA {
28 namespace {
29 const std::string OWNER = "owner";
30 const std::string NAME = "name";
31 const std::string ALIAS = "alias";
32 const std::string EXTRA_INFO = "extraInfo";
33 const std::string SYNC_ENABLE = "syncEnable";
34 const std::string AUTHORIZED_APPS = "authorizedApps";
35 const std::string ASSOCIATED_DATA = "associatedData";
36 const std::string ACCOUNT_CREDENTIAL = "accountCredential";
37 const std::string OAUTH_TOKEN = "oauthToken";
38 const std::string OAUTH_TOKEN_INFOS = "tokenInfos";
39 const std::string OAUTH_TYPE = "authType";
40 const std::string OAUTH_TOKEN_STATUS = "status";
41 const std::string OAUTH_AUTH_LIST = "authList";
42 const std::string OAUTH_TOKEN_TO_TYPE = "tokenToType";
43 const std::string HYPHEN = "#";
44 constexpr uint32_t APP_INDEX = 0;
45 constexpr uint32_t MAX_TOKEN_NUMBER = 128;
46 constexpr uint32_t MAX_OAUTH_LIST_SIZE = 512;
47 constexpr uint32_t MAX_ASSOCIATED_DATA_NUMBER = 1024;
48 constexpr uint32_t MAX_APP_AUTH_LIST_SIZE = 1024;
49 #ifdef HAS_ASSET_PART
50 constexpr uint32_t HASH_LENGTH = 32;
51 constexpr uint32_t WIDTH_FOR_HEX = 2;
52 #endif
53 constexpr int32_t MAX_MAP_SZIE = 1024;
54 }  // namespace
55 
56 #ifdef HAS_ASSET_PART
ComputeHash(const std::string & input,std::string & output)57 static void ComputeHash(const std::string &input, std::string &output)
58 {
59     unsigned char hash[HASH_LENGTH] = {0};
60     mbedtls_sha256_context context;
61     mbedtls_sha256_init(&context);
62     mbedtls_sha256_starts(&context, 0);
63     mbedtls_sha256_update(&context, reinterpret_cast<const unsigned char *>(input.c_str()), input.length());
64     mbedtls_sha256_finish(&context, hash);
65     mbedtls_sha256_free(&context);
66 
67     std::stringstream ss;
68     for (std::uint32_t i = 0; i < HASH_LENGTH; ++i) {
69         ss << std::hex << std::uppercase << std::setw(WIDTH_FOR_HEX) << std::setfill('0') << std::uint16_t(hash[i]);
70     }
71     ss >> output;
72 }
73 #endif
74 
AppAccountInfo()75 AppAccountInfo::AppAccountInfo()
76 {
77     owner_ = "";
78     name_ = "";
79     appIndex_ = APP_INDEX;
80     extraInfo_ = "";
81     authorizedApps_.clear();
82     syncEnable_ = false;
83     associatedData_ = "";
84     accountCredential_ = "";
85     alias_ = "";
86     oauthTokens_.clear();
87 }
88 
AppAccountInfo(const std::string & name,const std::string & owner)89 AppAccountInfo::AppAccountInfo(const std::string &name, const std::string &owner)
90 {
91     name_ = name;
92     owner_ = owner;
93     appIndex_ = APP_INDEX;
94     extraInfo_ = "";
95     authorizedApps_.clear();
96     syncEnable_ = false;
97     associatedData_ = "";
98     accountCredential_ = "";
99     alias_ = "";
100     oauthTokens_.clear();
101 }
102 
GetOwner()103 std::string AppAccountInfo::GetOwner()
104 {
105     return owner_;
106 }
107 
GetOwner(std::string & owner)108 void AppAccountInfo::GetOwner(std::string &owner)
109 {
110     owner = owner_;
111 }
112 
SetOwner(const std::string & owner)113 void AppAccountInfo::SetOwner(const std::string &owner)
114 {
115     owner_ = owner;
116     alias_ = "";
117 }
118 
GetName()119 std::string AppAccountInfo::GetName()
120 {
121     return name_;
122 }
123 
GetName(std::string & name) const124 void AppAccountInfo::GetName(std::string &name) const
125 {
126     name = name_;
127 }
128 
SetName(const std::string & name)129 void AppAccountInfo::SetName(const std::string &name)
130 {
131     name_ = name;
132     alias_ = "";
133 }
134 
GetAppIndex()135 uint32_t AppAccountInfo::GetAppIndex()
136 {
137     return appIndex_;
138 }
139 
SetAppIndex(const uint32_t & appIndex)140 void AppAccountInfo::SetAppIndex(const uint32_t &appIndex)
141 {
142     appIndex_ = appIndex;
143     alias_ = "";
144 }
145 
GetExtraInfo(std::string & extraInfo) const146 void AppAccountInfo::GetExtraInfo(std::string &extraInfo) const
147 {
148     extraInfo = extraInfo_;
149 }
150 
SetExtraInfo(const std::string & extraInfo)151 void AppAccountInfo::SetExtraInfo(const std::string &extraInfo)
152 {
153     extraInfo_ = extraInfo;
154 }
155 
EnableAppAccess(const std::string & authorizedApp,const uint32_t apiVersion)156 ErrCode AppAccountInfo::EnableAppAccess(const std::string &authorizedApp, const uint32_t apiVersion)
157 {
158     auto it = authorizedApps_.emplace(authorizedApp);
159     if (!it.second && apiVersion < Constants::API_VERSION9) {
160         return ERR_APPACCOUNT_SERVICE_ENABLE_APP_ACCESS_ALREADY_EXISTS;
161     }
162     if (authorizedApps_.size() > MAX_APP_AUTH_LIST_SIZE) {
163         ACCOUNT_LOGE("the authorization list is too large, whose capacity for each authType is %{public}d",
164             MAX_OAUTH_LIST_SIZE);
165         authorizedApps_.erase(authorizedApp);
166         return ERR_APPACCOUNT_SERVICE_OAUTH_LIST_MAX_SIZE;
167     }
168     return ERR_OK;
169 }
170 
DisableAppAccess(const std::string & authorizedApp,const uint32_t apiVersion)171 ErrCode AppAccountInfo::DisableAppAccess(const std::string &authorizedApp, const uint32_t apiVersion)
172 {
173     auto result = authorizedApps_.erase(authorizedApp);
174     if (result == 0 && apiVersion < Constants::API_VERSION9) {
175         return ERR_APPACCOUNT_SERVICE_DISABLE_APP_ACCESS_NOT_EXISTED;
176     }
177     return ERR_OK;
178 }
179 
CheckAppAccess(const std::string & authorizedApp,bool & isAccessible)180 ErrCode AppAccountInfo::CheckAppAccess(const std::string &authorizedApp, bool &isAccessible)
181 {
182     isAccessible = false;
183     auto it = authorizedApps_.find(authorizedApp);
184     if (it != authorizedApps_.end()) {
185         isAccessible = true;
186     }
187     return ERR_OK;
188 }
189 
GetAuthorizedApps(std::set<std::string> & apps) const190 void AppAccountInfo::GetAuthorizedApps(std::set<std::string> &apps) const
191 {
192     apps = authorizedApps_;
193 }
194 
SetAuthorizedApps(const std::set<std::string> & apps)195 void AppAccountInfo::SetAuthorizedApps(const std::set<std::string> &apps)
196 {
197     authorizedApps_ = apps;
198 }
199 
GetSyncEnable(bool & syncEnable) const200 void AppAccountInfo::GetSyncEnable(bool &syncEnable) const
201 {
202     syncEnable = syncEnable_;
203 }
204 
SetSyncEnable(const bool & syncEnable)205 void AppAccountInfo::SetSyncEnable(const bool &syncEnable)
206 {
207     syncEnable_ = syncEnable;
208 }
209 
InitCustomData(const std::map<std::string,std::string> & data)210 ErrCode AppAccountInfo::InitCustomData(const std::map<std::string, std::string> &data)
211 {
212     Json jsonObject = data;
213     try {
214         associatedData_ = jsonObject.dump();
215     } catch (Json::type_error& err) {
216         ACCOUNT_LOGE("failed to dump json object, reason: %{public}s", err.what());
217         return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR;
218     }
219     return ERR_OK;
220 }
221 
GetAllAssociatedData(std::map<std::string,std::string> & data) const222 ErrCode AppAccountInfo::GetAllAssociatedData(std::map<std::string, std::string> &data) const
223 {
224     auto jsonObject = Json::parse(associatedData_, nullptr, false);
225     if (jsonObject.is_discarded() || !jsonObject.is_object()) {
226         ACCOUNT_LOGE("jsonObject is_discarded");
227         return ERR_APPACCOUNT_SERVICE_GET_ASSOCIATED_DATA;
228     }
229     try {
230         data = jsonObject.get<std::map<std::string, std::string>>();
231     }  catch (Json::type_error& err) {
232         ACCOUNT_LOGE("failed to convert json object to map, reason: %{public}s", err.what());
233         return ERR_APPACCOUNT_SERVICE_GET_ASSOCIATED_DATA;
234     }
235     return ERR_OK;
236 }
237 
GetAssociatedData(const std::string & key,std::string & value) const238 ErrCode AppAccountInfo::GetAssociatedData(const std::string &key, std::string &value) const
239 {
240     auto jsonObject = Json::parse(associatedData_, nullptr, false);
241     if (jsonObject.is_discarded()) {
242         ACCOUNT_LOGI("jsonObject is_discarded");
243         jsonObject = Json::object();
244     }
245 
246     if (jsonObject.find(key) == jsonObject.end()) {
247         ACCOUNT_LOGE("failed to find value, key = %{public}s", key.c_str());
248         return ERR_APPACCOUNT_SERVICE_ASSOCIATED_DATA_KEY_NOT_EXIST;
249     }
250 
251     value = jsonObject.at(key);
252     return ERR_OK;
253 }
254 
SetAssociatedData(const std::string & key,const std::string & value)255 ErrCode AppAccountInfo::SetAssociatedData(const std::string &key, const std::string &value)
256 {
257     auto jsonObject = Json::parse(associatedData_, nullptr, false);
258     if (jsonObject.is_discarded() || (!jsonObject.is_object())) {
259         ACCOUNT_LOGI("jsonObject is discarded");
260         jsonObject = Json::object();
261     }
262     auto it = jsonObject.find(key);
263     if (it == jsonObject.end()) {
264         if (jsonObject.size() >= MAX_ASSOCIATED_DATA_NUMBER) {
265             ACCOUNT_LOGW("associated data is over size, the max number is: %{public}d", MAX_ASSOCIATED_DATA_NUMBER);
266             return ERR_APPACCOUNT_SERVICE_ASSOCIATED_DATA_OVER_SIZE;
267         }
268         jsonObject.emplace(key, value);
269     } else {
270         jsonObject[key] = value;
271     }
272 
273     try {
274         associatedData_ = jsonObject.dump();
275     } catch (Json::type_error& err) {
276         ACCOUNT_LOGE("failed to dump json object, reason: %{public}s", err.what());
277         return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR;
278     }
279     return ERR_OK;
280 }
281 
GetAccountCredential(const std::string & credentialType,std::string & credential) const282 ErrCode AppAccountInfo::GetAccountCredential(const std::string &credentialType, std::string &credential) const
283 {
284     auto jsonObject = Json::parse(accountCredential_, nullptr, false);
285     if (jsonObject.is_discarded()) {
286         jsonObject = Json::object();
287     }
288 
289     if (jsonObject.find(credentialType) == jsonObject.end()) {
290         ACCOUNT_LOGE("failed to find value, credentialType = %{public}s", credentialType.c_str());
291         return ERR_APPACCOUNT_SERVICE_ACCOUNT_CREDENTIAL_NOT_EXIST;
292     }
293 
294     credential = jsonObject.at(credentialType);
295     return ERR_OK;
296 }
297 
SetAccountCredential(const std::string & credentialType,const std::string & credential)298 ErrCode AppAccountInfo::SetAccountCredential(
299     const std::string &credentialType, const std::string &credential)
300 {
301     Json jsonObject;
302     if (accountCredential_.empty()) {
303         jsonObject = Json::object();
304     } else {
305         jsonObject = Json::parse(accountCredential_, nullptr, false);
306         if (jsonObject.is_discarded() || !jsonObject.is_object()) {
307             ACCOUNT_LOGE("jsonObject is not an object");
308             return ERR_ACCOUNT_COMMON_BAD_JSON_FORMAT_ERROR;
309         }
310     }
311 #ifndef HAS_ASSET_PART
312     jsonObject[credentialType] = credential;
313 #else
314     auto it = jsonObject.find(credentialType);
315     if (it == jsonObject.end()) {
316         std::string credentialTypeAlias;
317         ComputeHash(credentialType, credentialTypeAlias);
318         jsonObject[credentialType] = GetAlias() + credentialTypeAlias;
319     } else {
320         return ERR_OK;
321     }
322 #endif
323 
324     try {
325         accountCredential_ = jsonObject.dump();
326     } catch (Json::type_error& err) {
327         ACCOUNT_LOGE("failed to dump json object, reason: %{public}s", err.what());
328         return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR;
329     }
330     return ERR_OK;
331 }
332 
DeleteAccountCredential(const std::string & credentialType)333 ErrCode AppAccountInfo::DeleteAccountCredential(const std::string &credentialType)
334 {
335     auto jsonObject = Json::parse(accountCredential_, nullptr, false);
336     if (jsonObject.is_discarded() || !jsonObject.is_object() || (jsonObject.erase(credentialType) == 0)) {
337         ACCOUNT_LOGE("credential not found");
338         return ERR_APPACCOUNT_SERVICE_ACCOUNT_CREDENTIAL_NOT_EXIST;
339     }
340     accountCredential_ = jsonObject.dump();
341     return ERR_OK;
342 }
343 
GetOAuthToken(const std::string & authType,std::string & token,const uint32_t apiVersion) const344 ErrCode AppAccountInfo::GetOAuthToken(const std::string &authType, std::string &token, const uint32_t apiVersion) const
345 {
346     token = "";
347     auto it = oauthTokens_.find(authType);
348     if (apiVersion >= Constants::API_VERSION9) {
349         if ((it == oauthTokens_.end()) || (!it->second.status)) {
350             ACCOUNT_LOGE("oauth token not exist");
351             return ERR_APPACCOUNT_SERVICE_OAUTH_TOKEN_NOT_EXIST;
352         }
353     } else {
354         if ((it == oauthTokens_.end()) || (it->second.token.empty())) {
355             ACCOUNT_LOGE("oauth token not exist");
356             return ERR_APPACCOUNT_SERVICE_OAUTH_TOKEN_NOT_EXIST;
357         }
358     }
359     token = it->second.token;
360     return ERR_OK;
361 }
362 
SetOAuthToken(const std::string & authType,const std::string & token)363 ErrCode AppAccountInfo::SetOAuthToken(const std::string &authType, const std::string &token)
364 {
365     auto it = oauthTokens_.find(authType);
366     if (it != oauthTokens_.end()) {
367 #ifndef HAS_ASSET_PART
368         it->second.token = token;
369 #endif
370         it->second.status = true;
371         return ERR_OK;
372     }
373     if (oauthTokens_.size() >= MAX_TOKEN_NUMBER) {
374         ACCOUNT_LOGE("too many types of oauth token, capacity for each account is %{public}d", MAX_TOKEN_NUMBER);
375         return ERR_APPACCOUNT_SERVICE_OAUTH_TOKEN_MAX_SIZE;
376     }
377     OAuthTokenInfo tokenInfo;
378     tokenInfo.status = !token.empty();
379 #ifndef HAS_ASSET_PART
380     tokenInfo.token = token;
381 #else
382     std::string authTypeAlias;
383     ComputeHash(authType, authTypeAlias);
384     tokenInfo.token = GetAlias() + authTypeAlias;
385 #endif
386     oauthTokens_.emplace(authType, tokenInfo);
387     return ERR_OK;
388 }
389 
DeleteOAuthToken(const std::string & authType,const std::string & token)390 ErrCode AppAccountInfo::DeleteOAuthToken(const std::string &authType, const std::string &token)
391 {
392     auto it = oauthTokens_.find(authType);
393     if ((it != oauthTokens_.end()) && (it->second.token == token)) {
394 #ifndef HAS_ASSET_PART
395         it->second.token = "";
396 #endif
397         it->second.status = false;
398         return ERR_OK;
399     }
400     return ERR_APPACCOUNT_SERVICE_OAUTH_TOKEN_NOT_EXIST;
401 }
402 
DeleteAuthToken(const std::string & authType,const std::string & token,bool isOwnerSelf)403 ErrCode AppAccountInfo::DeleteAuthToken(const std::string &authType, const std::string &token, bool isOwnerSelf)
404 {
405     auto it = oauthTokens_.find(authType);
406     if (it == oauthTokens_.end()) {
407         return ERR_APPACCOUNT_SERVICE_OAUTH_TOKEN_NOT_EXIST;
408     }
409     if (it->second.token != token) {
410         return ERR_OK;
411     }
412     if (isOwnerSelf) {
413         oauthTokens_.erase(it);
414     }
415     it->second.status = false;
416     return ERR_OK;
417 }
418 
SetOAuthTokenVisibility(const std::string & authType,const std::string & bundleName,bool isVisible,const uint32_t apiVersion)419 ErrCode AppAccountInfo::SetOAuthTokenVisibility(
420     const std::string &authType, const std::string &bundleName, bool isVisible, const uint32_t apiVersion)
421 {
422     if (bundleName == owner_) {
423         return ERR_OK;
424     }
425     auto it = oauthTokens_.find(authType);
426     if (it == oauthTokens_.end()) {
427         if (apiVersion >= Constants::API_VERSION9) {
428             return ERR_APPACCOUNT_SERVICE_OAUTH_TYPE_NOT_EXIST;
429         }
430         if (!isVisible) {
431             return ERR_OK;
432         }
433         if (oauthTokens_.size() >= MAX_TOKEN_NUMBER) {
434             ACCOUNT_LOGE("too many types of oauth token, capacity for each account is %{public}d", MAX_TOKEN_NUMBER);
435             return ERR_APPACCOUNT_SERVICE_OAUTH_TOKEN_MAX_SIZE;
436         }
437         OAuthTokenInfo tokenInfo;
438         tokenInfo.authList.emplace(bundleName);
439         oauthTokens_.emplace(authType, tokenInfo);
440         return ERR_OK;
441     }
442     if (!isVisible) {
443         it->second.authList.erase(bundleName);
444         return ERR_OK;
445     }
446     it->second.authList.emplace(bundleName);
447     if (it->second.authList.size() > MAX_OAUTH_LIST_SIZE) {
448         ACCOUNT_LOGE("the authorization list is too large, whose capacity for each authType is %{public}d",
449             MAX_OAUTH_LIST_SIZE);
450         it->second.authList.erase(bundleName);
451         return ERR_APPACCOUNT_SERVICE_OAUTH_LIST_MAX_SIZE;
452     }
453     return ERR_OK;
454 }
455 
CheckOAuthTokenVisibility(const std::string & authType,const std::string & bundleName,bool & isVisible,const uint32_t apiVersion) const456 ErrCode AppAccountInfo::CheckOAuthTokenVisibility(
457     const std::string &authType, const std::string &bundleName, bool &isVisible, const uint32_t apiVersion) const
458 {
459     isVisible = false;
460     if (bundleName == owner_) {
461         isVisible = true;
462         return ERR_OK;
463     }
464     auto tokenInfoIt = oauthTokens_.find(authType);
465     if (tokenInfoIt == oauthTokens_.end()) {
466         if (apiVersion >= Constants::API_VERSION9) {
467             return ERR_APPACCOUNT_SERVICE_OAUTH_TYPE_NOT_EXIST;
468         } else {
469             return ERR_OK;
470         }
471     }
472     std::set<std::string> authList = tokenInfoIt->second.authList;
473     auto it = authList.find(bundleName);
474     if (it != authList.end()) {
475         isVisible = true;
476     }
477     return ERR_OK;
478 }
479 
GetAllOAuthTokens(std::vector<OAuthTokenInfo> & tokenInfos) const480 ErrCode AppAccountInfo::GetAllOAuthTokens(std::vector<OAuthTokenInfo> &tokenInfos) const
481 {
482     tokenInfos.clear();
483     for (auto it = oauthTokens_.begin(); it != oauthTokens_.end(); ++it) {
484         tokenInfos.push_back(it->second);
485     }
486     return ERR_OK;
487 }
488 
GetOAuthList(const std::string & authType,std::set<std::string> & oauthList,const uint32_t apiVersion) const489 ErrCode AppAccountInfo::GetOAuthList(
490     const std::string &authType, std::set<std::string> &oauthList, const uint32_t apiVersion) const
491 {
492     oauthList.clear();
493     auto it = oauthTokens_.find(authType);
494     if (it == oauthTokens_.end()) {
495         if (apiVersion >= Constants::API_VERSION9) {
496             return ERR_APPACCOUNT_SERVICE_OAUTH_TYPE_NOT_EXIST;
497         } else {
498             return ERR_OK;
499         }
500     }
501     oauthList = it->second.authList;
502     return ERR_OK;
503 }
504 
Marshalling(Parcel & parcel) const505 bool AppAccountInfo::Marshalling(Parcel &parcel) const
506 {
507     if (!parcel.WriteString(owner_)) {
508         ACCOUNT_LOGE("failed to write string for owner_");
509         return false;
510     }
511 
512     if (!parcel.WriteString(name_)) {
513         ACCOUNT_LOGE("failed to write string for name_");
514         return false;
515     }
516 
517     if (!parcel.WriteString(extraInfo_)) {
518         ACCOUNT_LOGE("failed to write string for extraInfo_");
519         return false;
520     }
521 
522     if (!WriteStringSet(authorizedApps_, parcel)) {
523         ACCOUNT_LOGE("failed to write string set for authorizedApps_");
524         return false;
525     }
526 
527     if (!parcel.WriteBool(syncEnable_)) {
528         ACCOUNT_LOGE("failed to write bool for syncEnable_");
529         return false;
530     }
531 
532     if (!parcel.WriteString(associatedData_)) {
533         ACCOUNT_LOGE("failed to write string for associatedData_");
534         return false;
535     }
536 
537     if (!parcel.WriteString(accountCredential_)) {
538         ACCOUNT_LOGE("failed to write string for accountCredential_");
539         return false;
540     }
541 
542     if (!WriteTokenInfos(oauthTokens_, parcel)) {
543         ACCOUNT_LOGE("failed to write string map for oauthTokens_");
544         return false;
545     }
546     return true;
547 }
548 
Unmarshalling(Parcel & parcel)549 AppAccountInfo *AppAccountInfo::Unmarshalling(Parcel &parcel)
550 {
551     AppAccountInfo *appAccountInfo = new (std::nothrow) AppAccountInfo();
552 
553     if ((appAccountInfo != nullptr) && (!appAccountInfo->ReadFromParcel(parcel))) {
554         ACCOUNT_LOGE("failed to read from parcel");
555         delete appAccountInfo;
556         appAccountInfo = nullptr;
557     }
558 
559     return appAccountInfo;
560 }
561 
ToJson() const562 Json AppAccountInfo::ToJson() const
563 {
564     auto tokenArray = Json::array();
565     for (auto it = oauthTokens_.begin(); it != oauthTokens_.end(); ++it) {
566         if (!it->second.status && it->second.authList.empty()) {
567             continue;
568         }
569         auto tokenObject = Json {
570             {OAUTH_TYPE, it->first},
571             {OAUTH_TOKEN, it->second.token},
572             {OAUTH_TOKEN_STATUS, it->second.status},
573             {OAUTH_AUTH_LIST, it->second.authList}
574         };
575         tokenArray.push_back(tokenObject);
576     }
577     auto jsonObject = Json {
578         {OWNER, owner_},
579         {NAME, name_},
580         {ALIAS, alias_},
581         {EXTRA_INFO, extraInfo_},
582         {AUTHORIZED_APPS, authorizedApps_},
583         {SYNC_ENABLE, syncEnable_},
584         {ASSOCIATED_DATA, associatedData_},
585         {ACCOUNT_CREDENTIAL, accountCredential_},
586         {OAUTH_TOKEN_INFOS, tokenArray},
587     };
588 
589     return jsonObject;
590 }
591 
ParseTokenInfosFromJson(const Json & jsonObject)592 void AppAccountInfo::ParseTokenInfosFromJson(const Json &jsonObject)
593 {
594     oauthTokens_.clear();
595     for (auto it = jsonObject.begin(); it != jsonObject.end(); ++it) {
596         OAuthTokenInfo tokenInfo;
597         if (it->find(OAUTH_TOKEN) != it->end() && it->at(OAUTH_TOKEN).is_string()) {
598             it->at(OAUTH_TOKEN).get_to(tokenInfo.token);
599         }
600         if (it->find(OAUTH_TOKEN_STATUS) != it->end() && it->at(OAUTH_TOKEN_STATUS).is_boolean()) {
601             it->at(OAUTH_TOKEN_STATUS).get_to(tokenInfo.status);
602         }
603         if (it->find(OAUTH_TYPE) != it->end() && it->at(OAUTH_TYPE).is_string()) {
604             it->at(OAUTH_TYPE).get_to(tokenInfo.authType);
605         }
606         if (it->find(OAUTH_AUTH_LIST) != it->end() && it->at(OAUTH_AUTH_LIST).is_array()) {
607             it->at(OAUTH_AUTH_LIST).get_to(tokenInfo.authList);
608         }
609         oauthTokens_.emplace(tokenInfo.authType, tokenInfo);
610     }
611 }
612 
FromJson(const Json & jsonObject)613 bool AppAccountInfo::FromJson(const Json &jsonObject)
614 {
615     const auto &jsonObjectEnd = jsonObject.end();
616 
617     OHOS::AccountSA::GetDataByType<std::string>(
618         jsonObject, jsonObjectEnd, OWNER, owner_, OHOS::AccountSA::JsonType::STRING);
619     OHOS::AccountSA::GetDataByType<std::string>(
620         jsonObject, jsonObjectEnd, NAME, name_, OHOS::AccountSA::JsonType::STRING);
621     OHOS::AccountSA::GetDataByType<std::string>(
622         jsonObject, jsonObjectEnd, ALIAS, alias_, OHOS::AccountSA::JsonType::STRING);
623     OHOS::AccountSA::GetDataByType<std::string>(
624         jsonObject, jsonObjectEnd, EXTRA_INFO, extraInfo_, OHOS::AccountSA::JsonType::STRING);
625     OHOS::AccountSA::GetDataByType<bool>(
626         jsonObject, jsonObjectEnd, SYNC_ENABLE, syncEnable_, OHOS::AccountSA::JsonType::BOOLEAN);
627     OHOS::AccountSA::GetDataByType<std::set<std::string>>(
628         jsonObject, jsonObjectEnd, AUTHORIZED_APPS, authorizedApps_, OHOS::AccountSA::JsonType::ARRAY);
629     OHOS::AccountSA::GetDataByType<std::string>(
630         jsonObject, jsonObjectEnd, ASSOCIATED_DATA, associatedData_, OHOS::AccountSA::JsonType::STRING);
631     OHOS::AccountSA::GetDataByType<std::string>(
632         jsonObject, jsonObjectEnd, ACCOUNT_CREDENTIAL, accountCredential_, OHOS::AccountSA::JsonType::STRING);
633     if (jsonObject.find(OAUTH_TOKEN_INFOS) != jsonObjectEnd) {
634         ParseTokenInfosFromJson(jsonObject.at(OAUTH_TOKEN_INFOS));
635     }
636     return true;
637 }
638 
ToString() const639 std::string AppAccountInfo::ToString() const
640 {
641     auto jsonObject = ToJson();
642     try {
643         return jsonObject.dump();
644     } catch (Json::type_error& err) {
645         ACCOUNT_LOGE("failed to dump json object, reason: %{public}s", err.what());
646         return "";
647     }
648 }
649 
GetPrimeKey() const650 std::string AppAccountInfo::GetPrimeKey() const
651 {
652     return (owner_ + HYPHEN + std::to_string(appIndex_) + HYPHEN + name_ + HYPHEN);
653 }
654 
GetAlias()655 std::string AppAccountInfo::GetAlias()
656 {
657 #ifdef HAS_ASSET_PART
658     if (alias_.empty()) {
659         ComputeHash(GetPrimeKey(), alias_);
660     }
661 #endif
662     return alias_;
663 }
664 
ReadFromParcel(Parcel & parcel)665 bool AppAccountInfo::ReadFromParcel(Parcel &parcel)
666 {
667     if (!parcel.ReadString(owner_)) {
668         ACCOUNT_LOGE("failed to read string for owner_");
669         return false;
670     }
671 
672     if (!parcel.ReadString(name_)) {
673         ACCOUNT_LOGE("failed to read string for name_");
674         return false;
675     }
676 
677     if (!parcel.ReadString(extraInfo_)) {
678         ACCOUNT_LOGE("failed to read string for extraInfo_");
679         return false;
680     }
681 
682     if (!ReadStringSet(authorizedApps_, parcel)) {
683         ACCOUNT_LOGE("failed to read string set for authorizedApps_");
684         return false;
685     }
686 
687     if (!parcel.ReadBool(syncEnable_)) {
688         ACCOUNT_LOGE("failed to read string for syncEnable_");
689         return false;
690     }
691 
692     if (!parcel.ReadString(associatedData_)) {
693         ACCOUNT_LOGE("failed to read string for associatedData_");
694         return false;
695     }
696 
697     if (!parcel.ReadString(accountCredential_)) {
698         ACCOUNT_LOGE("failed to read string for accountCredential_");
699         return false;
700     }
701 
702     if (!ReadTokenInfos(oauthTokens_, parcel)) {
703         ACCOUNT_LOGE("failed to read string map for oauthTokens_");
704         return false;
705     }
706     return true;
707 }
708 
WriteStringSet(const std::set<std::string> & stringSet,Parcel & data) const709 bool AppAccountInfo::WriteStringSet(const std::set<std::string> &stringSet, Parcel &data) const
710 {
711     if (!data.WriteUint32(stringSet.size())) {
712         ACCOUNT_LOGE("failed to WriteInt32 for stringSet.size()");
713         return false;
714     }
715 
716     for (auto it : stringSet) {
717         if (!data.WriteString(it)) {
718             ACCOUNT_LOGE("failed to WriteString for it");
719             return false;
720         }
721     }
722 
723     return true;
724 }
725 
ReadStringSet(std::set<std::string> & stringSet,Parcel & data)726 bool AppAccountInfo::ReadStringSet(std::set<std::string> &stringSet, Parcel &data)
727 {
728     uint32_t size = 0;
729     if (!data.ReadUint32(size)) {
730         ACCOUNT_LOGE("failed to ReadInt32 for size");
731         return false;
732     }
733 
734     if (size > Constants::MAX_CUSTOM_DATA_SIZE) {
735         ACCOUNT_LOGE("ReadStringSet oversize");
736         return false;
737     }
738     stringSet.clear();
739     for (uint32_t index = 0; index < size; index += 1) {
740         std::string it = data.ReadString();
741         if (it.size() == 0) {
742             ACCOUNT_LOGE("failed to ReadString for it");
743             return false;
744         }
745         stringSet.emplace(it);
746     }
747 
748     return true;
749 }
750 
WriteStringMap(const std::map<std::string,std::string> & stringMap,Parcel & data) const751 bool AppAccountInfo::WriteStringMap(const std::map<std::string, std::string> &stringMap, Parcel &data) const
752 {
753     if (!data.WriteInt32(stringMap.size())) {
754         ACCOUNT_LOGE("failed to WriteInt32 for stringSet.size()");
755         return false;
756     }
757 
758     for (auto& it : stringMap) {
759         if (!data.WriteString(it.first)) {
760             ACCOUNT_LOGE("failed to WriteString for authType");
761             return false;
762         }
763         if (!data.WriteString(it.second)) {
764             ACCOUNT_LOGE("failed to WriteString for token");
765             return false;
766         }
767     }
768 
769     return true;
770 }
771 
WriteTokenInfos(const std::map<std::string,OAuthTokenInfo> & tokenInfos,Parcel & data) const772 bool AppAccountInfo::WriteTokenInfos(const std::map<std::string, OAuthTokenInfo> &tokenInfos, Parcel &data) const
773 {
774     if (!data.WriteUint32(tokenInfos.size())) {
775         ACCOUNT_LOGE("failed to WriteInt32 for stringSet.size()");
776         return false;
777     }
778     for (auto& it : tokenInfos) {
779         if (!data.WriteString(it.first)) {
780             ACCOUNT_LOGE("failed to WriteString for authType");
781             return false;
782         }
783         if (!data.WriteString(it.second.token)) {
784             ACCOUNT_LOGE("failed to WriteString for token");
785             return false;
786         }
787         if (!WriteStringSet(it.second.authList, data)) {
788             ACCOUNT_LOGE("failed to WriteString for authList");
789             return false;
790         }
791     }
792     return true;
793 }
794 
ReadStringMap(std::map<std::string,std::string> & stringMap,Parcel & data)795 bool AppAccountInfo::ReadStringMap(std::map<std::string, std::string> &stringMap, Parcel &data)
796 {
797     int32_t size = 0;
798     if (!data.ReadInt32(size)) {
799         ACCOUNT_LOGE("failed to ReadInt32 for size");
800         return false;
801     }
802     if ((size < 0) || (size > MAX_MAP_SZIE)) {
803         ACCOUNT_LOGE("ReadStringMap oversize");
804         return false;
805     }
806     stringMap.clear();
807     for (int32_t index = 0; index < size; ++index) {
808         std::string key;
809         std::string value;
810         if (!data.ReadString(key)) {
811             ACCOUNT_LOGE("failed to ReadString for key");
812             return false;
813         }
814         if (!data.ReadString(value)) {
815             ACCOUNT_LOGE("failed to ReadString for value");
816             return false;
817         }
818         stringMap.emplace(key, value);
819     }
820 
821     return true;
822 }
823 
ReadTokenInfos(std::map<std::string,OAuthTokenInfo> & tokenInfos,Parcel & data)824 bool AppAccountInfo::ReadTokenInfos(std::map<std::string, OAuthTokenInfo> &tokenInfos, Parcel &data)
825 {
826     uint32_t size = 0;
827     if (!data.ReadUint32(size)) {
828         ACCOUNT_LOGE("failed to ReadInt32 for size");
829         return false;
830     }
831     if (size > MAX_TOKEN_NUMBER) {
832         ACCOUNT_LOGE("invalid token number");
833         return false;
834     }
835     tokenInfos.clear();
836     for (uint32_t index = 0; index < size; ++index) {
837         OAuthTokenInfo tokenInfo;
838         if (!data.ReadString(tokenInfo.authType)) {
839             ACCOUNT_LOGE("failed to ReadString for authType");
840             return false;
841         }
842         if (!data.ReadString(tokenInfo.token)) {
843             ACCOUNT_LOGE("failed to ReadString for token");
844             return false;
845         }
846         if (!ReadStringSet(tokenInfo.authList, data)) {
847             ACCOUNT_LOGE("failed to ReadString for authList");
848             return false;
849         }
850         tokenInfos.emplace(tokenInfo.authType, tokenInfo);
851     }
852     return true;
853 }
854 }  // namespace AccountSA
855 }  // namespace OHOS
856