systemprompt_api/routes/oauth/error/
conversions.rs1use systemprompt_config::SecretsBootstrapError;
8use systemprompt_models::errors::ConfigError;
9use systemprompt_oauth::OauthError;
10use systemprompt_traits::auth::AuthProviderError;
11
12use super::{OAuthErrorCode, OAuthHttpError};
13
14impl From<ConfigError> for OAuthHttpError {
15 fn from(err: ConfigError) -> Self {
16 Self::server_error(err.to_string())
17 }
18}
19
20impl From<OauthError> for OAuthHttpError {
21 fn from(err: OauthError) -> Self {
22 match &err {
23 OauthError::InvalidClient(_)
24 | OauthError::ClientNotFound(_)
25 | OauthError::InvalidClientMetadata(_) => Self::invalid_client(err.to_string()),
26 OauthError::InvalidGrant(_)
27 | OauthError::CodeNotFound(_)
28 | OauthError::TokenNotFound(_)
29 | OauthError::PkceMismatch(_)
30 | OauthError::Expired(_) => Self::invalid_grant(err.to_string()),
31 OauthError::Validation(_) => Self::invalid_request(err.to_string()),
32 OauthError::Unauthorized(_) => Self::access_denied(err.to_string()),
33 OauthError::UsernameTaken(_) => Self::username_unavailable(
34 "Username is already taken. Please choose a different username.",
35 ),
36 OauthError::EmailRegistered(_) => {
37 Self::email_exists("An account with this email already exists.")
38 },
39 OauthError::UserNotFound(_) => Self::not_found(err.to_string()),
40 OauthError::RegistrationStateExpired => Self::expired_challenge(
41 "Registration challenge has expired. Please start the registration process again.",
42 ),
43 OauthError::WebAuthnVerificationFailed(_) => Self::invalid_credential(
44 "WebAuthn verification failed. Please ensure your authenticator and browser are \
45 compatible.",
46 ),
47 OauthError::WebAuthn(_)
48 | OauthError::User(_)
49 | OauthError::Session(_)
50 | OauthError::TokenInvalid(_)
51 | OauthError::TokenAlgMismatch { .. }
52 | OauthError::TokenMissingKid
53 | OauthError::TokenUnknownKid { .. }
54 | OauthError::Provider(_)
55 | OauthError::Repository(_)
56 | OauthError::DatabaseRepository(_)
57 | OauthError::Config(_)
58 | OauthError::Crypto(_)
59 | OauthError::CimdFetch(_)
60 | OauthError::WebAuthnConfig(_)
61 | OauthError::Internal(_) => Self::server_error(err.to_string()),
62 }
63 }
64}
65
66impl From<AuthProviderError> for OAuthHttpError {
67 fn from(err: AuthProviderError) -> Self {
68 match &err {
69 AuthProviderError::InvalidCredentials | AuthProviderError::InvalidToken => {
70 Self::invalid_client(err.to_string())
71 },
72 AuthProviderError::UserNotFound => Self::not_found(err.to_string()),
73 AuthProviderError::TokenExpired => Self::invalid_grant(err.to_string()),
74 AuthProviderError::InsufficientPermissions => Self::access_denied(err.to_string()),
75 _ => Self::server_error(err.to_string()),
76 }
77 }
78}
79
80impl From<SecretsBootstrapError> for OAuthHttpError {
81 fn from(err: SecretsBootstrapError) -> Self {
82 Self::server_error(err.to_string())
83 }
84}
85
86impl From<sqlx::Error> for OAuthHttpError {
87 fn from(err: sqlx::Error) -> Self {
88 if let sqlx::Error::Database(db_err) = &err
89 && db_err.is_unique_violation()
90 {
91 return Self::new(OAuthErrorCode::UsernameUnavailable, err.to_string());
92 }
93 Self::server_error(err.to_string())
94 }
95}
96
97impl From<anyhow::Error> for OAuthHttpError {
98 fn from(err: anyhow::Error) -> Self {
99 Self::server_error(err.to_string())
100 }
101}