ferro_rs/authorization/mod.rs
1//! Authorization system for Ferro framework.
2//!
3//! Provides Laravel-like authorization with Gates and Policies.
4//!
5//! # Overview
6//!
7//! Ferro authorization works through two main concepts:
8//!
9//! - **Gates**: Simple closures for checking abilities not tied to specific models
10//! - **Policies**: Classes that organize authorization logic around a model
11//!
12//! # Gates
13//!
14//! Gates are simple closures that determine if a user can perform an action:
15//!
16//! ```rust,ignore
17//! use ferro_rs::authorization::Gate;
18//!
19//! // In bootstrap.rs
20//! Gate::define("view-dashboard", |user, _| {
21//! user.as_any().downcast_ref::<User>()
22//! .map(|u| (u.is_admin || u.has_role("manager")).into())
23//! .unwrap_or_else(AuthResponse::deny_silent)
24//! });
25//!
26//! // Admin bypass
27//! Gate::before(|user, _ability| {
28//! if let Some(u) = user.as_any().downcast_ref::<User>() {
29//! if u.is_super_admin {
30//! return Some(true);
31//! }
32//! }
33//! None
34//! });
35//!
36//! // In controller
37//! if Gate::allows("view-dashboard", None) {
38//! // Show dashboard
39//! }
40//!
41//! // Or authorize (returns Result)
42//! Gate::authorize("view-dashboard", None)?;
43//! ```
44//!
45//! # Policies
46//!
47//! Policies organize authorization logic around a specific model:
48//!
49//! ```rust,ignore
50//! use ferro_rs::authorization::{Policy, AuthResponse};
51//!
52//! pub struct PostPolicy;
53//!
54//! impl Policy<Post> for PostPolicy {
55//! type User = User;
56//!
57//! fn before(&self, user: &Self::User, _ability: &str) -> Option<bool> {
58//! if user.is_admin {
59//! return Some(true);
60//! }
61//! None
62//! }
63//!
64//! fn view(&self, _user: &Self::User, _post: &Post) -> AuthResponse {
65//! AuthResponse::allow()
66//! }
67//!
68//! fn update(&self, user: &Self::User, post: &Post) -> AuthResponse {
69//! (user.id == post.user_id).into()
70//! }
71//! }
72//! ```
73//!
74//! # Authorizable Trait
75//!
76//! User models can use the `Authorizable` trait for convenient methods:
77//!
78//! ```rust,ignore
79//! // Automatically available on all Authenticatable types
80//! if user.can("update", Some(&post)) {
81//! // Show edit button
82//! }
83//!
84//! user.authorize("delete", Some(&post))?;
85//! ```
86//!
87//! # Middleware
88//!
89//! Protect routes with authorization middleware:
90//!
91//! ```rust,ignore
92//! use ferro_rs::authorization::Authorize;
93//! use ferro_rs::can;
94//!
95//! Route::get("/admin", admin_dashboard)
96//! .middleware(Authorize::ability("view-admin"));
97//!
98//! // Or using the macro
99//! Route::get("/admin", admin_dashboard)
100//! .middleware(can!("view-admin"));
101//! ```
102
103mod authorizable;
104mod error;
105mod gate;
106mod middleware;
107mod policy;
108mod response;
109
110pub use authorizable::Authorizable;
111pub use error::AuthorizationError;
112pub use gate::Gate;
113pub use middleware::Authorize;
114pub use policy::Policy;
115pub use response::AuthResponse;