Changeset 8afbdd6 in Klonkt for src/routes/prutter.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/routes/prutter.js

    rb94c08e r8afbdd6  
    1818import db from '../config/database.js';
    1919import { renderPage } from '../middleware/render.js';
    20 import { requireAuth } from '../middleware/auth.js';
     20import { requireAuth, isViewer } from '../middleware/auth.js';
    2121import PermissionsService from '../services/PermissionsService.js';
    2222
     
    5555// ==================== START / RESUME CONVERSATION ====================
    5656router.get('/new', requirePrutter, (req, res) => {
     57  // Een gesprek starten is een schrijf-actie (INSERT) — een kijker mag dat niet.
     58  // De globale guard pakt dit niet omdat het een GET is, dus expliciet blokkeren.
     59  if (isViewer(req.session.user)) {
     60    res.status(403);
     61    return renderPage(req, res, 'pages/viewer-blocked', { pageTitle: 'Kijker-modus', bodyClass: 'on-special' });
     62  }
    5763  const targetUsername = (req.query.to || '').toString().trim();
    5864  if (!targetUsername) {
     
    9096  const messages = prutter.getMessages(conv.id, 200, 0).reverse();
    9197
    92   // Mark inbound messages as read
    93   prutter.markAsRead(conv.id, me);
     98  // Mark inbound messages as read — sla over voor kijkers (markAsRead is een
     99  // UPDATE; een GET valt buiten de globale guard, dus hier expliciet skippen).
     100  if (!isViewer(req.session.user)) prutter.markAsRead(conv.id, me);
    94101
    95102  renderPage(req, res, 'pages/prutter-conversation', {
Note: See TracChangeset for help on using the changeset viewer.