WellNuo/services/wifiPasswordStore.ts
Sergei 70f9a91be1 Remove console.log statements from codebase
Removed all console.log, console.error, console.warn, console.info, and console.debug statements from the main source code to clean up production output.

Changes:
- Removed 400+ console statements from TypeScript/TSX files
- Cleaned BLE services (BLEManager.ts, MockBLEManager.ts)
- Cleaned API services, contexts, hooks, and components
- Cleaned WiFi setup and sensor management screens
- Preserved console statements in test files (*.test.ts, __tests__/)
- TypeScript compilation verified successfully

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-29 12:44:16 -08:00

223 lines
6.0 KiB
TypeScript

/**
* WiFi Password Secure Storage Service
*
* Provides secure storage for WiFi passwords using expo-secure-store with encryption.
* All passwords are encrypted using AES-256-GCM before storage.
*/
import * as SecureStore from 'expo-secure-store';
import { encrypt, decrypt, isEncrypted } from './encryption';
const WIFI_PASSWORDS_KEY = 'WIFI_PASSWORDS';
const LEGACY_SINGLE_PASSWORD_KEY = 'LAST_WIFI_PASSWORD';
export interface WiFiPasswordMap {
[ssid: string]: string;
}
/**
* Save WiFi password for a specific network
* @param ssid Network SSID
* @param password Network password
*/
export async function saveWiFiPassword(ssid: string, password: string): Promise<void> {
try {
// Get existing passwords
const existing = await getAllWiFiPasswords();
// Encrypt the password
const encryptedPassword = await encrypt(password);
// Add/update the password
existing[ssid] = encryptedPassword;
// Save back to SecureStore
await SecureStore.setItemAsync(WIFI_PASSWORDS_KEY, JSON.stringify(existing));
} catch (error) {
throw error;
}
}
/**
* Get WiFi password for a specific network
* @param ssid Network SSID
* @returns Decrypted password or undefined if not found
*/
export async function getWiFiPassword(ssid: string): Promise<string | undefined> {
try {
const passwords = await getAllWiFiPasswords();
const encryptedPassword = passwords[ssid];
if (!encryptedPassword) {
return undefined;
}
// Decrypt the password
const decryptedPassword = await decrypt(encryptedPassword);
return decryptedPassword;
} catch (error) {
return undefined;
}
}
/**
* Get all saved WiFi passwords (encrypted format)
* Internal helper - passwords remain encrypted
* @returns Map of SSID to encrypted password
*/
async function getAllWiFiPasswordsEncrypted(): Promise<WiFiPasswordMap> {
try {
const stored = await SecureStore.getItemAsync(WIFI_PASSWORDS_KEY);
if (stored) {
return JSON.parse(stored);
}
return {};
} catch (error) {
return {};
}
}
/**
* Get all saved WiFi passwords (decrypted)
* @returns Map of SSID to decrypted password
*/
export async function getAllWiFiPasswords(): Promise<WiFiPasswordMap> {
try {
const encryptedPasswords = await getAllWiFiPasswordsEncrypted();
const decryptedPasswords: WiFiPasswordMap = {};
// Decrypt each password
for (const [ssid, encryptedPassword] of Object.entries(encryptedPasswords)) {
try {
decryptedPasswords[ssid] = await decrypt(encryptedPassword);
} catch (error) {
// Skip this password if decryption fails
}
}
return decryptedPasswords;
} catch (error) {
return {};
}
}
/**
* Remove WiFi password for a specific network
* @param ssid Network SSID
*/
export async function removeWiFiPassword(ssid: string): Promise<void> {
try {
const existing = await getAllWiFiPasswordsEncrypted();
// Remove the password
delete existing[ssid];
// Save back to SecureStore
if (Object.keys(existing).length > 0) {
await SecureStore.setItemAsync(WIFI_PASSWORDS_KEY, JSON.stringify(existing));
} else {
// If no passwords left, remove the key entirely
await SecureStore.deleteItemAsync(WIFI_PASSWORDS_KEY);
}
} catch (error) {
throw error;
}
}
/**
* Clear all saved WiFi passwords
* Should be called on logout
*/
export async function clearAllWiFiPasswords(): Promise<void> {
try {
await SecureStore.deleteItemAsync(WIFI_PASSWORDS_KEY);
} catch (error) {
throw error;
}
}
/**
* Migrate unencrypted passwords to encrypted format
* Checks each stored password and encrypts if needed
*/
export async function migrateToEncrypted(): Promise<void> {
try {
const stored = await SecureStore.getItemAsync(WIFI_PASSWORDS_KEY);
if (!stored) {
return;
}
const passwords: WiFiPasswordMap = JSON.parse(stored);
let migrated = 0;
const encryptedPasswords: WiFiPasswordMap = {};
// Check each password
for (const [ssid, password] of Object.entries(passwords)) {
if (isEncrypted(password)) {
// Already encrypted
encryptedPasswords[ssid] = password;
} else {
// Encrypt the plaintext password
encryptedPasswords[ssid] = await encrypt(password);
migrated++;
}
}
// Save back if any were migrated
if (migrated > 0) {
await SecureStore.setItemAsync(WIFI_PASSWORDS_KEY, JSON.stringify(encryptedPasswords));
} else {
}
} catch (error) {
// Don't throw - migration failure shouldn't break the app
}
}
/**
* Migrate WiFi passwords from AsyncStorage to SecureStore with encryption
* This function should be called once during app startup to migrate existing data
*/
export async function migrateFromAsyncStorage(): Promise<void> {
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const AsyncStorage = require('@react-native-async-storage/async-storage').default;
// Check if migration already done
const existing = await SecureStore.getItemAsync(WIFI_PASSWORDS_KEY);
if (existing) {
// Still run encryption migration in case they were migrated but not encrypted
await migrateToEncrypted();
return;
}
// Try to get old data from AsyncStorage
const oldPasswords = await AsyncStorage.getItem('WIFI_PASSWORDS');
if (oldPasswords) {
const passwords: WiFiPasswordMap = JSON.parse(oldPasswords);
const encryptedPasswords: WiFiPasswordMap = {};
// Encrypt each password during migration
for (const [ssid, password] of Object.entries(passwords)) {
encryptedPasswords[ssid] = await encrypt(password);
}
// Migrate to SecureStore with encryption
await SecureStore.setItemAsync(WIFI_PASSWORDS_KEY, JSON.stringify(encryptedPasswords));
// Remove from AsyncStorage
await AsyncStorage.removeItem('WIFI_PASSWORDS');
await AsyncStorage.removeItem(LEGACY_SINGLE_PASSWORD_KEY);
} else {
}
} catch (error) {
// Don't throw - migration failure shouldn't break the app
}
}