tenseleyflow/rcal / 97c7de7

Browse files

Clarify Google OAuth token errors

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
97c7de769e3741a41f0028f2a4a40e5f68d8a0d4
Parents
af9d202
Tree
89f0b17

1 changed file

StatusFile+-
M src/providers.rs 47 9
src/providers.rsmodified
@@ -3411,6 +3411,26 @@ fn google_error_message(response: MicrosoftHttpResponse) -> String {
34113411
     }
34123412
 }
34133413
 
3414
+fn google_oauth_error_message(response: MicrosoftHttpResponse) -> String {
3415
+    if let Ok(value) = serde_json::from_str::<Value>(&response.body)
3416
+        && let Some(error) = graph_string(&value, "error")
3417
+    {
3418
+        let description = graph_string(&value, "error_description");
3419
+        return match description {
3420
+            Some(description) if !description.is_empty() => {
3421
+                format!("Google OAuth {}: {error}: {description}", response.status)
3422
+            }
3423
+            _ => format!("Google OAuth {}: {error}", response.status),
3424
+        };
3425
+    }
3426
+    let body = response.body.trim();
3427
+    if body.is_empty() {
3428
+        format!("Google OAuth HTTP {}", response.status)
3429
+    } else {
3430
+        format!("Google OAuth HTTP {}: {body}", response.status)
3431
+    }
3432
+}
3433
+
34143434
 fn parse_oauth_json(response: MicrosoftHttpResponse) -> Result<Value, ProviderError> {
34153435
     if response.status != 200 {
34163436
         return Err(ProviderError::Auth(graph_error_message(response)));
@@ -3436,7 +3456,7 @@ fn google_token_from_response(
34363456
     existing_refresh_token: Option<String>,
34373457
 ) -> Result<GoogleToken, ProviderError> {
34383458
     if response.status != 200 {
3439
-        return Err(ProviderError::Auth(google_error_message(response)));
3459
+        return Err(ProviderError::Auth(google_oauth_error_message(response)));
34403460
     }
34413461
     let value = serde_json::from_str::<Value>(&response.body)
34423462
         .map_err(|err| ProviderError::Auth(format!("Google token response is invalid: {err}")))?;
@@ -4488,32 +4508,32 @@ impl fmt::Display for ProviderError {
44884508
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44894509
         match self {
44904510
             Self::Config(reason) => write!(f, "provider config error: {reason}"),
4491
-            Self::Auth(reason) => write!(f, "Microsoft auth error: {reason}"),
4492
-            Self::Keyring(reason) => write!(f, "Microsoft token keyring error: {reason}"),
4493
-            Self::Http(reason) => write!(f, "Microsoft HTTP error: {reason}"),
4511
+            Self::Auth(reason) => write!(f, "provider auth error: {reason}"),
4512
+            Self::Keyring(reason) => write!(f, "provider token keyring error: {reason}"),
4513
+            Self::Http(reason) => write!(f, "provider HTTP error: {reason}"),
44944514
             Self::Graph(reason) => write!(f, "Microsoft Graph error: {reason}"),
44954515
             Self::Api(reason) => write!(f, "provider API error: {reason}"),
4496
-            Self::Mapping(reason) => write!(f, "Microsoft event mapping error: {reason}"),
4516
+            Self::Mapping(reason) => write!(f, "provider event mapping error: {reason}"),
44974517
             Self::Validation(reason) => write!(f, "{reason}"),
4498
-            Self::NotFound(id) => write!(f, "Microsoft event '{id}' was not found"),
4518
+            Self::NotFound(id) => write!(f, "provider event '{id}' was not found"),
44994519
             Self::CacheRead { path, reason } => {
45004520
                 write!(
45014521
                     f,
4502
-                    "failed to read Microsoft cache {}: {reason}",
4522
+                    "failed to read provider cache {}: {reason}",
45034523
                     path.display()
45044524
                 )
45054525
             }
45064526
             Self::CacheParse { path, reason } => {
45074527
                 write!(
45084528
                     f,
4509
-                    "failed to parse Microsoft cache {}: {reason}",
4529
+                    "failed to parse provider cache {}: {reason}",
45104530
                     path.display()
45114531
                 )
45124532
             }
45134533
             Self::CacheWrite { path, reason } => {
45144534
                 write!(
45154535
                     f,
4516
-                    "failed to write Microsoft cache {}: {reason}",
4536
+                    "failed to write provider cache {}: {reason}",
45174537
                     path.display()
45184538
                 )
45194539
             }
@@ -4974,6 +4994,24 @@ mod tests {
49744994
         assert!(master.recurrence.is_some());
49754995
     }
49764996
 
4997
+    #[test]
4998
+    fn google_oauth_errors_parse_top_level_error_response() {
4999
+        let response = RecordingHttpClient::json(
5000
+            400,
5001
+            json!({
5002
+                "error": "invalid_request",
5003
+                "error_description": "client_secret is missing."
5004
+            }),
5005
+        );
5006
+
5007
+        let err = google_token_from_response(response, None).expect_err("400 fails");
5008
+
5009
+        assert_eq!(
5010
+            err.to_string(),
5011
+            "provider auth error: Google OAuth 400: invalid_request: client_secret is missing."
5012
+        );
5013
+    }
5014
+
49775015
     #[test]
49785016
     fn provider_write_targets_use_configured_editable_calendars() {
49795017
         let cache_file = temp_path("targets/microsoft-cache.json");