1use std::sync::{Arc, OnceLock};
4
5use async_trait::async_trait;
6use authz_resolver_sdk::{AuthZResolverClient, AuthZResolverPluginSpecV1};
7use modkit::Module;
8use modkit::context::ModuleCtx;
9use modkit::contracts::SystemCapability;
10use tracing::info;
11use types_registry_sdk::{RegisterResult, TypesRegistryClient};
12
13use crate::config::AuthZResolverConfig;
14use crate::domain::{AuthZResolverLocalClient, Service};
15
16#[modkit::module(
26 name = "authz-resolver",
27 deps = ["types-registry"],
28 capabilities = [system]
29)]
30pub(crate) struct AuthZResolver {
31 service: OnceLock<Arc<Service>>,
32}
33
34impl Default for AuthZResolver {
35 fn default() -> Self {
36 Self {
37 service: OnceLock::new(),
38 }
39 }
40}
41
42impl SystemCapability for AuthZResolver {}
46
47#[async_trait]
48impl Module for AuthZResolver {
49 #[tracing::instrument(skip_all, fields(vendor))]
50 async fn init(&self, ctx: &ModuleCtx) -> anyhow::Result<()> {
51 let cfg: AuthZResolverConfig = ctx.config()?;
52 tracing::Span::current().record("vendor", cfg.vendor.as_str());
53 info!(vendor = %cfg.vendor);
54
55 let registry = ctx.client_hub().get::<dyn TypesRegistryClient>()?;
57 let schema_str = AuthZResolverPluginSpecV1::gts_schema_with_refs_as_string();
58 let mut schema_json: serde_json::Value = serde_json::from_str(&schema_str)?;
59 if let Some(obj) = schema_json.as_object_mut() {
64 obj.insert(
65 "additionalProperties".to_owned(),
66 serde_json::Value::Bool(false),
67 );
68 }
69 let results = registry.register(vec![schema_json]).await?;
70 RegisterResult::ensure_all_ok(&results)?;
71 info!(
72 schema_id = %AuthZResolverPluginSpecV1::gts_schema_id(),
73 "Registered plugin schema in types-registry"
74 );
75
76 let hub = ctx.client_hub();
78 let svc = Arc::new(Service::new(hub, cfg.vendor));
79 self.service
80 .set(svc.clone())
81 .map_err(|_| anyhow::anyhow!("{} module already initialized", Self::MODULE_NAME))?;
82
83 let api: Arc<dyn AuthZResolverClient> = Arc::new(AuthZResolverLocalClient::new(svc));
85 ctx.client_hub().register::<dyn AuthZResolverClient>(api);
86
87 Ok(())
88 }
89}