mirror of
https://github.com/CloudNebulaProject/barycenter.git
synced 2026-04-10 13:10:42 +00:00
87 lines
2.8 KiB
Rust
87 lines
2.8 KiB
Rust
|
|
use axum::http::StatusCode;
|
||
|
|
use axum::response::{IntoResponse, Response};
|
||
|
|
use axum::Json;
|
||
|
|
use miette::Diagnostic;
|
||
|
|
use serde_json::json;
|
||
|
|
use thiserror::Error;
|
||
|
|
|
||
|
|
#[derive(Debug, Error, Diagnostic)]
|
||
|
|
pub enum AuthzError {
|
||
|
|
#[error("Failed to load policy file `{path}`")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::policy_load),
|
||
|
|
help("Check that the file exists and contains valid KDL syntax")
|
||
|
|
)]
|
||
|
|
PolicyLoadError {
|
||
|
|
path: String,
|
||
|
|
#[source]
|
||
|
|
source: std::io::Error,
|
||
|
|
},
|
||
|
|
|
||
|
|
#[error("Invalid policy: {0}")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::invalid_policy),
|
||
|
|
help("Each policy file must contain valid `resource`, `role`, `rule`, or `grant` KDL nodes")
|
||
|
|
)]
|
||
|
|
InvalidPolicy(String),
|
||
|
|
|
||
|
|
#[error("Invalid grant: {0}")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::invalid_grant),
|
||
|
|
help("Grant syntax: grant \"relation\" on=\"type/id\" to=\"subject_type/id\" (optionally to=\"type/id#relation\")")
|
||
|
|
)]
|
||
|
|
InvalidGrant(String),
|
||
|
|
|
||
|
|
#[error("Invalid condition expression: {0}")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::invalid_condition),
|
||
|
|
help("Supported operators: ==, !=, >, <, >=, <=, &&, ||, !, in. Paths use dot notation (e.g. request.ip)")
|
||
|
|
)]
|
||
|
|
InvalidCondition(String),
|
||
|
|
|
||
|
|
#[error("Undefined resource type `{0}`")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::undefined_resource),
|
||
|
|
help("Define the resource type with: resource \"<name>\" {{ relations {{ ... }} permissions {{ ... }} }}")
|
||
|
|
)]
|
||
|
|
UndefinedResourceType(String),
|
||
|
|
|
||
|
|
#[error("Undefined role `{0}`")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::undefined_role),
|
||
|
|
help("Define the role with: role \"<name>\" {{ permissions {{ ... }} }}")
|
||
|
|
)]
|
||
|
|
UndefinedRole(String),
|
||
|
|
|
||
|
|
#[error("Cyclic role inheritance detected: {0}")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::cyclic_roles),
|
||
|
|
help("Check the `includes` lists in your role definitions for circular references")
|
||
|
|
)]
|
||
|
|
CyclicRoleInheritance(String),
|
||
|
|
|
||
|
|
#[error("KDL parse error: {0}")]
|
||
|
|
#[diagnostic(
|
||
|
|
code(barycenter::authz::kdl_parse),
|
||
|
|
help("Check your KDL file syntax — see https://kdl.dev for the specification")
|
||
|
|
)]
|
||
|
|
KdlParse(String),
|
||
|
|
|
||
|
|
#[error("I/O error: {0}")]
|
||
|
|
#[diagnostic(code(barycenter::authz::io))]
|
||
|
|
Io(#[from] std::io::Error),
|
||
|
|
}
|
||
|
|
|
||
|
|
impl IntoResponse for AuthzError {
|
||
|
|
fn into_response(self) -> Response {
|
||
|
|
let (status, message) = match &self {
|
||
|
|
AuthzError::InvalidPolicy(_)
|
||
|
|
| AuthzError::InvalidGrant(_)
|
||
|
|
| AuthzError::InvalidCondition(_) => (StatusCode::BAD_REQUEST, self.to_string()),
|
||
|
|
_ => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
|
||
|
|
};
|
||
|
|
let body = json!({ "error": message });
|
||
|
|
(status, Json(body)).into_response()
|
||
|
|
}
|
||
|
|
}
|