use crate::network::{Api, ForgeApiKind, forgejo::ForgejoApi, gitlab::GitLabApi};
use reqwest::header::{HeaderValue, InvalidHeaderValue};
use secrecy::{CloneableSecret, SecretBox, zeroize::Zeroize};
use url::Url;
#[derive(Clone, Debug)]
pub struct Config {
pub certs_dir: String,
pub forge_kind: ForgeApiKind,
pub forge_list_users: bool,
pub forge_secret_key: Option<SecretHeader>,
pub forge_url: Url,
pub port: u16,
}
#[derive(Clone)]
pub(crate) struct ZeroizedHeaderValue(Vec<u8>);
impl CloneableSecret for ZeroizedHeaderValue {}
impl Zeroize for ZeroizedHeaderValue {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
impl ZeroizedHeaderValue {
pub(crate) fn try_from(value: String) -> Result<Self, InvalidHeaderValue> {
let mut value = HeaderValue::try_from(value)?;
value.set_sensitive(true);
Ok(Self::from(value))
}
pub(crate) fn from(value: HeaderValue) -> Self {
Self(value.as_bytes().to_owned())
}
pub(crate) fn as_header_value(&self) -> HeaderValue {
let mut value = HeaderValue::from_bytes(&self.0).expect("value already checked");
value.set_sensitive(true);
value
}
pub(crate) fn with_prefix(&self, prefix: &str) -> Self {
let value = [prefix.as_bytes(), self.0.as_slice()].concat();
Self(value)
}
}
pub(crate) type SecretHeader = SecretBox<ZeroizedHeaderValue>;
impl From<ZeroizedHeaderValue> for SecretHeader {
fn from(value: ZeroizedHeaderValue) -> Self {
Self::new(Box::new(value))
}
}
impl Default for Config {
fn default() -> Self {
Self {
certs_dir: String::from(".certs"),
forge_kind: ForgeApiKind::Forgejo,
forge_list_users: false,
forge_secret_key: None,
forge_url: Url::parse("http://localhost:3000").expect("Valid default URL"),
port: 1965,
}
}
}
impl Config {
pub fn forge_api(&self) -> Api {
let kind = self.forge_kind;
let forge_url = self.forge_url.clone();
let private_token = &self.forge_secret_key;
println!("Preparing {kind} API");
match kind {
ForgeApiKind::Forgejo => {
Api::Forgejo(ForgejoApi::from_url(forge_url, kind, private_token))
}
ForgeApiKind::Gitea => Api::Gitea(ForgejoApi::from_url(forge_url, kind, private_token)),
ForgeApiKind::GitLab => Api::GitLab(GitLabApi::from_url(forge_url, private_token)),
}
}
}