Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a7b3416619 | |||
| f357c89ac7 | |||
| b9415dcb17 | |||
| 65ba1b16e3 | |||
| 8c4ec67282 | |||
| 36e7dbf8aa |
@@ -1,3 +1,7 @@
|
||||
## v1.18.0
|
||||
- feat: Add SSO-style error page (404/500) for browser navigation instead of a bare text response
|
||||
- feat: navbar — username no longer underlined; only the active link is bold + underlined
|
||||
|
||||
## v1.16.1
|
||||
- fix: remove missing DEPLOYMENT.md from Docker build context
|
||||
|
||||
|
||||
+11
-1
@@ -4,6 +4,8 @@ const express = require('express');
|
||||
const compression = require('compression');
|
||||
|
||||
require('./models'); // wire model-redis + register models
|
||||
const conf = require('@simpleworkjs/conf');
|
||||
const buildInfo = require('./utils/build_info');
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -41,7 +43,15 @@ app.use((err, req, res, next) => {
|
||||
if(req.path.startsWith('/api/')){
|
||||
return res.status(status).json({name: err.name || 'Error', message: err.message || 'Error'});
|
||||
}
|
||||
res.status(status).send(err.message || 'Error');
|
||||
// Browser navigation gets the HTML error page (shared with SSO).
|
||||
res.status(status).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,
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "t42-jump-host",
|
||||
"version": "1.17.0",
|
||||
"version": "1.18.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "t42-jump-host",
|
||||
"version": "1.17.0",
|
||||
"version": "1.18.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^7.3.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "t42-jump-host",
|
||||
"version": "1.17.1",
|
||||
"version": "1.18.0",
|
||||
"description": "SSH jump host for the theta42 stack — LDAP-authenticated, directory-driven host bridging with audit and metrics",
|
||||
"author": [
|
||||
{
|
||||
|
||||
@@ -3,6 +3,12 @@ nav.navbar{
|
||||
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 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
+12
-2
@@ -46,9 +46,19 @@ if (conf.standalone && conf.standalone.enabled) {
|
||||
|
||||
// Every host in the inventory, unfiltered — for admins (the web UI's own
|
||||
// account is already gated by requireAdmin before this is ever called).
|
||||
function isManagedHost(r) {
|
||||
if (!r || r.kind !== 'host') return false;
|
||||
// If managed attribute is present, require it to be true/truthy
|
||||
if (r.metadata && r.metadata.managed !== undefined) {
|
||||
return r.metadata.managed === true || r.metadata.managed === 'true';
|
||||
}
|
||||
// Default to true for manually created hosts that lack explicit managed metadata
|
||||
return true;
|
||||
}
|
||||
|
||||
async function allHosts({ fetchImpl = fetch } = {}) {
|
||||
const resources = await directoryClient({ fetchImpl }).getResourcesByGroup(undefined, { kind: 'host' });
|
||||
return resources.filter(r => r.kind === 'host');
|
||||
return resources.filter(isManagedHost);
|
||||
}
|
||||
|
||||
async function accessibleHosts(user, { fetchImpl = fetch } = {}) {
|
||||
@@ -62,7 +72,7 @@ if (conf.standalone && conf.standalone.enabled) {
|
||||
console.error(`[access] ${error.message}`);
|
||||
}
|
||||
|
||||
const hosts = resources.filter(r => r.kind === 'host');
|
||||
const hosts = resources.filter(isManagedHost);
|
||||
cache.set(user.uid, { at: Date.now(), hosts });
|
||||
return hosts;
|
||||
}
|
||||
|
||||
@@ -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') %>
|
||||
@@ -49,7 +49,7 @@
|
||||
</ul>
|
||||
<div class="form-inline mt-2 mt-md-0">
|
||||
<% 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>
|
||||
</a>
|
||||
<% } else { %>
|
||||
|
||||
Reference in New Issue
Block a user