minco_http/
authorization.rs1use http::StatusCode;
2use minco_contract::ContractAuthorizationPolicy;
3
4use crate::{ApiFailure, Principal};
5
6pub fn authorize_operation(
11 principal: Option<&Principal>,
12 policy: &ContractAuthorizationPolicy,
13 request_id: &str,
14) -> Result<(), ApiFailure> {
15 if policy.anonymous {
16 return Ok(());
17 }
18 let Some(principal) = principal else {
19 return Err(ApiFailure::new(
20 StatusCode::UNAUTHORIZED,
21 "unauthenticated",
22 "Authentication required",
23 "A valid bearer credential is required for this operation.",
24 request_id,
25 ));
26 };
27
28 let permissions_allowed = policy
29 .permissions
30 .iter()
31 .all(|permission| principal.has_permission(permission));
32 let scopes_allowed = policy.alternatives.is_empty()
33 || policy.alternatives.iter().any(|alternative| {
34 alternative
35 .scopes
36 .iter()
37 .all(|scope| principal.has_scope(scope))
38 });
39 if permissions_allowed && scopes_allowed {
40 Ok(())
41 } else {
42 Err(ApiFailure::new(
43 StatusCode::FORBIDDEN,
44 "forbidden",
45 "Forbidden",
46 "The authenticated principal is not permitted to perform this operation.",
47 request_id,
48 ))
49 }
50}