rustauth_core/auth/oauth/
errors.rs1use std::error::Error;
2use std::fmt;
3
4use crate::error::RustAuthError;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum OAuthUserInfoError {
8 AccountNotLinked,
9 SignupDisabled,
10 UnableToCreateUser,
11 UnableToCreateSession,
12 UnableToLinkAccount,
13}
14
15impl OAuthUserInfoError {
16 pub fn code_str(self) -> &'static str {
17 match self {
18 Self::AccountNotLinked => "account_not_linked",
19 Self::SignupDisabled => "signup_disabled",
20 Self::UnableToCreateUser => "unable_to_create_user",
21 Self::UnableToCreateSession => "unable_to_create_session",
22 Self::UnableToLinkAccount => "unable_to_link_account",
23 }
24 }
25
26 pub fn message(self) -> &'static str {
27 match self {
28 Self::AccountNotLinked => "Account not linked",
29 Self::SignupDisabled => "Signup disabled",
30 Self::UnableToCreateUser => "Unable to create user",
31 Self::UnableToCreateSession => "Unable to create session",
32 Self::UnableToLinkAccount => "Unable to link account",
33 }
34 }
35}
36
37impl fmt::Display for OAuthUserInfoError {
38 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(formatter, "{}: {}", self.code_str(), self.message())
40 }
41}
42
43impl Error for OAuthUserInfoError {}
44
45impl From<OAuthUserInfoError> for RustAuthError {
46 fn from(error: OAuthUserInfoError) -> Self {
47 Self::OAuth(error.to_string())
48 }
49}
50
51const HANDLING_DOCS_URL: &str =
52 "https://www.better-auth.com/docs/concepts/oauth#handling-providers-without-email";
53
54pub fn missing_email_log_message(provider_id: &str, source: Option<&str>) -> String {
55 let subject = if source == Some("generic") {
56 format!("Generic OAuth provider \"{provider_id}\"")
57 } else {
58 format!("Provider \"{provider_id}\"")
59 };
60 let where_text = if source == Some("id_token") {
61 " in the id token"
62 } else {
63 ""
64 };
65 format!(
66 "{subject} did not return an email{where_text}. Either request the provider's email scope, or synthesize one via `mapProfileToUser`. See {HANDLING_DOCS_URL}"
67 )
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn oauth_user_info_error_bridges_to_rustauth_error() {
76 let error = OAuthUserInfoError::AccountNotLinked;
77 let bridged: RustAuthError = error.into();
78 assert_eq!(
79 bridged,
80 RustAuthError::OAuth("account_not_linked: Account not linked".to_owned())
81 );
82 }
83
84 #[test]
85 fn oauth_user_info_error_code_str_matches_http_helpers() {
86 assert_eq!(
87 OAuthUserInfoError::SignupDisabled.code_str(),
88 "signup_disabled"
89 );
90 assert_eq!(
91 OAuthUserInfoError::UnableToLinkAccount.message(),
92 "Unable to link account"
93 );
94 }
95}