| 136 | } |
| 137 | |
| 138 | std::unordered_map<std::string, std::string> LoadFileTokens(uint32_t accountId, uint32_t appId) { |
| 139 | auto localFileTokens = LocalMetadataStore::LoadFileTokens(accountId, appId); |
| 140 | if (!localFileTokens.empty() || !g_tokenProvider || !g_tokenProvider->IsAuthenticated()) |
| 141 | return localFileTokens; |
| 142 | |
| 143 | InflightSyncScope guard; |
| 144 | if (!guard) return localFileTokens; |
| 145 | |
| 146 | auto validRootTokens = LoadRootTokens(accountId, appId); |
| 147 | |
| 148 | std::vector<uint8_t> cloudData; |
| 149 | bool usedLegacyFileTokens = false; |
| 150 | if (!DownloadCloudMetadataWithLegacyFallback(accountId, appId, |
| 151 | kFileTokensFilename, kLegacyFileTokensFilename, |
| 152 | cloudData, &usedLegacyFileTokens)) |
| 153 | return localFileTokens; |
| 154 | |
| 155 | std::unordered_map<std::string, std::string> cloudFileTokens; |
| 156 | std::istringstream iss(std::string(cloudData.begin(), cloudData.end())); |
| 157 | std::string line; |
| 158 | while (std::getline(iss, line)) { |
| 159 | while (!line.empty() && (line.back() == '\r' || line.back() == '\n')) |
| 160 | line.pop_back(); |
| 161 | if (line.empty()) continue; |
| 162 | auto tab = line.find('\t'); |
| 163 | if (tab == std::string::npos) continue; |
| 164 | std::string cleanName = line.substr(0, tab); |
| 165 | std::string token = line.substr(tab + 1); |
| 166 | if (cleanName.empty()) continue; |
| 167 | if (!validRootTokens.empty() && !token.empty() && !validRootTokens.count(token)) continue; |
| 168 | cloudFileTokens[cleanName] = token; |
| 169 | } |
| 170 | |
| 171 | if (cloudFileTokens.empty()) return localFileTokens; |
| 172 | |
| 173 | if (!LocalMetadataStore::SaveFileTokens(accountId, appId, cloudFileTokens)) { |
| 174 | LOG("[TokenStore] LoadFileTokens app %u: failed to persist cloud token fallback locally", appId); |
| 175 | return localFileTokens; |
| 176 | } |
| 177 | |
| 178 | if (usedLegacyFileTokens) { |
| 179 | std::string cleaned; |
| 180 | for (const auto& [cleanName, token] : cloudFileTokens) |
| 181 | cleaned += cleanName + "\t" + token + "\n"; |
| 182 | if (UploadCloudMetadataText(accountId, appId, kFileTokensFilename, cleaned)) |
| 183 | RemoveCloudMetadataIfPresent(accountId, appId, kLegacyFileTokensFilename); |
| 184 | else |
| 185 | LOG("[TokenStore] LoadFileTokens app %u: failed to migrate legacy cloud file tokens", appId); |
| 186 | } else { |
| 187 | RemoveCloudMetadataIfPresent(accountId, appId, kLegacyFileTokensFilename); |
| 188 | } |
| 189 | |
| 190 | return cloudFileTokens; |
| 191 | } |
| 192 | |
| 193 | } // namespace CloudStorage |
no test coverage detected