gled-core 2.31.2

The engine of gled without a user interface: inputs, timing, rendering, Art-Net/DMX output and storage
Documentation
//! The SSH key the storage repository is reached with; its passphrase lives
//! in the system keychain, not in the persistent state.

use crate::action::UiAction;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};

static SSH_KEY_PASSPHRASE_ENTRY: Lazy<Option<keyring_core::Entry>> = Lazy::new(|| {
    keyring_core::Entry::new("gled2", "ssh_key_passphrase")
        .map_err(|err| UiAction::Error(format!("Could not get keyring entry: {err:?}")).enqueue())
        .ok()
});

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub(crate) struct GitCredentials {
    private_key_path: Option<PathBuf>,
    use_passphrase: bool,
}

impl GitCredentials {
    pub(crate) fn private_key_path(&self) -> Option<&Path> {
        self.private_key_path.as_deref()
    }

    pub(crate) fn set_private_key_path(&mut self, private_key_path: PathBuf) {
        self.private_key_path = Some(private_key_path);
    }

    pub(crate) fn use_passphrase(&self) -> bool {
        self.use_passphrase
    }

    pub(crate) fn set_use_passphrase(&mut self, use_passphrase: bool) {
        self.use_passphrase = use_passphrase;
    }

    pub(crate) fn passphrase(&self) -> Option<String> {
        if !self.use_passphrase {
            return None;
        }
        SSH_KEY_PASSPHRASE_ENTRY
            .as_ref()
            .and_then(|entry| entry.get_password().ok())
    }

    pub(crate) fn set_passphrase(&mut self, passphrase: String) {
        if let Some(entry) = SSH_KEY_PASSPHRASE_ENTRY.as_ref()
            && let Err(err) = entry.set_password(&passphrase)
        {
            UiAction::Error(format!(
                "Could not set passphrase in system keychain: {err:?}"
            ))
            .enqueue();
        }
    }
}