axum_gate/accounts/
errors.rs1use crate::errors::{ErrorSeverity, UserFriendlyError};
28use std::collections::hash_map::DefaultHasher;
29use std::fmt;
30use std::hash::{Hash, Hasher};
31use thiserror::Error;
32
33#[derive(Debug, Clone)]
35pub enum AccountOperation {
36 Create,
38 Delete,
40}
41
42impl fmt::Display for AccountOperation {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self {
45 AccountOperation::Create => write!(f, "create"),
46 AccountOperation::Delete => write!(f, "delete"),
47 }
48 }
49}
50
51#[derive(Debug, Error)]
55#[non_exhaustive]
56pub enum AccountsError {
57 #[error("Account operation {operation} failed: {message}")]
59 Operation {
60 operation: AccountOperation,
62 message: String,
64 account_id: Option<String>,
66 },
67}
68
69impl AccountsError {
70 pub fn operation(
72 operation: AccountOperation,
73 message: impl Into<String>,
74 account_id: Option<String>,
75 ) -> Self {
76 AccountsError::Operation {
77 operation,
78 message: message.into(),
79 account_id,
80 }
81 }
82
83 fn support_code_inner(&self) -> String {
85 let mut hasher = DefaultHasher::new();
86 match self {
87 AccountsError::Operation {
88 operation,
89 account_id,
90 ..
91 } => {
92 format!("ACCT-OP-{}-{:X}", operation.to_string().to_uppercase(), {
93 format!("{:?}{:?}", operation, account_id).hash(&mut hasher);
94 hasher.finish() % 10000
95 })
96 }
97 }
98 }
99}
100
101impl UserFriendlyError for AccountsError {
102 fn user_message(&self) -> String {
103 match self {
104 AccountsError::Operation { operation, .. } => match operation {
105 AccountOperation::Create => "We couldn't create your account right now. Please try again in a moment, or contact our support team if the problem continues.".to_string(),
106 AccountOperation::Delete => "We couldn't delete your account at this time. Please try again later, or contact our support team for assistance.".to_string(),
107 },
108 }
109 }
110
111 fn developer_message(&self) -> String {
112 match self {
113 AccountsError::Operation {
114 operation,
115 message,
116 account_id,
117 } => {
118 let account_context = account_id
119 .as_ref()
120 .map(|id| format!(" [Account: {}]", id))
121 .unwrap_or_default();
122 format!(
123 "Account operation {} failed: {}{}",
124 operation, message, account_context
125 )
126 }
127 }
128 }
129
130 fn support_code(&self) -> String {
131 self.support_code_inner()
132 }
133
134 fn severity(&self) -> ErrorSeverity {
135 match self {
136 AccountsError::Operation { operation, .. } => match operation {
137 AccountOperation::Delete => ErrorSeverity::Critical,
138 _ => ErrorSeverity::Error,
139 },
140 }
141 }
142
143 fn suggested_actions(&self) -> Vec<String> {
144 match self {
145 AccountsError::Operation { operation, .. } => match operation {
146 AccountOperation::Create => vec![
147 "Wait a moment and try creating your account again".to_string(),
148 "Ensure all required fields are filled out correctly".to_string(),
149 "Check your email for any verification requirements".to_string(),
150 "Contact our support team if the problem continues".to_string(),
151 ],
152 AccountOperation::Delete => vec![
153 "Contact our support team to assist with account deletion".to_string(),
154 "Ensure you have completed any required pre-deletion steps".to_string(),
155 "This operation may be temporarily unavailable for security reasons"
156 .to_string(),
157 ],
158 },
159 }
160 }
161
162 fn is_retryable(&self) -> bool {
163 match self {
164 AccountsError::Operation { operation, .. } => {
165 !matches!(operation, AccountOperation::Delete)
166 }
167 }
168 }
169}