Stability fixes: plugin-scoped contexts for owned pages, absent-href guard, checked locale mounts
CI / full-gate (push) Successful in 2m37s
CI / full-gate (push) Successful in 2m37s
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
handler; this renders until then. Data: model { nav, shell }.
|
||||
%><%
|
||||
const nav = include("partials/nav-tree", { nodes: model.nav });
|
||||
// These four messages carry markup (<code> spans), so they render raw — the documented
|
||||
// markup-carrying case. They interpolate nothing, so there is no untrusted data to escape.
|
||||
const body = `
|
||||
<div class="form-page">
|
||||
<section class="form-card">
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
<span class="brand-name"><%= brand %></span>
|
||||
</div>
|
||||
<%- include("partials/auth-card", {
|
||||
action: "/oauth2/consent",
|
||||
action: localeHref("/oauth2/consent"),
|
||||
body,
|
||||
method: "post",
|
||||
sub: t("consent.sub", { client: consent.client }),
|
||||
title: t("consent.title", { client: consent.client }),
|
||||
}) %>
|
||||
<% if (consent.account) { %>
|
||||
<form class="auth-alt" method="post" action="/logout">
|
||||
<form class="auth-alt" method="post" action="<%= localeHref("/logout") %>">
|
||||
<input type="hidden" name="<%= csrfField %>" value="<%= csrfToken %>">
|
||||
<%= t("consent.notYou") %> <button type="submit"><%= t("shell.signOut") %></button>
|
||||
</form>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
const providers = (sso && sso.providers) || [];
|
||||
const alt = locals.alt;
|
||||
-%>
|
||||
<form class="auth-card" method="<%= method %>"<% if (locals.action) { %> action="<%= locals.action %>"<% } %>>
|
||||
<form class="auth-card" method="<%= method %>"<% if (locals.action) { %> action="<%= localeHref(locals.action) %>"<% } %>>
|
||||
<div class="auth-head"><% if (back) { %><a class="auth-back" href="<%= localeHref(back.href) %>"><svg class="ico ico-sm" aria-hidden="true"><use href="#i-arrow-left"/></svg><%= back.label %></a><% } %><h1><%= locals.title %></h1><% if (locals.sub) { %><p class="auth-sub"><%= locals.sub %></p><% } %></div>
|
||||
<% if (providers.length) { -%>
|
||||
<div class="sso" aria-label="<%= sso.label || t("auth.sso.label") %>">
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
Item ∈ { head } · { sep } · { label, icon?, href? ⇒ <a>, hreflang?, current?, danger? } (default: menu-item button)
|
||||
· { group: { legend?, name, control?(="checkbox"|"radio"), options:{value,label,checked?}[] } }
|
||||
%><%
|
||||
const t = locals.trigger || {};
|
||||
const sumCls = "class" in t ? t.class : "btn";
|
||||
const trigger = locals.trigger || {}; // not `t` — that name is the translator in every view
|
||||
const sumCls = "class" in trigger ? trigger.class : "btn";
|
||||
const items = locals.items || [];
|
||||
const popCls = "menu-pop" + (locals.align === "left" ? " left" : "") + (locals.up ? " up" : "");
|
||||
const width = locals.width;
|
||||
-%>
|
||||
<details class="menu<%= locals.kebab ? " kebab" : "" %>"<%= locals.open ? " open" : "" %>>
|
||||
<summary<% if (sumCls) { %> class="<%= sumCls %>"<% } %><% if (t.label) { %> aria-label="<%= t.label %>"<% } %>><% if (t.html != null) { %><%- t.html %><% } else { if (t.icon) { %><svg class="ico ico-sm"><use href="#<%= t.icon %>"/></svg><% } if (t.text) { %><%= t.text %><% } } %></summary>
|
||||
<summary<% if (sumCls) { %> class="<%= sumCls %>"<% } %><% if (trigger.label) { %> aria-label="<%= trigger.label %>"<% } %>><% if (trigger.html != null) { %><%- trigger.html %><% } else { if (trigger.icon) { %><svg class="ico ico-sm"><use href="#<%= trigger.icon %>"/></svg><% } if (trigger.text) { %><%= trigger.text %><% } } %></summary>
|
||||
<div class="<%= popCls %>"<% if (width != null) { %> style="min-width:<%= typeof width === "number" ? width + "px" : width %>"<% } %>>
|
||||
<% items.forEach((it) => { -%>
|
||||
<% if (it.head != null) { -%>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<div class="menu-head"><%= t("shell.signedInAs", { name: user.name }) %></div>
|
||||
<button class="menu-item" type="button"><svg class="ico"><use href="#i-user" /></svg><%= t("shell.profile") %></button>
|
||||
<%# Sign out is a state change → a POST form (not a GET link), CSRF-guarded by app.ts %>
|
||||
<form class="menu-item-form" method="post" action="/logout">
|
||||
<form class="menu-item-form" method="post" action="<%= localeHref("/logout") %>">
|
||||
<input type="hidden" name="_csrf" value="<%= locals.csrfToken || '' %>" />
|
||||
<button class="menu-item danger" type="submit"><svg class="ico"><use href="#i-logout" /></svg><%= t("shell.signOut") %></button>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user