Merge pull request #211 from theta42/release/v1.33.0

feat: error page, admin-only DNS, navbar active styling (v1.33.0)
This commit is contained in:
2026-08-04 15:09:31 -04:00
committed by GitHub
7 changed files with 55 additions and 4 deletions
+5
View File
@@ -1,3 +1,8 @@
## v1.33.0
- feat: Add SSO-style error page (404/500) for browser navigation instead of a bare JSON/text response
- feat: DNS page is now admin-only (hidden from non-admins; API already admin-gated)
- feat: navbar — username no longer underlined; only the active link is bold + underlined
## v1.13.3 ## v1.13.3
- fix: remove missing DEPLOYMENT.md and docs/ from Docker build context - fix: remove missing DEPLOYMENT.md and docs/ from Docker build context
+15
View File
@@ -21,6 +21,8 @@ module.exports = app;
// Hold onto the auth middleware // Hold onto the auth middleware
const middleware = require('./middleware/auth'); const middleware = require('./middleware/auth');
const conf = require('@simpleworkjs/conf');
const buildInfo = require('./utils/build_info');
// Grab the projects PubSub // Grab the projects PubSub
app.contoller = require('./controller'); app.contoller = require('./controller');
@@ -115,6 +117,19 @@ app.use(async function(err, req, res, next) {
res.status(status); res.status(status);
// Only expose safe, non-internal fields to the client. // Only expose safe, non-internal fields to the client.
const body = { name: err.name, message: err.message }; const body = { name: err.name, message: err.message };
// Browser navigation gets the HTML error page (shared with SSO); API
// clients get JSON.
if (req.accepts('html') && !req.originalUrl.startsWith('/api/')) {
res.render('error', {
title: conf.environment !== 'production' ? 'dev' : '',
titleIcon: conf.environment !== 'production' ? '<i class="fa-brands fa-dev"></i>' : '',
name: conf.name,
logo: conf.logo,
...buildInfo,
error: err,
});
return;
}
res.json(body); res.json(body);
}catch(error){ }catch(error){
console.error('error in the catch-all error handler', error); console.error('error in the catch-all error handler', error);
+6
View File
@@ -3,6 +3,12 @@ nav.navbar{
padding-right: 1em; padding-right: 1em;
} }
/* Only the active top-nav link is bold + underlined; the username is plain. */
.top-nav a.active{
font-weight: bold;
text-decoration: underline;
}
body { body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
+1 -1
View File
@@ -37,7 +37,7 @@ module.exports = {
// in (plus the synthetic `admin` group when user/me reports isAdmin). // in (plus the synthetic `admin` group when user/me reports isAdmin).
nav: [ nav: [
{href: '/hosts', icon: 'fa-solid fa-network-wired', label: 'Hosts', groups: []}, {href: '/hosts', icon: 'fa-solid fa-network-wired', label: 'Hosts', groups: []},
{href: '/dns', icon: 'fa-solid fa-record-vinyl', label: 'DNS', groups: []}, {href: '/dns', icon: 'fa-solid fa-record-vinyl', label: 'DNS', groups: ['admin']},
{href: '/permissions', icon: 'fa-solid fa-user-shield', label: 'Permissions', groups: ['admin']}, {href: '/permissions', icon: 'fa-solid fa-user-shield', label: 'Permissions', groups: ['admin']},
{href: '/groups', icon: 'fa-solid fa-users-gear', label: 'Groups', groups: ['admin']}, {href: '/groups', icon: 'fa-solid fa-users-gear', label: 'Groups', groups: ['admin']},
], ],
+2 -2
View File
@@ -1,7 +1,7 @@
<%- include('top') %> <%- include('top') %>
<script type="text/javascript"> <script type="text/javascript">
// Require login to see this page. // Require an admin to see this page.
app.auth.forceLogin(); app.auth.forceLogin(['admin']);
</script> </script>
<style type="text/css"> <style type="text/css">
+25
View File
@@ -0,0 +1,25 @@
<%- include('top') %>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6 text-center">
<div class="mb-4">
<i class="fa-solid fa-triangle-exclamation text-warning" style="font-size: 4rem;"></i>
</div>
<h1 class="display-4 fw-bold text-dark"><%= error.status || 500 %></h1>
<h3 class="mb-3 text-secondary"><%= error.message || 'Something went wrong' %></h3>
<p class="text-muted mb-4">
<% if (error.status === 404) { %>
The page you are looking for doesn't exist or has been moved.
<% } else { %>
An unexpected error occurred. Please try again later.
<% } %>
</p>
<a href="/" class="btn btn-primary shadow-sm px-4 py-2">
<i class="fa-solid fa-house me-2"></i>Return to Home
</a>
</div>
</div>
</div>
<%- include('bottom') %>
+1 -1
View File
@@ -49,7 +49,7 @@
</ul> </ul>
<div class="form-inline mt-2 mt-md-0"> <div class="form-inline mt-2 mt-md-0">
<% if(ui.profileUrl){ %> <% if(ui.profileUrl){ %>
<a id="cl-username" class="navbar-text text-light me-3" href="<%- ui.profileUrl %>" style="display: none;"> <a id="cl-username" class="navbar-text text-light me-3 text-decoration-none" href="<%- ui.profileUrl %>" style="display: none;">
<i class="fa-solid fa-user me-1"></i><span id="cl-username-text"></span> <i class="fa-solid fa-user me-1"></i><span id="cl-username-text"></span>
</a> </a>
<% } else { %> <% } else { %>