ee76088f86
views/top.ejs, views/bottom.ejs and public/lib/js/app-base.js are now byte-identical across sso-manager-node, proxy and jump-host. Everything per-app moved into utils/ui.js, exposed to every render as `ui` via app.locals (nav items + their group gates, footer repo/docs/ToS links, favicon, profile/logout targets, update-banner on/off + label). Client framework changes: - One gating model everywhere: app-base.js reveals .group-required-<cn> for each of the current user user/me groups. sso-manager-node sends LDAP DNs in memberOf, the OIDC clients send CNs in groups; both normalise to CNs, and the clients isAdmin flag becomes a synthetic `admin` group, so proxy nav-admin items are now group-required-admin. - user/me is fetched once per page load and cached (app.auth.loadUser); nav, forceLogin and group-required elements all read that one promise. - isLoggedIn is dual-mode (Promise + node-style callback), so the async and callback call styles both work from one shared top.ejs. - forceLogin no longer uses $.holdReady (removed in jQuery 4): it redirects to /login?redirect=<path>, and still enforces required groups. - logOut only clears the session; the caller decides where to go next. - post/put/delete are dual-mode Promise/callback, which also removes the undefined `callback2` reference that threw on a non-function callback. Dependencies: jquery ^4.0.0 and ejs ^3.1.10 in all three apps. jump-host specifics: - .group-required base rule added to styles.css (no gated nav items yet). - #spa-shell drops its inline margin-top; styles.css already sets it, and the shared shell adjusts it when a banner is shown. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
31 lines
1.3 KiB
Plaintext
31 lines
1.3 KiB
Plaintext
</div><!-- end spa-shell -->
|
|
|
|
<!-- Shared UI shell — byte-identical across sso-manager-node, proxy and
|
|
jump-host. Everything per-app comes from `ui` (utils/ui.js, exposed via
|
|
app.locals in app.js). Edit all three copies together. -->
|
|
<footer class="py-2 bg-dark text-light mt-4">
|
|
<div class="container-fluid d-flex flex-wrap justify-content-between align-items-center small gap-2">
|
|
<span class="d-flex align-items-center gap-2">
|
|
<a href="https://theta42.com" target="_blank">
|
|
<img width="64" src="/static/img/theta42.svg"/>
|
|
</a>
|
|
© <%- buildYear %> theta42 ·
|
|
<a href="<%- ui.licenseUrl %>" target="_blank" class="text-light">MIT License</a>
|
|
</span>
|
|
<span class="d-flex align-items-center gap-3">
|
|
<a href="<%- ui.docsUrl %>"<%- ui.docsExternal ? ' target="_blank"' : '' %> class="text-light text-decoration-none">
|
|
<i class="fa-solid fa-book"></i> Docs
|
|
</a>
|
|
<a href="<%- ui.repoUrl %>" target="_blank" class="text-light text-decoration-none">
|
|
<i class="fa-brands fa-github"></i> GitHub
|
|
</a>
|
|
<% if(ui.tosUrl){ %>
|
|
<a href="<%- ui.tosUrl %>" class="text-light text-decoration-none">Terms of Service</a>
|
|
<% } %>
|
|
</span>
|
|
<span>v<%- buildVersion %> (<%- buildHash %>)</span>
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
</html>
|