Initial commit: Werkzeuge-Sammlung
Enthält: - rdp_client.py: RDP Client mit GUI und Monitor-Auswahl - rdp.sh: Bash-basierter RDP Client - teamleader_test/: Network Scanner Fullstack-App - teamleader_test2/: Network Mapper CLI Subdirectories mit eigenem Repo wurden ausgeschlossen. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
22
teamleader_test2/frontend/index.html
Normal file
22
teamleader_test2/frontend/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>LAN Graph Explorer</title>
|
||||
<link rel="stylesheet" href="/static/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>LAN Graph Explorer</h1>
|
||||
<p>Discover your local hosts and their relationships in a Visio-style topology.</p>
|
||||
<button id="refresh">Refresh scan</button>
|
||||
</header>
|
||||
<main>
|
||||
<div id="status">Idle</div>
|
||||
<svg id="topology" viewBox="0 0 1000 600"></svg>
|
||||
</main>
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<script src="/static/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
103
teamleader_test2/frontend/script.js
Normal file
103
teamleader_test2/frontend/script.js
Normal file
@@ -0,0 +1,103 @@
|
||||
const statusEl = document.querySelector('#status');
|
||||
const svg = d3.select('#topology');
|
||||
const width = 1000;
|
||||
const height = 600;
|
||||
|
||||
const linkGroup = svg.append('g').attr('class', 'links');
|
||||
const nodeGroup = svg.append('g').attr('class', 'nodes');
|
||||
|
||||
const simulation = d3.forceSimulation()
|
||||
.force('link', d3.forceLink().id(d => d.ip).distance(140))
|
||||
.force('charge', d3.forceManyBody().strength(-200))
|
||||
.force('center', d3.forceCenter(width / 2, height / 2));
|
||||
|
||||
function colorForNode(node) {
|
||||
if (node.comment && node.comment.includes('gateway')) return '#ffb347';
|
||||
if (node.comment && node.comment.includes('scanner')) return '#4db8ff';
|
||||
return node.via_ssh ? '#7fbea6' : '#d4d4d4';
|
||||
}
|
||||
|
||||
function render(data) {
|
||||
const edges = data.edges.map(edge => ({
|
||||
...edge,
|
||||
source: edge.source,
|
||||
target: edge.target,
|
||||
}));
|
||||
|
||||
const link = linkGroup.selectAll('line').data(edges, d => `${d.source}|${d.target}|${d.relation}`);
|
||||
link.join(
|
||||
enter => enter.append('line').attr('stroke-width', 2),
|
||||
update => update,
|
||||
exit => exit.remove()
|
||||
).attr('stroke', '#999');
|
||||
|
||||
const node = nodeGroup.selectAll('g').data(data.nodes, d => d.ip);
|
||||
const nodeEnter = node.enter().append('g').call(d3.drag()
|
||||
.on('start', dragstarted)
|
||||
.on('drag', dragged)
|
||||
.on('end', dragended));
|
||||
|
||||
nodeEnter.append('circle').attr('r', 26);
|
||||
nodeEnter.append('text')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('dy', '0.35em')
|
||||
.text(d => d.ip);
|
||||
|
||||
nodeEnter.append('title');
|
||||
|
||||
const nodeMerged = nodeEnter.merge(node);
|
||||
nodeMerged.select('circle').attr('fill', colorForNode);
|
||||
nodeMerged.select('title').text(d => `${d.ip}\n${d.dns_name || 'no reverse host'}\nvia SSH: ${d.via_ssh}`);
|
||||
|
||||
node.exit().remove();
|
||||
|
||||
simulation.nodes(data.nodes).on('tick', ticked);
|
||||
simulation.force('link').links(edges);
|
||||
simulation.alpha(1).restart();
|
||||
}
|
||||
|
||||
function ticked() {
|
||||
linkGroup.selectAll('line')
|
||||
.attr('x1', d => d.source.x)
|
||||
.attr('y1', d => d.source.y)
|
||||
.attr('x2', d => d.target.x)
|
||||
.attr('y2', d => d.target.y);
|
||||
|
||||
nodeGroup.selectAll('g')
|
||||
.attr('transform', d => `translate(${d.x},${d.y})`);
|
||||
}
|
||||
|
||||
function dragstarted(event, d) {
|
||||
if (!event.active) simulation.alphaTarget(0.3).restart();
|
||||
d.fx = d.x;
|
||||
d.fy = d.y;
|
||||
}
|
||||
|
||||
function dragged(event, d) {
|
||||
d.fx = event.x;
|
||||
d.fy = event.y;
|
||||
}
|
||||
|
||||
function dragended(event, d) {
|
||||
if (!event.active) simulation.alphaTarget(0);
|
||||
d.fx = null;
|
||||
d.fy = null;
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
statusEl.textContent = 'Scanning local LAN…';
|
||||
const response = await fetch('/api/scan');
|
||||
if (!response.ok) {
|
||||
throw new Error(`scan failed: ${response.status}`);
|
||||
}
|
||||
const payload = await response.json();
|
||||
render(payload);
|
||||
statusEl.textContent = `Last scanned ${new Date().toLocaleTimeString()}`;
|
||||
} catch (error) {
|
||||
statusEl.textContent = `Error: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('#refresh').addEventListener('click', refresh);
|
||||
refresh();
|
||||
71
teamleader_test2/frontend/style.css
Normal file
71
teamleader_test2/frontend/style.css
Normal file
@@ -0,0 +1,71 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: Inter, system-ui, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: #0f141a;
|
||||
color: #f4f5f7;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 1rem 2rem;
|
||||
background: linear-gradient(90deg, #1d2734, #0d121b);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
header p {
|
||||
margin: 0;
|
||||
color: #9da8b7;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
#status {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.95rem;
|
||||
color: #a5c9ff;
|
||||
}
|
||||
|
||||
#topology {
|
||||
width: min(100%, 1100px);
|
||||
background: #111827;
|
||||
border-radius: 1rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 25px 45px rgba(5, 5, 5, 0.4);
|
||||
}
|
||||
|
||||
circle {
|
||||
stroke: #fff;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
padding: 0.5rem 1rem;
|
||||
background: #2563eb;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 10px 20px rgba(37, 99, 235, 0.35);
|
||||
}
|
||||
Reference in New Issue
Block a user