stremio/GOOGLE_PLAY_ACCESS_SETUP.md
Jos Vooges | STH 4f76e39124 Move Google Play credentials into admin Settings UI.
Store encrypted service-account and group config in the database so Dokploy env vars are optional.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 03:10:59 +02:00

206 lines
7 KiB
Markdown

# Google Play Closed Testing — server-side setup
Deze functionaliteit beheert **distributietoegang** tot de Android-app via Google Play Closed Testing.
Het vervangt **niet** de bestaande app-login of API-autorisatie.
## Architectuur
```
Adminpaneel → backend → Google Cloud Identity Groups API → Google Group
↓
Google Play Closed Testing track
```
- Gebruikers worden **niet** individueel via de Play Developer API beheerd.
- De Closed Testing-track wordt **eenmalig** gekoppeld aan `PLAY_ACCESS_GROUP_EMAIL`.
- Het adminpaneel beheert alleen lidmaatschap van die groep.
## Benodigde configuratie
**Voorkeur:** vul alles in via het adminpaneel → **Instellingen → Google Play**.
Credentials worden versleuteld in de database opgeslagen (zoals OpenSubtitles).
Optioneel blijven environment variables werken als fallback (bijv. voor lokale development).
### Velden in Instellingen
| Veld | Verplicht | Beschrijving |
|------|-----------|--------------|
| Project ID | Ja | Google Cloud project ID |
| Service account e-mail | Ja | Service account e-mail |
| Private key | Ja | PEM private key |
| Workspace admin e-mail | Meestal ja | Admin voor domain-wide delegation |
| Workspace customer ID | Optioneel | Workspace customer ID |
| Play access group ID | Ja | Group resource ID (zonder `groups/` prefix) |
| Play access group e-mail | Ja | E-mailadres van de Google Group |
| Opt-in URL | Aanbevolen | Publieke Closed Testing opt-in URL |
### Optionele environment variables (fallback)
Stel deze alleen in als je géén Settings-UI gebruikt:
| Variabele | Beschrijving |
|-----------|--------------|
| `GOOGLE_CLOUD_PROJECT_ID` | Google Cloud project ID |
| `GOOGLE_SERVICE_ACCOUNT_EMAIL` | Service account e-mail |
| `GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY` | PEM private key (`\n` als `\\n` in env) |
| `PLAY_ACCESS_GROUP_ID` | Group resource ID |
| `PLAY_ACCESS_GROUP_EMAIL` | E-mailadres van de Google Group |
| `GOOGLE_WORKSPACE_ADMIN_EMAIL` | Admin voor domain-wide delegation |
| `GOOGLE_WORKSPACE_CUSTOMER_ID` | Workspace customer ID |
| `GOOGLE_PLAY_OPT_IN_URL` | Publieke Closed Testing opt-in URL |
| `GOOGLE_PLAY_SYNC_INTERVAL_MS` | Reconciliatie-interval (default: 86400000 = 24u) |
### Waar instellen
- **Productie (aanbevolen):** Admin UI → Instellingen → Google Play
- **Lokaal fallback:** `apps/master-api/.env`
- **Dokploy env:** alleen nodig als je Settings-UI niet wilt gebruiken
## Google Cloud — handmatige stappen
### 1. APIs inschakelen
In Google Cloud Console → APIs & Services:
- **Cloud Identity Groups API** (`cloudidentity.googleapis.com`)
### 2. Service account aanmaken
1. IAM & Admin → Service Accounts → Create
2. Download JSON key **of** kopieer private key naar `GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY`
3. Noteer `client_email` → `GOOGLE_SERVICE_ACCOUNT_EMAIL`
### 3. Domain-wide delegation (Workspace)
Als de group in Google Workspace staat:
1. Service account → Enable Domain-Wide Delegation
2. Google Admin Console → Security → API Controls → Domain-wide delegation
3. Voeg scope toe: `https://www.googleapis.com/auth/cloud-identity.groups`
4. Stel `GOOGLE_WORKSPACE_ADMIN_EMAIL` in op een super admin
### 4. Service account rechten op de group
De service account (of geïmpersonateerde admin) moet leden kunnen beheren:
- Google Group → **Group member manager** of **Owner**
- Of via Cloud Identity met de juiste IAM-rollen
### 5. Google Group aanmaken
Maak een **technische ACL-groep** (geen hardcoded naam in code):
- Niet publiek vindbaar
- Self-join uit
- Alleen beheerders beheren leden
- Ledenlijst niet zichtbaar voor gewone members
- Posten/conversations uit indien mogelijk
- Externe accounts alleen toestaan als nodig (bijv. `@gmail.com` testers)
Noteer:
- Group e-mail → `PLAY_ACCESS_GROUP_EMAIL`
- Group ID → `PLAY_ACCESS_GROUP_ID`
#### Group ID vinden
Via [Cloud Identity Groups API lookup](https://cloud.google.com/identity/docs/reference/rest/v1/groups/lookup):
```
GET https://cloudidentity.googleapis.com/v1/groups:lookup?groupKey.id=GROUP_EMAIL
```
Het veld `name` is bijv. `groups/03abc123` → `PLAY_ACCESS_GROUP_ID=03abc123`
### 6. Google Play Console — Closed Testing koppelen
1. Play Console → app → Testing → Closed testing
2. Maak of open een track
3. Testers → **Google Groups**
4. Voeg `PLAY_ACCESS_GROUP_EMAIL` toe
5. Kopieer de **opt-in URL** → `GOOGLE_PLAY_OPT_IN_URL`
## Gebruik in adminpaneel
1. Ga naar **Kijkers**
2. Per kijker: sectie **Google Play access**
- **Google Play email** — het Google-account voor Play (fallback: account-e-mail)
- **Store access** — ON/OFF
- **Status** — sync-status (ACTIVE, ERROR, …)
- **Retry synchronization** — bij ERROR
3. Pagina-acties:
- **Sync all** — alle kijkers synchroniseren
- **Reconcile** — lokale status vergelijken met Google Group
## Testgebruiker toevoegen
1. Maak kijker aan (of bestaande)
2. Vul Google Play e-mail in (bijv. `user@gmail.com`)
3. Zet **Store access** aan
4. Status wordt **ACTIVE** na succesvolle sync
5. Gebruiker opent `GOOGLE_PLAY_OPT_IN_URL` terwijl ingelogd met hetzelfde Google-account
6. Installeert app via Play Store
## Toegang intrekken
1. Zet **Store access** uit in adminpaneel
2. Backend verwijdert lidmaatschap uit de group
3. Nieuwe installs via Play zijn niet meer mogelijk
4. **Let op:** reeds geïnstalleerde apps blijven op het toestel — app-login/API blijft leidend voor contenttoegang
## Sync & reconciliatie
| Lokaal | Google Group | Actie |
|--------|--------------|-------|
| ON | member | OK |
| ON | geen member | toevoegen |
| OFF | member | verwijderen |
| OFF | geen member | OK |
- **Sync all:** past gewenste status toe voor alle kijkers
- **Reconcile:** vergelijkt en herstelt afwijkingen
- **Scheduled:** elke `GOOGLE_PLAY_SYNC_INTERVAL_MS` (default 24u)
## Foutafhandeling
Bij Google API-fouten:
- Gewenste instelling blijft bewaard
- Status → **ERROR**
- Fout staat in admin UI + audit log
- Gebruik **Retry synchronization**
Audit log tabel: `google_play_access_audit_logs` (geen tokens/keys gelogd).
## API endpoints (admin only)
| Method | Route |
|--------|-------|
| GET | `/api/v1/admin/google-play-access/config` |
| PATCH | `/api/v1/admin/viewers/:id/google-play-access` |
| POST | `/api/v1/admin/viewers/:id/google-play-access/retry` |
| POST | `/api/v1/admin/google-play-access/sync-all` |
| POST | `/api/v1/admin/google-play-access/reconcile` |
Body PATCH:
```json
{
"enabled": true,
"email": "user@gmail.com"
}
```
## Wat jij nog handmatig moet invullen
Stop hier — vul **geen** credentials in deze repo.
1. Maak Google Cloud service account + group + Play Closed Testing-koppeling (stappen hierboven)
2. Open adminpaneel → **Instellingen → Google Play**
3. Vul project, service account, private key, group ID/e-mail en opt-in URL in
4. Opslaan
5. Ga naar **Kijkers** en zet Store access aan voor een testgebruiker
Daarna master-api herstarten is alleen nodig als je de nieuwe code net hebt gedeployed.