Skip to main content

larust_auth/
authorize.rs

1use axum::http::StatusCode;
2use larust_core::AppError;
3
4/// Converts a boolean authorization check into a 403 on failure (Laravel's
5/// `$this->authorize(...)` controller helper). Not a `Gate`-style runtime
6/// registry - write the actual check as a plain typed method on your own
7/// model (`impl Post { pub fn can_update(&self, user: &User) -> bool {
8/// self.user_id == user.id } }`) and convert it at the call site:
9/// `authorize(post.can_update(&user))?;`. A typo in an ability name this
10/// way is a compile error, not a silently-always-false runtime lookup.
11///
12/// For the common CRUD-shaped case (view/create/update/delete on a model),
13/// prefer [`crate::Policy`] instead - it gives every model the same
14/// ability names and a matching `authorize_*` sugar method
15/// (`post.authorize_update(&user)?`) built on this same function. This
16/// helper remains the right tool for one-off, non-CRUD-shaped checks.
17pub fn authorize(allowed: bool) -> Result<(), AppError> {
18    if allowed {
19        Ok(())
20    } else {
21        Err(AppError::Http {
22            status: StatusCode::FORBIDDEN,
23            message: "This action is unauthorized.".to_string(),
24        })
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31
32    #[test]
33    fn allows_when_true() {
34        assert!(authorize(true).is_ok());
35    }
36
37    #[test]
38    fn rejects_with_403_when_false() {
39        let err = authorize(false).unwrap_err();
40        assert!(matches!(
41            err,
42            AppError::Http {
43                status: StatusCode::FORBIDDEN,
44                ..
45            }
46        ));
47    }
48}