guest role; guide section ticking

This commit is contained in:
2026-08-27 13:02:35 -04:00
parent d38a599292
commit 4da6c6aa36
45 changed files with 830 additions and 243 deletions

View File

@@ -11,7 +11,9 @@
</div>
</div>
<div class="sidebar-search">
<!-- Global search is authenticated; offering the box to a signed-out
reader gives them a control that can only answer 401. -->
<div v-if="authStore.isAuthenticated" class="sidebar-search">
<input
v-model="searchQuery"
type="text"
@@ -222,8 +224,23 @@ function buildNavItems(items) {
// Drop items the user cannot reach: a nav item may carry a `permission`
// (e.g. Slides -> slides.manage); hide it from anyone who lacks it so the
// link does not dead-end at the router guard. Admins hold every permission.
const visible = items.filter(item =>
!item.permission || authStore.hasPermission(item.permission))
//
// A signed-out visitor sees only what a plugin has declared guest-reachable.
// Without this the sidebar offers a signed-out reader the whole app and every
// link bounces them to the login page, which reads as a broken site rather
// than as a closed door.
// A nav item may name one permission or several; holding ANY of them is
// enough. GE-Enforce and Slides need that: the page is reachable by a
// manager and by a plain viewer, and they hold different strings.
const holds = item => {
if (!item.permission) return true
const names = Array.isArray(item.permission) ? item.permission : [item.permission]
return names.some(name => authStore.hasPermission(name))
}
// A signed-out visitor gets whatever the server sent, which is already
// filtered to what the guest role can reach - hasPermission knows nothing
// about guests, so asking it here would hide everything.
const visible = authStore.isAuthenticated ? items.filter(holds) : items
const known = new Set(NAV_SECTIONS.map(s => s.key).filter(Boolean))
const bucket = item => {