Changeset f7d142f in Klonkt for src/views/pages


Ignore:
Timestamp:
06/28/2026 03:36:22 PM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
81bb9c5
Parents:
127f87e
Message:

chore(csp): drop the last script unsafe-inline + add Permissions-Policy

Move every inline on* handler to a shared delegated data-* handler, so script-src-attr
can be 'none' instead of 'unsafe-inline'. Add a Permissions-Policy header disabling
camera/microphone/geolocation/Topics (embed features left at default).

  • views/shell.ejs — shared delegated submit/change/click/error handler (data-confirm, data-autosubmit, data-lang-switch, data-selectall, data-back, data-fallback)
  • views/{pages,partials}/*.ejs — 18 inline on* handlers -> data-* attributes (14 files)
  • server.js — scriptSrcAttr 'unsafe-inline' -> 'none'; Permissions-Policy header
Location:
src/views/pages
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/admin-audio.ejs

    r127f87e rf7d142f  
    121121                        style="<%= t.downloadable ? 'color:var(--accent,#6b8f71)' : 'opacity:.5' %>">⬇</button>
    122122              <% } %>
    123               <form action="/admin/audio/<%= t.id %>/delete" method="post" onsubmit="return confirm('<%= _aaudDelConfirm %>')" class="ax-track-delete">
     123              <form action="/admin/audio/<%= t.id %>/delete" method="post" data-confirm="<%= _aaudDelConfirm %>" class="ax-track-delete">
    124124                <button type="submit" class="ax-icon-btn ax-icon-btn-danger" aria-label="<%= _aaudDelete %>" title="<%= _aaudDelete %>">🗑</button>
    125125              </form>
     
    135135      <h2 style="margin:0 0 .4rem">🔊 <%= t('aaud.embed_player') %></h2>
    136136      <p style="opacity:.75;font-size:.9rem;margin:0 0 .6rem"><%= t('aaud.embed_hint') %></p>
    137       <textarea readonly rows="3" onclick="this.select()" style="width:100%;font-family:monospace;font-size:12px;padding:10px;border-radius:8px;border:1px solid var(--rule);background:var(--paper-2);color:inherit;">&lt;iframe src="<%= embedUrl %>" width="100%" height="420" frameborder="0" loading="lazy" style="border-radius:12px"&gt;&lt;/iframe&gt;</textarea>
     137      <textarea readonly rows="3" data-selectall style="width:100%;font-family:monospace;font-size:12px;padding:10px;border-radius:8px;border:1px solid var(--rule);background:var(--paper-2);color:inherit;">&lt;iframe src="<%= embedUrl %>" width="100%" height="420" frameborder="0" loading="lazy" style="border-radius:12px"&gt;&lt;/iframe&gt;</textarea>
    138138      <p style="margin:.6rem 0 0"><a class="btn" href="<%= embedUrl %>" target="_blank">▶ <%= t('aaud.preview_player') %></a></p>
    139139    </section>
  • src/views/pages/admin-newsletter.ejs

    r127f87e rf7d142f  
    2424
    2525  <% var _sendConfirm = t('anews.send_confirm', { n: c.confirmed }); %>
    26   <form method="POST" action="<%= siteUrlBase %>/admin/newsletter/send" class="anl-form">
     26  <form method="POST" action="<%= siteUrlBase %>/admin/newsletter/send" class="anl-form" data-confirm="<%= _sendConfirm %>">
    2727    <label><%= t('anews.subject') %>
    2828      <input type="text" name="subject" required maxlength="200" value="<%= (typeof nlSubject!=='undefined')?nlSubject:'' %>" placeholder="<%= t('anews.subject_ph') %>">
     
    3131      <textarea name="body" rows="10" required placeholder="<%= t('anews.body_ph') %>"><%= (typeof nlBody!=='undefined')?nlBody:'' %></textarea>
    3232    </label>
    33     <button type="submit" class="anl-send" <%= smtp ? '' : 'disabled' %> onclick="return confirm('<%= _sendConfirm %>')"><%= t('anews.send_btn', { n: c.confirmed }) %></button>
     33    <button type="submit" class="anl-send" <%= smtp ? '' : 'disabled' %>><%= t('anews.send_btn', { n: c.confirmed }) %></button>
    3434  </form>
    3535
  • src/views/pages/admin-shows.ejs

    r127f87e rf7d142f  
    1414  <form method="POST" action="<%= siteUrlBase %>/admin/shows/toggle" style="margin:0 0 14px">
    1515    <label style="display:flex;align-items:center;gap:10px;cursor:pointer;font-weight:600">
    16       <input type="checkbox" name="enabled" value="1" <%= agOn ? 'checked' : '' %> onchange="this.form.submit()" style="width:18px;height:18px;accent-color:var(--accent)">
     16      <input type="checkbox" name="enabled" value="1" <%= agOn ? 'checked' : '' %> data-autosubmit style="width:18px;height:18px;accent-color:var(--accent)">
    1717      <span><%= t('ashow.show_toggle') %> <small style="font-weight:400;opacity:.7"><%= t('ashow.show_toggle_hint') %></small></span>
    1818    </label>
     
    4545          <span class="ash-when"><%= s.date %><% if (s.time) { %> <%= s.time %><% } %></span>
    4646          <span class="ash-where"><%= s.city %><% if (s.venue) { %> — <%= s.venue %><% } %></span>
    47           <form method="POST" action="<%= siteUrlBase %>/admin/shows/<%= s.id %>/delete" onsubmit="return confirm('<%= _delConfirm %>')" style="margin:0">
     47          <form method="POST" action="<%= siteUrlBase %>/admin/shows/<%= s.id %>/delete" data-confirm="<%= _delConfirm %>" style="margin:0">
    4848            <button type="submit" class="ash-del">🗑</button>
    4949          </form>
  • src/views/pages/admin-sites.ejs

    r127f87e rf7d142f  
    9393            <% if (!s.is_primary && (typeof canMutate === 'undefined' || canMutate)) { %>
    9494              <form method="post" action="/admin/sites/<%= s.slug %>/make-primary" style="margin:0;display:inline"
    95                     onsubmit="return confirm('<%= _s_makeprim_c %>')">
     95                    data-confirm="<%= _s_makeprim_c %>">
    9696                <button type="submit" class="ax-icon-btn" aria-label="<%= _s_makeprim %>" title="<%= _s_makeprim_t %>">★</button>
    9797              </form>
     
    9999            <a href="/admin/sites/<%= s.slug %>/edit" class="ax-icon-btn" aria-label="<%= _s_edit %>" title="<%= _s_edit %>">✎</a>
    100100            <form method="post" action="/admin/sites/<%= s.slug %>/delete" class="ax-delete-form"
    101                   onsubmit="return confirm('<%= _s_del_c %>')">
     101                  data-confirm="<%= _s_del_c %>">
    102102              <button type="submit" class="ax-icon-btn ax-icon-btn-danger" aria-label="<%= _s_del %>" title="<%= _s_del %>">🗑</button>
    103103            </form>
  • src/views/pages/admin-updates.ejs

    r127f87e rf7d142f  
    4040    <% if (canCheck && canSelfUpdate) { %>
    4141    <form method="post" action="/admin/updates/run" class="set-form"
    42           onsubmit="return confirm('<%= t('aupd.run_confirm') %>');">
     42          data-confirm="<%= t('aupd.run_confirm') %>">
    4343      <button type="submit" class="btn btn-primary">
    4444        <%= upToDate ? '↻ ' + t('aupd.redeploy') : '⬆ ' + t('aupd.update_now') %>
  • src/views/pages/admin-users.ejs

    r127f87e rf7d142f  
    8080              <label class="ax-role">
    8181                <span><%= _u_rol %></span>
    82                 <select name="role" onchange="this.form.submit()" <% if (u.id === user.id || !canMutate) { %>disabled<% } %>>
     82                <select name="role" data-autosubmit <% if (u.id === user.id || !canMutate) { %>disabled<% } %>>
    8383                  <option value="kijker" <%= u.role === 'kijker' ? 'selected' : '' %>><%= _u_r_kijker %></option>
    8484                  <option value="member" <%= u.role === 'member' ? 'selected' : '' %>><%= _u_r_member %></option>
     
    9494                   : ''; %>
    9595              <form method="post" action="/admin/users/<%= u.id %>/delete" class="ax-delete-form"
    96                     onsubmit="return confirm('<%= t('ausr.del_confirm', { name: u.username }) %> <%= _warn %><%= t('ausr.del_undo') %>')">
     96                    data-confirm="<%= t('ausr.del_confirm', { name: u.username }) %> <%= _warn %><%= t('ausr.del_undo') %>">
    9797                <button type="submit" class="ax-icon-btn ax-icon-btn-danger" aria-label="<%= _u_del %>" title="<%= _u_del %>">🗑</button>
    9898              </form>
  • src/views/pages/authorize-interaction.ejs

    r127f87e rf7d142f  
    3737              <a class="fedi-goto-btn" href="<%= m.in_reply_to %>" target="_blank" rel="nofollow noopener"><svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 17 17 7"/><path d="M7 7h10v10"/></svg> <%= t('fedi.goto_post') %></a>
    3838              <% } %>
    39               <form method="post" action="/fediverse/<%= m.id %>/delete" class="fedi-del-form" onsubmit="return confirm('<%= t('fedi.delete_confirm') %>')">
     39              <form method="post" action="/fediverse/<%= m.id %>/delete" class="fedi-del-form" data-confirm="<%= t('fedi.delete_confirm') %>">
    4040                <button type="submit" class="fedi-del-btn"><svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg> <%= t('comments.delete') %></button>
    4141              </form>
  • src/views/pages/following.ejs

    r127f87e rf7d142f  
    2828          <form method="post" action="/news/autoboost" class="tl-foll-ab" title="<%= t('tl.autoboost_hint') %>">
    2929            <input type="hidden" name="actor_uri" value="<%= f.actor_uri %>">
    30             <label><input type="checkbox" name="auto_boost" value="1" <%= f.auto_boost ? 'checked' : '' %> onchange="this.form.submit()"> ✨ <%= t('tl.autoboost') %></label>
     30            <label><input type="checkbox" name="auto_boost" value="1" <%= f.auto_boost ? 'checked' : '' %> data-autosubmit> ✨ <%= t('tl.autoboost') %></label>
    3131          </form>
    3232          <form method="post" action="/news/unfollow"><input type="hidden" name="actor_uri" value="<%= f.actor_uri %>"><button type="submit" class="tl-unfollow"><%= t('tl.unfollow') %></button></form>
  • src/views/pages/news.ejs

    r127f87e rf7d142f  
    135135            <form method="post" action="/news/boost" class="tl-act-form tl-react-form"><input type="hidden" name="note" value="<%= p.id %>"><input type="hidden" name="author" value="<%= p.author_uri %>"><button type="submit" class="tl-act tl-act-boost<%= p.boosted ? ' is-on' : '' %>" title="<%= p.boosted ? t('tl.unboost') : t('fedi.boosts') %>" aria-label="<%= p.boosted ? t('tl.unboost') : t('fedi.boosts') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg></button></form>
    136136            <button type="button" class="tl-act tl-act-reply fedi-remote-reply-btn" data-fedi-uri="<%= p.id %>" data-fedi-ph="<%= t('fedi.remote_ph') %>" title="<%= t('fedi.remote_reply') %>" aria-label="<%= t('fedi.remote_reply') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg></button>
    137             <form method="post" action="/blocking/add" class="tl-act-form" onsubmit="return confirm('<%= t('tl.block') %>?');"><input type="hidden" name="target" value="<%= p.author_uri %>"><button type="submit" class="tl-act tl-act-block" title="<%= t('tl.block') %>" aria-label="<%= t('tl.block') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="4.9" y1="4.9" x2="19.1" y2="19.1"/></svg></button></form>
     137            <form method="post" action="/blocking/add" class="tl-act-form" data-confirm="<%= t('tl.block') %>?"><input type="hidden" name="target" value="<%= p.author_uri %>"><button type="submit" class="tl-act tl-act-block" title="<%= t('tl.block') %>" aria-label="<%= t('tl.block') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="4.9" y1="4.9" x2="19.1" y2="19.1"/></svg></button></form>
    138138          </div>
    139139        </li>
  • src/views/pages/post.ejs

    r127f87e rf7d142f  
    6868      <% } %>
    6969      <% if (permissions.canDeletePost(user, post, site)) { %>
    70         <form method="post" action="<%= _base %>/posts/<%= post.slug %>/delete" style="display:inline" onsubmit="return confirm('Delete this post?')">
     70        <form method="post" action="<%= _base %>/posts/<%= post.slug %>/delete" style="display:inline" data-confirm="Delete this post?">
    7171          <button type="submit" class="btn btn-danger">🗑 Delete</button>
    7272        </form>
  • src/views/pages/viewer-blocked.ejs

    r127f87e rf7d142f  
    88    </p>
    99    <div class="vb-actions">
    10       <button type="button" class="vb-btn vb-btn-primary" onclick="history.back()">← <%= t('vblk.back') %></button>
     10      <button type="button" class="vb-btn vb-btn-primary" data-back>← <%= t('vblk.back') %></button>
    1111      <a class="vb-btn" href="/"><%= t('vblk.to_home') %></a>
    1212    </div>
Note: See TracChangeset for help on using the changeset viewer.