mobile-music/lib/subsonic/credentials.dart
2026-07-29 14:14:18 -04:00

64 lines
2.1 KiB
Dart

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
/// A Subsonic server connection. The password is only ever held in memory and
/// in the platform secure store — never in plain app storage (mirrors Ratune's
/// keyring-first secret handling).
class SubsonicCredentials {
const SubsonicCredentials({
required this.url,
required this.username,
required this.password,
this.alias,
});
final String url;
final String username;
final String password;
/// Optional display label shown instead of the raw URL (Ratune `[server].alias`).
final String? alias;
String get display => alias?.isNotEmpty == true ? alias! : Uri.parse(url).host;
}
/// Persists [SubsonicCredentials] to the platform secure store
/// (Keychain / Keystore / libsecret).
class CredentialStore {
CredentialStore([FlutterSecureStorage? storage])
: _storage = storage ?? const FlutterSecureStorage();
final FlutterSecureStorage _storage;
static const _kUrl = 'subsonic_url';
static const _kUser = 'subsonic_username';
static const _kPass = 'subsonic_password';
static const _kAlias = 'subsonic_alias';
Future<void> save(SubsonicCredentials creds) async {
await _storage.write(key: _kUrl, value: creds.url);
await _storage.write(key: _kUser, value: creds.username);
await _storage.write(key: _kPass, value: creds.password);
await _storage.write(key: _kAlias, value: creds.alias ?? '');
}
Future<SubsonicCredentials?> load() async {
final url = await _storage.read(key: _kUrl);
final user = await _storage.read(key: _kUser);
final pass = await _storage.read(key: _kPass);
if (url == null || user == null || pass == null) return null;
final alias = await _storage.read(key: _kAlias);
return SubsonicCredentials(
url: url,
username: user,
password: pass,
alias: (alias == null || alias.isEmpty) ? null : alias,
);
}
Future<void> clear() async {
await _storage.delete(key: _kUrl);
await _storage.delete(key: _kUser);
await _storage.delete(key: _kPass);
await _storage.delete(key: _kAlias);
}
}