docs: kalenderen den anden vej, og én registrering til begge Google-ting
`caldav.md` beskrev to måder at sende opgaver *ud*. Den tredje er den modsatte retning og hører til samme sted, fordi det er dér, man ville lede. `configuration.md` hed "Gmail" og handler nu om Google: samme klient, to redirect-URI'er, to API'er, to scopes. Bemærkningen om en Internal-app står begge steder, fordi den gælder begge veje — og for én privat konto er kalenderens egen hemmelige ICS-adresse den kortere vej. Intet i verdande abonnerer på sådan en endnu.
This commit is contained in:
@@ -96,15 +96,16 @@ Apple Reminders, forward mail into it, and add it to Claude as a connector.
|
|||||||
| Mail-to-task | Done, tested |
|
| Mail-to-task | Done, tested |
|
||||||
| AI layer (Anthropic/OpenAI/Google/local) | Built, degrades when unconfigured |
|
| AI layer (Anthropic/OpenAI/Google/local) | Built, degrades when unconfigured |
|
||||||
| Gmail: OAuth2 with PKCE, polling, one-way to tasks | Done, tested |
|
| Gmail: OAuth2 with PKCE, polling, one-way to tasks | Done, tested |
|
||||||
|
| Google Calendar: read-only, laid over the task calendar | Built, never run against Google |
|
||||||
| Update notice for administrators | Done, tested |
|
| Update notice for administrators | Done, tested |
|
||||||
| Personal API tokens | Done, tested |
|
| Personal API tokens | Done, tested |
|
||||||
| OpenAPI 3.1 spec, checked against the router | Done, tested |
|
| OpenAPI 3.1 spec, checked against the router | Done, tested |
|
||||||
| End-to-end smoke tests (Playwright) | Done |
|
| End-to-end smoke tests (Playwright) | Done |
|
||||||
| Documentation, landing page, licence | Done |
|
| Documentation, landing page, licence | Done |
|
||||||
|
|
||||||
**Not finished:** Web Push, the AI providers and the Gmail API calls are
|
**Not finished:** Web Push, the AI providers, and the Gmail and Google Calendar
|
||||||
implemented against their specifications and have only ever been exercised there,
|
API calls are implemented against their specifications and have only ever been
|
||||||
not against live services. Everything else has an interface: opening a task shows
|
exercised there, not against live services. Everything else has an interface: opening a task shows
|
||||||
its description, sub-tasks, comments, files and reminders, and the settings pages
|
its description, sub-tasks, comments, files and reminders, and the settings pages
|
||||||
cover the account, notifications, integrations, AI, API tokens, import, export and
|
cover the account, notifications, integrations, AI, API tokens, import, export and
|
||||||
templates.
|
templates.
|
||||||
|
|||||||
+44
-7
@@ -1,13 +1,14 @@
|
|||||||
# Calendar and CalDAV
|
# Calendar and CalDAV
|
||||||
|
|
||||||
Two ways to get your tasks into a calendar, and they are not the same thing.
|
Two ways to get your tasks into a calendar, one way to get a calendar into
|
||||||
|
verdande, and none of the three is the same thing.
|
||||||
|
|
||||||
| | [Feed](#subscribing-to-a-feed) | [CalDAV](#connecting-a-caldav-client) |
|
| | [Feed](#subscribing-to-a-feed) | [CalDAV](#connecting-a-caldav-client) | [Google Calendar](#showing-a-google-calendar-in-verdande) |
|
||||||
|---|---|---|
|
|---|---|---|---|
|
||||||
| Direction | Read only | Two-way |
|
| Direction | Tasks out, read only | Tasks out, two-way | Events **in**, read only |
|
||||||
| Works with | Anything that subscribes to a URL | Apple Reminders, Thunderbird, DAVx⁵ |
|
| Works with | Anything that subscribes to a URL | Apple Reminders, Thunderbird, DAVx⁵ | A Google account |
|
||||||
| You can tick things off | No | Yes |
|
| You can tick things off | No | Yes | No — an event is not a task |
|
||||||
| Setup | Paste a URL | Username and token |
|
| Setup | Paste a URL | Username and token | Connect, then pick calendars |
|
||||||
|
|
||||||
## Subscribing to a feed
|
## Subscribing to a feed
|
||||||
|
|
||||||
@@ -39,6 +40,42 @@ most people actually keep.
|
|||||||
**Settings → Calendar feed → Rotate** issues a new one and breaks the old
|
**Settings → Calendar feed → Rotate** issues a new one and breaks the old
|
||||||
immediately.
|
immediately.
|
||||||
|
|
||||||
|
## Showing a Google calendar in verdande
|
||||||
|
|
||||||
|
The two sections above send your tasks *out*. This is the other direction: your
|
||||||
|
Google calendar drawn underneath them, so one screen answers "what does this day
|
||||||
|
already have in it".
|
||||||
|
|
||||||
|
**Settings → Integrations → Google Calendar → Connect**, then tick the calendars
|
||||||
|
you want and press Save. They appear in **Calendar** in the sidebar, in Google's
|
||||||
|
own colour for each one, beside your own tasks with due dates.
|
||||||
|
|
||||||
|
It needs the same OAuth client Gmail uses, with the Calendar API enabled and the
|
||||||
|
second redirect URI registered — see [Configuration](configuration.md#google).
|
||||||
|
|
||||||
|
!!! warning "Read only"
|
||||||
|
verdande never writes to your Google calendar. An event cannot be dragged,
|
||||||
|
edited or ticked off here; clicking one opens it in Google, which is where it
|
||||||
|
can be changed. Your own tasks in the same grid still drag to another day as
|
||||||
|
they always have.
|
||||||
|
|
||||||
|
Writing would need the `calendar.events` scope and an answer to what should
|
||||||
|
happen when both sides moved the same meeting — which is a synchronisation
|
||||||
|
model rather than a scope, and it is deliberately not built yet.
|
||||||
|
|
||||||
|
!!! note "The Internal client applies here too"
|
||||||
|
An OAuth client registered as *Internal* in a Google Workspace can only be
|
||||||
|
used by accounts in that workspace, calendars included. A personal
|
||||||
|
`@gmail.com` address is refused with `org_internal`. For one personal account
|
||||||
|
the shorter road is the calendar's own secret address: in Google Calendar,
|
||||||
|
**Settings → the calendar → Integrate calendar → Secret address in iCal
|
||||||
|
format**. Nothing in verdande subscribes to one yet — it is the next piece of
|
||||||
|
this feature.
|
||||||
|
|
||||||
|
Events are kept for ninety days back and a year forward, refreshed every fifteen
|
||||||
|
minutes and whenever you press **Fetch now**. Paging the grid past that window
|
||||||
|
says so rather than showing an empty month.
|
||||||
|
|
||||||
## Connecting a CalDAV client
|
## Connecting a CalDAV client
|
||||||
|
|
||||||
This is the one where ticking something off in Apple Reminders ticks it off here.
|
This is the one where ticking something off in Apple Reminders ticks it off here.
|
||||||
|
|||||||
+26
-7
@@ -39,12 +39,24 @@ Any Go duration: `720h`, `30m`, `45s`.
|
|||||||
yourself, password resets are written to the log, and reminders arrive in the
|
yourself, password resets are written to the log, and reminders arrive in the
|
||||||
app and as Web Push rather than by email.
|
app and as Web Push rather than by email.
|
||||||
|
|
||||||
## Gmail
|
## Google
|
||||||
|
|
||||||
Only needed if anyone will connect a mailbox. Register an OAuth client in Google
|
Only needed if anyone will connect a Gmail mailbox or a Google calendar. One
|
||||||
Cloud (**APIs & Services → Credentials → OAuth client ID → Web application**) with
|
registration covers both: register an OAuth client in Google Cloud
|
||||||
the redirect URI `https://your-address/oauth/gmail/callback`, enable the Gmail API,
|
(**APIs & Services → Credentials → OAuth client ID → Web application**) and add
|
||||||
and add the `gmail.readonly` scope.
|
**both** redirect URIs:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://your-address/oauth/gmail/callback
|
||||||
|
https://your-address/oauth/calendar/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
Then enable the APIs and scopes for whichever you want:
|
||||||
|
|
||||||
|
| For | Enable | Scope |
|
||||||
|
|---|---|---|
|
||||||
|
| Mailboxes | Gmail API | `gmail.readonly` |
|
||||||
|
| Calendar | Google Calendar API | `calendar.readonly` |
|
||||||
|
|
||||||
| Variable | What it does |
|
| Variable | What it does |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -52,8 +64,15 @@ and add the `gmail.readonly` scope.
|
|||||||
| `VERDANDE_GMAIL_CLIENT_SECRET` | The client secret. |
|
| `VERDANDE_GMAIL_CLIENT_SECRET` | The client secret. |
|
||||||
|
|
||||||
One registration serves every user on the instance; each person authorises their
|
One registration serves every user on the instance; each person authorises their
|
||||||
own mailbox from **Settings → Gmail**. The redirect URI is derived from
|
own mailbox from **Settings → Integrations → Gmail** and their own calendar from
|
||||||
`VERDANDE_BASE_URL`, so it cannot drift out of step with what you registered.
|
**Settings → Integrations → Google Calendar**. Both redirect URIs are derived from
|
||||||
|
`VERDANDE_BASE_URL`, so they cannot drift out of step with what you registered.
|
||||||
|
|
||||||
|
!!! note "Two connections, two grants"
|
||||||
|
Connecting a calendar does not disturb a working Gmail connection, and
|
||||||
|
disconnecting one does not take the other with it. Google issues a refresh
|
||||||
|
token per authorisation and keeps up to a hundred of them live per account,
|
||||||
|
each carrying only the scopes it was granted with.
|
||||||
|
|
||||||
## Secrets
|
## Secrets
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ administrator who can read yours.
|
|||||||
**Settings → Integrations → Gmail → Connect.**
|
**Settings → Integrations → Gmail → Connect.**
|
||||||
|
|
||||||
Gmail needs an OAuth client, which is the instance's registration with Google
|
Gmail needs an OAuth client, which is the instance's registration with Google
|
||||||
rather than anybody's account — see [Configuration](configuration.md#gmail).
|
rather than anybody's account — see [Configuration](configuration.md#google).
|
||||||
Once it is set up, each person connects their own mailbox through it.
|
Once it is set up, each person connects their own mailbox through it.
|
||||||
|
|
||||||
Choose what makes a task:
|
Choose what makes a task:
|
||||||
|
|||||||
Reference in New Issue
Block a user