272 lines
9.9 KiB
Markdown
272 lines
9.9 KiB
Markdown
# Google API communication
|
|
|
|
Sluzba poskytuje obecnou komunikacni vrstvu pro Google API. Neobsahuje secrets ve zdrojovem kodu a pro verejne routovani pouziva `ROOT_PATH`, aby Swagger/OpenAPI fungoval za AppFactory prefixem `/apps/<app-id>`.
|
|
|
|
## Discovery
|
|
|
|
- `GET /google/discovery/apis` vraci seznam Google API dostupnych pres Google Discovery service.
|
|
- `GET /google/discovery/apis/{api}/{version}/rest` vraci REST discovery dokument konkretniho API, napr. `drive/v3`.
|
|
|
|
Discovery endpointy slouzi k dohledani dostupnych resource, metod, schema a OAuth scope pro konkretni Google API.
|
|
|
|
## OAuth
|
|
|
|
- `POST /google/oauth/token` podporuje `authorization_code` a `refresh_token` grant.
|
|
- `GET /google/oauth/scopes` vraci doporucene scopes pro podporovane sluzby.
|
|
- `GET /google/oauth/authorize-url` vygeneruje Google consent URL.
|
|
- `POST /google/oauth/service-account-token` podporuje service account JWT bearer flow.
|
|
- `POST /google/oauth/revoke` revokuje token.
|
|
- `GET /google/oauth/tokeninfo` vraci informace o access tokenu nebo ID tokenu.
|
|
|
|
OAuth client a service account hodnoty je vhodne predavat pres environment variables:
|
|
|
|
- `GOOGLE_CLIENT_ID`
|
|
- `GOOGLE_CLIENT_SECRET`
|
|
- `GOOGLE_SERVICE_ACCOUNT_EMAIL`
|
|
- `GOOGLE_PRIVATE_KEY`
|
|
- `GOOGLE_SCOPES`
|
|
|
|
### Env promenne a request alternativy
|
|
|
|
Swagger obsahuje `GET /google/configuration`, ktery vypise podporovane env promenne, jejich pouziti a alternativy v requestu. Endpoint nevraci hodnoty secrets.
|
|
|
|
- `GOOGLE_CLIENT_ID`: `clientId`, `X-Google-Client-Id`
|
|
- `GOOGLE_CLIENT_SECRET`: `clientSecret`, `X-Google-Client-Secret`
|
|
- `GOOGLE_REDIRECT_URI`: `redirectUri`, `X-Google-Redirect-Uri`
|
|
- `GOOGLE_SERVICE_ACCOUNT_EMAIL`: `serviceAccountEmail`, `X-Google-Service-Account-Email`
|
|
- `GOOGLE_PRIVATE_KEY`: `privateKey`, `X-Google-Private-Key`
|
|
- `GOOGLE_SCOPES`: `scope`, `scopes`, `X-Google-Scopes`
|
|
- `GOOGLE_SERVICE_ACCOUNT_JSON`: `serviceAccountJson`, `serviceAccountJsonEnv`, `X-Google-Service-Account-Json`, `X-Google-Service-Account-Json-Env`
|
|
- `GOOGLE_ACCESS_TOKEN`: `Authorization: Bearer <token>`, `accessToken`, `accessTokenEnv`, `X-Google-Access-Token`, `X-Google-Access-Token-Env`
|
|
- `GOOGLE_API_KEY`: `apiKey`, `apiKeyEnv`, `X-Google-Api-Key`, `X-Google-Api-Key-Env`
|
|
|
|
### Service account JSON
|
|
|
|
Google service account JSON neobsahuje `access_token`. Obsahuje hlavne `client_email`, `private_key` a `token_uri`. Sluzba z techto poli sama vytvori JWT assertion, zavola Google OAuth token endpoint a ziska docasny `access_token`.
|
|
|
|
Produktove endpointy proto lze volat primo s:
|
|
|
|
- `serviceAccountJson` v body
|
|
- `X-Google-Service-Account-Json` header
|
|
- `serviceAccountJsonEnv` nebo `X-Google-Service-Account-Json-Env`, napr. `GOOGLE_SERVICE_ACCOUNT_JSON`
|
|
|
|
Je nutne dodat scopes:
|
|
|
|
- `serviceAccountScopes` v body
|
|
- `X-Google-Service-Account-Scopes` header
|
|
- nebo `GOOGLE_SCOPES`
|
|
|
|
Priklad pro zapis do Sheets:
|
|
|
|
```json
|
|
{
|
|
"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1abcDEFghiJKLmnopQRstuVWXyz/edit#gid=0",
|
|
"sheetName": "Objednavky",
|
|
"mode": "append",
|
|
"values": [
|
|
["2026-06-15", "ACME", 1234]
|
|
],
|
|
"serviceAccountScopes": [
|
|
"https://www.googleapis.com/auth/spreadsheets"
|
|
],
|
|
"serviceAccountJson": {
|
|
"type": "service_account",
|
|
"project_id": "project-id",
|
|
"private_key_id": "key-id",
|
|
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
|
|
"client_email": "service-account@project-id.iam.gserviceaccount.com",
|
|
"client_id": "123456789",
|
|
"token_uri": "https://oauth2.googleapis.com/token"
|
|
}
|
|
}
|
|
```
|
|
|
|
### OAuth krok za krokem
|
|
|
|
1. Zavolej `GET /google/oauth/scopes`.
|
|
2. Vyber scopes, napr. Sheets + Drive metadata:
|
|
|
|
```text
|
|
https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.metadata.readonly
|
|
```
|
|
|
|
3. Zavolej:
|
|
|
|
```text
|
|
GET /google/oauth/authorize-url?redirectUri=https://example.test/oauth/callback&scopes=https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.metadata.readonly
|
|
```
|
|
|
|
4. Otevri `authorizationUrl` z odpovedi.
|
|
5. Po souhlasu Google presmeruje na `redirectUri` s query parametrem `code`.
|
|
6. Code vymen:
|
|
|
|
```json
|
|
{
|
|
"grantType": "authorization_code",
|
|
"code": "code-from-google-redirect",
|
|
"redirectUri": "https://example.test/oauth/callback"
|
|
}
|
|
```
|
|
|
|
7. `access_token` posilej do produktovych endpointu jako:
|
|
|
|
```text
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
Pro dlouhodobe pouziti si uloz `refresh_token` mimo zdrojovy kod a obnovuj token pres:
|
|
|
|
```json
|
|
{
|
|
"grantType": "refresh_token",
|
|
"refreshToken": "stored-refresh-token"
|
|
}
|
|
```
|
|
|
|
## Obecne REST volani
|
|
|
|
`POST /google/request` je genericka proxy pro Google REST API. Request obsahuje HTTP metodu, cilovou Google URL nebo kombinaci `baseUrl` a `path`, volitelne query parametry, body a autorizaci.
|
|
|
|
Priklad volani Google Drive:
|
|
|
|
```json
|
|
{
|
|
"method": "GET",
|
|
"baseUrl": "https://www.googleapis.com",
|
|
"path": "/drive/v3/files",
|
|
"query": {
|
|
"pageSize": 10
|
|
},
|
|
"accessTokenEnv": "GOOGLE_ACCESS_TOKEN"
|
|
}
|
|
```
|
|
|
|
Z bezpecnostnich duvodu jsou povolene jen HTTPS URL na Google domenach. Requesty na jine hosty sluzba odmita.
|
|
|
|
## Konkretni produktove endpointy
|
|
|
|
Krome obecne proxy jsou dostupne konkretni wrappery nad nejbeznejsimi Google API:
|
|
|
|
### Calendar
|
|
|
|
- `GET /google/calendar/calendars`
|
|
- `POST /google/calendar/calendars`
|
|
- `GET /google/calendar/calendars/{calendarId}`
|
|
- `PATCH /google/calendar/calendars/{calendarId}`
|
|
- `DELETE /google/calendar/calendars/{calendarId}`
|
|
- `GET /google/calendar/calendars/{calendarId}/events`
|
|
- `POST /google/calendar/calendars/{calendarId}/events`
|
|
- `GET /google/calendar/calendars/{calendarId}/events/{eventId}`
|
|
- `PATCH /google/calendar/calendars/{calendarId}/events/{eventId}`
|
|
- `DELETE /google/calendar/calendars/{calendarId}/events/{eventId}`
|
|
- `POST /google/calendar/calendars/{calendarId}/events/{eventId}/move`
|
|
|
|
### Sheets
|
|
|
|
- `GET /google/sheets/spreadsheets` - seznam Google Sheets souboru; `spreadsheetId` je `files[].id`
|
|
- `POST /google/sheets/spreadsheets`
|
|
- `GET /google/sheets/spreadsheets/{spreadsheetId}`
|
|
- `GET /google/sheets/spreadsheets/{spreadsheetId}/sheets` - seznam tabu/listu; numericke `sheetId` je `sheets[].properties.sheetId`, A1 range pouziva `sheets[].properties.title`
|
|
- `POST /google/sheets/write-by-url` - zapis hodnot podle plne URL spreadsheetu a nazvu listu
|
|
- `POST /google/sheets/spreadsheets/{spreadsheetId}/batch-update`
|
|
- `GET /google/sheets/spreadsheets/{spreadsheetId}/values?range=Sheet1!A1:B10`
|
|
- `PUT /google/sheets/spreadsheets/{spreadsheetId}/values?range=Sheet1!A1`
|
|
- `POST /google/sheets/spreadsheets/{spreadsheetId}/values/append?range=Sheet1!A1`
|
|
- `POST /google/sheets/spreadsheets/{spreadsheetId}/values/batch-update`
|
|
- `POST /google/sheets/spreadsheets/{spreadsheetId}/values/batch-clear`
|
|
|
|
#### Zapis podle URL a nazvu listu
|
|
|
|
Endpoint `POST /google/sheets/write-by-url` je urceny pro bezny zapis bez rucni prace se `spreadsheetId` a A1 range.
|
|
|
|
```json
|
|
{
|
|
"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1abcDEFghiJKLmnopQRstuVWXyz/edit#gid=0",
|
|
"sheetName": "Objednavky",
|
|
"startCell": "A1",
|
|
"mode": "append",
|
|
"valueInputOption": "USER_ENTERED",
|
|
"values": [
|
|
["Datum", "Zakaznik", "Castka"],
|
|
["2026-06-15", "ACME", 1234]
|
|
]
|
|
}
|
|
```
|
|
|
|
Chovani:
|
|
|
|
- `mode=append` vola Google Sheets append a prida radky pod existujici tabulku.
|
|
- `mode=update` vola Google Sheets update a prepise bunky od `startCell`.
|
|
- `sheetName` muze obsahovat mezery i apostrofy; sluzba ho sama escapuje do A1 range.
|
|
- `spreadsheetUrl` muze byt bezna URL ve tvaru `https://docs.google.com/spreadsheets/d/{spreadsheetId}/edit#gid=0`.
|
|
|
|
### Drive
|
|
|
|
- `GET /google/drive/files`
|
|
- `POST /google/drive/files`
|
|
- `GET /google/drive/files/{fileId}`
|
|
- `PATCH /google/drive/files/{fileId}`
|
|
- `DELETE /google/drive/files/{fileId}`
|
|
- `GET /google/drive/files/{fileId}/export?mimeType=application/pdf`
|
|
- `GET /google/drive/files/{fileId}/permissions`
|
|
- `POST /google/drive/files/{fileId}/permissions`
|
|
- `DELETE /google/drive/files/{fileId}/permissions/{permissionId}`
|
|
|
|
### Gmail
|
|
|
|
- `GET /google/gmail/profile`
|
|
- `GET /google/gmail/messages`
|
|
- `GET /google/gmail/messages/{messageId}`
|
|
- `POST /google/gmail/messages/send`
|
|
- `GET /google/gmail/labels`
|
|
- `POST /google/gmail/labels`
|
|
|
|
### Docs, Slides a Forms
|
|
|
|
- `POST /google/docs/documents`
|
|
- `GET /google/docs/documents/{documentId}`
|
|
- `POST /google/docs/documents/{documentId}/batch-update`
|
|
- `POST /google/slides/presentations`
|
|
- `GET /google/slides/presentations/{presentationId}`
|
|
- `POST /google/slides/presentations/{presentationId}/batch-update`
|
|
- `POST /google/forms/forms`
|
|
- `GET /google/forms/forms/{formId}`
|
|
- `POST /google/forms/forms/{formId}/batch-update`
|
|
- `GET /google/forms/forms/{formId}/responses`
|
|
|
|
### People a Tasks
|
|
|
|
- `GET /google/people/connections`
|
|
- `GET /google/people/{resourceName}`
|
|
- `POST /google/people/contacts`
|
|
- `PATCH /google/people/{resourceName}`
|
|
- `DELETE /google/people/{resourceName}`
|
|
- `GET /google/tasks/lists`
|
|
- `POST /google/tasks/lists`
|
|
- `GET /google/tasks/lists/{tasklistId}/tasks`
|
|
- `POST /google/tasks/lists/{tasklistId}/tasks`
|
|
- `PATCH /google/tasks/lists/{tasklistId}/tasks/{taskId}`
|
|
- `DELETE /google/tasks/lists/{tasklistId}/tasks/{taskId}`
|
|
|
|
## Kde vzit ID
|
|
|
|
- `calendarId`: `GET /google/calendar/calendars`, hlavni kalendar lze typicky volat jako `primary`.
|
|
- `eventId`: `GET /google/calendar/calendars/{calendarId}/events`.
|
|
- `spreadsheetId`: `GET /google/sheets/spreadsheets`, pole `files[].id`.
|
|
- `sheetId`: `GET /google/sheets/spreadsheets/{spreadsheetId}/sheets`, pole `sheets[].properties.sheetId`.
|
|
- `fileId`: `GET /google/drive/files`, pole `files[].id`.
|
|
- `messageId`: `GET /google/gmail/messages`, pole `messages[].id`.
|
|
- `documentId`: ID Google Docs souboru z Drive.
|
|
- `presentationId`: ID Google Slides souboru z Drive.
|
|
- `formId`: ID Google Forms souboru z Drive nebo odpoved z `POST /google/forms/forms`.
|
|
|
|
## AppFactory overeni
|
|
|
|
Po deploy over:
|
|
|
|
- `GET /apps/google-service/health`
|
|
- `GET /apps/google-service/docs`
|
|
- `GET /apps/google-service/openapi.json`
|
|
|
|
OpenAPI dokument musi obsahovat `servers[0].url` s hodnotou `ROOT_PATH`, napr. `/apps/google-service`, aby Swagger UI volalo endpointy pres verejnou proxy cestu.
|