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 fmt::Display for SalesforceAuthError {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        match self {
51            SalesforceAuthError::Config(msg) => write!(f, "configuration error: {msg}"),
52            SalesforceAuthError::PrivateKey(msg) => write!(f, "private key error: {msg}"),
53            SalesforceAuthError::Jwt(msg) => write!(f, "JWT assertion error: {msg}"),
54            SalesforceAuthError::Http(msg) => write!(f, "HTTP error: {msg}"),
55            SalesforceAuthError::Authorization {
56                error_code,
57                error_description,
58            } => write!(
59                f,
60                "authorization failed: {error_code} - {error_description}"
61            ),
62            SalesforceAuthError::TokenExchange(msg) => {
63                write!(f, "DC JWT exchange failed: {msg}")
64            }
65            SalesforceAuthError::TokenParse(msg) => write!(f, "token parse error: {msg}"),
66            SalesforceAuthError::TokenExpired => write!(f, "DC JWT has expired"),
67            SalesforceAuthError::Io(msg) => write!(f, "I/O error: {msg}"),
68        }
69    }
70}
71
72impl std::error::Error for SalesforceAuthError {}
73
74impl From<reqwest::Error> for SalesforceAuthError {
75    fn from(err: reqwest::Error) -> Self {
76        SalesforceAuthError::Http(err.to_string())
77    }
78}
79
80impl From<jsonwebtoken::errors::Error> for SalesforceAuthError {
81    fn from(err: jsonwebtoken::errors::Error) -> Self {
82        SalesforceAuthError::Jwt(err.to_string())
83    }
84}
85
86impl From<rsa::pkcs8::Error> for SalesforceAuthError {
87    fn from(err: rsa::pkcs8::Error) -> Self {
88        SalesforceAuthError::PrivateKey(err.to_string())
89    }
90}
91
92impl From<url::ParseError> for SalesforceAuthError {
93    fn from(err: url::ParseError) -> Self {
94        SalesforceAuthError::Config(format!("invalid URL: {err}"))
95    }
96}
97
98impl From<serde_json::Error> for SalesforceAuthError {
99    fn from(err: serde_json::Error) -> Self {
100        SalesforceAuthError::TokenParse(err.to_string())
101    }
102}