Changeset 8afbdd6 in Klonkt for src/middleware/auth.js


Ignore:
Timestamp:
06/14/2026 06:07:51 PM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
c869272
Parents:
b94c08e
Message:

feat: viewer role + artists directory + Klonkt Hub Beta rebrand

Viewer role (replaces the separate view-mode/readonly toggle):

  • 'kijker' is now a real role (VALID_ROLES) selectable in Admin. May view EVERYTHING including Admin, but cannot modify anything.
  • isViewer(user) (= role kijker or legacy readonly flag) is the source; requireGod/requireSiteManager(BySlug) let a viewer through (viewing), the global guard 403s every write. Existing readonly accounts are migrated on each role change (readonly=0).
  • Write leaks via GET patched: /prutter/new (INSERT) blocks for viewers, /prutter/:id skips markAsRead (UPDATE); WS upgrade rejects viewers (the HTTP guard doesn't cover WebSockets).
  • Clean "Viewer mode" page (viewer-blocked) instead of raw 403 text; styled sticky banner; account page shows read-only UI instead of an upload button that silently 403s. canMutate hides write buttons.

Scalability (>50 artists):

  • Hub home shows max 24 (most active first) + "All N artists ->".
  • New searchable, paginated /artiesten directory (hub only).
  • 'user' + 'artiesten' reserved as slugs.

Rebrand PrutFolio v1 -> Klonkt Hub Beta (footer, PWA manifest, account/
admin texts, default page title, startup, README; internal package +
PWA id 'prutfolio' remain for stability).

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/middleware/auth.js

    rb94c08e r8afbdd6  
    3737}
    3838
     39// Een 'kijker' mag ALLES bekijken (incl. Beheer) maar NIETS wijzigen. De
     40// schrijf-blokkade zit in de globale guard in server.js; deze helper bepaalt
     41// alleen "is dit een alleen-lezen account?". `readonly` is de legacy-vlag die
     42// we nog meenemen zodat niet-gemigreerde demo-accounts geblokkeerd blijven.
     43export function isViewer(user) {
     44  return !!user && (user.role === 'kijker' || !!user.readonly);
     45}
     46
    3947export function requireGod(req, res, next) {
    4048  if (!req.session?.user) return loginRedirect(req, res);
    41   if (req.session.user.role !== 'god') {
     49  const role = req.session.user.role;
     50  // god beheert; een kijker mág het Beheer-paneel zien (alleen-lezen) — de
     51  // globale guard 403't elke write, dus dit geeft enkel kijk-toegang.
     52  if (role !== 'god' && role !== 'kijker') {
    4253    return res.status(403).send('God role required');
    4354  }
     
    5263  if (!req.session?.user) return loginRedirect(req, res);
    5364  const u = req.session.user;
    54   if (u.role === 'god') return next();
     65  if (u.role === 'god' || u.role === 'kijker') return next(); // kijker = alleen-lezen kijk-toegang
    5566  const site = res.locals.site;
    5667  if (site && site.owner_id === u.id) return next();
     
    6273  if (!req.session?.user) return loginRedirect(req, res);
    6374  const u = req.session.user;
    64   if (u.role === 'god') return next();
     75  if (u.role === 'god' || u.role === 'kijker') return next(); // kijker = alleen-lezen kijk-toegang
    6576  const site = db.prepare('SELECT owner_id FROM sites WHERE slug = ?').get(req.params.slug);
    6677  if (site && site.owner_id === u.id) return next();
Note: See TracChangeset for help on using the changeset viewer.