Changeset 98ecf51 in Klonkt for src/routes/admin-sites.js


Ignore:
Timestamp:
06/18/2026 03:19:09 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
7881080
Parents:
6a2abb1
Message:

Hub #1+#2: site admin permissions work + assign owner to another user

#1 — canAdminSite was reading user.siteRoles which was NEVER populated (dead
code) → only god and the literal owner passed admin checks. Now canAdminSite
queries site_members directly (an assigned co-admin). requireSiteManager/BySlug
use canAdminSite so collaborators can access site management too.

#2 — owner_id was hard-coded to the creating god → you couldn't assign a site to
another user (the core of hub mode was missing). Now: god-only "Owner" select in
the site form; create/save set owner_id + a site_members-admin row for that owner
(upsert). Non-god doesn't see the field and cannot change the owner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/admin-sites.js

    r6a2abb1 r98ecf51  
    137137}
    138138
     139/** Geldige user-id voor owner-toewijzing, of null bij leeg/onbekend. */
     140function validOwnerId(raw) {
     141  const id = (raw || '').toString().trim();
     142  if (!id) return null;
     143  return db.prepare('SELECT 1 FROM users WHERE id = ?').get(id) ? id : null;
     144}
     145
     146/** Geef een user admin-rechten op een site (idempotent upsert). */
     147function grantSiteAdmin(siteId, userId) {
     148  db.prepare(`
     149    INSERT INTO site_members (site_id, user_id, role) VALUES (?, ?, 'admin')
     150    ON CONFLICT(site_id, user_id) DO UPDATE SET role = 'admin'
     151  `).run(siteId, userId);
     152}
     153
     154/** Kandidaat-owners voor het owner-keuzeveld (god-only). */
     155function listOwnerCandidates() {
     156  return db.prepare('SELECT id, username, role FROM users ORDER BY username').all();
     157}
     158
    139159// ==================== LIST ====================
    140160router.get('/', requireGod, (req, res) => {
     
    163183    bodyClass: 'on-admin',
    164184    isNew: true,
    165     site: { slug: '', ...siteEditableFields() },
     185    site: { slug: '', owner_id: req.session.user.id, ...siteEditableFields() },
     186    users: listOwnerCandidates(),
    166187    palettes: ThemeService.listPalettes(),
    167188    accents: ThemeService.listAccents(),
     
    187208
    188209  const f = { ...siteEditableFields(), ...req.body };
     210
     211  // Owner: god mag de site aan een ANDERE gebruiker toewijzen — dit is de kern
     212  // van hub-modus (elke gebruiker z'n eigen, zelf te beheren Klonkt). Leeg of
     213  // ongeldig → de aanmakende god zelf.
     214  const ownerId = validOwnerId(req.body.owner_id) || req.session.user.id;
     215
    189216  const siteId = uuid();
    190217  db.prepare(`
     
    200227    (f.description || '').slice(0, 500),
    201228    (f.tagline || '').slice(0, 200),
    202     req.session.user.id,
     229    ownerId,
    203230    f.language || 'nl',
    204231    f.palette || 'sage',
     
    213240  );
    214241
    215   // The site_members entry lets the god/owner show up in canAdminSite checks.
    216   db.prepare(`
    217     INSERT INTO site_members (site_id, user_id, role) VALUES (?, ?, 'admin')
    218   `).run(siteId, req.session.user.id);
    219 
    220   res.redirect(`/admin/sites/${slug}/edit?success=` + encodeURIComponent('Site created'));
     242  // De OWNER (niet per se de aanmaker) krijgt een site_members-admin-rij → zo komt
     243  // 'ie door canAdminSite + de requireSiteManager-gates en beheert 'ie z'n site.
     244  grantSiteAdmin(siteId, ownerId);
     245
     246  res.redirect(`/admin/sites/${slug}/edit?success=` + encodeURIComponent('Site aangemaakt'));
    221247});
    222248
     
    236262    isNew: false,
    237263    site,
     264    users: listOwnerCandidates(),
    238265    palettes: ThemeService.listPalettes(),
    239266    accents: ThemeService.listAccents(),
     
    314341  );
    315342
    316   res.redirect(`/admin/sites/${req.params.slug}/edit?success=` + encodeURIComponent('Saved'));
     343  // Owner (her)toewijzen — ALLEEN god. Een site-owner die z'n eigen site bewerkt
     344  // kan de eigenaar niet wijzigen (het veld wordt voor niet-god ook niet getoond).
     345  if (req.session.user.role === 'god') {
     346    const newOwner = validOwnerId(req.body.owner_id);
     347    if (newOwner) {
     348      db.prepare('UPDATE sites SET owner_id = ? WHERE id = ?').run(newOwner, site.id);
     349      grantSiteAdmin(site.id, newOwner);
     350    }
     351  }
     352
     353  res.redirect(`/admin/sites/${req.params.slug}/edit?success=` + encodeURIComponent('Opgeslagen'));
    317354});
    318355
Note: See TracChangeset for help on using the changeset viewer.