use std::sync::Arc;
use super::audit::AuthzAuditSink;
use super::composite::CompositeAuthzHook;
use super::hook::SharedAuthzHook;
#[derive(Clone)]
pub struct AuthzHookContext {
pub pool: Arc<sqlx::PgPool>,
pub sink: Arc<dyn AuthzAuditSink>,
}
impl std::fmt::Debug for AuthzHookContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AuthzHookContext").finish_non_exhaustive()
}
}
#[derive(Debug, Clone, Copy)]
pub struct AuthzHookRegistration {
pub factory: fn(&AuthzHookContext) -> SharedAuthzHook,
}
inventory::collect!(AuthzHookRegistration);
#[must_use]
pub fn discover_authz_hook(ctx: &AuthzHookContext) -> Option<SharedAuthzHook> {
let hooks: Vec<SharedAuthzHook> = inventory::iter::<AuthzHookRegistration>()
.map(|reg| (reg.factory)(ctx))
.collect();
match hooks.len() {
0 => None,
1 => hooks.into_iter().next(),
_ => Some(Arc::new(CompositeAuthzHook::new(hooks))),
}
}
#[macro_export]
macro_rules! register_authz_hook {
($factory:expr) => {
::inventory::submit! {
$crate::authz::AuthzHookRegistration {
factory: $factory,
}
}
};
}