List Google calendars and choose the one to push to (Feature 16)
CI / ci (push) Successful in 3m49s
CI / ci (pull_request) Successful in 3m34s

GET /api/v1/integrations/google/calendars trades the stored refresh token
for an access token, reads every calendarList page and answers
[{id, summary, primary, accessRole}] for writer and owner calendars only.
PUT /api/v1/integrations/google/calendar {calendar_id} validates the id
against that same filtered listing and stores calendar_id and
calendar_name; any other id is 422 unknown_calendar.

Both hold the service's account lock, answer 409 not_connected with
nothing connected, and 502 reconnect_required when Google no longer
accepts the grant, leaving the connection as it is. The gcaltest fake
gains the refresh grant and a pausable calendarList endpoint.

Maestro task 0fe3f1f2-4932-4d10-81dd-74c4f630d215.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 21:15:24 -04:00
co-authored by Claude Opus 5.5
parent f06b57c921
commit 1e3e42e0b1
14 changed files with 1007 additions and 44 deletions
+2
View File
@@ -194,6 +194,8 @@ type Querier interface {
RedraftWeekPlan(ctx context.Context, arg RedraftWeekPlanParams) error
// An unknown id returns sql.ErrNoRows.
SetDinnerFavorite(ctx context.Context, arg SetDinnerFavoriteParams) (Dinner, error)
// Sets the chosen calendar; affects no row when nothing is connected.
SetIntegrationsGoogleCalendar(ctx context.Context, arg SetIntegrationsGoogleCalendarParams) (int64, error)
// Marks a pending batch running; a batch in any other status is left as
// it is (0 rows).
StartSuggestionBatch(ctx context.Context, arg StartSuggestionBatchParams) (int64, error)
+21
View File
@@ -139,6 +139,27 @@ func (q *Queries) GetRecipeSearchSettings(ctx context.Context) (RecipeSearchSett
return i, err
}
const setIntegrationsGoogleCalendar = `-- name: SetIntegrationsGoogleCalendar :execrows
UPDATE integrations_google
SET calendar_id = ?, calendar_name = ?, updated_at = ?
WHERE id = 1
`
type SetIntegrationsGoogleCalendarParams struct {
CalendarID sql.NullString
CalendarName sql.NullString
UpdatedAt string
}
// Sets the chosen calendar; affects no row when nothing is connected.
func (q *Queries) SetIntegrationsGoogleCalendar(ctx context.Context, arg SetIntegrationsGoogleCalendarParams) (int64, error) {
result, err := q.db.ExecContext(ctx, setIntegrationsGoogleCalendar, arg.CalendarID, arg.CalendarName, arg.UpdatedAt)
if err != nil {
return 0, err
}
return result.RowsAffected()
}
const upsertAISettings = `-- name: UpsertAISettings :one
INSERT INTO ai_settings (
id, provider, base_url, model, temperature, system_prompt, api_key_ct,