This commit is contained in:
ilyastar9999
2025-12-02 14:01:34 +03:00
parent 96e1e5a7e0
commit cffbd77b74
31 changed files with 3335 additions and 0 deletions

107
web/templates/alerts.html Normal file
View File

@@ -0,0 +1,107 @@
{% extends "base.html" %}
{% block title %}Alerts - A/D Infrastructure Control{% endblock %}
{% block content %}
<div class="row mb-4">
<div class="col-12">
<h1>Security Alerts <i class="bi bi-arrow-clockwise refresh-btn" id="refreshAlerts"></i></h1>
</div>
</div>
<div class="row mb-3">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<h5>Send Test Alert</h5>
<div class="input-group">
<input type="text" class="form-control" id="testMessage" placeholder="Enter test message">
<button class="btn btn-primary" onclick="sendTestAlert()">
<i class="bi bi-send"></i> Send to Telegram
</button>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5>Alert History</h5>
</div>
<div class="card-body">
<div class="list-group" id="alertsList">
<div class="text-center py-3">Loading...</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
function loadAlerts() {
$.get('/api/alerts?limit=100', function (data) {
if (data && data.length > 0) {
let html = '';
data.forEach(alert => {
let badgeClass = alert.severity === 'critical' ? 'danger' : 'warning';
let notifiedBadge = alert.notified
? '<span class="badge bg-success">Notified</span>'
: '<span class="badge bg-secondary">Pending</span>';
html += `
<div class="list-group-item">
<div class="d-flex justify-content-between align-items-start">
<div class="flex-grow-1">
<div class="mb-2">
<span class="badge bg-${badgeClass}">${alert.severity.toUpperCase()}</span>
${notifiedBadge}
<span class="badge bg-info">${alert.alert_type}</span>
<small class="text-muted ms-2">${new Date(alert.created_at).toLocaleString()}</small>
</div>
<p class="mb-0">${alert.message}</p>
</div>
</div>
</div>
`;
});
$('#alertsList').html(html);
} else {
$('#alertsList').html('<div class="text-center py-3 text-muted">No alerts</div>');
}
});
}
function sendTestAlert() {
const message = $('#testMessage').val();
if (!message) {
alert('Please enter a message');
return;
}
$.ajax({
url: '/api/telegram/send',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({ message: message }),
success: function (data) {
alert('Message sent to Telegram!');
$('#testMessage').val('');
},
error: function (xhr) {
alert(`Failed to send message: ${xhr.responseJSON?.detail || 'Unknown error'}`);
}
});
}
$(document).ready(function () {
loadAlerts();
$('#refreshAlerts').click(loadAlerts);
setInterval(loadAlerts, 10000); // Auto-refresh every 10 seconds
});
</script>
{% endblock %}

169
web/templates/attacks.html Normal file
View File

@@ -0,0 +1,169 @@
{% extends "base.html" %}
{% block title %}Attacks - A/D Infrastructure Control{% endblock %}
{% block content %}
<div class="row mb-4">
<div class="col-12">
<h1>Attacks Monitor <i class="bi bi-arrow-clockwise refresh-btn" id="refreshAttacks"></i></h1>
</div>
</div>
<div class="row mb-3">
<div class="col-12">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-primary active" id="filterAll">All Attacks</button>
<button type="button" class="btn btn-outline-success" id="filterOur">Our Attacks</button>
<button type="button" class="btn btn-outline-danger" id="filterAgainstUs">Attacks to Us</button>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5>Attacks by Service</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Service</th>
<th>Total</th>
<th>Our Attacks</th>
<th>Against Us</th>
<th>Points Gained</th>
<th>Points Lost</th>
</tr>
</thead>
<tbody id="serviceStatsTable">
<tr>
<td colspan="6" class="text-center">Loading...</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5>Recent Attacks</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover table-sm">
<thead>
<tr>
<th>Time</th>
<th>Attacker</th>
<th>Victim</th>
<th>Service</th>
<th>Points</th>
<th>Type</th>
</tr>
</thead>
<tbody id="attacksTable">
<tr>
<td colspan="6" class="text-center">Loading...</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
let currentFilter = 'all';
function loadServiceStats() {
$.get('/api/attacks/by-service', function (data) {
if (data && data.length > 0) {
let html = '';
data.forEach(stat => {
html += `
<tr>
<td><strong>${stat.service_name}</strong></td>
<td>${stat.total_attacks}</td>
<td><span class="text-success">${stat.our_attacks}</span></td>
<td><span class="text-danger">${stat.attacks_to_us}</span></td>
<td><span class="text-success">+${stat.points_gained.toFixed(2)}</span></td>
<td><span class="text-danger">-${stat.points_lost.toFixed(2)}</span></td>
</tr>
`;
});
$('#serviceStatsTable').html(html);
}
});
}
function loadAttacks() {
let url = '/api/attacks?limit=100';
if (currentFilter === 'our') {
url += '&our_attacks=true';
} else if (currentFilter === 'against') {
url += '&attacks_to_us=true';
}
$.get(url, function (data) {
if (data && data.length > 0) {
let html = '';
data.forEach(attack => {
let typeLabel = '';
if (attack.is_our_attack) {
typeLabel = '<span class="badge bg-success">Our Attack</span>';
} else if (attack.is_attack_to_us) {
typeLabel = '<span class="badge bg-danger">Against Us</span>';
}
html += `
<tr>
<td>${new Date(attack.timestamp).toLocaleString()}</td>
<td>Team ${attack.attacker_team_id}</td>
<td>Team ${attack.victim_team_id}</td>
<td>${attack.service_name}</td>
<td>${attack.points ? attack.points.toFixed(2) : '-'}</td>
<td>${typeLabel}</td>
</tr>
`;
});
$('#attacksTable').html(html);
} else {
$('#attacksTable').html('<tr><td colspan="6" class="text-center text-muted">No attacks</td></tr>');
}
});
}
function setFilter(filter) {
currentFilter = filter;
$('.btn-group button').removeClass('active');
$(`#filter${filter.charAt(0).toUpperCase() + filter.slice(1)}`).addClass('active');
loadAttacks();
}
$(document).ready(function () {
loadServiceStats();
loadAttacks();
$('#refreshAttacks').click(function () {
loadServiceStats();
loadAttacks();
});
$('#filterAll').click(() => setFilter('all'));
$('#filterOur').click(() => setFilter('our'));
$('#filterAgainstUs').click(() => setFilter('against'));
setInterval(loadAttacks, 5000); // Auto-refresh every 5 seconds
});
</script>
{% endblock %}

92
web/templates/base.html Normal file
View File

@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}A/D Infrastructure Control{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<style>
body {
padding-top: 60px;
}
.navbar-brand {
font-weight: bold;
}
.stat-card {
border-left: 4px solid #007bff;
}
.stat-card.danger {
border-left-color: #dc3545;
}
.stat-card.success {
border-left-color: #28a745;
}
.stat-card.warning {
border-left-color: #ffc107;
}
.service-running {
color: #28a745;
}
.service-stopped {
color: #dc3545;
}
.refresh-btn {
cursor: pointer;
}
</style>
{% block extra_css %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<i class="bi bi-shield-check"></i> A/D Control
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/"><i class="bi bi-speedometer2"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/services"><i class="bi bi-hdd-stack"></i> Services</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/attacks"><i class="bi bi-bullseye"></i> Attacks</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/alerts"><i class="bi bi-exclamation-triangle"></i> Alerts</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="/logout"><i class="bi bi-box-arrow-right"></i> Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
{% block content %}{% endblock %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
{% block extra_js %}{% endblock %}
</body>
</html>

137
web/templates/index.html Normal file
View File

@@ -0,0 +1,137 @@
{% extends "base.html" %}
{% block title %}Dashboard - A/D Infrastructure Control{% endblock %}
{% block content %}
<div class="row mb-4">
<div class="col-12">
<h1>Dashboard <i class="bi bi-arrow-clockwise refresh-btn" id="refreshDashboard"></i></h1>
</div>
</div>
<div class="row mb-4">
<div class="col-md-3">
<div class="card stat-card">
<div class="card-body">
<h6 class="text-muted">Total Services</h6>
<h2 id="totalServices">-</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card success">
<div class="card-body">
<h6 class="text-muted">Our Attacks</h6>
<h2 id="ourAttacks">-</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card danger">
<div class="card-body">
<h6 class="text-muted">Attacks to Us</h6>
<h2 id="attacksToUs">-</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card warning">
<div class="card-body">
<h6 class="text-muted">Critical Alerts</h6>
<h2 id="criticalAlerts">-</h2>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
<h5>Services Status</h5>
</div>
<div class="card-body">
<div id="servicesStatus" class="list-group">
<div class="text-center py-3">Loading...</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
<h5>Recent Alerts</h5>
</div>
<div class="card-body">
<div id="recentAlerts" class="list-group">
<div class="text-center py-3">Loading...</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
function loadDashboard() {
$.get('/api/dashboard', function (data) {
// Update stats
$('#totalServices').text(data.services ? data.services.length : 0);
$('#ourAttacks').text(data.scoreboard?.attacks_by_us || 0);
$('#attacksToUs').text(data.scoreboard?.attacks_to_us || 0);
$('#criticalAlerts').text(data.scoreboard?.critical_alerts_5min || 0);
// Update services status
if (data.services && data.services.length > 0) {
let html = '';
data.services.forEach(service => {
let statusClass = service.status === 'running' ? 'service-running' : 'service-stopped';
let icon = service.status === 'running' ? 'check-circle-fill' : 'x-circle-fill';
html += `
<div class="list-group-item">
<div class="d-flex justify-content-between align-items-center">
<span>${service.name}</span>
<span class="${statusClass}">
<i class="bi bi-${icon}"></i> ${service.status}
</span>
</div>
</div>
`;
});
$('#servicesStatus').html(html);
}
});
// Load recent alerts
$.get('/api/alerts?limit=5', function (data) {
if (data && data.length > 0) {
let html = '';
data.forEach(alert => {
let badgeClass = alert.severity === 'critical' ? 'danger' : 'warning';
html += `
<div class="list-group-item">
<div class="d-flex justify-content-between align-items-start">
<div>
<span class="badge bg-${badgeClass}">${alert.severity}</span>
<small class="text-muted ms-2">${new Date(alert.created_at).toLocaleString()}</small>
<p class="mb-0 mt-1">${alert.message}</p>
</div>
</div>
</div>
`;
});
$('#recentAlerts').html(html);
} else {
$('#recentAlerts').html('<div class="text-center py-3 text-muted">No alerts</div>');
}
});
}
$(document).ready(function () {
loadDashboard();
$('#refreshDashboard').click(loadDashboard);
setInterval(loadDashboard, 10000); // Auto-refresh every 10 seconds
});
</script>
{% endblock %}

47
web/templates/login.html Normal file
View File

@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - A/D Infrastructure Control</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.login-card {
max-width: 400px;
width: 100%;
}
</style>
</head>
<body>
<div class="login-card">
<div class="card shadow-lg">
<div class="card-body p-5">
<h2 class="text-center mb-4">
<i class="bi bi-shield-check"></i> A/D Control
</h2>
{% if error %}
<div class="alert alert-danger">{{ error }}</div>
{% endif %}
<form method="POST">
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required autofocus>
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
</div>
</div>
</div>
</body>
</html>

130
web/templates/services.html Normal file
View File

@@ -0,0 +1,130 @@
{% extends "base.html" %}
{% block title %}Services - A/D Infrastructure Control{% endblock %}
{% block content %}
<div class="row mb-4">
<div class="col-12">
<h1>Services <i class="bi bi-arrow-clockwise refresh-btn" id="refreshServices"></i></h1>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Path</th>
<th>Status</th>
<th>Last Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="servicesTable">
<tr>
<td colspan="5" class="text-center">Loading...</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Logs Modal -->
<div class="modal fade" id="logsModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Service Logs</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<pre id="logsContent"
style="max-height: 500px; overflow-y: auto; background: #f8f9fa; padding: 15px;"></pre>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
function loadServices() {
$.get('/api/services', function (data) {
if (data && data.length > 0) {
let html = '';
data.forEach(service => {
let statusBadge = service.status === 'running'
? '<span class="badge bg-success">Running</span>'
: '<span class="badge bg-secondary">Stopped</span>';
html += `
<tr>
<td><strong>${service.name}</strong></td>
<td><code>${service.path}</code></td>
<td>${statusBadge}</td>
<td>${new Date(service.last_updated).toLocaleString()}</td>
<td>
<div class="btn-group btn-group-sm">
<button class="btn btn-success" onclick="serviceAction(${service.id}, 'start')">
<i class="bi bi-play-fill"></i>
</button>
<button class="btn btn-warning" onclick="serviceAction(${service.id}, 'restart')">
<i class="bi bi-arrow-clockwise"></i>
</button>
<button class="btn btn-danger" onclick="serviceAction(${service.id}, 'stop')">
<i class="bi bi-stop-fill"></i>
</button>
<button class="btn btn-info" onclick="viewLogs(${service.id})">
<i class="bi bi-file-text"></i>
</button>
</div>
</td>
</tr>
`;
});
$('#servicesTable').html(html);
} else {
$('#servicesTable').html('<tr><td colspan="5" class="text-center text-muted">No services registered</td></tr>');
}
});
}
function serviceAction(serviceId, action) {
if (!confirm(`Are you sure you want to ${action} this service?`)) return;
$.ajax({
url: `/api/services/${serviceId}/action`,
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({ action: action }),
success: function (data) {
alert(`Service ${action} successful!`);
loadServices();
},
error: function (xhr) {
alert(`Failed to ${action} service: ${xhr.responseJSON?.detail || 'Unknown error'}`);
}
});
}
function viewLogs(serviceId) {
$.get(`/api/services/${serviceId}/logs?lines=200`, function (data) {
$('#logsContent').text(data.logs || 'No logs available');
new bootstrap.Modal(document.getElementById('logsModal')).show();
});
}
$(document).ready(function () {
loadServices();
$('#refreshServices').click(loadServices);
setInterval(loadServices, 15000); // Auto-refresh every 15 seconds
});
</script>
{% endblock %}