Changeset 2248cd2 in Klonkt
- Timestamp:
- 06/16/2026 10:28:54 PM (3 months ago)
- Branches:
- main
- Children:
- e2a8e31
- Parents:
- 221a209
- Location:
- src
- Files:
-
- 3 edited
-
config/google.js (modified) (3 diffs)
-
routes/admin-settings.js (modified) (3 diffs)
-
views/pages/admin-settings.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/config/google.js
r221a209 r2248cd2 1 1 // Google OAuth2 voor LUISTERAARS (reageren). Per-instance: de self-hoster zet 2 // z'n EIGEN Google-client in .env. Zo hangt elke site aan z'n eigen Google Cloud3 // project— geen centrale afhankelijkheid, geen gedeelde aansprakelijkheid.2 // z'n EIGEN Google-client. Zo hangt elke site aan z'n eigen Google Cloud project 3 // — geen centrale afhankelijkheid, geen gedeelde aansprakelijkheid. 4 4 // 5 // Optioneel: staat dit niet ingesteld, dan is er simpelweg geen "Login met6 // Google"-knop en blijft de rest van de site werken. Google-login geeft NOOIT7 // beheerrechten — beheer gaat via het wachtwoord-account.5 // Config-bron (in deze volgorde): app_settings (ingesteld via Beheer → Instellingen), 6 // anders de env-vars. Niet ingesteld → geen "Login met Google"-knop; de rest van 7 // de site werkt door. Google-login geeft NOOIT beheerrechten. 8 8 // 9 // Config via env: 10 // GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET 11 // GOOGLE_REDIRECT_URI = https://<dit-domein>/auth/google/callback 9 // De redirect-URI wordt afgeleid van PUBLIC_BASE_URL (<base>/auth/google/callback), 10 // of expliciet via GOOGLE_REDIRECT_URI. Die exacte URL moet in Google Cloud staan. 12 11 13 const CLIENT_ID = process.env.GOOGLE_CLIENT_ID || ''; 14 const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET || ''; 15 const REDIRECT_URI = process.env.GOOGLE_REDIRECT_URI || ''; 12 import { getSetting } from '../services/SettingsService.js'; 16 13 17 14 const AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth'; … … 19 16 const USERINFO_URL = 'https://openidconnect.googleapis.com/v1/userinfo'; 20 17 18 // Dynamisch lezen (UI-wijziging werkt zonder herstart). app_settings wint, env = fallback. 19 function clientId() { 20 return getSetting('google_client_id', '') || process.env.GOOGLE_CLIENT_ID || ''; 21 } 22 function clientSecret() { 23 return getSetting('google_client_secret', '') || process.env.GOOGLE_CLIENT_SECRET || ''; 24 } 25 export function redirectUri() { 26 if (process.env.GOOGLE_REDIRECT_URI) return process.env.GOOGLE_REDIRECT_URI; 27 const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, ''); 28 return base ? `${base}/auth/google/callback` : ''; 29 } 30 31 export function currentClientId() { return clientId(); } // niet-geheim, voor het formulier 32 export function clientSecretSet() { return !!clientSecret(); } 21 33 export function googleConfigured() { 22 return !!( CLIENT_ID && CLIENT_SECRET && REDIRECT_URI);34 return !!(clientId() && clientSecret() && redirectUri()); 23 35 } 24 36 25 37 export function authorizeUrl(state) { 26 38 const p = new URLSearchParams({ 27 client_id: CLIENT_ID,28 redirect_uri: REDIRECT_URI,39 client_id: clientId(), 40 redirect_uri: redirectUri(), 29 41 response_type: 'code', 30 42 scope: 'openid email profile', … … 39 51 const body = new URLSearchParams({ 40 52 code, 41 client_id: CLIENT_ID,42 client_secret: CLIENT_SECRET,43 redirect_uri: REDIRECT_URI,53 client_id: clientId(), 54 client_secret: clientSecret(), 55 redirect_uri: redirectUri(), 44 56 grant_type: 'authorization_code', 45 57 }); -
src/routes/admin-settings.js
r221a209 r2248cd2 23 23 import { getTenancy, setTenancy, getSetting, setSetting } from '../services/SettingsService.js'; 24 24 import { entitlementStatus, premiumUnlocked } from '../services/PatreonService.js'; 25 import { googleConfigured, redirectUri, currentClientId, clientSecretSet } from '../config/google.js'; 25 26 26 27 const router = express.Router(); … … 76 77 hubHeroOverlay: clampOverlay(getSetting('hub_hero_overlay')), 77 78 premium: entitlementStatus(), 79 google: { 80 configured: googleConfigured(), 81 redirectUri: redirectUri(), 82 clientId: currentClientId(), 83 secretSet: clientSecretSet(), 84 }, 78 85 success: req.query.success || null, 79 86 error: req.query.error || null, … … 129 136 }); 130 137 138 // Google-login (luisteraars) configureren — Client ID + Secret in app_settings. 139 // De redirect-URI leiden we af van PUBLIC_BASE_URL (zie config/google.js). 140 router.post('/google', requireGod, (req, res) => { 141 if (req.body.clear === '1') { 142 setSetting('google_client_id', ''); 143 setSetting('google_client_secret', ''); 144 return res.redirect('/admin/settings?success=' + encodeURIComponent('Google-login losgekoppeld')); 145 } 146 setSetting('google_client_id', (req.body.google_client_id || '').toString().trim()); 147 // Secret alleen overschrijven als er een nieuwe waarde is ingevoerd (leeg = laat staan). 148 const secret = (req.body.google_client_secret || '').toString().trim(); 149 if (secret) setSetting('google_client_secret', secret); 150 res.redirect('/admin/settings?success=' + encodeURIComponent('Google-login opgeslagen')); 151 }); 152 131 153 export default router; -
src/views/pages/admin-settings.ejs
r221a209 r2248cd2 63 63 </section> 64 64 <% } %> 65 66 <%# Google-login voor luisteraars (reageren) — per-site eigen Google-client. %> 67 <section class="set-card" style="margin-top:1rem"> 68 <h2>Google-login (luisteraars)</h2> 69 <p class="set-help">Laat bezoekers met Google inloggen om te reageren — met je <strong>eigen</strong> 70 Google Cloud-client. Maak er een aan op 71 <a href="https://console.cloud.google.com/apis/credentials" target="_blank" rel="noopener">console.cloud.google.com</a> 72 (OAuth client-ID, type "Web application"). 73 <% if (google && google.configured) { %><strong>Status: ingesteld ✓</strong><% } else { %>Nog niet ingesteld.<% } %></p> 74 75 <% if (google && google.redirectUri) { %> 76 <p class="set-help" style="margin-bottom:.7rem">Zet deze <strong>exacte</strong> redirect-URI in je Google-client 77 (Authorized redirect URIs):<br><code style="user-select:all"><%= google.redirectUri %></code></p> 78 <% } else { %> 79 <p class="set-help" style="color:var(--accent)">Stel eerst <code>PUBLIC_BASE_URL</code> in — daar wordt de redirect-URI van afgeleid.</p> 80 <% } %> 81 82 <form method="post" action="/admin/settings/google" class="set-form"> 83 <label class="set-field"> 84 <span>Client ID</span> 85 <input type="text" name="google_client_id" value="<%= google ? google.clientId : '' %>" placeholder="123-abc.apps.googleusercontent.com" autocomplete="off"> 86 </label> 87 <label class="set-field"> 88 <span>Client Secret <% if (google && google.secretSet) { %><small style="font-weight:400">— ingesteld; leeg laten = ongewijzigd</small><% } %></span> 89 <input type="password" name="google_client_secret" placeholder="<%= (google && google.secretSet) ? '•••••••• (ingesteld)' : 'GOCSPX-…' %>" autocomplete="off"> 90 </label> 91 <div style="display:flex; gap:.5rem; flex-wrap:wrap"> 92 <button type="submit" class="btn btn-primary">Opslaan</button> 93 <% if (google && (google.clientId || google.secretSet)) { %> 94 <button type="submit" name="clear" value="1" class="btn">Loskoppelen</button> 95 <% } %> 96 </div> 97 </form> 98 <% if (typeof premiumEnabled !== 'undefined' && premiumEnabled && !(premium && premium.premium)) { %> 99 <p class="set-help" style="margin-top:.7rem; color:var(--accent)">Premium-laag staat aan zonder Patreon — de Google-knop blijft verborgen tot premium ontgrendeld is.</p> 100 <% } %> 101 </section> 65 102 66 103 <% if (tenancy === 'hub') { %>
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)