From f82b602518e6b17c5c2b448b655ad2572beb20ad Mon Sep 17 00:00:00 2001 From: Lubrsy706 Date: Thu, 14 May 2026 01:18:08 +0800 Subject: [PATCH 1/3] fix(auth): include Gmail settings scope --- crates/google-workspace-cli/src/auth_commands.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/google-workspace-cli/src/auth_commands.rs b/crates/google-workspace-cli/src/auth_commands.rs index d7571e74..aab5c75d 100644 --- a/crates/google-workspace-cli/src/auth_commands.rs +++ b/crates/google-workspace-cli/src/auth_commands.rs @@ -264,6 +264,7 @@ pub const MINIMAL_SCOPES: &[&str] = &[ "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/gmail.modify", + "https://www.googleapis.com/auth/gmail.settings.basic", "https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/documents", "https://www.googleapis.com/auth/presentations", @@ -289,6 +290,7 @@ pub const FULL_SCOPES: &[&str] = &[ "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/gmail.modify", + "https://www.googleapis.com/auth/gmail.settings.basic", "https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/documents", "https://www.googleapis.com/auth/presentations", @@ -1549,6 +1551,10 @@ const SCOPE_ENTRIES: &[ScopeEntry] = &[ scope: "https://www.googleapis.com/auth/gmail.modify", label: "Gmail", }, + ScopeEntry { + scope: "https://www.googleapis.com/auth/gmail.settings.basic", + label: "Gmail Settings", + }, ScopeEntry { scope: "https://www.googleapis.com/auth/calendar", label: "Google Calendar", @@ -1745,6 +1751,9 @@ mod tests { let scopes = run_resolve_scopes(ScopeMode::Default, None); assert_eq!(scopes.len(), DEFAULT_SCOPES.len()); assert_eq!(scopes[0], "https://www.googleapis.com/auth/drive"); + assert!( + scopes.contains(&"https://www.googleapis.com/auth/gmail.settings.basic".to_string()) + ); } #[test] @@ -1789,6 +1798,9 @@ mod tests { fn resolve_scopes_full_returns_full_scopes() { let scopes = run_resolve_scopes(ScopeMode::Full, None); assert_eq!(scopes.len(), FULL_SCOPES.len()); + assert!( + scopes.contains(&"https://www.googleapis.com/auth/gmail.settings.basic".to_string()) + ); } #[test] From 3e42111b9deaca4da3186f424820b85ba0b2980c Mon Sep 17 00:00:00 2001 From: Lubrsy706 Date: Thu, 14 May 2026 03:52:31 +0800 Subject: [PATCH 2/3] fix(auth): filter redundant Gmail settings scope --- .../google-workspace-cli/src/auth_commands.rs | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/crates/google-workspace-cli/src/auth_commands.rs b/crates/google-workspace-cli/src/auth_commands.rs index aab5c75d..496faff6 100644 --- a/crates/google-workspace-cli/src/auth_commands.rs +++ b/crates/google-workspace-cli/src/auth_commands.rs @@ -859,14 +859,20 @@ fn filter_redundant_restrictive_scopes(scopes: Vec) -> Vec { // broader scopes. Each entry maps a restrictive scope to the broader scopes // that make it redundant. The restrictive scope is removed only if at least // one of its broader alternatives is already in the list. - const RESTRICTIVE_SCOPES: &[(&str, &[&str])] = &[( - "https://www.googleapis.com/auth/gmail.metadata", - &[ - "https://mail.google.com/", - "https://www.googleapis.com/auth/gmail.modify", - "https://www.googleapis.com/auth/gmail.readonly", - ], - )]; + const RESTRICTIVE_SCOPES: &[(&str, &[&str])] = &[ + ( + "https://www.googleapis.com/auth/gmail.metadata", + &[ + "https://mail.google.com/", + "https://www.googleapis.com/auth/gmail.modify", + "https://www.googleapis.com/auth/gmail.readonly", + ], + ), + ( + "https://www.googleapis.com/auth/gmail.settings.basic", + &["https://mail.google.com/"], + ), + ]; let scope_set: std::collections::HashSet = scopes.iter().cloned().collect(); @@ -2372,6 +2378,26 @@ mod tests { assert_eq!(result, scopes); } + #[test] + fn filter_restrictive_removes_settings_basic_when_full_gmail_present() { + let scopes = vec![ + "https://mail.google.com/".to_string(), + "https://www.googleapis.com/auth/gmail.settings.basic".to_string(), + ]; + let result = filter_redundant_restrictive_scopes(scopes); + assert_eq!(result, vec!["https://mail.google.com/"]); + } + + #[test] + fn filter_restrictive_keeps_settings_basic_without_full_gmail() { + let scopes = vec![ + "https://www.googleapis.com/auth/gmail.modify".to_string(), + "https://www.googleapis.com/auth/gmail.settings.basic".to_string(), + ]; + let result = filter_redundant_restrictive_scopes(scopes.clone()); + assert_eq!(result, scopes); + } + #[test] fn mask_secret_long_string() { let masked = mask_secret("GOCSPX-abcdefghijklmnopqrstuvwxyz"); From 6528f7a4461ec2bcd74bd28ba8141a31560ebe1d Mon Sep 17 00:00:00 2001 From: Lubrsy706 Date: Thu, 14 May 2026 10:02:53 +0800 Subject: [PATCH 3/3] fix(auth): keep Gmail settings scope opt-in --- crates/google-workspace-cli/src/auth_commands.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/google-workspace-cli/src/auth_commands.rs b/crates/google-workspace-cli/src/auth_commands.rs index 496faff6..f84ddb23 100644 --- a/crates/google-workspace-cli/src/auth_commands.rs +++ b/crates/google-workspace-cli/src/auth_commands.rs @@ -264,7 +264,6 @@ pub const MINIMAL_SCOPES: &[&str] = &[ "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/gmail.modify", - "https://www.googleapis.com/auth/gmail.settings.basic", "https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/documents", "https://www.googleapis.com/auth/presentations", @@ -1758,7 +1757,7 @@ mod tests { assert_eq!(scopes.len(), DEFAULT_SCOPES.len()); assert_eq!(scopes[0], "https://www.googleapis.com/auth/drive"); assert!( - scopes.contains(&"https://www.googleapis.com/auth/gmail.settings.basic".to_string()) + !scopes.contains(&"https://www.googleapis.com/auth/gmail.settings.basic".to_string()) ); }