#include "WifiCredentialStore.h" #include #include #include void WifiCredentialStore::toJson(JsonDocument& doc) const { doc["lastConnectedSsid"] = lastConnectedSsid; JsonArray arr = doc["credentials"].to(); for (const auto& cred : credentials) { JsonObject obj = arr.add(); obj["ssid"] = cred.ssid; obj["password_obf"] = obfuscation::obfuscateToBase64(cred.password); } } bool WifiCredentialStore::fromJson(JsonVariantConst doc) { lastConnectedSsid = doc["lastConnectedSsid"] | ""; // Tolerate a missing/invalid 'credentials' key (treat as empty list); only // a JSON parse error is fatal. A null JsonArray iterates zero times. credentials.clear(); JsonArrayConst arr = doc["credentials"].as(); credentials.reserve(std::min(arr.size(), MAX_NETWORKS)); bool needsResave = false; for (JsonObjectConst obj : arr) { if (credentials.size() >= MAX_NETWORKS) break; WifiCredential cred; cred.ssid = obj["ssid"] | ""; cred.password = extractPassword(obj, needsResave); credentials.push_back(cred); } LOG_DBG("WCS", "Loaded %zu WiFi credentials from file", credentials.size()); if (needsResave) { LOG_DBG("WCS", "Resaving JSON with obfuscated passwords"); saveToFile(); } return true; } bool WifiCredentialStore::addCredential(const std::string& ssid, const std::string& password) { // Check if this SSID already exists and update it const auto cred = find_if(credentials.begin(), credentials.end(), [&ssid](const WifiCredential& cred) { return cred.ssid == ssid; }); if (cred != credentials.end()) { cred->password = password; LOG_DBG("WCS", "Updated credentials for: %s", ssid.c_str()); return saveToFile(); } // Check if we've reached the limit if (credentials.size() >= MAX_NETWORKS) { LOG_DBG("WCS", "Cannot add more networks, limit of %zu reached", MAX_NETWORKS); return false; } // Add new credential credentials.push_back({ssid, password}); LOG_DBG("WCS", "Added credentials for: %s", ssid.c_str()); return saveToFile(); } bool WifiCredentialStore::removeCredential(const std::string& ssid) { const auto cred = find_if(credentials.begin(), credentials.end(), [&ssid](const WifiCredential& cred) { return cred.ssid == ssid; }); if (cred != credentials.end()) { credentials.erase(cred); LOG_DBG("WCS", "Removed credentials for: %s", ssid.c_str()); if (ssid == lastConnectedSsid) { clearLastConnectedSsid(); } return saveToFile(); } return false; // Not found } const WifiCredential* WifiCredentialStore::findCredential(const std::string& ssid) const { const auto cred = find_if(credentials.begin(), credentials.end(), [&ssid](const WifiCredential& cred) { return cred.ssid == ssid; }); if (cred != credentials.end()) { return &*cred; } return nullptr; } bool WifiCredentialStore::hasSavedCredential(const std::string& ssid) const { return findCredential(ssid) != nullptr; } void WifiCredentialStore::setLastConnectedSsid(const std::string& ssid) { if (lastConnectedSsid != ssid) { lastConnectedSsid = ssid; saveToFile(); } } const std::string& WifiCredentialStore::getLastConnectedSsid() const { return lastConnectedSsid; } void WifiCredentialStore::clearLastConnectedSsid() { if (!lastConnectedSsid.empty()) { lastConnectedSsid.clear(); saveToFile(); } } void WifiCredentialStore::clearAll() { credentials.clear(); lastConnectedSsid.clear(); saveToFile(); LOG_DBG("WCS", "Cleared all WiFi credentials"); }