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