From 3660486153a16760d2b980e546bbbd29408fb8d4 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 16 Aug 2026 00:03:51 +0000 Subject: Replace Google Tasks service-account auth with real OAuth Service-account auth structurally cannot see a regular user's personal task lists (no equivalent of Calendar's per-item sharing model) -- confirmed via GetTaskLists returning exactly the service account's own empty "My Tasks" list, never the real user's three lists. Zero rows were ever cached in production as a result. Adds a standard 3-legged OAuth flow: /settings/google-tasks/connect redirects to Google's consent screen (AccessTypeOffline+ApprovalForce so a refresh_token is always issued), /callback exchanges the code and persists the token (new oauth_tokens table), /disconnect clears it. GoogleTasksClient now takes an option.ClientOption instead of a credentials file path; NewGoogleTasksOAuthClient wraps it with a dbTokenSource that reloads/refreshes from the DB on each access-token expiry and re-persists -- carefully preserving the original refresh_token when Google's refresh response omits one (it usually does), which would otherwise silently and permanently break future refreshes. Settings page shows connection status and a Connect/Disconnect button. Calendar keeps using service-account auth (that one actually works). Requires a one-time manual step: create an OAuth 2.0 Client ID in Google Cloud Console and set GOOGLE_OAUTH_CLIENT_ID/SECRET in .env -- documented in .env.example. --- .env.example | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to '.env.example') diff --git a/.env.example b/.env.example index 597a39f..b93cf90 100644 --- a/.env.example +++ b/.env.example @@ -13,6 +13,25 @@ TRELLO_TOKEN= # PlanToEat API is not publicly available - leave empty unless you have access # PLANTOEAT_API_KEY= +# Google Calendar (OPTIONAL) — service-account auth, works because a calendar +# can be shared with any email including a service account's. +# GOOGLE_CREDENTIALS_FILE=/path/to/service-account.json +# GOOGLE_CALENDAR_ID=primary + +# Google Tasks (OPTIONAL) — real user OAuth, NOT service-account auth. A +# service account has no path to a regular user's personal task lists (no +# equivalent of Calendar's sharing model), so this needs its own OAuth 2.0 +# Client ID from Google Cloud Console (APIs & Services > Credentials > +# Create Credentials > OAuth client ID > Web application), with an +# Authorized redirect URI matching GOOGLE_OAUTH_REDIRECT_URL below exactly. +# Enable the Tasks API on the project, and if the OAuth consent screen is in +# "Testing" mode, add your own Google account as a test user. Once set, +# visit /settings in the running app and click "Connect Google Tasks". +# GOOGLE_OAUTH_CLIENT_ID= +# GOOGLE_OAUTH_CLIENT_SECRET= +# GOOGLE_OAUTH_REDIRECT_URL=https://doot.terst.org/settings/google-tasks/callback +# GOOGLE_TASKS_LIST_ID=@default + # Paths # Database file location (relative or absolute path) DATABASE_PATH=./dashboard.db -- cgit v1.2.3