9.5 KiB
MSFT- und Google-Connector: CalendarAdapter + ContactsAdapter, plus Reconnect-Button
Beschreibung und Kontext
Der Infomaniak-Connector liefert seit dem 2026-04-28 die drei Services kDrive, Calendar und Contacts. Die analogen Services fuer Microsoft und Google fehlten bislang in der UDB. Ziel dieses Builds: vier neue ServiceAdapter (MSFT-Calendar, MSFT-Contacts, Google-Calendar, Google-Contacts), so dass die UDB pro Connection einen einheitlichen Service-Pool zeigt und der Agent fuer Calendar/Contacts gegen alle drei Provider gleichermassen arbeiten kann.
Zusaetzliche Anforderung: ein Reconnect-Button im Frontend. Bestehende
MSFT-/Google-Connections wurden mit einem kleineren Scope-Set autorisiert.
Beim Hinzufuegen neuer Scopes (Calendars.Read, Contacts.Read,
calendar.readonly, contacts.readonly) liefern die Provider auf einer
Re-Authorisierung sonst still dieselben alten Tokens, weil sie
include_granted_scopes (Google) bzw. prompt=select_account (MSFT)
default-maessig nutzen -- die neuen Scopes wuerden nie das Tokenset
erreichen.
Architektur
oauthProviderConfig.googleDataScopes+=calendar.readonly,contacts.readonlyoauthProviderConfig.msftDataScopes+=Calendars.Read,Contacts.ReadconnectorMsft.CalendarAdapter(neu)- Endpoints:
me/calendars,me/calendars/{id}/events - Pagination via
@odata.nextLink(Helper_stripGraphBaseaus dem Modul) - Pfad:
""-> Calendars;"/{calendarId}"-> Events - Download: synthetisches RFC-5545 VCALENDAR/VEVENT (Graph hat keinen
$value-Endpoint fuer Events)
- Endpoints:
connectorMsft.ContactsAdapter(neu)- Endpoints:
me/contactFolders,me/contactFolders/{id}/contacts, plus virtueller Default-Folderdefault->me/contacts - Download: vCard 3.0 (N/FN/ORG/TITLE/EMAIL/TEL/ADR/NOTE)
- Endpoints:
- Helper:
_eventToIcs,_contactToVcard,_safeFileName,_personLabel,_icsEscape,_icsDateTime(alle modullokal) connectorMsft.MsftConnector._SERVICE_MAP+="calendar"+"contact"connectorGoogle.CalendarAdapter(neu)- Endpoints:
users/me/calendarList,calendars/{id}/events?singleEvents=true&orderBy=startTime - Download:
.icsaus Event-Detail synthetisiert - Search:
events?q=...per Calendar-ID (Defaultprimary)
- Endpoints:
connectorGoogle.ContactsAdapter(neu)- Endpoints:
contactGroups+ virtuellerall->people/me/connections - Gruppen-Mitglieder via
contactGroups/{id}->memberResourceNames->people:batchGet?resourceNames=...&personFields=... - Search:
people:searchContacts - Download: vCard 3.0 aus
personFields=names,emailAddresses,phoneNumbers, organizations,addresses,biographies,memberships
- Endpoints:
connectorGoogle.GoogleConnector._SERVICE_MAP+="calendar"+"contact"routeFeatureWorkspaceundrouteFeatureGraphicalEditorService-Label-/Icon-Maps +=kdrive,calendar,contact(so dass die UDB sinnvolle Bezeichnungen anzeigt -- vorher war Infomaniak-kDrive ungelabelt durchgerutscht)
Reconnect-Flow
routeDataConnections.connect_service(POST /api/connections/{id}/connect) akzeptiert optionalen Body{"reauth": true}und haengt&reauth=1an die zurueckgegebeneauth_url.routeSecurityMsft.auth_connectsetzt beireauth=1prompt=consent(stattselect_account/login). Das erzwingt den Microsoft-Consent-Screen und liefert die neuen Scopes nach.routeSecurityGoogle.auth_connectdroppt beireauth=1include_granted_scopes=true(default-truemacht Google "vergesslich" fuer neu hinzugekommene Scopes -- ohne diesen Drop blieben die neuen Scopes still aussen vor).- ClickUp ignoriert den Param (FastAPI laesst unbekannte Query-Args durchrutschen) -- das ist OK, weil ClickUp keine Scope-Erweiterung hat.
- Frontend:
connectionApi.connectService(id, reauth?)haengt den Body an.useConnections.connectWithPopup(id, reauth?)reicht durch (auch der separateuseOAuthConnect-Hook).ConnectionsPagehat ein neuescustomActionreconnectmitFaSyncAlt-Icon, eigenemreconnectingConnections-Set undvisible-Filterstatus === 'active' && authority in {msft, google, clickup}. Der Refresh-Button bleibt fuer Token-Refresh ohne Re-Consent erhalten.
Fokus und kritische Details
- Pagination: MSFT Calendar/Contacts paginieren bei
$top<=100; wir ziehen@odata.nextLinkdurch wie OutlookAdapter und stoppen beieffectiveLimit. - iCal-Bauen: Wir ueberlassen das nicht einer Library, weil RFC-5545
fuer einzelne VEVENT-Faelle trivial ist und der Overhead einer
Dependency (
icalendar) nicht gerechtfertigt ist. Escape und DTSTAMP/DTSTART/DTEND in UTC. - vCard-Bauen: vCard 3.0 weil universell von Outlook/Google/macOS Contacts akzeptiert. ADR-Felder: leere Felder werden als leere Slots gerendert (nicht weggelassen), damit das Format gueltig bleibt.
- Default-Contacts-Folder: Outlook hat einen unsichtbaren
Default-Ordner -- den simulieren wir mit dem Pseudo-Folder
default, der intern aufme/contactsmappt. Ohne diesen Eintrag waere der Default-Ordner aus der UDB nicht erreichbar. - People-API Group-Resolution:
contactGroups/{id}liefert keine vollstaendigen Person-Records, nurmemberResourceNames. Wir batchen diese in 200er-Chunks viapeople:batchGet. Limit fuer Resource-Names pro Batch ist 200 (Google API spec). - Reconnect ohne Token-Vernichtung: Wir loeschen die alte Token nicht -- der Auth-Callback ueberschreibt sie atomar nach erfolgreichem Code-Exchange. Bei abgebrochenem Reconnect bleibt der bisherige Token gueltig.
Entscheidungen
- Calendar/Contacts read-only: Wir nehmen
Calendars.Read/calendar.readonly/Contacts.Read/contacts.readonly-- nicht ReadWrite. Der UDB-Use-Case ist ausschliesslich Lesen + Suche + Download. Schreibrechte werden bei einem konkreten Bedarf separat diskutiert (mehr Scopes erhoehen Consent-Aufwand und Risk-Profile unnoetig). - Reconnect statt eigenem Endpoint: Wir spendieren keinen separaten
/reconnect-Endpoint, sondern einen Body-Param am bestehenden/connect. Vorteil: ein einziger Authorisierungspfad, identische Callback-Behandlung, kein doppeltes State-Management. include_granted_scopesDrop bei Google: Defaulttrueist freundlich fuer Token-Reuse, aber die offizielle Google-Doku warnt ausdruecklich, dass es bei Scope-Erweiterung ueberraschend Tokens ohne neue Scopes ausstellt.falsebei Reconnect ist die robustere Wahl.prompt=consentbei MSFT: Microsoft erkennt zusaetzliche Scopes zwar normalerweise selbststaendig und zeigt einen Consent-Screen, aber das ist nur best-effort. Mitprompt=consentist es garantiert.- vCard 3.0 statt 4.0: 4.0 hat noch immer schlechte Outlook- Kompatibilitaet beim Import; 3.0 ist der Common-Denominator.
.icsper Hand bauen stattiCalendar-Lib: Eine externe Dependency lohnt fuer einen einzigen VEVENT je Download nicht.
Umsetzungs-Checkliste
oauthProviderConfig.py:googleDataScopes+msftDataScopesergaenztconnectorMsft.CalendarAdapter(browse/download/search)connectorMsft.ContactsAdapter(browse/download/search)connectorMsft._SERVICE_MAP:calendar,contactregistriertconnectorMsft._eventToIcs,_contactToVcard, HelpersconnectorGoogle.CalendarAdapter(browse/download/search)connectorGoogle.ContactsAdapter(browse/download/search inkl. Group-Resolution)connectorGoogle._SERVICE_MAP:calendar,contactregistriertconnectorGoogle._googleEventToIcs,_googlePersonToVcard, HelpersrouteFeatureWorkspaceService-Label/Icon-Maps erweitertrouteFeatureGraphicalEditorService-Label/Icon-Maps erweitertrouteDataConnections.connect_service: optionalerreauth-BodyrouteSecurityMsft.auth_connect:reauth->prompt=consentrouteSecurityGoogle.auth_connect:reauth-> dropinclude_granted_scopes- Frontend
connectionApi.connectService(id, reauth?) - Frontend
useConnections.connectWithPopup(id, reauth?)(beide Hooks) - Frontend
ConnectionsPage:Reconnect-Button mitFaSyncAlt-Icon und eigenem Loading-Set - Manuelle Verifikation: existierende MSFT-Connection neu durchklicken (Reconnect), Calendar+Contacts in der UDB verifizieren; existierende Google-Connection genauso
- Manuelle Verifikation: Calendar-Download liefert eine
importierbare
.ics(Outlook-Test); Contacts-Download liefert eine importierbare.vcf - Doc-Sync:
wiki/b-reference/auth-and-rbac.md,wiki/b-reference/connectors.mdaktualisieren (neue Scopes, Reconnect-Pfad), Topics-Liste pruefen
Akzeptanzkriterien
- Bestehende MSFT-/Google-Connection -> Reconnect-Button -> nach
Consent erscheinen
CalendarundContactsals zusaetzliche Service-Knoten in der UDB. - Calendar-Browse listet die User-Calendars; Klick auf einen
Calendar listet die juengsten Events; Download eines Events
liefert eine
.icsmit DTSTART/DTEND/SUMMARY/LOCATION. - Contacts-Browse listet ContactFolders (MSFT) bzw. ContactGroups
(Google); Klick listet die enthaltenen Contacts; Download liefert
eine
.vcfmit FN, ORG, EMAIL, TEL. - Frischer Connect (neue MSFT-Connection) zieht die neuen Scopes ohne
Reconnect (weil sie im initialen
msftDataScopes/googleDataScopesenthalten sind). - ClickUp- und FTP-Connections sind unbeeintraechtigt; bei Infomaniak ist der Reconnect-Button korrekt nicht sichtbar (Authority-Whitelist).