modo/guards.rs
1//! Flat index of every route-level gating layer.
2//!
3//! Each `require_*` function returns a tower [`Layer`](tower::Layer) that
4//! short-circuits the request with an [`Error`](crate::Error) response when
5//! the caller fails the check. Apply them at the wiring site with
6//! [`axum::Router::route_layer`] so the guard only runs for the routes it
7//! protects:
8//!
9//! ```ignore
10//! use axum::{Router, routing::get};
11//! use modo::guards;
12//!
13//! async fn dashboard() -> &'static str { "ok" }
14//!
15//! let app: Router<()> = Router::new()
16//! .route("/admin", get(dashboard))
17//! .route_layer(guards::require_authenticated())
18//! .route_layer(guards::require_role(["admin"]))
19//! .route_layer(guards::require_feature("admin_panel"));
20//! ```
21//!
22//! Available guards:
23//!
24//! - [`require_authenticated`] — rejects anonymous requests
25//! - [`require_role`] — rejects callers missing any of the listed roles
26//! - [`require_scope`] — rejects API keys without the given scope
27//! - [`require_feature`] — rejects tenants whose tier lacks a feature flag
28//! - [`require_limit`] — rejects tenants who would exceed a usage limit
29
30pub use crate::auth::guard::{require_authenticated, require_role, require_scope};
31pub use crate::tier::{require_feature, require_limit};