use std::sync::{Arc, OnceLock};
use async_trait::async_trait;
use authz_resolver_sdk::{AuthZResolverClient, AuthZResolverPluginSpecV1};
use modkit::Module;
use modkit::context::ModuleCtx;
use modkit::contracts::SystemCapability;
use tracing::info;
use types_registry_sdk::{RegisterResult, TypesRegistryClient};
use crate::config::AuthZResolverConfig;
use crate::domain::{AuthZResolverLocalClient, Service};
#[modkit::module(
name = "authz-resolver",
deps = ["types-registry"],
capabilities = [system]
)]
pub(crate) struct AuthZResolver {
service: OnceLock<Arc<Service>>,
}
impl Default for AuthZResolver {
fn default() -> Self {
Self {
service: OnceLock::new(),
}
}
}
impl SystemCapability for AuthZResolver {}
#[async_trait]
impl Module for AuthZResolver {
#[tracing::instrument(skip_all, fields(vendor))]
async fn init(&self, ctx: &ModuleCtx) -> anyhow::Result<()> {
let cfg: AuthZResolverConfig = ctx.config()?;
tracing::Span::current().record("vendor", cfg.vendor.as_str());
info!(vendor = %cfg.vendor);
let registry = ctx.client_hub().get::<dyn TypesRegistryClient>()?;
let schema_str = AuthZResolverPluginSpecV1::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 = %AuthZResolverPluginSpecV1::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 AuthZResolverClient> = Arc::new(AuthZResolverLocalClient::new(svc));
ctx.client_hub().register::<dyn AuthZResolverClient>(api);
Ok(())
}
}