# 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.