batman (working version kinda)

This commit is contained in:
pika 2025-03-30 19:20:13 +02:00
commit 6dd38036e7
65 changed files with 3950 additions and 0 deletions

View file

@ -0,0 +1,57 @@
{% extends "layout.html" %}
{% block content %}
<div class="container-xl">
<div class="page-header d-print-none">
<div class="row align-items-center">
<div class="col">
<h2 class="page-title">
Add New Application
</h2>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-body">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="POST" action="{{ url_for('dashboard.app_new') }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="mb-3">
<label class="form-label required">Application Name</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="mb-3">
<label class="form-label required">Server</label>
<select class="form-select" name="server_id" required>
<option value="">Select a server</option>
{% for server in servers %}
<option value="{{ server.id }}">{{ server.hostname }} ({{ server.ip_address }})</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Documentation</label>
<textarea class="form-control" name="documentation" rows="6"
placeholder="Use Markdown for formatting"></textarea>
<small class="form-hint">Supports Markdown formatting</small>
</div>
<div class="d-flex justify-content-end">
<a href="{{ url_for('dashboard.server_list') }}" class="btn btn-link me-2">Cancel</a>
<button type="submit" class="btn btn-primary">Save Application</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,125 @@
{% extends "layout.html" %}
{% block content %}
<div class="container-xl">
<div class="page-header d-print-none">
<div class="row align-items-center">
<div class="col">
<h2 class="page-title">Dashboard</h2>
</div>
<div class="col-auto ms-auto d-print-none">
<div class="btn-list">
<a href="{{ url_for('dashboard.server_new') }}" class="btn btn-primary d-none d-sm-inline-block">
<i class="ti ti-plus"></i> New Server
</a>
</div>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-4">
<div class="card stats-card">
<div class="card-body p-4 text-center">
<div class="h1 m-0">{{ server_count }}</div>
<div class="text-muted mb-3">Servers</div>
<div class="d-flex justify-content-center">
<a href="{{ url_for('dashboard.server_list') }}" class="btn btn-sm btn-primary">
View All
</a>
<a href="{{ url_for('dashboard.server_new') }}" class="btn btn-sm btn-outline-primary ms-2">
Add New
</a>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card stats-card">
<div class="card-body p-4 text-center">
<div class="h1 m-0">{{ subnet_count }}</div>
<div class="text-muted mb-3">Subnets</div>
<div class="d-flex justify-content-center">
<a href="{{ url_for('ipam.ipam_home') }}" class="btn btn-sm btn-primary">
View All
</a>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card stats-card">
<div class="card-body p-4 text-center">
<div class="h1 m-0">{{ app_count }}</div>
<div class="text-muted mb-3">Applications</div>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3 class="card-title">Recent Servers</h3>
</div>
<div class="card-body">
{% if latest_servers %}
<div class="list-group list-group-flush">
{% for server in latest_servers %}
<a href="{{ url_for('dashboard.server_view', server_id=server.id) }}"
class="list-group-item list-group-item-action">
<div class="row align-items-center">
<div class="col-auto">
<span class="avatar bg-primary text-white">
{{ server.hostname[0].upper() }}
</span>
</div>
<div class="col text-truncate">
<div class="d-block text-truncate">{{ server.hostname }}</div>
<div class="text-muted text-truncate small">{{ server.ip_address }}</div>
</div>
</div>
</a>
{% endfor %}
</div>
{% else %}
<div class="text-center py-3">
<div class="mb-3">No servers added yet</div>
<a href="{{ url_for('dashboard.server_new') }}" class="btn btn-outline-primary">
Add Your First Server
</a>
</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3 class="card-title">Subnet Utilization</h3>
</div>
<div class="card-body">
{% if subnets %}
{% for subnet in subnets %}
<div class="mb-3">
<div class="d-flex justify-content-between mb-1">
<div>{{ subnet.cidr }}</div>
<div>{{ subnet.used_ips }} / 254 IPs</div>
</div>
<div class="progress">
<div class="progress-bar bg-primary" style="width: {{ subnet.usage_percent }}%"></div>
</div>
</div>
{% endfor %}
{% else %}
<div class="text-center py-3">
<div class="mb-3">No subnets added yet</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,61 @@
{% extends "layout.html" %}
{% block content %}
<div class="container-xl">
<div class="page-header d-print-none">
<div class="row align-items-center">
<div class="col">
<h2 class="page-title">
Add New Server
</h2>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-body">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="POST" action="{{ url_for('dashboard.server_new') }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="mb-3">
<label class="form-label required">Hostname</label>
<input type="text" class="form-control" name="hostname" required>
</div>
<div class="mb-3">
<label class="form-label required">IP Address</label>
<input type="text" class="form-control" name="ip_address" placeholder="192.168.1.10" required>
</div>
<div class="mb-3">
<label class="form-label required">Subnet</label>
<select class="form-select" name="subnet_id" required>
<option value="">Select a subnet</option>
{% for subnet in subnets %}
<option value="{{ subnet.id }}">{{ subnet.cidr }} ({{ subnet.location }})</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Documentation</label>
<textarea class="form-control" name="documentation" rows="6"
placeholder="Use Markdown for formatting"></textarea>
<small class="form-hint">Supports Markdown formatting</small>
</div>
<div class="d-flex justify-content-end">
<a href="{{ url_for('dashboard.server_list') }}" class="btn btn-link me-2">Cancel</a>
<button type="submit" class="btn btn-primary">Save Server</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,62 @@
{% extends "layout.html" %}
{% block content %}
<div class="container-xl">
<div class="page-header d-print-none">
<div class="row align-items-center">
<div class="col">
<h2 class="page-title">
Servers
</h2>
</div>
<div class="col-auto ms-auto">
<a href="{{ url_for('dashboard.server_new') }}" class="btn btn-primary">
<i class="fas fa-plus me-2"></i> Add Server
</a>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-body">
{% if servers %}
<div class="table-responsive">
<table class="table table-vcenter table-hover">
<thead>
<tr>
<th>Hostname</th>
<th>IP Address</th>
<th>Subnet</th>
<th>Created</th>
<th class="w-1"></th>
</tr>
</thead>
<tbody>
{% for server in servers %}
<tr>
<td>{{ server.hostname }}</td>
<td>{{ server.ip_address }}</td>
<td>{{ server.subnet.cidr if server.subnet else 'N/A' }}</td>
<td>{{ server.created_at.strftime('%Y-%m-%d') }}</td>
<td>
<a href="{{ url_for('dashboard.server_view', server_id=server.id) }}" class="btn btn-sm btn-primary">
View
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<div class="mb-3">No servers added yet</div>
<a href="{{ url_for('dashboard.server_new') }}" class="btn btn-primary">
Add Your First Server
</a>
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,142 @@
{% extends "layout.html" %}
{% block content %}
<div class="container-xl">
<div class="page-header d-print-none">
<div class="row align-items-center">
<div class="col">
<h2 class="page-title">
{{ server.hostname }}
</h2>
<div class="text-muted mt-1">{{ server.ip_address }}</div>
</div>
<div class="col-auto ms-auto d-print-none">
<a href="{{ url_for('dashboard.server_list') }}" class="btn btn-link">
Back to Servers
</a>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h3 class="card-title">Documentation</h3>
</div>
<div class="card-body markdown-body">
{% if server.documentation %}
{{ markdown(server.documentation)|safe }}
{% else %}
<div class="text-center text-muted py-3">
No documentation available for this server.
</div>
{% endif %}
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h3 class="card-title">Applications</h3>
<a href="{{ url_for('dashboard.app_new') }}" class="btn btn-sm btn-primary">
Add Application
</a>
</div>
</div>
<div class="card-body">
{% if apps %}
<table class="table table-vcenter">
<thead>
<tr>
<th>Name</th>
<th>Ports</th>
</tr>
</thead>
<tbody>
{% for app in apps %}
<tr>
<td>{{ app.name }}</td>
<td>
{% for port in app.ports %}
<span class="badge bg-primary">
{{ port.port }}/{{ port.type }} {% if port.desc %}({{ port.desc }}){% endif %}
</span>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="text-center py-3">
<div class="mb-3">No applications registered for this server</div>
<a href="{{ url_for('dashboard.app_new') }}" class="btn btn-outline-primary">
Add Application
</a>
</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h3 class="card-title">Server Information</h3>
</div>
<div class="card-body">
<div class="mb-2">
<strong>Hostname:</strong> {{ server.hostname }}
</div>
<div class="mb-2">
<strong>IP Address:</strong> {{ server.ip_address }}
</div>
<div class="mb-2">
<strong>Subnet:</strong> {{ server.subnet.cidr if server.subnet else 'N/A' }}
</div>
<div class="mb-2">
<strong>Location:</strong> {{ server.subnet.location if server.subnet else 'N/A' }}
</div>
<div class="mb-2">
<strong>Created:</strong> {{ server.created_at.strftime('%Y-%m-%d') }}
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h3 class="card-title">Open Ports</h3>
</div>
<div class="card-body">
{% if server.get_open_ports() %}
<div class="list-group list-group-flush">
{% for port in server.get_open_ports() %}
<div class="list-group-item">
<div class="row align-items-center">
<div class="col-auto">
<span class="badge bg-primary">{{ port.port }}</span>
</div>
<div class="col">
<div class="text-truncate">
{{ port.type|upper }}
{% if port.desc %}
<span class="text-muted">{{ port.desc }}</span>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="text-center text-muted py-3">
No open ports detected.
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}