Files
jump-host/nodejs/views/dashboard.ejs
T
wmantly 4fb4e77007 Dashboard: list hosts you can reach; bump @simpleworkjs/ldap to 1.0.1
- New GET /api/user/hosts (auth-only): all hosts for admins, group-filtered
  list for everyone else.
- accessibleHosts() accepts a pre-resolved user.groups, so the web UI's
  OIDC session skips a redundant LDAP getGroups(dn) call.
- Dashboard shows a "Hosts you can reach" / "All hosts" table.
- @simpleworkjs/ldap 1.0.1 fixes addSshKey's ObjectClassViolationError on
  accounts predating the ldapPublicKey objectClass -- was aborting key
  injection (and the SSH connection) on affected accounts.
- Bump to 1.5.0.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 23:11:23 -04:00

90 lines
3.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<%- include('top') %>
<script type="text/javascript">app.auth.forceLogin();</script>
<div class="row g-3 mb-4">
<div class="col-6 col-md-3">
<div class="card shadow-sm text-center"><div class="card-body">
<div class="display-6" id="stat-active"></div>
<div class="text-muted small text-uppercase">Active sessions</div>
</div></div>
</div>
<div class="col-6 col-md-3">
<div class="card shadow-sm text-center"><div class="card-body">
<div class="display-6" id="stat-total"></div>
<div class="text-muted small text-uppercase">Total connections</div>
</div></div>
</div>
<div class="col-6 col-md-3">
<div class="card shadow-sm text-center"><div class="card-body">
<div class="display-6 text-danger" id="stat-fail"></div>
<div class="text-muted small text-uppercase">Failed</div>
</div></div>
</div>
<div class="col-6 col-md-3">
<div class="card shadow-sm text-center"><div class="card-body">
<div class="display-6" id="stat-users"></div>
<div class="text-muted small text-uppercase">Users seen</div>
</div></div>
</div>
</div>
<div class="row g-3 mb-4">
<div class="col-12">
<div class="card shadow-sm">
<div class="card-header"><i class="fa-solid fa-network-wired me-1"></i> <span id="my-hosts-title">Hosts you can reach</span></div>
<table class="table table-sm mb-0"><tbody id="my-hosts"></tbody></table>
</div>
</div>
</div>
<div class="row g-3">
<div class="col-md-6">
<div class="card shadow-sm"><div class="card-header"><i class="fa-solid fa-server me-1"></i> Top hosts</div>
<table class="table table-sm mb-0"><tbody id="top-hosts"></tbody></table>
</div>
</div>
<div class="col-md-6">
<div class="card shadow-sm"><div class="card-header"><i class="fa-solid fa-user me-1"></i> Top users</div>
<table class="table table-sm mb-0"><tbody id="top-users"></tbody></table>
</div>
</div>
</div>
<script type="text/javascript">
function rows(sel, list){
var $b = $(sel).empty();
if(!list || !list.length){ $b.append('<tr><td class="text-muted">No data.</td></tr>'); return; }
list.forEach(function(x){
$b.append('<tr><td>' + app.jump.esc(x.name) + '</td><td class="text-end">' + x.count + '</td></tr>');
});
}
function hostRows(sel, hosts){
var $b = $(sel).empty();
if(!hosts || !hosts.length){ $b.append('<tr><td class="text-muted">No hosts reachable.</td></tr>'); return; }
hosts.forEach(function(h){
var addr = (h.metadata && (h.metadata.ip || h.metadata.address)) || '';
$b.append('<tr><td>' + app.jump.esc(h.displayName || h.name || h.slug) + '</td>'
+ '<td class="text-muted small">' + app.jump.esc(h.slug) + '</td>'
+ '<td class="text-end text-muted small">' + app.jump.esc(addr) + '</td></tr>');
});
}
$(document).ready(async function(){
app.jump.metrics(function(error, data){
if(error || !data) return;
$('#stat-active').text(data.active);
$('#stat-total').text(data.total);
$('#stat-fail').text(data.fail);
$('#stat-users').text((data.topUsers || []).length);
rows('#top-hosts', data.topHosts);
rows('#top-users', data.topUsers);
});
await app.auth.loadUser();
if(app.auth.isAdmin()) $('#my-hosts-title').text('All hosts');
app.jump.hosts(function(error, data){
if(error) return hostRows('#my-hosts', []);
hostRows('#my-hosts', data && data.results);
});
});
</script>
<%- include('bottom') %>