mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-09-28 04:34:53 +02:00
440 lines
21 KiB
HTML
440 lines
21 KiB
HTML
{% extends 'base/base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}
|
|
Scan history
|
|
{% endblock title %}
|
|
|
|
{% block custom_js_css_link %}
|
|
<link rel="stylesheet" type="text/css" href="{% static 'plugins/table/datatable/datatables.css' %}">
|
|
<link rel="stylesheet" type="text/css" href="{% static 'assets/css/forms/theme-checkbox-radio.css' %}">
|
|
<link rel="stylesheet" type="text/css" href="{% static 'plugins/table/datatable/dt-global_style.css' %}">
|
|
<link rel="stylesheet" type="text/css" href="{% static 'plugins/table/datatable/custom_dt_custom.css' %}">
|
|
<script src="{% static 'plugins/sweetalerts/promise-polyfill.js' %}"></script>
|
|
<link href="{% static 'plugins/sweetalerts/sweetalert2.min.css' %}" rel="stylesheet" type="text/css" />
|
|
<link href="{% static 'plugins/sweetalerts/sweetalert.css' %}" rel="stylesheet" type="text/css" />
|
|
<link href="{% static 'assets/css/components/custom-sweetalert.css' %}" rel="stylesheet" type="text/css" />
|
|
<link href="{% static 'assets/css/components/custom-modal.css' %}" rel="stylesheet" type="text/css" />
|
|
<link href="{% static 'assets/css/custom.css' %}" rel="stylesheet" type="text/css" />
|
|
{% endblock custom_js_css_link %}
|
|
|
|
{% block breadcrumb_title %}
|
|
<li class="breadcrumb-item active" aria-current="page">Scan History</li>
|
|
{% endblock breadcrumb_title %}
|
|
|
|
{% block main_content %}
|
|
<div class="statbox widget box box-shadow">
|
|
<div class="widget-header">
|
|
<div class="row">
|
|
<div class="col-xl-12 col-md-12 col-sm-12 col-12">
|
|
<h4>Scan History</h4>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="widget-content widget-content-area">
|
|
<div class="mt-2 ml-2 mb-4">
|
|
<a class="btn btn-primary dropdown-toggle" href="#" role="button" id="filterMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-filter"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon></svg>
|
|
Filter
|
|
</a>
|
|
<div class="dropdown-menu dropdown-menu-left mt-2" aria-labelledby="filterMenu" style="will-change: transform; width: 35%">
|
|
<div class="p-2">
|
|
<h5 class="mb-2">Filters</h5>
|
|
<div class="mt-2">
|
|
<span class="text-dark">Filter by Organization</span>
|
|
<select class="form-control" id="filterByOrganization">
|
|
</select>
|
|
</div>
|
|
<div class="mt-2">
|
|
<span class="text-dark">Filter by Targets</span>
|
|
<select class="form-control" id="filterByTarget">
|
|
</select>
|
|
</div>
|
|
<div class="mt-2">
|
|
<span class="text-dark mt-1">Filter by Scan Type</span>
|
|
<select class="form-control" id="filterByScanType">
|
|
</select>
|
|
</div>
|
|
<div class="mt-2">
|
|
<span class="text-dark">Filter by Scan Status</span>
|
|
<select class="form-control" id="filterByScanStatus">
|
|
</select>
|
|
</div>
|
|
<a href="#" class="text-info float-right mt-3" id="resetFilters">Reset Filters</a>
|
|
</div>
|
|
</div>
|
|
<a class="btn btn-outline-danger mb-2 float-right disabled" href="#" onclick="deleteMultipleScan()" id="delete_multiple_button">Delete Scans</a>
|
|
<div class="mt-3">
|
|
<div id="filteringText">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<form method="POST" id="scan_history_form">
|
|
{% csrf_token %}
|
|
<div class="table-responsive mb-4">
|
|
<table id="scan_history_table" class="table style-2 table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th class="text-center">Serial</th>
|
|
<th class="">Domain Name</th>
|
|
<th class="text-center">Scan Summary</th>
|
|
<th class="text-center">Scan Type</th>
|
|
<th class="text-center">Scanned On</th>
|
|
<th class="text-center">Status</th>
|
|
<th class="">Progress</th>
|
|
<th class="text-center">Result</th>
|
|
<th class="text-center">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for scan_history in scan_history.all %}
|
|
<tr>
|
|
<td class="checkbox-column"> {{ scan_history.id }} </td>
|
|
<td class="">
|
|
{{ scan_history.domain.name }}
|
|
{% if scan_history.domain.get_organization %}
|
|
<br>
|
|
{% for organization in scan_history.domain.get_organization %}
|
|
<span class="badge outline-badge-dark m-1 bs-tooltip" title="Domain {{domain.name}} belongs to organization {{organization.name}}">{{ organization.name }}</span>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</td>
|
|
<td class="text-center">
|
|
<span class="badge badge-pills badge-info bs-tooltip" title="Subdomains">{{scan_history.get_subdomain_count}}</span>
|
|
<span class="badge badge-pills badge-warning bs-tooltip" title="Endpoints">{{scan_history.get_endpoint_count}}</span>
|
|
<span class="badge badge-pills badge-danger bs-tooltip" title="{{scan_history.get_critical_vulnerability_count}} Critical, {{scan_history.get_high_vulnerability_count}} High, {{scan_history.get_medium_vulnerability_count}} Medium Vulnerabilities">{{scan_history.get_vulnerability_count}}</span>
|
|
</td>
|
|
<td class="text-center">{{ scan_history.scan_type }}</td>
|
|
<td class="text-center">{{ scan_history.start_scan_date }}</td>
|
|
<td class="text-center">
|
|
{% if scan_history.scan_status == -1 %}
|
|
<span class="text-warning bs-tooltip" data-placement="top" title="Waiting for other scans to complete">{% include 'base/_items/progress_spin.html' %}Pending</span>
|
|
{% elif scan_history.scan_status == 0 %}
|
|
<span class="text-danger">Failed</span>
|
|
{% elif scan_history.scan_status == 1 %}
|
|
<span class="text-info">{% include 'base/_items/progress_spin.html' %}In Progress</span>
|
|
{% elif scan_history.scan_status == 2 %}
|
|
<span class="text-success">Successful</span>
|
|
{% elif scan_history.scan_status == 3 %}
|
|
<span class="text-danger">Aborted</span>
|
|
{% else %}
|
|
<span class="text-danger">Unknown</span>
|
|
{% endif %}
|
|
</td>
|
|
<td class="text-center">
|
|
{% if scan_history.scan_status == -1 %}
|
|
<div class="progress">
|
|
<div class="progress-bar bg-warning progress-bar-striped" role="progressbar" style="width: 10%" aria-valuemin="0" aria-valuemax="100">
|
|
</div>
|
|
</div>
|
|
{% elif scan_history.scan_status == 0 %}
|
|
<div class="progress">
|
|
<div class="progress-bar bg-danger progress-bar-striped progress-bar-animated" role="progressbar" style="width: {% widthratio scan_history.scanactivity_set.all|length scan_history.scan_type.get_number_of_steps|add:4 100 %}%" aria-valuemin="0" aria-valuemax="4">
|
|
</div>
|
|
</div>
|
|
{% elif scan_history.scan_status == 1 %}
|
|
<div class="progress">
|
|
<div class="progress-bar bg-info progress-bar-striped progress-bar-animated" role="progressbar" style="width: {% widthratio scan_history.scanactivity_set.all|length scan_history.scan_type.get_number_of_steps|add:4 100 %}%" aria-valuemin="0" aria-valuemax="4">
|
|
</div>
|
|
</div>
|
|
{% elif scan_history.scan_status == 2 %}
|
|
<div class="progress bs-tooltip" data-placement="top" title="Scan Completed">
|
|
<div class="progress-bar bg-success progress-bar-striped" role="progressbar" style="width: 100%" aria-valuemin="0" aria-valuemax="100">
|
|
</div>
|
|
</div>
|
|
{% elif scan_history.scan_status == 3 %}
|
|
<div class="progress">
|
|
<div class="progress-bar bg-danger progress-bar-striped" role="progressbar" style="width: {% widthratio scan_history.scanactivity_set.all|length scan_history.scan_type.get_number_of_steps|add:4 100 %}%" aria-valuemin="0" aria-valuemax="4">
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<div class="progress">
|
|
<div class="progress-bar bg-danger progress-bar-striped" role="progressbar" style="width: 100%" aria-valuemin="0" aria-valuemax="100">
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</td>
|
|
<td class="text-center">
|
|
<a href="{% url 'detail_scan' scan_history.id %}" class="btn btn-outline-primary">View</a>
|
|
</td>
|
|
<td class="text-center">
|
|
{% if scan_history.scan_status == 1 or scan_history.scan_status == -1 %}
|
|
|
|
{% else %}
|
|
<a href="{% url 'start_scan' scan_history.domain.id %}" class="bs-tooltip m-1" data-toggle="tooltip" data-placement="top" title="" data-original-title="Rescan {{ scan_history.domain.name }}">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-refresh-ccw"><polyline points="1 4 1 10 7 10"></polyline><polyline points="23 20 23 14 17 14"></polyline><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"></path></svg>
|
|
</a>
|
|
{% endif %}
|
|
{% if scan_history.scan_status == 1 or scan_history.scan_status == -1%}
|
|
<a onclick="stop_scan('{{ scan_history.celery_id }}')" href="#" class="bs-tooltip m-1" data-toggle="tooltip" data-placement="top" title="" data-original-title="Stop Scan">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather table-delete feather-alert-octagon"><polygon points="7.86 2 16.14 2 22 7.86 22 16.14 16.14 22 7.86 22 2 16.14 2 7.86 7.86 2"></polygon><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
|
|
</a>
|
|
{% endif %}
|
|
{% if scan_history.scan_status == 1 or scan_history.scan_status == -1 %}
|
|
|
|
{% else %}
|
|
<a onclick="delete_scan({{ scan_history.id }})" href="#" class="bs-tooltip m-1" data-toggle="tooltip" data-placement="top" title="" data-original-title="Delete Scan {{ scan_history.domain.name }}">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather table-delete feather-x-circle">
|
|
<circle cx="12" cy="12" r="10"></circle>
|
|
<line x1="15" y1="9" x2="9" y2="15"></line>
|
|
<line x1="9" y1="9" x2="15" y2="15"></line>
|
|
</svg>
|
|
</a>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
{% endblock main_content %}
|
|
|
|
|
|
{% block page_level_script %}
|
|
<script src="{% static 'custom/custom.js' %}"></script>
|
|
<script src="{% static 'startScan/js/custom_start_scan.js' %}"></script>
|
|
<script src="{% static 'plugins/table/datatable/datatables.js' %}"></script>
|
|
<script src="{% static 'plugins/sweetalerts/sweetalert2.min.js' %}"></script>
|
|
<script src="{% static 'plugins/sweetalerts/custom-sweetalert.js' %}"></script>
|
|
<script>
|
|
$(document).ready(function(){
|
|
var table = $('#scan_history_table').DataTable({
|
|
headerCallback:function(e, a, t, n, s) {
|
|
e.getElementsByTagName("th")[0].innerHTML='<label class="new-control new-checkbox checkbox-outline-info m-auto">\n<input type="checkbox" class="new-control-input chk-parent" id="head_checkbox" onclick=mainCheckBoxSelected()>\n<span class="new-control-indicator"></span><span style="visibility:hidden">c</span>\n</label>';
|
|
},
|
|
columnDefs:[ {
|
|
targets:0, width:"30px", className:"", orderable:!1, render:function(e, a, t, n) {
|
|
return'<label class="new-control new-checkbox checkbox-outline-info m-auto">\n<input type="checkbox" name="history['+ e + ']" class="new-control-input child-chk targets_checkbox" value="' + e + '" onchange=toggleMultipleTargetButton()>\n<span class="new-control-indicator"></span><span style="visibility:hidden">c</span>\n</label>';
|
|
}
|
|
}],
|
|
"oLanguage": {
|
|
"oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
|
|
"sInfo": "Showing page _PAGE_ of _PAGES_",
|
|
"sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
|
|
"sSearchPlaceholder": "Search...",
|
|
"sLengthMenu": "Results : _MENU_",
|
|
},
|
|
"lengthMenu": [10, 20, 50, 100, 500, 1000],
|
|
"pageLength": 10,
|
|
"dom": "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'f>>>" +
|
|
"<'table-responsive'tr>" +
|
|
"<'dt--bottom-section d-sm-flex justify-content-sm-between text-center'<'dt--pages-count mb-sm-0 mb-3'i><'dt--pagination'p>>",
|
|
"initComplete": function(settings, json) {
|
|
table = settings.oInstance.api();
|
|
var rows = table.rows({selected:true}).indexes();
|
|
|
|
// populate filter menu from datatables
|
|
// populate targets
|
|
var selectedData = table.cells(rows, 1).data();
|
|
var target_array = [];
|
|
for (var i = 0; i < selectedData.length; i++) {
|
|
col1_data = selectedData[i];
|
|
domain_name = col1_data.match(/([^\n]+)/g)[0];
|
|
target_array.push(domain_name);
|
|
}
|
|
target_array = Array.from(new Set(target_array));
|
|
for (target in target_array) {
|
|
select = document.getElementById('filterByTarget');
|
|
var option = document.createElement('option');
|
|
option.value = target_array[target];
|
|
option.innerHTML = target_array[target];
|
|
select.appendChild(option);
|
|
}
|
|
|
|
// populate Scan Type
|
|
var selectedData = table.cells(rows, 3).data();
|
|
var scan_type_array = [];
|
|
for (var i = 0; i < selectedData.length; i++) {
|
|
col1_data = selectedData[i];
|
|
scan_type_array.push(col1_data);
|
|
}
|
|
|
|
scan_type_array = Array.from(new Set(scan_type_array));
|
|
for (engine in scan_type_array) {
|
|
select = document.getElementById('filterByScanType');
|
|
var option = document.createElement('option');
|
|
option.value = scan_type_array[engine];
|
|
option.innerHTML = scan_type_array[engine];
|
|
select.appendChild(option);
|
|
}
|
|
}
|
|
});
|
|
multiCheck(table);
|
|
|
|
// filter organization populate
|
|
$.getJSON(`/api/listOrganizations?&format=json`, function(data) {
|
|
data = data['organizations']
|
|
for (organization in data) {
|
|
name = data[organization]['name'];
|
|
select = document.getElementById('filterByOrganization');
|
|
var option = document.createElement('option');
|
|
option.value = name;
|
|
option.innerHTML = name;
|
|
select.appendChild(option);
|
|
}
|
|
}).fail(function(){
|
|
});
|
|
|
|
// filtering for scan status
|
|
var status_types = ['Pending', 'Scanning', 'Aborted', 'Successful', 'Failed'];
|
|
for (status in status_types) {
|
|
select = document.getElementById('filterByScanStatus');
|
|
var option = document.createElement('option');
|
|
option.value = status_types[status];
|
|
option.innerHTML = status_types[status];
|
|
select.appendChild(option);
|
|
}
|
|
|
|
var org_filter = document.getElementById('filterByOrganization');
|
|
org_filter.addEventListener('change', function() {
|
|
table.search(this.value).draw();
|
|
document.getElementById('filteringText').innerHTML = `<span class="badge badge-primary">Organization: ${this.value}
|
|
<span id="clearFilterChip" class="badge-link" onclick="document.getElementById('resetFilters').click()">X</span>
|
|
</span>`;
|
|
$('.bs-tooltip').tooltip();
|
|
Snackbar.show({
|
|
text: `Filtering by organization ${this.value}`,
|
|
pos: 'top-center'
|
|
});
|
|
}, false);
|
|
|
|
var status_filter = document.getElementById('filterByScanStatus');
|
|
status_filter.addEventListener('change', function() {
|
|
table.search(this.value).draw();
|
|
switch (this.value) {
|
|
case 'Pending':
|
|
badge_color = 'warning';
|
|
break;
|
|
case 'Scanning':
|
|
badge_color = 'info';
|
|
break;
|
|
case 'Aborted':
|
|
badge_color = 'danger';
|
|
break;
|
|
case 'Failed':
|
|
badge_color = 'danger';
|
|
break;
|
|
case 'Successful':
|
|
badge_color = 'success';
|
|
break;
|
|
default:
|
|
badge_color = 'primary'
|
|
}
|
|
document.getElementById('filteringText').innerHTML = `<span class="badge badge-${badge_color}">Scan Status: ${this.value}
|
|
<span id="clearFilterChip" class="badge-link" onclick="document.getElementById('resetFilters').click()">X</span>
|
|
</span>`;
|
|
Snackbar.show({
|
|
text: `Filtering by scan status ${this.value}`,
|
|
pos: 'top-center'
|
|
});
|
|
}, false);
|
|
|
|
var engine_filter = document.getElementById('filterByScanType');
|
|
engine_filter.addEventListener('change', function() {
|
|
table.search(this.value).draw();
|
|
document.getElementById('filteringText').innerHTML = `<span class="badge badge-primary">Scan Engine: ${this.value}
|
|
<span id="clearFilterChip" class="badge-link" onclick="document.getElementById('resetFilters').click()">X</span>
|
|
</span>`;
|
|
Snackbar.show({
|
|
text: `Filtering by Engine ${this.value}`,
|
|
pos: 'top-center'
|
|
});
|
|
}, false);
|
|
|
|
var target_filter = document.getElementById('filterByTarget');
|
|
target_filter.addEventListener('change', function() {
|
|
table.search(this.value).draw();
|
|
document.getElementById('filteringText').innerHTML = `<span class="badge badge-primary">Target/Domain: ${this.value}
|
|
<span id="clearFilterChip" class="badge-link" onclick="document.getElementById('resetFilters').click()">X</span>
|
|
</span>`;
|
|
Snackbar.show({
|
|
text: `Filtering by Engine ${this.value}`,
|
|
pos: 'top-center'
|
|
});
|
|
}, false);
|
|
|
|
// reset filtering
|
|
var reset_filter = document.getElementById('resetFilters');
|
|
reset_filter.addEventListener('click', function() {
|
|
resetFilters(table);
|
|
}, false);
|
|
|
|
});
|
|
|
|
function resetFilters(table_obj) {
|
|
table_obj.search("").draw();
|
|
Snackbar.show({
|
|
text: `Filters Reset`,
|
|
pos: 'top-center'
|
|
});
|
|
document.getElementById('filteringText').innerHTML = '';
|
|
}
|
|
|
|
function checkedCount () {
|
|
// this function will count the number of boxes checked
|
|
item = document.getElementsByClassName("targets_checkbox");
|
|
count = 0;
|
|
for (var i = 0; i < item.length; i++) {
|
|
if (item[i].checked) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
function toggleMultipleTargetButton() {
|
|
if (checkedCount() > 0) {
|
|
$("#delete_multiple_button").removeClass("disabled");
|
|
}
|
|
else
|
|
{
|
|
$("#delete_multiple_button").addClass("disabled");
|
|
}
|
|
}
|
|
|
|
function mainCheckBoxSelected() {
|
|
var input = document.querySelector('#head_checkbox');
|
|
if (input.checked) {
|
|
$("#delete_multiple_button").removeClass("disabled");
|
|
}
|
|
else
|
|
{
|
|
$("#delete_multiple_button").addClass("disabled");
|
|
}
|
|
}
|
|
|
|
function deleteMultipleScan() {
|
|
if (!checkedCount()) {
|
|
swal({
|
|
title: '',
|
|
text: "Oops! No targets has been selected!",
|
|
type: 'error',
|
|
padding: '2em'
|
|
})
|
|
}
|
|
else {
|
|
// atleast one target is selected
|
|
swal.queue([{
|
|
title: 'Are you sure you want to delete '+ checkedCount() +' Scans?',
|
|
text: "This action is irreversible.\nThis will delete all the scan data and vulnerabilities related to the scan.",
|
|
type: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonText: 'Delete',
|
|
padding: '2em',
|
|
showLoaderOnConfirm: true,
|
|
preConfirm: function() {
|
|
deleteForm = document.getElementById("scan_history_form");
|
|
deleteForm.action = "../delete/multiple";
|
|
deleteForm.submit();
|
|
}
|
|
}])
|
|
}
|
|
}
|
|
|
|
</script>
|
|
{% endblock page_level_script %}
|