AIL-framework/var/www/templates/dashboard/dashboard.html

455 lines
17 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>AIL Framework</title>
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
<!-- Core CSS -->
<link href="{{ url_for('static', filename='css/bootstrap4.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
<!-- JS -->
<script src="{{ url_for('static', filename='js/jquery.js')}}"></script>
<script src="{{ url_for('static', filename='js/helper.js')}}"></script>
<script src="{{ url_for('static', filename='js/popper.min.js')}}"></script>
<script src="{{ url_for('static', filename='js/echarts.min.js')}}"></script>
<script src="{{ url_for('static', filename='js/bootstrap4.min.js')}}"></script>
<style>
.popover {
max-width: none;
width: 500px;
}
.icon-button {
position: relative;
display: inline-block;
border: none;
background: none;
{#padding: 0;#}
margin: 0;
cursor: pointer;
outline: inherit;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
.icon-wrapper {
position: relative;
display: inline-block;
}
.notification-badge {
position: absolute;
top: -10px;
right: -10px;
font-size: 14px;
background: forestgreen;
}
</style>
</head>
<body>
{% include 'nav_bar.html' %}
<div class="container-fluid">
<div class="row">
<div class="col-12 col-xl-6">
<div id="feeders_dashboard" style="width: 100%; height:600px;"></div>
<div class="card mt-1 mb-4">
<div class="card-header text-white bg-dark">
<div class="row">
<div class="col-1">
<i class="fas fa-user-secret fa-2x"></i>
</div>
<div class="col-5">
<div class="row">
<div class="col-6">
<div>
<a href="{{ url_for('crawler_splash.domains_search_today') }}?type=onion&up=True" class="badge badge-success" id="stat_crawler_onion_domain_up">{{ crawlers_stats['onion']['up'] }}</a> Up
</div>
<div>
<a href="{{ url_for('crawler_splash.domains_search_today') }}?type=onion&down=True" class="badge badge-danger" id="stat_crawler_onion_domain_down">{{ crawlers_stats['onion']['down'] }}</a> Down
</div>
</div>
<div class="col-6">
<div>
<a href="{{ url_for('crawler_splash.domains_search_today') }}?type=onion&up=True&down=True" class="badge badge-success" id="stat_crawler_onion_total">{{ crawlers_stats['onion']['crawled'] }}</a> Crawled
</div>
<div>
<span class="badge badge-warning" id="stat_crawler_onion_queue">{{ crawlers_stats['onion']['queue'] }}</span> Queue
</div>
</div>
</div>
</div>
<div class="col-1">
<i class="fab fa-html5 fa-2x"></i>
</div>
<div class="col-5">
<div class="row">
<div class="col-6">
<div>
<a href="{{ url_for('crawler_splash.domains_search_today') }}?type=web&up=True" class="badge badge-success" id="stat_crawler_regular_domain_up">{{ crawlers_stats['web']['up'] }}</a> UP
</div>
<div>
<a href="{{ url_for('crawler_splash.domains_search_today') }}?type=web&down=True" class="badge badge-danger" id="stat_crawler_regular_domain_down">{{ crawlers_stats['web']['down'] }}</a> DOWN
</div>
</div>
<div class="col-6">
<div>
<a href="{{ url_for('crawler_splash.domains_search_today') }}?type=web&up=True&down=True" class="badge badge-success" id="stat_crawler_regular_total">{{ crawlers_stats['web']['crawled'] }}</a> Crawled
</div>
<div>
<span class="badge badge-warning" id="stat_crawler_regular_queue">{{ crawlers_stats['web']['queue'] }}</span> Queue
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 col-xl-6">
<h3 class="text-center mt-1 mb-4" id="current_date"></h3>
<div class="row">
{% for obj_type in nb_objects %}
<div class="col-sm-6 col-md-4 col-lg-3 text-center mb-4">
{% with type=obj_type, name=nb_objects[obj_type]['name'], icon=nb_objects[obj_type]['icon']['icon'], nb=nb_objects[obj_type]['nb'], url=nb_objects[obj_type]['link'] %}
{% include 'objects/block_obj_button.html' %}
{% endwith %}
</div>
{% endfor %}
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-xl-6">
<table class="table">
<thead>
<tr>
<th><i class="fa-solid fa-crosshairs"></i></th>
<th>tracker</th>
<th class="text-center"><i class="fas fa-cube"></i></th>
<th>Time</th>
</tr>
</thead>
<tbody id="tracked_objs">
{% for tracker in trackers %}
<tr>
<td>{{ tracker['type'] }}</td>
<td style="word-break: break-all;">
<a href="{{ url_for('hunters.show_tracker') }}?uuid={{ tracker['uuid'] }}">{% if tracker['description'] %}{{ tracker['description'] }}{% else %}{{ tracker['tracked'] }}{% endif %}</a>
</td>
<td class="text-center">
<a href="{{ tracker['obj']['link'] }}" onmouseenter="show_obj_tooltip(this, '{{ tracker['obj']['gid'] }}')" onmouseleave="hide_obj_tooltip(this)">
<svg height="26" width="26" style="pointer-events:none;">
<g class="nodes">
<circle cx="13" cy="13" r="13" fill="{{ tracker['obj']['icon']['color'] }}"></circle>
<text x="13" y="13" text-anchor="middle" dominant-baseline="central" class="{{ tracker['obj']['icon']['style'] }}" font-size="16px">{{ tracker['obj']['icon']['icon'] }}</text>
</g>
</svg>
</a>
</td>
<td>{{ tracker['timestamp'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col-12 col-xl-6">
<table class="table">
<thead>
<tr>
<th class="text-center"><i class="fas fa-cube"></i></th>
<th>ID</th>
<th><i class="fas fa-tag"></i> Tags</th>
<th>Time</th>
</tr>
</thead>
<tbody id="t_tags_objs">
{% for t_obj in tagged_objs %}
<tr>
<td>
<a href="{{ t_obj['link'] }}" onmouseenter="show_obj_tooltip(this, '{{ t_obj['gid'] }}')" onmouseleave="hide_obj_tooltip(this)">
<svg height="26" width="26">
<g class="nodes">
<circle cx="13" cy="13" r="13" fill="{{ t_obj['icon']['color'] }}"></circle>
<text x="13" y="13" text-anchor="middle" dominant-baseline="central" class="{{ t_obj['icon']['style'] }}" font-size="16px">{{ t_obj['icon']['icon'] }}</text>
</g>
</svg>
</a>
</td>
<td style="word-break: break-all;">
<a href="{{ t_obj['link'] }}">{{ t_obj['id'] }}</a>
</td>
<td>
{% for tag in t_obj['tags'] %}
<span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }}</span>
{% endfor %}
</td>
<td>{{ t_obj['date_tag'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
var chart = {};
$(document).ready(function(){
$("#page-Dashboard").addClass("active");
$("#nav_dashboard_{{obj_type}}").addClass("active");
updateDate();
});
var btn_selector = {
{% for obj_type in nb_objects %}
'{{ obj_type }}': $("#obj_btn_{{ obj_type }}"),
{% endfor %}
}
</script>
<script>
var tags_colors = ['primary', 'success', 'danger', 'warning', 'info'];
var url_obj_description = "{{ url_for('correlation.get_description') }}?object_id=";
// Init Dashboard
var feederChart = echarts.init(document.getElementById('feeders_dashboard'));
window.addEventListener('resize', function() {
feederChart.resize();
});
var optionFeeder;
var maxDataLength = 21;
var feeders_names = [{% for feeder in feeders_dashboard['data'] %}'{{ feeder }}', {% endfor %}]
var feeders_xaxis = [{% for date in feeders_dashboard['dates'] %}'{{ date }}', {% endfor %}]
var feeders_data = {
{% for feeder in feeders_dashboard['data'] %}
'{{ feeder }}': {{ feeders_dashboard['data'][feeder] }},
{% endfor %}
}
optionFeeder = {
title: {
text: 'Feeders'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: feeders_names
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: feeders_xaxis
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{% for feeder in feeders_dashboard['data'] %}
{
name: '{{ feeder }}',
type: 'line',
stack: 'Total',
areaStyle: {},
emphasis: {
focus: 'series'
},
data: feeders_data['{{ feeder }}']
},
{% endfor %}
]
};
optionFeeder && feederChart.setOption(optionFeeder);
{# TODO UPDATE NEW FEEDER NAME#}
function updateFeederChart(data) {
let new_date = data['date']
feeders_xaxis.push(new_date)
feeders_xaxis.shift()
for (const f_name in data['data']) {
if (f_name in feeders_data) {
feeders_data[f_name].push(data['data'][f_name])
feeders_data[f_name].shift()
} else {
let fdata = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, data['data'][f_name]]
feeders_names.push(f_name)
feeders_data[f_name] = fdata
// add new feeder
optionFeeder.legend.data.push(f_name)
optionFeeder.series.push({name: f_name, type: 'line', stack: 'Total', areaStyle: {}, emphasis: {focus: 'series'}, data: feeders_data[f_name]})
}
}
feederChart.setOption(optionFeeder)
}
function updateDate() {
let d = new Date();
let day = d.getUTCDate();
if (day < 10) {
day = "0" + day;
}
let current_date = d.getUTCFullYear() + ' - ' + (d.getUTCMonth() + 1) + ' - ' + day;
$('#current_date').text(current_date)
}
function updateNbObjects(data) {
for (const obj_type in data) {
btn_selector[obj_type].text(data[obj_type]);
}
}
function updateCrawlerStats(data) {
updateDate();
$("#stat_crawler_onion_domain_up").text(data['onion']['up']);
$("#stat_crawler_onion_domain_down").text(data['onion']['down']);
$("#stat_crawler_onion_total").text(data['onion']['crawled']);
$("#stat_crawler_onion_queue").text(data['onion']['queue']);
$("#stat_crawler_regular_domain_up").text(data['web']['up']);
$("#stat_crawler_regular_domain_down").text(data['web']['down']);
$("#stat_crawler_regular_total").text(data['web']['crawled']);
$("#stat_crawler_regular_queue").text(data['web']['queue']);
}
///////
function create_obj_svg(container, obj_gid, url, color, fa_style, icon) {
var svg_obj = '<svg height="26" width="26"> <g class="nodes"> <circle cx="13" cy="13" r="13" fill="' + color + '"></circle> <text x="13" y="13" text-anchor="middle" dominant-baseline="central" class="' + fa_style + '" font-size="16px">' + icon + '</text> </g> </svg>';
var obj_link = $('<a>');
obj_link.on('mouseenter', function () {
show_obj_tooltip(this, obj_gid);
});
obj_link.on('mouseleave', function () {
hide_obj_tooltip(this);
});
obj_link.attr('href', url);
obj_link.html(svg_obj);
container.append(obj_link);
return container
}
function create_tags_badges(container, tags) {
var tspan = '';
for (const i in tags) {
tspan = tspan + '<span class="badge badge-' + 'primary' + '">' + sanitize_text(tags[i]) + '</span>'
}
return tspan;
}
function update_tags_obj_dashboard(data) {
// delete table
var tbody = $("#t_tags_objs");
var ntd;
tbody.empty();
for (const elem in data) {
let obj = data[elem];
var row = $('<tr></tr>');
ntd = $('<td></td>');
row.append(create_obj_svg(ntd, obj['gid'], obj.link, obj['icon']['color'], obj['icon']['style'], obj['icon']['icon']))
row.append('<td style="word-break: break-all;"><a href="'+ obj['link'] + '">' + sanitize_text(obj['id']) + '</a></td>');
ntd = $('<td></td>');
row.append(create_tags_badges(ntd, obj['tags']));
row.append('<td>' + obj['date_tag'] + '</td>');
tbody.append(row);
{# {% for tag in t_obj['tags'] %}#}
{# <span class="badge badge-{{ bootstrap_label[loop.index0 % 5] }}">{{ tag }}</span>#}
{# {% endfor %}#}
{#</td>#}
}
}
function update_tracked_objs_dashboard(data) {
// delete table
var tbody = $("#tracked_objs");
var ntd;
tbody.empty();
for (const elem in data) {
let tracker = data[elem];
var row = $('<tr></tr>');
row.append('<td>' + tracker['type'] + '</td>');
let name;
if (tracker['description']) {
name = tracker['description'];
} else {
name = tracker['tracked'];
}
row.append('<td style="word-break: break-all;"><a href="{{ url_for('hunters.show_tracker') }}?uuid=' + tracker['uuid'] + '">' + sanitize_text(name) + '</a></td>');
ntd = $('<td class="text-center"></td>');
row.append(create_obj_svg(ntd, tracker['obj']['gid'], tracker['obj']['link'], tracker['obj']['icon']['color'], tracker['obj']['icon']['style'], tracker['obj']['icon']['icon']));
row.append('<td>' + tracker['timestamp'] + '</td>');
tbody.append(row);
}
}
// WebSocket
var socket = new WebSocket("wss://" + window.location.host + "/ws/dashboard");
socket.wsocket = function(event) {
console.log("WebSocket connection opened:", event);
};
socket.onmessage = function(event) {
$("[data-toggle='popover']").popover('destroy');
let data = JSON.parse(event.data);
updateFeederChart(data['feeders']);
updateNbObjects(data['objs']);
updateCrawlerStats(data['crawler']);
update_tracked_objs_dashboard(data['trackers']);
update_tags_obj_dashboard(data['tags']);
};
socket.onerror = function(error) {
console.error('WebSocket error:', error);
};
socket.onclose = function(event) {
console.log('WebSocket connection closed:', event);
};
</script>
</body>
</html>