use std::sync::{Arc, OnceLock};
use async_trait::async_trait;
use authn_resolver_sdk::{AuthNResolverClient, AuthNResolverPluginSpecV1};
use modkit::Module;
use modkit::context::ModuleCtx;
use modkit::contracts::SystemCapability;
use tracing::info;
use types_registry_sdk::{RegisterResult, TypesRegistryClient};
use crate::config::AuthNResolverConfig;
use crate::domain::{AuthNResolverLocalClient, Service};
#[modkit::module(
name = "authn-resolver",
deps = ["types-registry"],
capabilities = [system]
)]
pub(crate) struct AuthNResolver {
service: OnceLock<Arc<Service>>,
}
impl Default for AuthNResolver {
fn default() -> Self {
Self {
service: OnceLock::new(),
}
}
}
impl SystemCapability for AuthNResolver {}
#[async_trait]
impl Module for AuthNResolver {
#[tracing::instrument(skip_all, fields(vendor))]
async fn init(&self, ctx: &ModuleCtx) -> anyhow::Result<()> {
let cfg: AuthNResolverConfig = ctx.config_or_default()?;
tracing::Span::current().record("vendor", cfg.vendor.as_str());
info!(vendor = %cfg.vendor);
let registry = ctx.client_hub().get::<dyn TypesRegistryClient>()?;
let schema_str = AuthNResolverPluginSpecV1::gts_schema_with_refs_as_string();
let mut schema_json: serde_json::Value = serde_json::from_str(&schema_str)?;
if let Some(obj) = schema_json.as_object_mut() {
obj.insert(
"additionalProperties".to_owned(),
serde_json::Value::Bool(false),
);
}
let results = registry.register(vec![schema_json]).await?;
RegisterResult::ensure_all_ok(&results)?;
info!(
schema_id = %AuthNResolverPluginSpecV1::gts_schema_id(),
"Registered plugin schema in types-registry"
);
let hub = ctx.client_hub();
let svc = Arc::new(Service::new(hub, cfg.vendor));
self.service
.set(svc.clone())
.map_err(|_| anyhow::anyhow!("{} module already initialized", Self::MODULE_NAME))?;
let api: Arc<dyn AuthNResolverClient> = Arc::new(AuthNResolverLocalClient::new(svc));
ctx.client_hub().register::<dyn AuthNResolverClient>(api);
Ok(())
}
}