actix_web_security/authentication/error/
error_handler.rs1use std::collections::HashMap;
6
7use actix_web::dev::HttpResponseBuilder;
8use actix_web::http::{header, StatusCode};
9use actix_web::{error, HttpResponse};
10use once_cell::sync::Lazy;
11
12use crate::authentication::error::error_type::AuthenticationError;
13
14static AUTH_ERROR_STATUS_CODE_MAPPING: Lazy<HashMap<AuthenticationError, u16>> = Lazy::new(|| {
16 let mut error_codes: HashMap<AuthenticationError, u16> = HashMap::new();
17 add_env_error_code(AuthenticationError::InvalidAuthentication, &mut error_codes);
18 add_env_error_code(AuthenticationError::InvalidToken, &mut error_codes);
19 add_env_error_code(
20 AuthenticationError::InvalidAuthorizationHeader,
21 &mut error_codes,
22 );
23 add_env_error_code(AuthenticationError::UsernameNotFound, &mut error_codes);
24 add_env_error_code(
25 AuthenticationError::AuthorizationHeaderNotSet,
26 &mut error_codes,
27 );
28 error_codes
29});
30
31static AUTH_ERROR_MESSAGE_MAPPING: Lazy<HashMap<AuthenticationError, String>> = Lazy::new(|| {
32 let mut error_messages: HashMap<AuthenticationError, String> = HashMap::new();
33 add_env_error_message(
34 AuthenticationError::InvalidAuthentication,
35 "invalid authentication".to_string(),
36 &mut error_messages,
37 );
38 add_env_error_message(
39 AuthenticationError::InvalidToken,
40 "access denied".to_string(),
41 &mut error_messages,
42 );
43 add_env_error_message(
44 AuthenticationError::InvalidAuthorizationHeader,
45 "invalid authorization header".to_string(),
46 &mut error_messages,
47 );
48 add_env_error_message(
49 AuthenticationError::UsernameNotFound,
50 "access denied".to_string(),
51 &mut error_messages,
52 );
53 add_env_error_message(
54 AuthenticationError::AuthorizationHeaderNotSet,
55 "authorization header not set".to_string(),
56 &mut error_messages,
57 );
58 error_messages
59});
60
61static AUTH_ERROR_CONTENT_TYPE: Lazy<String> =
62 Lazy::new(|| match std::env::var("AUTH_ERROR_CONTENT_TYPE") {
63 Ok(content_type) => content_type,
64 _ => "text/html; charset=utf-8".to_string(),
65 });
66
67fn add_env_error_code(
68 error: AuthenticationError,
69 error_codes: &mut HashMap<AuthenticationError, u16>,
70) {
71 match std::env::var(format!("{}_code", error)) {
72 Ok(code) => error_codes.insert(
73 error,
74 code.parse::<u16>().expect("Invalid status code mapping"),
75 ),
76 _ => error_codes.insert(error, 401),
77 };
78}
79
80fn add_env_error_message(
81 error: AuthenticationError,
82 default_message: String,
83 error_messages: &mut HashMap<AuthenticationError, String>,
84) {
85 match std::env::var(format!("{}_message", error)) {
86 Ok(message) => error_messages.insert(error, message),
87 _ => error_messages.insert(error, default_message),
88 };
89}
90
91pub fn overwrite_auth_error_status_code(error: AuthenticationError, status_code: u16) {
95 assert!((100..=1000).contains(&status_code), "Invalid status code");
96 std::env::set_var(format!("{}_code", error), status_code.to_string());
97}
98
99pub fn overwrite_auth_error_message(error: AuthenticationError, message: String) {
102 std::env::set_var(format!("{}_message", error), message);
103}
104
105pub fn set_auth_error_content_type(content_type: String) {
108 std::env::set_var("AUTH_ERROR_CONTENT_TYPE", content_type);
109}
110
111impl error::ResponseError for AuthenticationError {
112 fn status_code(&self) -> StatusCode {
113 match *self {
114 AuthenticationError::InvalidAuthentication => {
115 dynamic_status_code(&AuthenticationError::InvalidAuthentication)
116 }
117 AuthenticationError::AuthorizationHeaderNotSet => {
118 dynamic_status_code(&AuthenticationError::AuthorizationHeaderNotSet)
119 }
120 AuthenticationError::InvalidAuthorizationHeader => {
121 dynamic_status_code(&AuthenticationError::InvalidAuthorizationHeader)
122 }
123 AuthenticationError::UsernameNotFound => {
124 dynamic_status_code(&AuthenticationError::UsernameNotFound)
125 }
126 AuthenticationError::InvalidToken => {
127 dynamic_status_code(&AuthenticationError::InvalidToken)
128 }
129 }
130 }
131
132 fn error_response(&self) -> HttpResponse {
133 HttpResponseBuilder::new(self.status_code())
134 .set_header(header::CONTENT_TYPE, AUTH_ERROR_CONTENT_TYPE.to_string())
135 .body(dynamic_error_message(self))
136 }
137}
138
139fn dynamic_status_code(error: &AuthenticationError) -> StatusCode {
140 StatusCode::from_u16(
141 *AUTH_ERROR_STATUS_CODE_MAPPING
142 .get(error)
143 .expect("Status code mapping missing"),
144 )
145 .expect("Invalid status code mapping found")
146}
147
148fn dynamic_error_message(error: &AuthenticationError) -> String {
149 AUTH_ERROR_MESSAGE_MAPPING
150 .get(error)
151 .expect("Error message mapping missing")
152 .clone()
153}