diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-08-16 00:03:51 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-08-16 00:03:51 +0000 |
| commit | 3660486153a16760d2b980e546bbbd29408fb8d4 (patch) | |
| tree | e29199d88b7365eca0438e41ac23fa0bd533f7c2 /internal/handlers/handlers.go | |
| parent | b55cfbbd433bed6035dfa228ee700e2cca060ca4 (diff) | |
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.
Diffstat (limited to 'internal/handlers/handlers.go')
| -rw-r--r-- | internal/handlers/handlers.go | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index aedbd11..fc66f84 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -15,7 +15,9 @@ import ( "sync" "time" + "github.com/alexedwards/scs/v2" "github.com/go-chi/chi/v5" + "golang.org/x/oauth2" "task-dashboard/internal/api" "task-dashboard/internal/auth" @@ -33,20 +35,22 @@ func newID() string { // Handler holds dependencies for HTTP handlers type Handler struct { - store *store.Store - trelloClient api.TrelloAPI - planToEatClient api.PlanToEatAPI - googleCalendarClient api.GoogleCalendarAPI - googleTasksClient api.GoogleTasksAPI - claudomatorClient api.ClaudomatorClient - config *config.Config - renderer Renderer - BuildVersion string - WebAuthnEnabled bool + store *store.Store + trelloClient api.TrelloAPI + planToEatClient api.PlanToEatAPI + googleCalendarClient api.GoogleCalendarAPI + googleTasksClient api.GoogleTasksAPI + googleTasksOAuthConfig *oauth2.Config + claudomatorClient api.ClaudomatorClient + config *config.Config + renderer Renderer + sessions *scs.SessionManager + BuildVersion string + WebAuthnEnabled bool } // New creates a new Handler instance -func New(s *store.Store, trello api.TrelloAPI, planToEat api.PlanToEatAPI, googleCalendar api.GoogleCalendarAPI, googleTasks api.GoogleTasksAPI, claudomator api.ClaudomatorClient, cfg *config.Config, buildVersion string, webAuthnEnabled bool) *Handler { +func New(s *store.Store, trello api.TrelloAPI, planToEat api.PlanToEatAPI, googleCalendar api.GoogleCalendarAPI, googleTasks api.GoogleTasksAPI, googleTasksOAuthConfig *oauth2.Config, claudomator api.ClaudomatorClient, cfg *config.Config, sessions *scs.SessionManager, buildVersion string, webAuthnEnabled bool) *Handler { // Template functions funcMap := template.FuncMap{ "subtract": func(a, b int) int { return a - b }, @@ -125,16 +129,18 @@ func New(s *store.Store, trello api.TrelloAPI, planToEat api.PlanToEatAPI, googl } return &Handler{ - store: s, - trelloClient: trello, - planToEatClient: planToEat, - googleCalendarClient: googleCalendar, - googleTasksClient: googleTasks, - claudomatorClient: claudomator, - config: cfg, - renderer: NewTemplateRenderer(tmpl), - BuildVersion: buildVersion, - WebAuthnEnabled: webAuthnEnabled, + store: s, + trelloClient: trello, + planToEatClient: planToEat, + googleCalendarClient: googleCalendar, + googleTasksClient: googleTasks, + googleTasksOAuthConfig: googleTasksOAuthConfig, + claudomatorClient: claudomator, + config: cfg, + renderer: NewTemplateRenderer(tmpl), + sessions: sessions, + BuildVersion: buildVersion, + WebAuthnEnabled: webAuthnEnabled, } } |
