sawe 0.1.2

wrapper for salvo with handlebars, ufs, uiicons & SEO rendering
use salvo::conn::rustls::{Keycert, RustlsConfig};

use rcgen::{generate_simple_self_signed, CertifiedKey};


static DEFAULT_HOSTS: &[&str] = &[ "localhost", "127.0.0.1", "0.0.0.0", "::1", "::" ];

pub fn generate_or_load_self_signed(
    path: impl AsRef<std::path::Path> + Copy,
    subject_alt_names: Option<Vec<&str>>
) -> Result<(Vec<u8>, Vec<u8>), TlsServerError> {
    
    if !path.as_ref().exists() {
        std::fs::create_dir_all(path)?;
    }

    let key = path.as_ref().join("key.pem");
    let certs = path.as_ref().join("certs.pem");

    if !key.exists() && !certs.exists() {
        let CertifiedKey { cert, signing_key } = generate_simple_self_signed(
            subject_alt_names
                .unwrap_or(DEFAULT_HOSTS.to_vec())
                .iter()
                .map(|i| i.to_string())
                .collect::<Vec<String>>()
        ).unwrap();
        std::fs::write(&key, signing_key.serialize_pem())?;
        std::fs::write(&certs, cert.pem())?;
    }

    Ok((std::fs::read(certs)?, std::fs::read(key)?))

}

pub fn create_rustls_config(
    path: impl AsRef<std::path::Path> + Copy,
    subject_alt_names: Option<Vec<&str>>
) -> Result<RustlsConfig, TlsServerError> {

    let tls = generate_or_load_self_signed(path.as_ref(), subject_alt_names)?;

    Ok(RustlsConfig::new(Keycert::new().cert(tls.0).key(tls.1)))

}

#[derive(Debug, thiserror::Error)]
pub enum TlsServerError {
    #[error(transparent)]
    Io(#[from] std::io::Error),
    #[error(transparent)]
    Fmt(#[from] std::fmt::Error),
    #[error(transparent)]
    SalvoError(#[from] salvo::Error),
    #[error(transparent)]
    Join(#[from] tokio::task::JoinError),
}