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