WIP
This commit is contained in:
commit
663af59488
8 changed files with 3534 additions and 0 deletions
96
src/config.rs
Normal file
96
src/config.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
use clap::builder::{TryMapValueParser, TypedValueParser, ValueParserFactory};
|
||||
use clio::CachedInput;
|
||||
use eyre::Context;
|
||||
use futures::future::try_join_all;
|
||||
use indexmap::IndexMap;
|
||||
use openidconnect::{
|
||||
core::{CoreClient, CoreProviderMetadata},
|
||||
ClientId, ClientSecret, IssuerUrl, Scope,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct Config {
|
||||
pub oidc: IndexMap<String, OIDCProvider>,
|
||||
}
|
||||
|
||||
impl ValueParserFactory for Config {
|
||||
type Parser = TryMapValueParser<
|
||||
<CachedInput as ValueParserFactory>::Parser,
|
||||
fn(CachedInput) -> eyre::Result<Config>,
|
||||
>;
|
||||
|
||||
fn value_parser() -> Self::Parser {
|
||||
CachedInput::value_parser().try_map(Config::load)
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub const EXAMPLE: &'static str =
|
||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/config.toml.sample"));
|
||||
pub fn load_str(input: &str, path: impl ToString) -> eyre::Result<Config> {
|
||||
toml::from_str(input).wrap_err_with(|| path.to_string())
|
||||
}
|
||||
|
||||
pub fn load(input: CachedInput) -> eyre::Result<Config> {
|
||||
let s = std::str::from_utf8(input.get_data()).wrap_err_with(|| input.path().to_string())?;
|
||||
toml::from_str(s).wrap_err_with(|| input.path().to_string())
|
||||
}
|
||||
|
||||
pub async fn resolve(&mut self) -> eyre::Result<()> {
|
||||
try_join_all(self.oidc.iter_mut().map(|(_, provider)| provider.resolve())).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OIDCProviderState {
|
||||
pub client: CoreClient,
|
||||
pub provider_metadata: CoreProviderMetadata,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct OIDCProvider {
|
||||
pub pretty_name: String,
|
||||
pub issuer_url: IssuerUrl,
|
||||
pub client_id: ClientId,
|
||||
pub secret: ClientSecret,
|
||||
pub scopes: Vec<Scope>,
|
||||
#[serde(skip)]
|
||||
state: Option<OIDCProviderState>,
|
||||
}
|
||||
|
||||
impl OIDCProvider {
|
||||
pub fn state(&self) -> &OIDCProviderState {
|
||||
self.state.as_ref().expect("resolve called by main")
|
||||
}
|
||||
pub async fn resolve(&mut self) -> eyre::Result<()> {
|
||||
let provider_metadata = CoreProviderMetadata::discover_async(
|
||||
self.issuer_url.clone(),
|
||||
openidconnect::reqwest::async_http_client,
|
||||
)
|
||||
.await?;
|
||||
let client = CoreClient::from_provider_metadata(
|
||||
provider_metadata.clone(),
|
||||
self.client_id.clone(),
|
||||
Some(self.secret.clone()),
|
||||
);
|
||||
let client = client.disable_openid_scope();
|
||||
self.state = Some(OIDCProviderState {
|
||||
client,
|
||||
provider_metadata,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_example() -> eyre::Result<()> {
|
||||
Config::load_str(Config::EXAMPLE, "config.toml.sample")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue