Files
pmomusic/pmoconfig
Eric Coissac fe9dd9aba6 ♻️ refactor(pmowebrenderer): factoriser handlers et supprimer duplications
- Remplacer les Arc+Box::pin manuels par la macro action_handler!(captures(...))
- Supprimer helpers locaux dupliqués dans renderer.rs (add_var, add_action)
- Extraire handlers génériques pour GET requests
- Factoriser extraction metadata dans set_uri_handler /set_next_uriHandler  
- Simplifier build_renderingcontrol en retirant pipeline inutile
- Mettre à jour edition Rust de 2021 vers 2024 dans tous les Cargo.toml
- Corriger pattern matching inutile `ref` sur déréférencement dans pmoaudio et pmoflac
2026-04-05 14:09:46 +02:00
..
2025-12-11 21:35:17 +00:00

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 :

  1. Répertoire fourni en paramètre
  2. Variable d'environnement PMOMUSIC_CONFIG
  3. .pmomusic dans le répertoire courant
  4. .pmomusic dans 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 configuration
  • GET /api/config/{path} - Récupère une valeur spécifique
  • PUT /api/config/{path} - Modifie une valeur
  • GET /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.