Migrate pmoutils crate to registry version 0.1.2 and update all dependencies to use the registry version instead of local path references. Remove pmoutils from Cargo.lock and Cargo.toml files where it was previously used as a local path dependency. Move ToXmlElement trait to pmodidl crate and update all usages to import from pmodidl instead of pmoutils. Fix parameter order in find_process_using_port function call.
pmoconfig - PMOMusic Configuration Module
Module de gestion de configuration pour PMOMusic avec support du chiffrement des mots de passe.
Fonctionnalités
- ✅ Configuration YAML avec valeurs par défaut intégrées
- ✅ Fusion automatique entre config par défaut et config utilisateur
- ✅ Overrides via variables d'environnement (
PMOMUSIC_CONFIG__) - ✅ Getters/setters type-safe pour les valeurs de configuration
- ✅ Pattern singleton thread-safe pour l'accès global
- ✅ 🔒 Chiffrement des mots de passe basé sur l'UUID de la machine
- ✅ API REST optionnelle (feature
api)
Utilisation de base
use pmoconfig::get_config;
// Obtenir la configuration globale
let config = get_config();
// Lire des valeurs
let port = config.get_http_port();
let cache_dir = config.get_cover_cache_dir()?;
// Modifier des valeurs
config.set_http_port(9000)?;
Chiffrement des mots de passe
PMOConfig intègre un système de chiffrement transparent des mots de passe basé sur l'UUID matériel de la machine.
Chiffrer un mot de passe
cargo run --example encrypt_password -- encrypt "MonMotDePasse"
Sortie :
Original: MonMotDePasse
Encrypted: encrypted:yRyu/jNlJRSdVz0eE+JX56UC2Tk016TmESDoLT6npLBJB3ZuhJ0XTqNOQjiXkkcB
Add this to your config.yaml:
password: "encrypted:yRyu/jNlJRSdVz0eE+JX56UC2Tk016TmESDoLT6npLBJB3ZuhJ0XTqNOQjiXkkcB"
Configuration
config.yaml avec mot de passe chiffré :
accounts:
qobuz:
username: user@example.com
password: encrypted:yRyu/jNlJRSdVz0eE+JX56UC2Tk016TmESDoLT6npLBJB3ZuhJ0XTqNOQjiXkkcB
Utilisation dans le code
use pmoconfig::encryption;
// Déchiffrement automatique (gère plaintext et encrypted)
let password = encryption::get_password(&value)?;
// Chiffrer
let encrypted = encryption::encrypt_password("secret")?;
// Déchiffrer
let decrypted = encryption::decrypt_password(&encrypted)?;
// Tester si chiffré
if encryption::is_encrypted(&value) {
// ...
}
Caractéristiques du chiffrement
- Algorithme : AES-256-GCM
- Clé : Dérivée de l'UUID matériel (SHA-256)
- Format :
encrypted:BASE64(nonce + ciphertext) - Déterministe : Même password = même ciphertext
Avantages
✅ Pas de keyring/keychain requis ✅ Pas de clé maître à gérer ✅ Transparent pour l'utilisateur ✅ Migration progressive (supporte plaintext et encrypted) ✅ Déchiffrement automatique
Limitations
⚠️ Non portable entre machines ⚠️ Sécurité limitée contre accès physique ⚠️ Pas de protection contre root/admin
📖 Documentation complète : PASSWORD_ENCRYPTION.md
Structure de la configuration
host:
http_port: 8080
base_url: "http://192.168.1.10:8080"
cover_cache:
directory: cache_covers
size: 2000
audio_cache:
directory: cache_audio
size: 500
logger:
buffer_capacity: 200
enable_console: true
min_level: INFO
playlists:
directory: playlists
devices:
mediarenderer:
pmo_mediarenderer:
udn: e4b68fbc-2bd5-4cea-98d8-be843fec0bd4
mediaserver:
pmo_mediaserver:
udn: 17fe2ea6-8908-4e30-bc52-b28ea4cab3e4
accounts:
qobuz:
username: user@example.com
password: encrypted:ABC123... # ← Mot de passe chiffré
appid: '798273057'
secret: 806331c3b0b641da923b890aed01d04a
Répertoires de configuration
La configuration est recherchée dans cet ordre :
- Répertoire fourni en paramètre
- Variable d'environnement
PMOMUSIC_CONFIG .pmomusicdans le répertoire courant.pmomusicdans le répertoire home (~/.pmomusic)
Overrides via variables d'environnement
# Format: PMOMUSIC_CONFIG__section__key
export PMOMUSIC_CONFIG__host__http_port=9000
export PMOMUSIC_CONFIG__host__logger__min_level=DEBUG
# Lancer l'application
./pmomusic
API REST (feature api)
[dependencies]
pmoconfig = { path = "../pmoconfig", features = ["api"] }
use pmoconfig::api::create_config_router;
use axum::Router;
let config_router = create_config_router();
let app = Router::new().nest("/api/config", config_router);
Endpoints disponibles :
GET /api/config- Récupère toute la configurationGET /api/config/{path}- Récupère une valeur spécifiquePUT /api/config/{path}- Modifie une valeurGET /api/config/docs- Documentation OpenAPI/Swagger
Exemples
Exemple complet
Voir examples/encrypt_password.rs pour un exemple complet de chiffrement/déchiffrement.
Utilisation dans un projet
use pmoconfig::{get_config, encryption};
use anyhow::Result;
fn main() -> Result<()> {
let config = get_config();
// Lire la configuration
let port = config.get_http_port();
println!("HTTP port: {}", port);
// Lire un mot de passe (automatiquement déchiffré)
let password_value = config.get_value(&["accounts", "service", "password"])?;
if let serde_yaml::Value::String(s) = password_value {
let password = encryption::get_password(&s)?;
println!("Password loaded successfully");
}
Ok(())
}
Tests
# Tests unitaires
cargo test
# Tests du module encryption
cargo test encryption
# Tester l'outil de chiffrement
cargo run --example encrypt_password -- test
Dépendances
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
anyhow = "1.0"
dirs = "6.0"
uuid = { version = "1.18", features = ["v4"] }
tracing = "0.1"
# Chiffrement
aes-gcm = "0.10"
sha2 = "0.10"
base64 = "0.22"
# Feature API (optionnel)
axum = { version = "0.8", optional = true }
utoipa = { version = "5.3", optional = true }
Licence
Voir LICENSE dans la racine du projet.