Changeset 0b7ebbf in Klonkt


Ignore:
Timestamp:
06/16/2026 01:12:00 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
57929aa
Parents:
63edb0d (diff), efdde37 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'feat/cirkels-v1'

# Conflicts:
# src/routes/admin-settings.js

Files:
8 added
5 edited

Legend:

Unmodified
Added
Removed
  • src/config/database.js

    r63edb0d r0b7ebbf  
    4747  // Per-site Prutter toggle: when off, DM endpoints/UI are hidden for that site.
    4848  ensureColumn('sites', 'enable_prutter', 'INTEGER DEFAULT 1');
     49  // Cirkels: mag deze site in cirkels van anderen verschijnen (surfacing opt-out).
     50  ensureColumn('sites', 'allow_circle', 'INTEGER DEFAULT 1');
    4951
    5052  // v9 audit additions —————————————————————————————————————————
     
    106108  `);
    107109  db.prepare("INSERT OR IGNORE INTO app_settings (key, value) VALUES ('tenancy', 'solo')").run();
     110
     111  // ── Cirkels (federatie) ─────────────────────────────────────
     112  // Decentrale, asymmetrische verbindingen tussen solo-instances.
     113  db.exec(`
     114    CREATE TABLE IF NOT EXISTS circle_links (
     115      id TEXT PRIMARY KEY,
     116      local_site_id TEXT NOT NULL,
     117      remote_url TEXT NOT NULL,
     118      remote_actor_id TEXT,
     119      label TEXT,
     120      status TEXT DEFAULT 'active',
     121      added_at DATETIME DEFAULT CURRENT_TIMESTAMP,
     122      last_synced DATETIME,
     123      last_error TEXT,
     124      UNIQUE(local_site_id, remote_url),
     125      FOREIGN KEY (local_site_id) REFERENCES sites(id)
     126    );
     127    CREATE TABLE IF NOT EXISTS remote_actors (
     128      id TEXT PRIMARY KEY,
     129      url TEXT UNIQUE NOT NULL,
     130      name TEXT,
     131      summary TEXT,
     132      avatar TEXT,
     133      public_key TEXT NOT NULL,
     134      fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP
     135    );
     136    CREATE TABLE IF NOT EXISTS remote_posts (
     137      id TEXT PRIMARY KEY,
     138      actor_id TEXT NOT NULL,
     139      published DATETIME,
     140      title TEXT,
     141      summary TEXT,
     142      url TEXT,
     143      media_json TEXT,
     144      raw_json TEXT,
     145      fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
     146      FOREIGN KEY (actor_id) REFERENCES remote_actors(id)
     147    );
     148  `);
    108149}
    109150
  • src/routes/admin-settings.js

    r63edb0d r0b7ebbf  
    8888
    8989    if (typeof req.body.tenancy !== 'undefined') {
    90       setTenancy(req.body.tenancy === 'hub' ? 'hub' : 'solo');
     90      setTenancy(req.body.tenancy); // valideert naar solo | hub | circle
    9191    }
    9292    if (typeof req.body.hub_title !== 'undefined') {
  • src/server.js

    r63edb0d r0b7ebbf  
    4343import artistsRoutes from './routes/artists.js';
    4444import postsRoutes from './routes/posts.js';
     45import federationRoutes from './routes/federation.js';
     46import { startCircleSyncLoop } from './services/CircleService.js';
     47import adminCircleRoutes from './routes/admin-circle.js';
     48import circleRoutes from './routes/circle.js';
    4549
    4650if (!process.env.SESSION_SECRET) {
     
    145149initializeDatabase();
    146150
     151// Cirkels: periodieke achtergrond-sync van remote instances (no-op tenzij tenancy='circle').
     152startCircleSyncLoop();
     153
    147154// Bundle HTMX: copy from node_modules into our own assets dir so we can serve
    148155// it locally (no third-party CDN). Idempotent — only copies if size differs.
     
    165172const prutter = new PrutterService(db);
    166173app.locals.prutter = prutter;
     174
     175// Cirkels-federatie: publieke, site-agnostische endpoints (/.klonkt/*).
     176// Vóór resolveSite/theme — ze hebben geen site-context nodig.
     177app.use(federationRoutes);
    167178
    168179app.use(resolveSite);
     
    216227app.use('/admin/comments', adminCommentsRoutes);
    217228app.use('/admin/settings', adminSettingsRoutes);
     229app.use('/admin/circle', adminCircleRoutes);
    218230app.use('/admin', adminRoutes);
    219231app.use('/prutter', prutterRoutes);
     
    229241app.get('/artiesten', (req, res) => res.redirect(301, req.originalUrl.replace(/^\/artiesten/, '/leden'))); // oude URL -> /leden
    230242app.use('/', hubRoutes); // hub-overview op '/' (solo: next() -> postsRoutes)
     243app.use('/', circleRoutes); // /cirkel-feed (solo/hub: next() -> postsRoutes)
    231244app.use('/', postsRoutes);
    232245
  • src/services/SettingsService.js

    r63edb0d r0b7ebbf  
    3535
    3636export function getTenancy() {
    37   return getSetting('tenancy', 'solo') === 'hub' ? 'hub' : 'solo';
     37  const v = getSetting('tenancy', 'solo');
     38  return v === 'hub' ? 'hub' : v === 'circle' ? 'circle' : 'solo';
    3839}
    3940
    4041export function setTenancy(mode) {
    41   setSetting('tenancy', mode === 'hub' ? 'hub' : 'solo');
     42  const m = (mode === 'hub' || mode === 'circle') ? mode : 'solo';
     43  setSetting('tenancy', m);
    4244}
  • src/views/pages/admin-settings.ejs

    r63edb0d r0b7ebbf  
    2525          <strong>Hub</strong> — bedrijfssite met <code>/user/</code>.
    2626          <small>Jij (admin) wijst gebruikers een eigen Klonkt Hub toe. Gesloten cirkel: geen open registratie.</small>
     27        </span>
     28      </label>
     29      <label class="set-opt">
     30        <input type="radio" name="tenancy" value="circle" <%= tenancy === 'circle' ? 'checked' : '' %>>
     31        <span>
     32          <strong>Cirkels</strong> &mdash; solo + federatie.
     33          <small>E&eacute;n eigen site die de publieke posts van andere Klonkt-sites toont. Asymmetrisch: jij bepaalt wie in jouw cirkel zit.</small>
    2734        </span>
    2835      </label>
     
    8087  </section>
    8188  <% } %>
     89
     90  <% if (tenancy === 'circle') { %>
     91  <section class="set-card" style="margin-top:1rem">
     92    <h2>Cirkel</h2>
     93    <p class="set-help">
     94      Beheer welke andere Klonkt-sites je in je cirkel toont, en of jouw site in
     95      cirkels van anderen mag verschijnen.
     96    </p>
     97    <p><a href="/admin/circle" class="btn btn-primary">Beheer je cirkel &rarr;</a></p>
     98  </section>
     99  <% } %>
    82100</div>
    83101
Note: See TracChangeset for help on using the changeset viewer.