Changeset c80e78b in Klonkt for src/views


Ignore:
Timestamp:
06/14/2026 04:39:57 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
ae924a2
Parents:
89d6536
Message:

auth: replace username/password with Google login

Listeners (and the owner) now log in via Google instead of a local
username/password account. This lowers the barrier to commenting and
removes the home-built password/registration system.

  • src/config/google.js: raw OAuth2 helpers (authorize/token/userinfo) via the built-in fetch, config-driven. Boot keeps working without credentials.
  • src/routes/auth.js: /auth/google + /auth/google/callback (find-or-create user on email, ADMIN_EMAIL -> god, set session). login/register/reset POST handlers removed; /login now shows the Google button.
  • database.js: idempotent column users.google_sub.
  • account.js + account.ejs: change-password removed.
  • auth-login.ejs / welcome.ejs: Google button instead of password form.
  • shared-styles.ejs: .btn-google styling.
  • .env.example: GOOGLE_CLIENT_ID/SECRET/REDIRECT_URI + ADMIN_EMAIL.

Existing users are matched on email (owner retains their site).
DO NOT deploy to roboburr until the Google credentials are in .env, otherwise
the owner locks themselves out.

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

Location:
src/views
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/account.ejs

    r89d6536 rc80e78b  
    55    <div>
    66      <h1>Account</h1>
    7       <p class="ax-tagline">Profiel en wachtwoord.</p>
     7      <p class="ax-tagline">Profiel en avatar.</p>
    88    </div>
    99  </header>
     
    6565  </section>
    6666
    67   <%# ── PASSWORD ──────────────────────────────────────────── %>
     67  <%# ── INLOG ─────────────────────────────────────────────── %>
    6868  <section class="ax-card">
    69     <div class="ax-card-title">Wachtwoord wijzigen</div>
    70     <form action="/account/password" method="post" class="ax-form">
    71       <label class="ax-field">
    72         <span>Huidig wachtwoord</span>
    73         <input type="password" name="current" required autocomplete="current-password">
    74       </label>
    75       <div class="ax-row ax-row-2">
    76         <label class="ax-field">
    77           <span>Nieuw wachtwoord <small>(min 8 tekens)</small></span>
    78           <input type="password" name="new_password" required minlength="8" autocomplete="new-password">
    79         </label>
    80         <label class="ax-field">
    81           <span>Bevestig nieuw wachtwoord</span>
    82           <input type="password" name="confirm" required minlength="8" autocomplete="new-password">
    83         </label>
    84       </div>
    85       <div class="ax-form-actions">
    86         <button type="submit" class="ax-btn ax-btn-primary">🔒 Wachtwoord wijzigen</button>
    87       </div>
    88     </form>
     69    <div class="ax-card-title">Inloggen</div>
     70    <p class="ax-tagline" style="margin:0">Je bent ingelogd via Google (<%= account.email %>). Er is geen apart wachtwoord.</p>
    8971  </section>
    9072
  • src/views/pages/auth-login.ejs

    r89d6536 rc80e78b  
    11<div class="container auth-page">
    2   <h1>Login</h1>
    3   <% if (typeof success !== 'undefined' && success) { %><div class="alert alert-success"><%= success %></div><% } %>
     2  <h1>Inloggen</h1>
    43  <% if (error) { %><div class="alert alert-error"><%= error %></div><% } %>
    5   <form method="post" action="/auth/login" class="auth-form">
    6     <% if (typeof next !== 'undefined' && next) { %>
    7       <input type="hidden" name="next" value="<%= next %>">
     4
     5  <div class="auth-form auth-google">
     6    <% if (googleReady) { %>
     7      <p class="auth-intro">Log in met je Google-account om mee te praten.</p>
     8      <a class="btn btn-google" href="/auth/google<%= (typeof next !== 'undefined' && next) ? '?next=' + encodeURIComponent(next) : '' %>">
     9        <svg class="g-icon" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true">
     10          <path fill="#4285F4" d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62z"/>
     11          <path fill="#34A853" d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18z"/>
     12          <path fill="#FBBC05" d="M3.97 10.72a5.4 5.4 0 0 1 0-3.44V4.95H.96a9 9 0 0 0 0 8.1l3.01-2.33z"/>
     13          <path fill="#EA4335" d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58A9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58z"/>
     14        </svg>
     15        <span>Inloggen met Google</span>
     16      </a>
     17    <% } else { %>
     18      <p class="auth-intro">Inloggen via Google is op deze site nog niet ingesteld.</p>
    819    <% } %>
    9     <label>
    10       <span>Username or email</span>
    11       <input type="text" name="username" value="<%= username %>" required autofocus autocomplete="username">
    12     </label>
    13     <label>
    14       <span>Password</span>
    15       <input type="password" name="password" required autocomplete="current-password">
    16     </label>
    17     <button type="submit" class="btn btn-primary">Login</button>
    18     <p class="auth-link">No account?
    19       <a href="/auth/register<%= (typeof next !== 'undefined' && next) ? '?next=' + encodeURIComponent(next) : '' %>">Register</a>
    20     </p>
    21     <p class="auth-link auth-link-muted"><a href="/auth/reset-request">Forgot password?</a></p>
    22   </form>
     20  </div>
    2321</div>
  • src/views/pages/welcome.ejs

    r89d6536 rc80e78b  
    55  <% if (!user) { %>
    66    <div class="welcome-actions">
    7       <a href="/auth/register" class="btn btn-primary">Create your account</a>
    8       <a href="/auth/login" class="btn">Already have one? Login</a>
     7      <a href="/auth/login" class="btn btn-primary">Inloggen met Google</a>
    98    </div>
    10     <p class="welcome-note">The first user becomes <strong>god</strong> and gets a personal site auto-created.</p>
     9    <p class="welcome-note">De eerste gebruiker die inlogt wordt <strong>god</strong> en krijgt automatisch een eigen site.</p>
    1110  <% } else { %>
    1211    <p>Hi <%= user.username %>! No site is configured yet.</p>
  • src/views/partials/shared-styles.ejs

    r89d6536 rc80e78b  
    117117.auth-link { text-align: center; color: var(--ink-muted); font-size: 0.9rem; margin: 1rem 0 0; }
    118118.auth-link a { color: var(--accent); }
     119.auth-google { align-items: stretch; }
     120.auth-intro { text-align: center; color: var(--ink-muted); font-size: 0.95rem; margin: 0 0 1rem; }
     121.btn-google {
     122  justify-content: center; gap: 0.6rem; padding: 0.7rem; font-size: 1rem;
     123  background: #fff; color: #1f1f1f; border: 1px solid #dadce0;
     124}
     125.btn-google:hover { background: #f7f8f8; border-color: #dadce0; }
     126.btn-google .g-icon { flex-shrink: 0; }
    119127
    120128/* HTMX loading indicator */
Note: See TracChangeset for help on using the changeset viewer.