Changeset 283f618 in Klonkt


Ignore:
Timestamp:
06/26/2026 07:26:26 AM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
f278df9
Parents:
eb2fe08
Message:

feat(fediverse): add an ActivityPub on/off toggle (off = no federation, no comments)

A solo site can now run without the fediverse. ap_enabled (default on, Beheer ->
Instellingen). When off: /ap/*, WebFinger and NodeInfo 404 (undiscoverable), the
'from the fediverse' reactions section is hidden on posts (= no comments, since
native comments were removed), the profile follow button and the fediverse admin
links disappear. Cirkels is separate (not gated here).

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

Location:
src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • src/middleware/render.js

    reb2fe08 r283f618  
    1717import PermissionsService from '../services/PermissionsService.js';
    1818import { isViewer } from './auth.js';
    19 import { getSetting } from '../services/SettingsService.js';
     19import { getSetting, apEnabled } from '../services/SettingsService.js';
    2020import { isPremium as isPremiumInstance, premiumEnabled, premiumUnlocked } from '../services/PatreonService.js';
    2121import ActivityPubService from '../services/ActivityPubService.js';
     
    122122    canSeeBeheer,
    123123    canManageFedi,
     124    apEnabled: apEnabled(),
    124125    isViewer: _isViewer,
    125126    canMutate: !_isViewer,
  • src/routes/activitypub.js

    reb2fe08 r283f618  
    1717import AP from '../services/ActivityPubService.js';
    1818import { apReadLimiter, apInboxLimiter } from '../middleware/rate-limit.js';
     19import { apEnabled } from '../services/SettingsService.js';
    1920
    2021const router = express.Router();
     22// The whole fediverse layer can be turned off (solo "no federation" mode):
     23// then /ap/*, WebFinger and NodeInfo are simply gone — the site is undiscoverable
     24// and unfederatable.
     25router.use((req, res, next) => { if (!apEnabled()) return res.status(404).end(); next(); });
    2126// Generous per-IP baseline over all /ap/* (reads). The inbox POST gets an
    2227// additional, tighter cap inline (it triggers outbound fetches).
  • src/routes/admin-settings.js

    reb2fe08 r283f618  
    8282    smtp: mailerStatus(),
    8383    footerNewsletter: getSetting('footer_newsletter') === '1',
     84    apEnabledSetting: getSetting('ap_enabled', '1') !== '0',
    8485    success: req.query.success || null,
    8586    error: req.query.error || null,
     
    166167});
    167168
     169// Fediverse (ActivityPub) on/off. Off = no federation + no fediverse reactions.
     170router.post('/ap', requireGod, (req, res) => {
     171  setSetting('ap_enabled', req.body.ap_enabled ? '1' : '0');
     172  res.redirect('/admin/settings?success=' + encodeURIComponent('Fediverse-instelling opgeslagen'));
     173});
     174
    168175// Send a test email to a specified address (or the logged-in user).
    169176router.post('/smtp/test', requireGod, async (req, res) => {
  • src/services/SettingsService.js

    reb2fe08 r283f618  
    4949  setSetting('tenancy', m);
    5050}
     51
     52// ActivityPub / fediverse federation. ON by default. '0' = off: the site does
     53// not federate, /ap/* is gone, and the "from the fediverse" reactions disappear
     54// — which (since native comments were removed) means no comments at all.
     55export function apEnabled() {
     56  return getSetting('ap_enabled', '1') !== '0';
     57}
  • src/services/i18n.js

    reb2fe08 r283f618  
    188188    'aset.newsletter_help_2': 'van je site zodat bezoekers zich op elke pagina kunnen inschrijven. (De volledige aanmeldpagina blijft op',
    189189    'aset.newsletter_show_footer': 'Aanmeldveld in de footer tonen',
     190    'aset.fediverse': 'Fediverse (ActivityPub)',
     191    'aset.fediverse_help': 'Laat je site meedoen met de fediverse: mensen op Mastodon (of een andere Klonkt) kunnen je volgen, liken en reageren — en die reacties verschijnen onder je posts. Zet je dit uit, dan federeert je site niet en zijn er geen reacties (een rustige, op zichzelf staande blog).',
     192    'aset.fediverse_toggle': 'Fediverse aan (volgen, liken, reageren)',
    190193    'aset.email_smtp': 'E-mail (SMTP)',
    191194    'aset.smtp_help_1': 'Nodig om de',
     
    11961199    'aset.newsletter_help_2': 'of your site so visitors can subscribe from any page. (The full sign-up page stays at',
    11971200    'aset.newsletter_show_footer': 'Show sign-up field in the footer',
     1201    'aset.fediverse': 'Fediverse (ActivityPub)',
     1202    'aset.fediverse_help': 'Let your site join the fediverse: people on Mastodon (or another Klonkt) can follow, like and reply — and those replies show up under your posts. Turn this off and your site does not federate and has no comments (a quiet, standalone blog).',
     1203    'aset.fediverse_toggle': 'Fediverse on (follow, like, comment)',
    11981204    'aset.email_smtp': 'Email (SMTP)',
    11991205    'aset.smtp_help_1': 'Needed to',
     
    22032209    'aset.newsletter_help_2': 'deiner Site, damit sich Besucher auf jeder Seite eintragen können. (Die vollständige Anmeldeseite bleibt unter',
    22042210    'aset.newsletter_show_footer': 'Anmeldefeld in der Fußzeile anzeigen',
     2211    'aset.fediverse': 'Fediverse (ActivityPub)',
     2212    'aset.fediverse_help': 'Lass deine Seite am Fediverse teilnehmen: Leute auf Mastodon (oder einem anderen Klonkt) können dir folgen, liken und antworten — und diese Antworten erscheinen unter deinen Beiträgen. Schaltest du das aus, föderiert deine Seite nicht und hat keine Kommentare (ein ruhiger, eigenständiger Blog).',
     2213    'aset.fediverse_toggle': 'Fediverse an (Folgen, Liken, Kommentieren)',
    22052214    'aset.email_smtp': 'E-Mail (SMTP)',
    22062215    'aset.smtp_help_1': 'Erforderlich, um den',
  • src/views/pages/admin-settings.ejs

    reb2fe08 r283f618  
    117117  </section>
    118118  <% } %>
     119
     120  <%# Fediverse (ActivityPub) on/off. Off = no federation + no fediverse reactions,
     121      which (since native comments were removed) means no comments at all. %>
     122  <section class="set-card" style="margin-top:1rem">
     123    <h2><%= t('aset.fediverse') %></h2>
     124    <p class="set-help"><%= t('aset.fediverse_help') %></p>
     125    <form method="post" action="/admin/settings/ap" class="set-form">
     126      <label class="set-toggle" style="display:flex;align-items:center;gap:.6rem;cursor:pointer">
     127        <input type="checkbox" name="ap_enabled" value="1" <%= (typeof apEnabledSetting === 'undefined' || apEnabledSetting) ? 'checked' : '' %>>
     128        <span><%= t('aset.fediverse_toggle') %></span>
     129      </label>
     130      <div class="set-actions"><button type="submit" class="btn btn-primary"><%= t('aset.save') %></button></div>
     131    </form>
     132  </section>
    119133
    120134  <%# E-mail / SMTP — required for sending newsletters, notify-mails and password resets. %>
  • src/views/pages/admin.ejs

    reb2fe08 r283f618  
    5757      <a href="/admin/shows" class="btn"><%= t('admin.b_agenda') %></a>
    5858    <% } %>
    59     <a href="/tijdlijn" class="btn">🌐 <%= t('tl.title') %></a>
    60     <a href="/meldingen" class="btn">🔔 <%= t('notif.title') %></a>
    61     <a href="/fediverse" class="btn">🐘 <%= t('admin.b_fediverse') %></a>
    62     <a href="/blokkeren" class="btn">🚫 <%= t('blk.title') %></a>
     59    <% if (typeof apEnabled === 'undefined' || apEnabled) { %>
     60      <a href="/tijdlijn" class="btn">🌐 <%= t('tl.title') %></a>
     61      <a href="/meldingen" class="btn">🔔 <%= t('notif.title') %></a>
     62      <a href="/fediverse" class="btn">🐘 <%= t('admin.b_fediverse') %></a>
     63      <a href="/blokkeren" class="btn">🚫 <%= t('blk.title') %></a>
     64    <% } %>
    6365    <a href="/admin/updates" class="btn"><%= t('admin.b_updates') %></a>
    6466    <a href="/admin/handleiding" class="btn"><%= t('admin.b_help') %></a>
  • src/views/pages/post.ejs

    reb2fe08 r283f618  
    7070  <% var _postAbsUrl = (typeof ogOrigin !== 'undefined' && ogOrigin ? ogOrigin : '') + (typeof _base !== 'undefined' && _base ? _base : '') + '/' + post.slug; %>
    7171  <% var _fedi = (typeof fediverse !== 'undefined' && fediverse) ? fediverse : { thread: [], likeCount: 0, announceCount: 0 }; %>
    72   <% if (post.status === 'published') { %>
     72  <% if (post.status === 'published' && (typeof apEnabled === 'undefined' || apEnabled)) { %>
    7373    <section class="post-fediverse post-comments" id="fediverse">
    7474      <h2 class="comments-heading"><%= t('fedi.heading') %></h2>
  • src/views/partials/profile-header.ejs

    reb2fe08 r283f618  
    7070      <%# Follow-via-fediverse: a compact icon in the links row (keeps the header
    7171          short), and hidden for the owner — you don't follow yourself. %>
    72       <% var _showFollow = (typeof canManageFedi === 'undefined' || !canManageFedi) && site && site.slug; %>
     72      <% var _showFollow = (typeof canManageFedi === 'undefined' || !canManageFedi) && site && site.slug && (typeof apEnabled === 'undefined' || apEnabled); %>
    7373      <% if (_profileLinks.length || _showFollow) { %>
    7474        <% const _platforms = (typeof platforms_catalog !== 'undefined' && platforms_catalog) || {}; %>
Note: See TracChangeset for help on using the changeset viewer.