Skip to main content

hyperdb_api_salesforce/
error.rs

1// Copyright (c) 2026, Salesforce, Inc. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Error types for Salesforce Data Cloud authentication.
5
6use std::fmt;
7
8/// Result type for Salesforce authentication operations.
9pub type SalesforceAuthResult<T> = Result<T, SalesforceAuthError>;
10
11/// Errors that can occur during the Salesforce Data Cloud token flow
12/// (OAuth Access Token acquisition and DC JWT exchange).
13#[derive(Debug)]
14pub enum SalesforceAuthError {
15    /// Invalid configuration (missing required fields, invalid URLs, etc.)
16    Config(String),
17
18    /// Failed to parse or load the RSA private key for JWT Bearer Token Flow
19    PrivateKey(String),
20
21    /// JWT assertion creation or signing failed
22    Jwt(String),
23
24    /// HTTP request failed (network-level error)
25    Http(String),
26
27    /// OAuth Access Token or DC JWT request rejected by Salesforce (4xx response)
28    Authorization {
29        /// Error code from Salesforce (e.g., "`invalid_grant`")
30        error_code: String,
31        /// Human-readable error description
32        error_description: String,
33    },
34
35    /// DC JWT exchange failed
36    TokenExchange(String),
37
38    /// Token response parsing failed (invalid response format)
39    TokenParse(String),
40
41    /// DC JWT has expired
42    TokenExpired,
43
44    /// Network or I/O error
45    Io(String),
46}
47
48impl SalesforceAuthError {
49    /// Constructs a [`Self::Config`] error.
50    pub fn config(message: impl Into<String>) -> Self {
51        SalesforceAuthError::Config(message.into())
52    }
53
54    /// Constructs a [`Self::PrivateKey`] error.
55    pub fn private_key(message: impl Into<String>) -> Self {
56        SalesforceAuthError::PrivateKey(message.into())
57    }
58
59    /// Constructs a [`Self::Jwt`] error.
60    pub fn jwt(message: impl Into<String>) -> Self {
61        SalesforceAuthError::Jwt(message.into())
62    }
63
64    /// Constructs a [`Self::Http`] error.
65    pub fn http(message: impl Into<String>) -> Self {
66        SalesforceAuthError::Http(message.into())
67    }
68
69    /// Constructs a [`Self::Authorization`] error.
70    pub fn authorization(
71        error_code: impl Into<String>,
72        error_description: impl Into<String>,
73    ) -> Self {
74        SalesforceAuthError::Authorization {
75            error_code: error_code.into(),
76            error_description: error_description.into(),
77        }
78    }
79
80    /// Constructs a [`Self::TokenExchange`] error.
81    pub fn token_exchange(message: impl Into<String>) -> Self {
82        SalesforceAuthError::TokenExchange(message.into())
83    }
84
85    /// Constructs a [`Self::TokenParse`] error.
86    pub fn token_parse(message: impl Into<String>) -> Self {
87        SalesforceAuthError::TokenParse(message.into())
88    }
89
90    /// Constructs a [`Self::Io`] error.
91    pub fn io(message: impl Into<String>) -> Self {
92        SalesforceAuthError::Io(message.into())
93    }
94}
95
96impl fmt::Display for SalesforceAuthError {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        match self {
99            SalesforceAuthError::Config(msg) => write!(f, "configuration error: {msg}"),
100            SalesforceAuthError::PrivateKey(msg) => write!(f, "private key error: {msg}"),
101            SalesforceAuthError::Jwt(msg) => write!(f, "JWT assertion error: {msg}"),
102            SalesforceAuthError::Http(msg) => write!(f, "HTTP error: {msg}"),
103            SalesforceAuthError::Authorization {
104                error_code,
105                error_description,
106            } => write!(
107                f,
108                "authorization failed: {error_code} - {error_description}"
109            ),
110            SalesforceAuthError::TokenExchange(msg) => {
111                write!(f, "DC JWT exchange failed: {msg}")
112            }
113            SalesforceAuthError::TokenParse(msg) => write!(f, "token parse error: {msg}"),
114            SalesforceAuthError::TokenExpired => write!(f, "DC JWT has expired"),
115            SalesforceAuthError::Io(msg) => write!(f, "I/O error: {msg}"),
116        }
117    }
118}
119
120impl std::error::Error for SalesforceAuthError {}
121
122impl From<reqwest::Error> for SalesforceAuthError {
123    fn from(err: reqwest::Error) -> Self {
124        SalesforceAuthError::Http(err.to_string())
125    }
126}
127
128impl From<jsonwebtoken::errors::Error> for SalesforceAuthError {
129    fn from(err: jsonwebtoken::errors::Error) -> Self {
130        SalesforceAuthError::Jwt(err.to_string())
131    }
132}
133
134impl From<rsa::pkcs8::Error> for SalesforceAuthError {
135    fn from(err: rsa::pkcs8::Error) -> Self {
136        SalesforceAuthError::PrivateKey(err.to_string())
137    }
138}
139
140impl From<url::ParseError> for SalesforceAuthError {
141    fn from(err: url::ParseError) -> Self {
142        SalesforceAuthError::Config(format!("invalid URL: {err}"))
143    }
144}
145
146impl From<serde_json::Error> for SalesforceAuthError {
147    fn from(err: serde_json::Error) -> Self {
148        SalesforceAuthError::TokenParse(err.to_string())
149    }
150}