stremio/GOOGLE_PLAY_ACCESS_SETUP.md
Jos Vooges | STH 0eb0c5d367 Add admin Google Play Closed Testing access via Cloud Identity Groups.
Admins can enable or revoke store access per viewer; membership syncs to a configurable Google Group without changing app auth.

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

187 lines
6.1 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 environment variables
Stel deze in op de **master-api** server (niet in de admin UI, niet in Git):
| Variabele | Verplicht | Beschrijving |
|-----------|-----------|--------------|
| `GOOGLE_CLOUD_PROJECT_ID` | Ja | Google Cloud project ID |
| `GOOGLE_SERVICE_ACCOUNT_EMAIL` | Ja | Service account e-mail |
| `GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY` | Ja | PEM private key ( `\n` als `\n` in env) |
| `PLAY_ACCESS_GROUP_ID` | Ja | Group resource ID (zonder `groups/` prefix mag ook) |
| `PLAY_ACCESS_GROUP_EMAIL` | Ja | E-mailadres van de Google Group |
| `GOOGLE_WORKSPACE_ADMIN_EMAIL` | Meestal ja | Admin voor domain-wide delegation |
| `GOOGLE_WORKSPACE_CUSTOMER_ID` | Optioneel | Workspace customer ID |
| `GOOGLE_PLAY_OPT_IN_URL` | Aanbevolen | Publieke Closed Testing opt-in URL |
| `GOOGLE_PLAY_SYNC_INTERVAL_MS` | Optioneel | Reconciliatie-interval (default: 86400000 = 24u) |
### Waar instellen
- **Lokaal:** `apps/master-api/.env`
- **Productie/Dokploy:** omgeving van de master-api container (`deploy/master/.env` template)
## 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. `GOOGLE_CLOUD_PROJECT_ID`
2. `GOOGLE_SERVICE_ACCOUNT_EMAIL`
3. `GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY`
4. `GOOGLE_WORKSPACE_ADMIN_EMAIL` (indien Workspace)
5. `PLAY_ACCESS_GROUP_ID`
6. `PLAY_ACCESS_GROUP_EMAIL`
7. `GOOGLE_PLAY_OPT_IN_URL`
Daarna master-api herstarten en in adminpaneel testen met één tester-account.