Files
microsoft-365-service/README.md
T
JiriUhlir fb97a8bf63 Parametr select u vypisu, telo udalosti v calendarView
- calendar/view: include_body a body_type (html, text), telo udalosti
  rovnou ve vypisu bez dalsiho volani
- select u vypisu mailu, udalosti, calendarView, jedne udalosti a skupin;
  nahrazuje vychozi sadu poli
- app/graph_fields.py: vychozi sady a seznamy dostupnych poli, Swagger
  je zobrazuje v popisu parametru
- README: endpointy, popis select, zaznam zmen
2026-09-23 06:51:05 +02:00

8.4 KiB

Microsoft 365 Service

FastAPI služba pro server-to-server komunikaci s Microsoft 365 přes Microsoft Graph.

Konfigurace

V Microsoft Entra ID vytvořte app registration, přidělte požadovaná aplikační oprávnění pro Microsoft Graph a nastavte tyto environment proměnné:

MS365_TENANT_ID=00000000-0000-0000-0000-000000000000
MS365_CLIENT_ID=00000000-0000-0000-0000-000000000000
MS365_CLIENT_SECRET=secret-value
MS365_GRAPH_BASE_URL=https://graph.microsoft.com/v1.0
MS365_GRAPH_SCOPE=https://graph.microsoft.com/.default
MS365_REQUEST_TIMEOUT_SECONDS=30

Služba používá OAuth2 client credentials flow, takže oprávnění pro Microsoft Graph musí být aplikační oprávnění schválená administrátorem.

Credentials v request hlavičkách

Credentials se posílají v každém requestu v hlavičkách jako obyčejné hodnoty:

X-MS365-Tenant-Id: <tenant id klienta>
X-MS365-Client-Id: <client id aplikace CSBOT>
X-MS365-Client-Secret: <client secret VALUE aplikace CSBOT, ne secret id>

Všechny tři hlavičky musí být pohromadě, jinak služba vrátí 400. Když se nepošle žádná, použijí se MS365_TENANT_ID, MS365_CLIENT_ID a MS365_CLIENT_SECRET z prostředí služby.

Příklad v PowerShellu:

$Headers = @{
    "X-MS365-Tenant-Id"     = $TenantId
    "X-MS365-Client-Id"     = $ClientId
    "X-MS365-Client-Secret" = $ClientSecret
}
Invoke-RestMethod -Method Get -Headers $Headers `
    -Uri "https://services.csbot.cz/apps/microsoft-365-service/users/$UserMailbox/calendar"

Multitenant napojení klientů (CSBOT MS365 Connector)

Služba je stavěná pro jednu multitenant Entra aplikaci CSBOT, přes kterou se připojují Microsoft 365 tenanty jednotlivých klientů. Podrobné zadání je v Notion stránce "MS365 práva konektoru".

  • MS365_CLIENT_ID a MS365_CLIENT_SECRET patří aplikaci CSBOT a jsou pro všechny klienty stejné.
  • MS365_TENANT_ID je tenant konkrétního klienta. Token se získává proti https://login.microsoftonline.com/{tenant klienta}/oauth2/v2.0/token.
  • Při volání za různé klienty se tenant id posílá v hlavičce X-MS365-Tenant-Id (viz "Credentials v request hlavičkách"), client id a secret zůstávají stejné.
  • Klient nevytváří vlastní App Registration ani nepředává secret. Jeho administrátor jen schválí admin consent. URL pro consent vrací GET /admin-consent/url?redirect_uri=...&state=... (bere tenant id a client id z hlaviček nebo z env). Callback po consentu (parametry tenant a admin_consent=True) zpracovává backend CSBOT, ne tato služba.
  • Služba je bezstavová a neověřuje, zda mailbox, plan id nebo bucket id patří danému zákazníkovi. Tenant isolation (customer id -> tenant id, mailbox, plan id, bucket id) musí držet volající backend, hodnoty nesmí přicházet přímo od LLM.

Postup testu po consentu klienta: GET /status, GET /users/{mailbox}/calendar (vrátí id a name kalendáře, nejlevnější ověření přístupu), GET /users/{mailbox}/calendar/view, POST /users/{mailbox}/calendar/events + DELETE, GET /planner/plans/{plan_id}/tasks, POST /planner/tasks + DELETE.

Implementované služby

  • Users: výpis a načtení uživatelů.
  • Mail: výpis zpráv a odesílání e-mailů včetně příloh.
  • Calendar: načtení kalendáře schránky (id, name), výpis událostí, calendarView v zadaném rozsahu, volné termíny (getSchedule), načtení, vytvoření, úprava a smazání události včetně Teams online meetingů.
  • Planner: výpis plánů skupiny, bucketů a tasků plánu, načtení, vytvoření, úprava a smazání tasku. Úprava a smazání používají ETag (If-Match). Když hlavička chybí, služba si aktuální ETag načte sama.
  • OneDrive: výpis souborů v rootu a upload malých souborů.
  • Groups a Teams: výpis skupin a výpis kanálů týmu.
  • Admin consent: sestavení consent URL pro administrátora klientského tenantu.

API

GET  /health
GET  /version
GET  /status
GET  /users?top=25&search=jane
GET  /users/{user_id}
GET  /users/{user_id}/mail/messages?folder=Inbox&top=25&select=...
POST /users/{user_id}/mail/send
GET  /admin-consent/url?redirect_uri=...&state=...
GET  /users/{user_id}/calendar
GET  /users/{user_id}/calendar/events?top=25&select=...
POST /users/{user_id}/calendar/events
GET  /users/{user_id}/calendar/view?start=...&end=...&top=25&time_zone=Europe/Prague&include_body=true&body_type=text&select=...
POST /users/{user_id}/calendar/schedule
GET  /users/{user_id}/calendar/events/{event_id}?select=...
PATCH  /users/{user_id}/calendar/events/{event_id}
DELETE /users/{user_id}/calendar/events/{event_id}
GET  /users/{user_id}/drive/root/children?top=25
PUT  /users/{user_id}/drive/root/{path}
GET  /groups?top=25&select=...
GET  /groups/{group_id}/planner/plans
GET  /teams/{team_id}/channels
GET  /planner/plans/{plan_id}/buckets
GET  /planner/plans/{plan_id}/tasks
POST /planner/tasks
GET  /planner/tasks/{task_id}
PATCH  /planner/tasks/{task_id}     (volitelně hlavička If-Match)
DELETE /planner/tasks/{task_id}     (volitelně hlavička If-Match)

Parametry start a end u calendarView jsou ISO 8601 s offsetem, například 2026-09-08T08:00:00+02:00. Tělo událostí se ve výpisu nevrací, dokud se nepošle include_body=true; body_type=text vrátí tělo jako čistý text místo HTML.

Výpisy mailů, událostí a skupin a načtení jedné události vracejí jen výchozí sadu polí. Parametr select (pole oddělená čárkou) ji nahradí; výchozí sada i seznam dostupných polí jsou u každého endpointu ve Swaggeru a v app/graph_fields.py. Neznámé pole Graph odmítne a služba vrátí 502 s jeho chybou. Datumy u Planneru (due_date_time, start_date_time) jsou ISO 8601 s offsetem, například 2026-09-10T16:00:00Z. Řešitelé se předávají jako Graph user id v assign_user_ids, odebírají v unassign_user_ids.

user_id může být Microsoft Graph user id nebo user principal name, například jane@example.com.

Požadovaná Graph oprávnění

Přidělte pouze oprávnění, která dané nasazení skutečně používá:

  • Users: User.Read.All
  • Čtení mailů: Mail.Read
  • Odesílání mailů: Mail.Send
  • Čtení a zápis do kalendáře, calendarView, getSchedule: Calendars.ReadWrite
  • Planner: Tasks.ReadWrite.All (zahrnuje i čtení, Tasks.Read.All netřeba)
  • Čtení a zápis do OneDrive: Files.ReadWrite.All
  • Výpis skupin a Teams kanálů: Group.Read.All, Team.ReadBasic.All, Channel.ReadBasic.All

Pro konektor CSBOT (Calendar + Planner) je minimum Calendars.ReadWrite a Tasks.ReadWrite.All, obě jako Application permissions. Calendars.ReadWrite platí na všechny mailboxy tenantu, omezení na konkrétní mailbox se řeší na straně klienta v Exchange Online (application access policy), ne v této službě.

Ukázky pro klienty

  • examples/csharp/ListUsersTop10: konzolová aplikace .NET 8, volá GET /users?top=10 s hlavičkami X-MS365-*. Popis v examples/csharp/README.md.

Lokální spuštění

pip install -r requirements.txt
uvicorn app.main:app --reload

Vygenerované OpenAPI UI otevřete na http://localhost:8000/docs.

job queue test Thu May 28 02:12:07 PM CEST 2026

job queue test Thu May 28 02:12:28 PM CEST 2026

websocket logs test Fri May 29 11:03:58 AM CEST 2026

Záznam změn

  • 2026-09-22: parametr select u výpisu mailů, událostí, calendarView, jedné události a skupin. Výchozí sady a seznamy polí v app/graph_fields.py, Swagger je zobrazuje.

  • 2026-09-22: calendar/view má include_body a body_type (html, text), tělo události se dá dotáhnout rovnou ve výpisu bez dalšího volání na jednotlivé události.

  • 2026-09-22: šifrování hlaviček X-MS365-* odstraněno, hodnoty se posílají tak, jak jsou. Zrušena proměnná MS365_CREDENTIAL_ENCODING_SECRET a závislost cryptography.

  • 2026-09-22: GET /users/{user_id}/calendar (objekt kalendáře schránky, id a name) pro read-only ověření přístupu ke kalendáři klienta přes e-mail schránky.

  • 2026-09-09: verze 1.1.0. Podle Notion zadání "MS365 práva konektoru" doplněn Calendar (calendarView, getSchedule, get/patch/delete události), Planner (plány, buckety, tasky, create/patch/delete s ETag) a GET /admin-consent/url. Kód ověřen jen importem aplikace a serializací schémat, proti reálnému tenantu netestováno (chybí DEV App Registration).

  • 2026-09-09: přidána C# ukázka examples/csharp/ListUsersTop10 (top 10 z /users).