system settings
git clone https://git.lucas.co/cce-system-interface.git
Google login: request tasks + calendar.readonly scopes, keep is_default
cce-list-sync and cce-calendar-sync read the OAuth tokens this flow
stores in accounts.json, so the consent request now also asks for
Google Tasks and read-only Calendar. Existing accounts need one re-login
to pick the scopes up.
Re-login replaces the same-email account wholesale; it used to reset
is_default to false in passing, so signing in again to the default mail
account silently un-defaulted it. The replacement now inherits the flag.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
src/pages/accounts.rs | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/pages/accounts.rs b/src/pages/accounts.rs
index 75dec5a..9126ddc 100644
--- a/src/pages/accounts.rs
+++ b/src/pages/accounts.rs
@@ -325,8 +325,10 @@ async fn google_login_flow(sender: &calloop::channel::Sender<AppAction>) {
// Mail scopes: these accounts feed cce-mail's IMAP/SMTP (XOAUTH2 needs
// https://mail.google.com/). The old request asked for cloud-platform/
// cclog/aicode scopes — tokens Gmail rejects with AUTHENTICATIONFAILED.
+ // tasks + calendar.readonly feed cce-list-sync and cce-calendar-sync,
+ // which read the tokens this flow stores in accounts.json.
let auth_url = format!(
- "https://accounts.google.com/o/oauth2/v2/auth?client_id={}&redirect_uri=http%3A%2F%2Flocalhost%3A36137%2Fauth%2Fcallback&response_type=code&scope=https%3A%2F%2Fmail.google.com%2F+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&access_type=offline&prompt=consent&code_challenge={}&code_challenge_method=S256",
+ "https://accounts.google.com/o/oauth2/v2/auth?client_id={}&redirect_uri=http%3A%2F%2Flocalhost%3A36137%2Fauth%2Fcallback&response_type=code&scope=https%3A%2F%2Fmail.google.com%2F+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ftasks+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&access_type=offline&prompt=consent&code_challenge={}&code_challenge_method=S256",
client_config.client_id,
challenge
);
@@ -907,9 +909,12 @@ pub fn update(state: &mut AccountsState, msg: AccountsMessage) {
AccountsMessage::GoogleLoginFinished => {
state.oauth_listener_running = false;
}
- AccountsMessage::GoogleLoginSuccess(new_acc) => {
+ AccountsMessage::GoogleLoginSuccess(mut new_acc) => {
let email = new_acc.email.clone();
if let Some(pos) = state.accounts.iter().position(|a| a.email == email) {
+ // A re-login refreshes credentials; it must not silently
+ // un-default the account it replaces.
+ new_acc.is_default = state.accounts[pos].is_default;
state.accounts[pos] = new_acc;
} else {
state.accounts.push(new_acc);