Changeset f4b7b6a in Klonkt


Ignore:
Timestamp:
06/19/2026 09:31:54 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
1e2e9e7
Parents:
1080d14
Message:

feat(auth): public login = Google only; admin login hidden at /auth/admin

  • /auth/login shows visitors only "Sign in with Google" (listeners/fans).
  • Admin login (username/password) moved to hidden /auth/admin, linked from nowhere. POST errors + password-reset success redirect to /auth/admin.
  • gerr=admin notice (Google with admin address) now links to /auth/admin.

Co-Authored-By: Claude <noreply@…>

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG.md

    r1080d14 rf4b7b6a  
    1515
    1616### Gewijzigd
     17- Login gesplitst: de publieke loginpagina (`/auth/login`) toont voor bezoekers nu
     18  **alleen** Google-login (luisteraars/fans). De beheerders-login (gebruikersnaam +
     19  wachtwoord) staat verborgen op `/auth/admin` (nergens gelinkt).
    1720- Post-navigatie (Newer/Older) houdt nu op elke post dezelfde twee-kaarten-structuur:
    1821  ontbreekt er een nieuwere/oudere post, dan staat er een subtiele uitgegrijsde
  • src/routes/auth.js

    r1080d14 rf4b7b6a  
    4444}
    4545
    46 // ==================== LOGIN (beheerder = wachtwoord) ====================
     46// ==================== LOGIN ====================
     47// Publieke loginpagina: voor BEZOEKERS alleen Google-login (luisteraars/fans).
     48// De beheerders-login (wachtwoord) staat hier bewust NIET — die zit verborgen op
     49// /auth/admin (zie hieronder), zodat de admin-login niet zichtbaar is op de plek
     50// waar bezoekers heen worden gestuurd.
    4751router.get('/login', (req, res) => {
    4852  const next = safeNext(req.query.next) || '';
     
    5660    success: req.query.success || null,
    5761    username: '',
     62    adminLogin: false,
    5863    googleReady: fanLoginReady(),
     64    next,
     65  });
     66});
     67
     68// Verborgen beheerders-login (gebruikersnaam + wachtwoord). Nergens in de UI
     69// gelinkt — de beheerder navigeert hier rechtstreeks naartoe (/auth/admin).
     70router.get('/admin', (req, res) => {
     71  const next = safeNext(req.query.next) || '';
     72  if (req.session.user) return res.redirect(next || '/');
     73  if (isSetupMode()) return res.redirect('/auth/register' + (next ? '?next=' + encodeURIComponent(next) : ''));
     74  renderPage(req, res, 'pages/auth-login', {
     75    pageTitle: 'Beheerder inloggen',
     76    bodyClass: 'on-special on-auth',
     77    error: req.query.error || null,
     78    gerr: null,
     79    success: req.query.success || null,
     80    username: '',
     81    adminLogin: true,
     82    googleReady: false,
    5983    next,
    6084  });
     
    6589  const next = safeNext(req.body.next) || '';
    6690
     91  // Foutweergave op de (verborgen) beheerders-loginpagina: toon het wachtwoord-
     92  // formulier opnieuw (adminLogin:true), niet de Google-only publieke pagina.
    6793  const renderErr = (error, status = 400) => {
    6894    res.status(status);
    6995    return renderPage(req, res, 'pages/auth-login', {
    70       pageTitle: 'Inloggen', bodyClass: 'on-special',
    71       error, success: null, username: username || '', googleReady: fanLoginReady(), next,
     96      pageTitle: 'Beheerder inloggen', bodyClass: 'on-special on-auth',
     97      error, gerr: null, success: null, username: username || '',
     98      adminLogin: true, googleReady: false, next,
    7299    });
    73100  };
     
    229256      updated_at = CURRENT_TIMESTAMP WHERE id = ?
    230257  `).run(hash, row.id);
    231   res.redirect('/auth/login?success=' + encodeURIComponent('Wachtwoord gereset — log nu in.'));
     258  res.redirect('/auth/admin?success=' + encodeURIComponent('Wachtwoord gereset — log nu in.'));
    232259});
    233260
  • src/views/pages/auth-login.ejs

    r1080d14 rf4b7b6a  
     1<%
     2  // adminLogin = de verborgen beheerders-loginpagina (/auth/admin): toont het
     3  // gebruikersnaam/wachtwoord-formulier. De publieke /auth/login toont voor
     4  // bezoekers ALLEEN Google-login (luisteraars/fans). Zo staat de admin-login
     5  // niet zichtbaar op de plek waar bezoekers heen gestuurd worden.
     6  var _admin = (typeof adminLogin !== 'undefined' && adminLogin);
     7%>
    18<div class="container auth-page">
    2   <h1>Inloggen</h1>
     9  <h1><%= _admin ? 'Beheerder inloggen' : 'Inloggen' %></h1>
    310  <% if (typeof success !== 'undefined' && success) { %><div class="alert alert-success"><%= success %></div><% } %>
    411  <%
     
    613      admin: { icon: '🔐', title: 'Dit is een beheerders-account',
    714        body: 'Je logde in met Google, maar dit e-mailadres hoort bij de beheerder van deze site. Inloggen met Google is alleen voor luisteraars/fans — beheerders gebruiken altijd hun wachtwoord (zo kan een Google-login nooit per ongeluk beheerrechten geven).',
    8         list: ['<strong>Ben je de beheerder?</strong> Log hieronder in met je <strong>gebruikersnaam + wachtwoord</strong>.', '<strong>Wil je als fan inloggen?</strong> Gebruik een <strong>ander Google-account</strong> (niet je beheerdersadres).'] },
     15        list: ['<strong>Ben je de beheerder?</strong> <a href="/auth/admin">Log in met je gebruikersnaam + wachtwoord</a>.', '<strong>Wil je als fan inloggen?</strong> Gebruik een <strong>ander Google-account</strong> (niet je beheerdersadres).'] },
    916      session: { icon: '⏱️', title: 'Login afgebroken', body: 'De Google-login is afgebroken of de sessie was verlopen. Probeer het gewoon opnieuw.' },
    10       email: { icon: '✉️', title: 'Geen geverifieerd e-mailadres', body: 'Je Google-account heeft geen geverifieerd e-mailadres. Verifieer je adres bij Google, of log in met je wachtwoord.' },
     17      email: { icon: '✉️', title: 'Geen geverifieerd e-mailadres', body: 'Je Google-account heeft geen geverifieerd e-mailadres. Verifieer je adres bij Google.' },
    1118      linked: { icon: '🔗', title: 'Adres al gekoppeld', body: 'Dit e-mailadres is al aan een ander Google-account gekoppeld. Gebruik dat account, of neem contact op met de beheerder.' },
    12       unavailable: { icon: '🚫', title: 'Google-login niet beschikbaar', body: 'Inloggen met Google is op deze site (nog) niet ingesteld. Log in met je gebruikersnaam en wachtwoord.' },
     19      unavailable: { icon: '🚫', title: 'Google-login niet beschikbaar', body: 'Inloggen met Google is op deze site (nog) niet ingesteld.' },
    1320      failed: { icon: '⚠️', title: 'Google-login mislukt', body: 'Er ging iets mis bij het inloggen met Google. Probeer het opnieuw.' },
    1421    };
     
    2431  <% } else if (error) { %><div class="alert alert-error"><%= error %></div><% } %>
    2532
    26   <form method="post" action="/auth/login" class="auth-form">
    27     <% if (typeof next !== 'undefined' && next) { %>
    28       <input type="hidden" name="next" value="<%= next %>">
    29     <% } %>
    30     <label>
    31       <span>Gebruikersnaam of e-mail</span>
    32       <input type="text" name="username" value="<%= username %>" required autofocus autocomplete="username">
    33     </label>
    34     <label>
    35       <span>Wachtwoord</span>
    36       <input type="password" name="password" required autocomplete="current-password">
    37     </label>
    38     <button type="submit" class="btn btn-primary">Inloggen</button>
    39     <p class="auth-link auth-link-muted"><a href="/auth/reset-request">Wachtwoord vergeten?</a></p>
    40   </form>
    41 
    42   <% if (googleReady) { %>
    43     <div class="auth-divider"><span>of als luisteraar</span></div>
     33  <% if (_admin) { %>
     34    <%# Verborgen beheerders-login (wachtwoord). %>
     35    <form method="post" action="/auth/login" class="auth-form">
     36      <% if (typeof next !== 'undefined' && next) { %>
     37        <input type="hidden" name="next" value="<%= next %>">
     38      <% } %>
     39      <label>
     40        <span>Gebruikersnaam of e-mail</span>
     41        <input type="text" name="username" value="<%= username %>" required autofocus autocomplete="username">
     42      </label>
     43      <label>
     44        <span>Wachtwoord</span>
     45        <input type="password" name="password" required autocomplete="current-password">
     46      </label>
     47      <button type="submit" class="btn btn-primary">Inloggen</button>
     48      <p class="auth-link auth-link-muted"><a href="/auth/reset-request">Wachtwoord vergeten?</a></p>
     49    </form>
     50  <% } else if (googleReady) { %>
     51    <%# Publieke login: alleen Google, voor luisteraars/fans. %>
     52    <p class="auth-sub">Log in om te reageren en je favorieten te bewaren.</p>
    4453    <a class="btn btn-google" href="/auth/google<%= (typeof next !== 'undefined' && next) ? '?next=' + encodeURIComponent(next) : '' %>">
    4554      <svg class="g-icon" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true">
     
    5160      <span>Inloggen met Google</span>
    5261    </a>
     62  <% } else { %>
     63    <div class="alert">Inloggen met Google is op deze site nog niet ingesteld.</div>
    5364  <% } %>
    5465</div>
     
    6172  .auth-notice-list { margin: 0; padding-left: 18px; line-height: 1.6; }
    6273  .auth-notice-list li { margin: 4px 0; }
     74  .auth-sub { color: var(--ink-muted); margin: 0 0 1rem; }
    6375</style>
Note: See TracChangeset for help on using the changeset viewer.