ferro_rs/authorization/
response.rs1use std::fmt;
4
5#[derive(Debug, Clone)]
10pub enum AuthResponse {
11 Allow,
13 Deny {
15 message: Option<String>,
17 status: u16,
19 },
20}
21
22impl AuthResponse {
23 pub fn allow() -> Self {
25 Self::Allow
26 }
27
28 pub fn deny(message: impl Into<String>) -> Self {
30 Self::Deny {
31 message: Some(message.into()),
32 status: 403,
33 }
34 }
35
36 pub fn deny_silent() -> Self {
38 Self::Deny {
39 message: None,
40 status: 403,
41 }
42 }
43
44 pub fn deny_as_not_found() -> Self {
49 Self::Deny {
50 message: None,
51 status: 404,
52 }
53 }
54
55 pub fn deny_with_status(message: impl Into<String>, status: u16) -> Self {
57 Self::Deny {
58 message: Some(message.into()),
59 status,
60 }
61 }
62
63 pub fn allowed(&self) -> bool {
65 matches!(self, Self::Allow)
66 }
67
68 pub fn denied(&self) -> bool {
70 matches!(self, Self::Deny { .. })
71 }
72
73 pub fn message(&self) -> Option<&str> {
75 match self {
76 Self::Deny { message, .. } => message.as_deref(),
77 Self::Allow => None,
78 }
79 }
80
81 pub fn status(&self) -> u16 {
83 match self {
84 Self::Allow => 200,
85 Self::Deny { status, .. } => *status,
86 }
87 }
88}
89
90impl From<bool> for AuthResponse {
91 fn from(allowed: bool) -> Self {
92 if allowed {
93 Self::Allow
94 } else {
95 Self::Deny {
96 message: None,
97 status: 403,
98 }
99 }
100 }
101}
102
103impl fmt::Display for AuthResponse {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 match self {
106 Self::Allow => write!(f, "Allowed"),
107 Self::Deny {
108 message: Some(msg), ..
109 } => write!(f, "Denied: {msg}"),
110 Self::Deny { message: None, .. } => write!(f, "Denied"),
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_allow() {
121 let response = AuthResponse::allow();
122 assert!(response.allowed());
123 assert!(!response.denied());
124 assert_eq!(response.status(), 200);
125 }
126
127 #[test]
128 fn test_deny_with_message() {
129 let response = AuthResponse::deny("Not authorized");
130 assert!(!response.allowed());
131 assert!(response.denied());
132 assert_eq!(response.message(), Some("Not authorized"));
133 assert_eq!(response.status(), 403);
134 }
135
136 #[test]
137 fn test_deny_silent() {
138 let response = AuthResponse::deny_silent();
139 assert!(response.denied());
140 assert_eq!(response.message(), None);
141 assert_eq!(response.status(), 403);
142 }
143
144 #[test]
145 fn test_deny_as_not_found() {
146 let response = AuthResponse::deny_as_not_found();
147 assert!(response.denied());
148 assert_eq!(response.status(), 404);
149 }
150
151 #[test]
152 fn test_from_bool_true() {
153 let response: AuthResponse = true.into();
154 assert!(response.allowed());
155 }
156
157 #[test]
158 fn test_from_bool_false() {
159 let response: AuthResponse = false.into();
160 assert!(response.denied());
161 }
162
163 #[test]
164 fn test_display() {
165 assert_eq!(AuthResponse::allow().to_string(), "Allowed");
166 assert_eq!(
167 AuthResponse::deny("Forbidden").to_string(),
168 "Denied: Forbidden"
169 );
170 assert_eq!(AuthResponse::deny_silent().to_string(), "Denied");
171 }
172}