source: Klonkt/src/routes/admin.js@ 42081fb

main
Last change on this file since 42081fb was 8cb1dc7, checked in by roboburr <roboburr@…>, 3 months ago

hub: artist self-management — owner manages their own subsite (posts/appearance/comments)

A site owner (member) now gets a "My PrutFolio" dashboard and can manage their
OWN site; cross-site access is restricted.

  • auth.js: requireSiteManager (owner of res.locals.site or god) + requireSiteManagerBySlug (owner of :slug or god).
  • admin.js: /admin role-aware -> god=hub management, owner=my-site dashboard, member without site=403.
  • admin-sites.js: /:slug/edit + /save owner-or-god (was god-only); upload-photo requireAuth. list/new/create/delete remain god-only.
  • admin-comments.js: requireSiteManager + redirects/form actions via siteUrlBase so the artist context (/user/<slug>/admin/comments) is correct.
  • render.js: userOwnsSite flag; topnav + overview show "Admin" for owners; topnav "New post" uses siteUrlBase.
  • pages/my-site.ejs: artist dashboard.

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

  • Property mode set to 100644
File size: 2.6 KB
RevLine 
[7bc636b]1/**
2 * Admin routes — Phase B stub.
3 * Read-only god-only overview of users / sites / posts.
4 * Real admin dashboard (create/delete sites, manage users, etc.) comes later.
5 */
6
7import express from 'express';
8import db from '../config/database.js';
9import { renderPage } from '../middleware/render.js';
[8cb1dc7]10import { requireAuth } from '../middleware/auth.js';
[6351545]11import { getTenancy } from '../services/SettingsService.js';
[7bc636b]12
13const router = express.Router();
14
[8cb1dc7]15router.get('/', requireAuth, (req, res) => {
16 const user = req.session.user;
17
18 // Niet-god: een artiest die een eigen site bezit krijgt een "Mijn PrutFolio"-
19 // dashboard, gescopet op z'n eigen site. Bezit 'ie geen site -> geen beheer.
20 if (user.role !== 'god') {
21 const mySite = db.prepare(
22 'SELECT * FROM sites WHERE owner_id = ? ORDER BY created_at ASC LIMIT 1'
23 ).get(user.id);
24 if (!mySite) return res.status(403).send('Geen beheer beschikbaar voor dit account.');
25
26 const mine = {
27 posts: db.prepare("SELECT COUNT(*) AS c FROM posts WHERE site_id = ?").get(mySite.id).c,
28 published: db.prepare("SELECT COUNT(*) AS c FROM posts WHERE site_id = ? AND status = 'published'").get(mySite.id).c,
29 };
30 return renderPage(req, res, 'pages/my-site', {
31 pageTitle: 'Mijn PrutFolio',
32 bodyClass: 'on-admin',
33 mySite,
34 mine,
35 });
36 }
37
[6351545]38 const tenancy = getTenancy();
39
40 // De primaire/owner-site — in solo dé site, in hub de hoofdsite. Geeft de
41 // "Uiterlijk"-tegel z'n edit-link.
42 const primarySite = db.prepare(
43 'SELECT slug, title FROM sites ORDER BY created_at ASC LIMIT 1'
44 ).get() || null;
45
[7bc636b]46 const stats = {
47 users: db.prepare('SELECT COUNT(*) AS c FROM users').get().c,
48 sites: db.prepare('SELECT COUNT(*) AS c FROM sites').get().c,
49 posts: db.prepare('SELECT COUNT(*) AS c FROM posts').get().c,
50 published: db.prepare(
51 "SELECT COUNT(*) AS c FROM posts WHERE status = 'published'"
52 ).get().c,
53 };
54
[6351545]55 // Sites/users-tabellen zijn alleen in hub relevant; in solo besparen we de query.
56 const sites = tenancy === 'hub' ? db.prepare(`
[7bc636b]57 SELECT s.slug, s.title, s.created_at, u.username AS owner_username
58 FROM sites s
59 LEFT JOIN users u ON u.id = s.owner_id
60 ORDER BY s.created_at DESC
61 LIMIT 50
[6351545]62 `).all() : [];
[7bc636b]63
[6351545]64 const users = tenancy === 'hub' ? db.prepare(`
[7bc636b]65 SELECT username, email, role, created_at
66 FROM users
67 ORDER BY created_at DESC
68 LIMIT 50
[6351545]69 `).all() : [];
[7bc636b]70
71 renderPage(req, res, 'pages/admin', {
[6351545]72 pageTitle: 'Beheer',
[7bc636b]73 bodyClass: 'on-admin',
[6351545]74 tenancy,
75 primarySite,
[7bc636b]76 stats,
77 sites,
78 users,
79 });
80});
81
82export default router;
Note: See TracBrowser for help on using the repository browser.