axum_gate/secrets/
errors.rs1use crate::errors::{ErrorSeverity, UserFriendlyError};
28use crate::hashing::HashingOperation;
29use std::collections::hash_map::DefaultHasher;
30use std::hash::{Hash, Hasher};
31use thiserror::Error;
32
33#[derive(Debug, Error)]
37#[non_exhaustive]
38pub enum SecretError {
39 #[error("Secret hashing error: {operation} - {message}")]
42 Hashing {
43 operation: HashingOperation,
45 message: String,
47 algorithm: Option<String>,
49 expected_format: Option<String>,
51 },
52}
53
54impl SecretError {
55 pub fn hashing_with_algorithm(
57 operation: HashingOperation,
58 message: impl Into<String>,
59 algorithm: impl Into<String>,
60 ) -> Self {
61 SecretError::Hashing {
62 operation,
63 message: message.into(),
64 algorithm: Some(algorithm.into()),
65 expected_format: None,
66 }
67 }
68
69 pub fn hashing_with_context(
71 operation: HashingOperation,
72 message: impl Into<String>,
73 algorithm: Option<String>,
74 expected_format: Option<String>,
75 ) -> Self {
76 SecretError::Hashing {
77 operation,
78 message: message.into(),
79 algorithm,
80 expected_format,
81 }
82 }
83
84 fn support_code_inner(&self) -> String {
85 let mut hasher = DefaultHasher::new();
86 match self {
87 SecretError::Hashing {
88 operation,
89 algorithm,
90 ..
91 } => {
92 format!("SECR-HASH-{}-{:X}", operation.to_string().to_uppercase(), {
93 format!("{:?}{:?}", operation, algorithm).hash(&mut hasher);
94 hasher.finish() % 10000
95 })
96 }
97 }
98 }
99}
100
101impl UserFriendlyError for SecretError {
102 fn user_message(&self) -> String {
103 match self {
104 SecretError::Hashing { operation, .. } => match operation {
105 HashingOperation::Hash => "There's an issue with the security processing system. Please try again in a moment.".to_string(),
106 HashingOperation::Verify => "We couldn't verify your credentials due to a technical issue. Please try signing in again.".to_string(),
107 },
108 }
109 }
110
111 fn developer_message(&self) -> String {
112 match self {
113 SecretError::Hashing {
114 operation,
115 message,
116 algorithm,
117 expected_format,
118 } => {
119 let algo_s = algorithm
120 .as_ref()
121 .map(|a| format!(" [Algorithm: {}]", a))
122 .unwrap_or_default();
123 let exp_s = expected_format
124 .as_ref()
125 .map(|e| format!(" [Expected: {}]", e))
126 .unwrap_or_default();
127 format!(
128 "Secret hashing {} failed: {}{}{}",
129 operation, message, algo_s, exp_s
130 )
131 }
132 }
133 }
134
135 fn support_code(&self) -> String {
136 self.support_code_inner()
137 }
138
139 fn severity(&self) -> ErrorSeverity {
140 match self {
141 SecretError::Hashing { .. } => ErrorSeverity::Critical,
142 }
143 }
144
145 fn suggested_actions(&self) -> Vec<String> {
146 match self {
147 SecretError::Hashing { operation, .. } => match operation {
148 HashingOperation::Hash => vec![
149 "This is a critical security system error".to_string(),
150 "Contact our support team immediately".to_string(),
151 "Do not retry operations that involve password or secret changes".to_string(),
152 ],
153 HashingOperation::Verify => vec![
154 "Double-check your password for typos".to_string(),
155 "Ensure Caps Lock is not accidentally enabled".to_string(),
156 "If you're certain your password is correct, contact support".to_string(),
157 "Try using password recovery if verification continues to fail".to_string(),
158 ],
159 },
160 }
161 }
162
163 fn is_retryable(&self) -> bool {
164 match self {
165 SecretError::Hashing { operation, .. } => match operation {
166 HashingOperation::Hash => false,
167 HashingOperation::Verify => true, },
169 }
170 }
171}