Repository navigation
fix(calendar): log and show why connecting a calendar failed - #669
Merged
Merged
Conversation
The OAuth callback redirected to /settings?tab=account, whose legacy redirect drops the query string, so no outcome reached the Calendars card. It now lands on /settings/integrations. A failure at the token exchange, account lookup or calendar list step is logged with the step, the HTTP status and the provider's error code and message, and the code travels to the card as `reason`. The card shows the failure inline, with hints for the common Google Workspace and Microsoft 365 causes. The provider-error helpers move from the push service into calendar_service so both paths share them. Fixes: #668
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Description
Fixes #668.
Why nothing was shown. The callback's 303 went to
/settings?tab=account&calendar=error&provider=google. Since the settings reorganisation (#154), the settings index turns?tab=accountinto/settings/profileand drops every other query parameter, and the Calendars card lives on Integrations. No callback outcome has reached the page since then, success included. The redirect now points at/settings/integrations?calendar=<status>&provider=<provider>.Why nothing was logged. The calendar list's
HTTPStatusErrorescapedhandle_callback, and the endpoint's catch-all redirected without a log line. The three provider steps after consent (token exchange, account lookup, calendar list) now run in_read_connecting_account, which raisesCalendarConnectFailedwith the step, the provider's error code and a described failure. The endpoint logsConnecting a google calendar failed at the calendar list step: HTTP 403 <reason>: <message>and addsreason=<code>to the redirect. Nothing is stored until all three steps succeed, so a 403 at the calendar list still leaves nocalendar_connectionsrow. The Microsoft callback shared the gap and gets the same handling.Also logged now: an authorisation error the provider sends back in the query string (the OAuth
errorand anyAADSTSnumber, never the description), a configuration or expired-session failure, any other callback or start failure (by type), and the reason for a failed initial or periodic sync.What the user sees. A failed connection shows an error notice at the top of the Calendars card, kept until dismissed or the next Connect. It has the title "Could not connect Google Calendar" (or Outlook Calendar), a plain-words explanation for known codes, a Google Workspace or Microsoft 365 hint where one applies, and "Reason given by Google:
". A success or a cancelled sign-in is still a toast.Shared helpers.
_truncate_error,_google_error_reason,_provider_error_fieldsand_describe_push_failure(renamed_describe_provider_failure) move fromcalendar_push_service.pytocalendar_service/provider_errors.py, and the push service imports them. Push behaviour is unchanged, except that an email address a provider echoes back is now masked in the log andlast_error.docs/CALENDAR.mdgains "Connecting Fails After Sign-In", with the common reasons and where the log line appears.Decision record
SettingsIndexcarry query strings through legacy redirects would also work, but it changes every old?tab=link for no current need.[A-Za-z][A-Za-z0-9_.-]{0,63}in the API and again in the page, so a crafted link cannot put arbitrary text on the settings page. Google's numericerror.coderepeats the HTTP status, so the log keepsHTTP 403witherrors[].reasonbeside it.notACalendarUser,accessNotConfigured,insufficientPermissions,ACCESS_TOKEN_SCOPE_INSUFFICIENT,forbidden,PERMISSION_DENIEDandadmin_policy_enforced; Graph'sErrorAccessDeniedandMailboxNotEnabledForRESTAPI; the token endpoint'sinvalid_client,unauthorized_clientandinvalid_grant. Any other code reads "Google refused the connection." with the code shown as given.Type of change
Checks run
scripts/check.pygates (lint, format, blindexcept, heldpins, typecheck, docs, alembic) and the full pytest suite with Postgres, 3692 passed. Host side: whitespace, file size, docs validator,git diff --check.npm run lint,npm run check:contrast(1188 pairings),npm run test(1765 passed),npm run build.cd site && npm ci && npm run buildpython3 scripts/validate_docs.pyTwo API tests drive the Google and the Microsoft callback through a stub provider that accepts the code and the account lookup, then answers the calendar list with 403. They check the redirect's
reason, the log line, that no token, code, state or address reaches the log, and that nocalendar_connectionsrow exists. Further tests cover the authorisation-error path, a craftederrorvalue, the shared helpers and the card's notice. All of them fail onmain.Migration impact
python3 scripts/check_migrations.pyrun against a throwaway Postgres.Documentation impact
.github/CONTRIBUTING.md, "Documentation Ownership"):docs/CALENDAR.md, Connecting a Calendar and a new Connecting Fails After Sign-In section.Security impact
reasonis shape-checked on both sides. Log text comes from the response body's error fields only.docs/SECURITY.mdboundaries preserved and updated where behaviour changed.Manual verification
None by hand beyond the tests. After the live rebuild, connecting the Workspace account from #668 again should show the notice in the Calendars card and log the reason Google gave.