first sync
Some checks failed
Deployment Verification / deploy-and-test (push) Failing after 29s

This commit is contained in:
2025-03-04 07:59:21 +01:00
parent 9cdcf486b6
commit 506716e703
1450 changed files with 577316 additions and 62 deletions

View File

@ -0,0 +1,99 @@
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
Table = $("#activities_table").DataTable({
dom: 'Blfrtip',
aaData: [],
bSort: false,
aoColumns: [
{ "data": "activity_date",
"render": $.fn.dataTable.render.text()
},
{
"data": "user_name",
"render": $.fn.dataTable.render.text()
},
{ "data": "case_name",
"render": $.fn.dataTable.render.text()
},
{ "data": "user_input",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (data == true){
data = "<i class='fas fa-check text-success text-center'></i>";
} else {
data = "<i class='fas fa-times text-muted'></i>";
}
}
return data;
} },
{ "data": "is_from_api",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (data == true){
data = "<i class='fas fa-check text-success'></i>";
} else {
data = "<i class='fas fa-times text-muted'></i>";
}
}
return data;
} },
{ "data": "activity_desc",
"render": $.fn.dataTable.render.text()
}
],
filter: true,
info: true,
processing: true,
retrieve: true,
initComplete: function () {
tableFiltering(this.api(), 'activities_table');
},
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
]
});
$("#activities_table").css("font-size", 12);
function refresh_activities() {
get_activities ();
notify_success('Refreshed');
}
function get_activities () {
show_loader();
if ($('#non_case_related_act').is(':checked')) {
url = '/activities/list-all';
} else {
url = '/activities/list';
}
get_request_api(url)
.done((data) => {
if(notify_auto_api(data, true)) {
jsdata = data;
if (jsdata.status == "success") {
Table.clear();
Table.rows.add(data.data);
Table.columns.adjust().draw();
Table.buttons().container().appendTo($('#activities_table_info'));
hide_loader();
}
}
}).fail((data) => {
hide_loader();
Table.clear();
Table.columns.adjust().draw();
});
}
$(document).ready(function(){
get_activities();
$('#non_case_related_act').on('change', function() {
get_activities();
});
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,534 @@
/* reload the asset table */
g_asset_id = null;
g_asset_desc_editor = null;
function reload_assets() {
get_case_assets();
}
function edit_in_asset_desc() {
if($('#container_asset_desc_content').is(':visible')) {
$('#container_asset_description').show(100);
$('#container_asset_desc_content').hide(100);
$('#asset_edition_btn').hide(100);
$('#asset_preview_button').hide(100);
} else {
$('#asset_preview_button').show(100);
$('#asset_edition_btn').show(100);
$('#container_asset_desc_content').show(100);
$('#container_asset_description').hide(100);
}
}
/* Fetch a modal that is compatible with the requested asset type */
function add_assets() {
url = 'assets/add/modal' + case_param();
$('#modal_add_asset_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_asset_desc_editor = get_new_ace_editor('asset_description', 'asset_desc_content', 'target_asset_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null);
g_asset_desc_editor.setOption("minLines", "10");
edit_in_asset_desc();
let headers = get_editor_headers('g_asset_desc_editor', null, 'asset_edition_btn');
$('#asset_edition_btn').append(headers);
$('#ioc_links').select2({});
$('#submit_new_assets').on("click", function () {
let assets = $('#assets_name').val();
let assets_list = assets.split('\n');
for (let index in assets_list) {
let data = $('#form_new_assets').serializeObject();
data['asset_name'] = assets_list[index];
delete data['assets_name'];
if (data['asset_name'] == "" || data['asset_name'] == null || data['asset_name'] == '\n') {
continue;
}
data['csrf_token'] = $('#csrf_token').val();
if (typeof data["ioc_links"] == "string") {
data["ioc_links"] = [data["ioc_links"]]
}
data['asset_tags'] = $('#asset_tags').val();
data['asset_description'] = g_asset_desc_editor.getValue();
let ret = get_custom_attributes_fields();
let has_error = ret[0].length > 0;
let attributes = ret[1];
if (has_error) {
return false;
}
data['custom_attributes'] = attributes;
post_request_api('assets/add', JSON.stringify(data), true, function () {
$('#submit_new_assets').text('Saving data..')
.attr("disabled", true)
.removeClass('bt-outline-success')
.addClass('btn-success', 'text-dark');
})
.done((data) => {
if (data.status == 'success') {
reload_assets();
if (index == (assets_list.length - 1)) {
$('#modal_add_asset').modal('hide');
notify_success("Assets created");
}
} else {
$('#submit_new_assets').text('Save again');
swal("Oh no !", data.message, "error")
}
})
.always(function () {
$('#submit_new_assets')
.attr("disabled", false)
.addClass('bt-outline-success')
.removeClass('btn-success', 'text-dark');
})
.fail(function (error) {
$('#submit_new_assets').text('Save');
propagate_form_api_errors(error.responseJSON.data);
})
}
return false;
})
$('#modal_add_asset').modal({ show: true });
$('#asset_name').focus();
});
$('.dtr-modal').hide();
}
/* Retrieve the list of assets and build a datatable for each type of asset */
function get_case_assets() {
show_loader();
get_request_api('/case/assets/list')
.done(function (response) {
if (response.status == 'success') {
if (response.data != null) {
jsdata = response.data;
if (jsdata.assets.length > 299) {
set_page_warning("Backref disabled due to too many assets in the case");
} else {
set_page_warning("");
}
Table.clear();
Table.rows.add(jsdata.assets);
Table.columns.adjust().draw();
load_menu_mod_options('asset', Table, delete_asset);
set_last_state(jsdata.state);
hide_loader();
Table.responsive.recalc();
$('[data-toggle="popover"]').popover({html: true, container: 'body'});
} else {
Table.clear().draw();
swal("Oh no !", data.message, "error")
}
} else {
Table.clear().draw()
}
})
}
/* Delete an asset */
function delete_asset(asset_id) {
do_deletion_prompt("You are about to delete asset #" + asset_id)
.then((doDelete) => {
if (doDelete) {
post_request_api('assets/delete/' + asset_id)
.done((data) => {
if (data.status == 'success') {
reload_assets();
$('#modal_add_asset').modal('hide');
notify_success('Asset deleted');
} else {
swal("Oh no !", data.message, "error")
}
});
}
});
}
/* Fetch the details of an asset and allow modification */
function asset_details(asset_id) {
url = 'assets/' + asset_id + '/modal' + case_param();
$('#modal_add_asset_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_asset_id = asset_id;
g_asset_desc_editor = get_new_ace_editor('asset_description', 'asset_desc_content', 'target_asset_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null, false, false);
g_asset_desc_editor.setOption("minLines", "10");
preview_asset_description(true);
headers = get_editor_headers('g_asset_desc_editor', null, 'asset_edition_btn');
$('#asset_edition_btn').append(headers);
$('#ioc_links').select2({});
$('#submit_new_asset').on("click", function () {
update_asset(true);
return false;
})
load_menu_mod_options_modal(asset_id, 'asset', $("#asset_modal_quick_actions"));
$('.dtr-modal').hide();
$('#modal_add_asset').modal({ show: true });
edit_in_asset_desc();
});
return false;
}
function preview_asset_description(no_btn_update) {
if(!$('#container_asset_description').is(':visible')) {
asset_desc = g_asset_desc_editor.getValue();
converter = get_showdown_convert();
html = converter.makeHtml(do_md_filter_xss(asset_desc));
asset_desc_html = do_md_filter_xss(html);
$('#target_asset_desc').html(asset_desc_html);
$('#container_asset_description').show();
if (!no_btn_update) {
$('#asset_preview_button').html('<i class="fa-solid fa-eye-slash"></i>');
}
$('#container_asset_desc_content').hide();
}
else {
$('#container_asset_description').hide();
if (!no_btn_update) {
$('#asset_preview_button').html('<i class="fa-solid fa-eye"></i>');
}
$('#asset_preview_button').html('<i class="fa-solid fa-eye"></i>');
$('#container_asset_desc_content').show();
}
}
function save_asset(){
$('#submit_new_asset').click();
}
function update_asset(do_close){
if(!$('form#form_new_asset').valid()) {
return false;
}
var data = $('#form_new_asset').serializeObject();
if (typeof data["ioc_links"] === "string") {
data["ioc_links"] = [data["ioc_links"]]
} else if (typeof data["ioc_links"] === "object") {
tmp_data = [];
for (ioc_link in data["ioc_links"]) {
if (typeof ioc_link === "string") {
tmp_data.push(data["ioc_links"][ioc_link]);
}
}
data["ioc_links"] = tmp_data;
}
else {
data["ioc_links"] = [];
}
data['asset_tags'] = $('#asset_tags').val();
data['asset_description'] = g_asset_desc_editor.getValue();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data['custom_attributes'] = attributes;
post_request_api('assets/update/' + g_asset_id, JSON.stringify(data), true)
.done((data) => {
if (data.status == 'success') {
reload_assets();
$('#submit_new_asset').text("Saved").addClass('btn-outline-success').removeClass('btn-outline-danger').removeClass('btn-outline-warning');
$('#last_saved').removeClass('btn-danger').addClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-check");
if (do_close) {
$('#modal_add_asset').modal('hide');
}
notify_success('Asset updated');
} else {
$('#submit_new_asset').text('Save again');
swal("Oh no !", data.message, "error")
}
})
return false;
}
function fire_upload_assets() {
$('#modal_upload_assets').modal('show');
}
function upload_assets() {
var file = $("#input_upload_assets").get(0).files[0];
var reader = new FileReader();
reader.onload = function (e) {
fileData = e.target.result
var data = new Object();
data['csrf_token'] = $('#csrf_token').val();
data['CSVData'] = fileData;
post_request_api('/case/assets/upload', JSON.stringify(data), true)
.done((data) => {
jsdata = data;
if (jsdata.status == "success") {
reload_assets();
$('#modal_upload_assets').modal('hide');
swal("Got news for you", data.message, "success");
} else {
swal("Got bad news for you", data.message, "error");
}
})
};
reader.readAsText(file)
return false;
}
function generate_sample_csv(){
csv_data = "asset_name,asset_type_name,asset_description,asset_ip,asset_domain,asset_tags\n"
csv_data += '"My computer","Mac - Computer","Computer of Mme Michu","192.168.15.5","iris.local","Compta|Mac"\n'
csv_data += '"XCAS","Windows - Server","Xcas server","192.168.15.48","iris.local",""'
download_file("sample_assets.csv", "text/csv", csv_data);
}
/* Page is ready, fetch the assets of the case */
$(document).ready(function(){
/* add filtering fields for each table of the page (must be done before datatable initialization) */
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
Table = $("#assets_table").DataTable({
dom: '<"container-fluid"<"row"<"col"l><"col"f>>>rt<"container-fluid"<"row"<"col"i><"col"p>>>',
aaData: [],
aoColumns: [
{
"data": "asset_name",
"className": "dt-nowrap",
"render": function (data, type, row, meta) {
if (type === 'display' || type === 'filter' || type === 'sort' || type === 'export') {
if (row['asset_domain']) {
datak = sanitizeHTML(row['asset_domain'])+"\\"+ sanitizeHTML(data);
} else {
datak = sanitizeHTML(data);
}
if (data.length > 60) {
datak = data.slice(0, 60) + " (..)";
}
if (isWhiteSpace(data)) {
datak = '#' + row['asset_id'];
}
share_link = buildShareLink(row['asset_id']);
if (row['asset_compromise_status_id'] == 1) {
src_icon = row['asset_icon_compromised'];
} else {
src_icon = row['asset_icon_not_compromised'];
}
ret = '<img class="mr-2" title="'+ sanitizeHTML(row['asset_type']) +'" style="width:1.5em;height:1.5em" src=\'/static/assets/img/graph/' + src_icon +
'\'> <a href="' + share_link + '" data-selector="true" title="Asset ID #'+ row['asset_id'] +
'" onclick="asset_details(\'' + row['asset_id'] + '\');return false;">' + datak +'</a>';
if (row.link.length > 0) {
var has_compro = false;
var datacontent = 'data-content="';
for (idx in row.link) {
if (row.link[idx]['asset_compromise_status_id'] == 1) {
has_compro = true;
datacontent += `<b><a target='_blank' rel='noopener' href='/case/assets?cid=${row.link[idx]['case_id']}&shared=${row.link[idx]['asset_id']}'>Observed <sup><i class='fa-solid fa-arrow-up-right-from-square ml-1 mr-1 text-muted'></i></sup></a></b> as <b class='text-danger'>compromised</b><br/> on <b><a href='/case?cid=${row.link[idx]['case_id']}'>case #${row.link[idx]['case_id']} <sup><i class='fa-solid fa-arrow-up-right-from-square ml-1 mr-1 text-muted'></i></sup></a></a></b> (${row.link[idx]['case_open_date'].replace('00:00:00 GMT', '')}) for the same customer.<br/><br/>`;
} else {
datacontent += `<b><a target='_blank' rel='noopener' href='/case/assets?cid=${row.link[idx]['case_id']}&shared=${row.link[idx]['asset_id']}'>Observed <sup><i class='fa-solid fa-arrow-up-right-from-square ml-1 mr-1 text-muted'></i></sup></a></b> as <b class='text-success'>not compromised</b><br/> on <b><a href='/case?cid=${row.link[idx]['case_id']}'>case #${row.link[idx]['case_id']} <sup><i class='fa-solid fa-arrow-up-right-from-square ml-1 mr-1 text-muted'></i></sup></a></a></b> (${row.link[idx]['case_open_date'].replace('00:00:00 GMT', '')}) for the same customer.<br/><br/>`;
}
}
if (has_compro) {
ret += `<a tabindex="0" class="fas fa-meteor ml-2 text-danger" style="cursor: pointer;" data-html="true"
data-toggle="popover" data-trigger="focus" title="Observed in previous case" `;
} else {
ret += `<a tabindex="0" class="fas fa-info-circle ml-2 text-success" style="cursor: pointer;" data-html="true"
data-toggle="popover" data-trigger="focus" title="Observed in previous case" `;
}
ret += datacontent;
ret += '"></i>';
}
return ret;
}
return data;
}
},
{
"data": "asset_type",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{ "data": "asset_description",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover-click-close" style="cursor: pointer;" title="Info" data-trigger="hover" href="#" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{ "data": "asset_ip",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{ "data": "asset_compromise_status_id",
"render": function(data, type, row) {
if (data == 0) { ret = '<span class="badge badge-muted">TBD</span>';}
else if (data == 1) { ret = '<span class="badge badge-danger">Yes</span>';}
else if (data == 2) { ret = '<span class="badge badge-success">No</span>';}
else { ret = '<span class="badge badge-warning">Unknown</span>';}
return ret;
}
},
{
"data": "ioc_links",
"render": function (data, type, row, meta) {
if ((type === 'filter' || type === 'display') && data != null) {
datas = "";
for (ds in data) {
datas += '<span class="badge badge-light">' + sanitizeHTML(data[ds]['ioc_value']) + '</span>';
}
return datas;
} else if (type === 'export' && data != null) {
let datas = data.map(ds => sanitizeHTML(ds['ioc_value'])).join(',');
return datas;
}
return data;
}
},
{ "data": "asset_tags",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null ) {
tags = "";
de = data.split(',');
for (tag in de) {
tags += '<span class="badge badge-light ml-2">' + sanitizeHTML(de[tag]) + '</span>';
}
return tags;
}
return data;
}
},
{
"data": "analysis_status",
"render": function(data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
if (data == 'To be done') {
flag = 'danger';
} else if (data == 'Started') {
flag = 'warning';
} else if (data == 'Done') {
flag = 'success';
} else {
flag = 'muted';
}
data = '<span class="badge ml-2 badge-'+ flag +'">' + data + '</span>';
}
return data;
}
}
],
filter: true,
info: true,
ordering: true,
processing: true,
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.childRow,
renderer: $.fn.dataTable.Responsive.renderer.tableAll()
}
},
language: {
"processing": '<i class="fa fa-spinner fa-spin" style="font-size:24px;color:rgb(75, 183, 245);"></i>'
},
retrieve: true,
buttons: [],
orderCellsTop: true,
initComplete: function () {
tableFiltering(this.api(), 'assets_table');
},
select: true
});
$("#assets_table").css("font-size", 12);
Table.on( 'responsive-resize', function ( e, datatable, columns ) {
hide_table_search_input( columns );
});
var buttons = new $.fn.dataTable.Buttons(Table, {
buttons: [
{ "extend": 'csvHtml5', "text":'<i class="fas fa-cloud-download-alt"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Download as CSV', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } } ,
{ "extend": 'copyHtml5', "text":'<i class="fas fa-copy"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Copy', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } },
{ "extend": 'colvis', "text":'<i class="fas fa-eye-slash"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Toggle columns' }
]
}).container().appendTo($('#tables_button'));
get_case_assets();
setInterval(function() { check_update('assets/state'); }, 3000);
shared_id = getSharedLink();
if (shared_id) {
asset_details(shared_id);
}
});

View File

@ -0,0 +1,72 @@
function get_case_graph() {
get_request_api('graph/getdata')
.done((data) => {
if (data.status == 'success') {
redrawAll(data.data);
hide_loader();
} else {
$('#submit_new_asset').text('Save again');
swal("Oh no !", data.message, "error")
}
})
}
var network;
function redrawAll(data) {
if (data.nodes.length == 0) {
$('#card_main_load').show();
$('#graph-container').text('No events in graph');
hide_loader();
return true;
}
var container = document.getElementById("graph-container");
var options = {
edges: {
smooth: {
enabled: true,
type: 'continuous',
roundness: 0.5
}
},
layout: {
randomSeed: 2,
improvedLayout: true
},
interaction: {
hideEdgesOnDrag: false
},
width: (window.innerWidth - 400) + "px",
height: (window.innerHeight- 250) + "px",
"physics": {
"forceAtlas2Based": {
"gravitationalConstant": -167,
"centralGravity": 0.04,
"springLength": 0,
"springConstant": 0.02,
"damping": 0.9
},
"minVelocity": 0.41,
"solver": "forceAtlas2Based",
"timestep": 0.45
}
};
nodes = data.nodes;
edges = data.edges;
network = new vis.Network(container, data, options);
network.on("stabilizationIterationsDone", function () {
network.setOptions( { physics: false } );
});
}
/* Page is ready, fetch the assets of the case */
$(document).ready(function(){
get_case_graph();
});

View File

@ -0,0 +1,478 @@
/* reload the ioc table */
var g_ioc_id = null;
var g_ioc_desc_editor = null;
function reload_iocs() {
get_case_ioc();
}
function edit_in_ioc_desc() {
if($('#container_ioc_desc_content').is(':visible')) {
$('#container_ioc_description').show(100);
$('#container_ioc_desc_content').hide(100);
$('#ioc_edition_btn').hide(100);
$('#ioc_preview_button').hide(100);
} else {
$('#ioc_preview_button').show(100);
$('#ioc_edition_btn').show(100);
$('#container_ioc_desc_content').show(100);
$('#container_ioc_description').hide(100);
}
}
/* Fetch a modal that is compatible with the requested ioc type */
function add_ioc() {
url = 'ioc/add/modal' + case_param();
$('#modal_add_ioc_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_ioc_desc_editor = get_new_ace_editor('ioc_description', 'ioc_desc_content', 'target_ioc_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null);
g_ioc_desc_editor.setOption("minLines", "10");
edit_in_ioc_desc();
headers = get_editor_headers('g_ioc_desc_editor', null, 'ioc_edition_btn');
$('#ioc_edition_btn').append(headers);
$('#submit_new_ioc').on("click", function () {
if(!$('form#form_new_ioc').valid()) {
return false;
}
var data = $('#form_new_ioc').serializeObject();
data['ioc_tags'] = $('#ioc_tags').val();
data['ioc_description'] = g_ioc_desc_editor.getValue();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data['custom_attributes'] = attributes;
id = $('#ioc_id').val();
if ($('#ioc_one_per_line').is(':checked')) {
let iocs_values = $('#ioc_value').val();
let iocs_list = iocs_values.split(/\r?\n/);
for (let index in iocs_list) {
if (iocs_list[index] === '' || iocs_list[index] === '\n') {
continue;
}
data['ioc_value'] = iocs_list[index];
post_request_api('ioc/add', JSON.stringify(data), true, function () {
$('#submit_new_ioc').text('Saving data..')
.attr("disabled", true)
.removeClass('bt-outline-success')
.addClass('btn-success', 'text-dark');
})
.done((data) => {
if (data.status == 'success') {
reload_iocs();
notify_success(data.message);
if (index == (iocs_list.length - 1)) {
$('#modal_add_ioc').modal('hide');
}
} else {
$('#submit_new_ioc').text('Save again');
swal("Oh no !", data.message, "error")
}
})
.always(function () {
$('#submit_new_ioc')
.attr("disabled", false)
.addClass('bt-outline-success')
.removeClass('btn-success', 'text-dark');
})
}
}
else {
post_request_api('ioc/add', JSON.stringify(data), true, function () {
$('#submit_new_ioc').text('Saving data..')
.attr("disabled", true)
.removeClass('bt-outline-success')
.addClass('btn-success', 'text-dark');
})
.done((data) => {
if (data.status == 'success') {
reload_iocs();
notify_success(data.message);
$('#modal_add_ioc').modal('hide');
} else {
$('#submit_new_ioc').text('Save again');
swal("Oh no !", data.message, "error")
}
})
.always(function () {
$('#submit_new_ioc')
.attr("disabled", false)
.addClass('bt-outline-success')
.removeClass('btn-success', 'text-dark');
})
}
return false;
});
$('#modal_add_ioc').modal({ show: true });
$('#ioc_value').focus();
});
return false;
}
function save_ioc() {
$('#submit_new_ioc').click();
}
/* Retrieve the list of iocs and build a datatable for each type of ioc */
function get_case_ioc() {
show_loader();
get_request_api("/case/ioc/list")
.done(function (response) {
if (response.status == 'success') {
if (response.data != null) {
jsdata = response.data;
Table.clear();
Table.rows.add(jsdata.ioc);
set_last_state(jsdata.state);
$('#ioc_table_wrapper').on('click', function(e){
if($('.popover').length>1)
$('.popover').popover('hide');
$(e.target).popover('toggle');
});
$('#ioc_table_wrapper').show();
$('[data-toggle="popover"]').popover();
Table.columns.adjust().draw();
load_menu_mod_options('ioc', Table, delete_ioc);
hide_loader();
Table.responsive.recalc();
} else {
Table.clear().draw();
swal("Oh no !", data.message, "error")
}
} else {
Table.clear().draw()
}
})
}
/* Edit an ioc */
function edit_ioc(ioc_id) {
url = 'ioc/' + ioc_id + '/modal' + case_param();
$('#modal_add_ioc_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_ioc_id = ioc_id;
g_ioc_desc_editor = get_new_ace_editor('ioc_description', 'ioc_desc_content', 'target_ioc_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null, false, false);
g_ioc_desc_editor.setOption("minLines", "10");
preview_ioc_description(true);
headers = get_editor_headers('g_ioc_desc_editor', null, 'ioc_edition_btn');
$('#ioc_edition_btn').append(headers);
load_menu_mod_options_modal(ioc_id, 'ioc', $("#ioc_modal_quick_actions"));
$('.dtr-modal').hide();
$('#modal_add_ioc').modal({ show: true });
edit_in_ioc_desc();
});
}
function preview_ioc_description(no_btn_update) {
if(!$('#container_ioc_description').is(':visible')) {
ioc_desc = g_ioc_desc_editor.getValue();
converter = get_showdown_convert();
html = converter.makeHtml(do_md_filter_xss(ioc_desc));
ioc_desc_html = do_md_filter_xss(html);
$('#target_ioc_desc').html(ioc_desc_html);
$('#container_ioc_description').show();
if (!no_btn_update) {
$('#ioc_preview_button').html('<i class="fa-solid fa-eye-slash"></i>');
}
$('#container_ioc_desc_content').hide();
}
else {
$('#container_ioc_description').hide();
if (!no_btn_update) {
$('#ioc_preview_button').html('<i class="fa-solid fa-eye"></i>');
}
$('#ioc_preview_button').html('<i class="fa-solid fa-eye"></i>');
$('#container_ioc_desc_content').show();
}
}
function update_ioc(ioc_id) {
update_ioc_ext(ioc_id, true);
}
/* Update an ioc */
function update_ioc_ext(ioc_id, do_close) {
if(!$('form#form_new_ioc').valid()) {
return false;
}
if (ioc_id === undefined || ioc_id === null) {
ioc_id = g_ioc_id;
}
var data = $('#form_new_ioc').serializeObject();
data['ioc_tags'] = $('#ioc_tags').val();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data['ioc_description'] = g_ioc_desc_editor.getValue();
data['custom_attributes'] = attributes;
post_request_api('ioc/update/' + ioc_id, JSON.stringify(data), true)
.done((data) => {
if (data.status == 'success') {
reload_iocs();
$('#submit_new_ioc').text("Saved").addClass('btn-outline-success').removeClass('btn-outline-danger').removeClass('btn-outline-warning');
$('#last_saved').removeClass('btn-danger').addClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-check");
if (do_close !== undefined && do_close === true) {
$('#modal_add_ioc').modal('hide');
}
notify_success(data.message);
} else {
$('#submit_new_ioc').text('Save again');
swal("Oh no !", data.message, "error")
}
})
}
/* Delete an ioc */
function delete_ioc(ioc_id) {
do_deletion_prompt("You are about to delete IOC #" + ioc_id)
.then((doDelete) => {
if (doDelete) {
post_request_api('ioc/delete/' + ioc_id)
.done((data) => {
if (data.status == 'success') {
reload_iocs();
notify_success(data.message);
$('#modal_add_ioc').modal('hide');
} else {
swal("Oh no !", data.message, "error")
}
})
}
});
}
function fire_upload_iocs() {
$('#modal_upload_ioc').modal('show');
}
function upload_ioc() {
var file = $("#input_upload_ioc").get(0).files[0];
var reader = new FileReader();
reader.onload = function (e) {
fileData = e.target.result
var data = new Object();
data['csrf_token'] = $('#csrf_token').val();
data['CSVData'] = fileData;
post_request_api('/case/ioc/upload', JSON.stringify(data), true)
.done((data) => {
jsdata = data;
if (jsdata.status == "success") {
reload_iocs();
$('#modal_upload_ioc').modal('hide');
swal("Got news for you", data.message, "success");
} else {
swal("Got bad news for you", data.message, "error");
}
})
};
reader.readAsText(file)
return false;
}
function generate_sample_csv(){
csv_data = "ioc_value,ioc_type,ioc_description,ioc_tags,ioc_tlp\n"
csv_data += "1.1.1.1,ip-dst,Cloudflare DNS IP address,Cloudflare|DNS,green\n"
csv_data += "wannacry.exe,filename,Wannacry sample found,Wannacry|Malware|PE,amber"
download_file("sample_iocs.csv", "text/csv", csv_data);
}
/* Page is ready, fetch the iocs of the case */
$(document).ready(function(){
/* add filtering fields for each table of the page (must be done before datatable initialization) */
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
Table = $("#ioc_table").DataTable({
dom: '<"container-fluid"<"row"<"col"l><"col"f>>>rt<"container-fluid"<"row"<"col"i><"col"p>>>',
fixedHeader: true,
aaData: [],
aoColumns: [
{
"data": "ioc_value",
"render": function (data, type, row, meta) {
if (type === 'display') {
let datak = '';
if (isWhiteSpace(data) || data === null) {
datak = '#' + row['ioc_id'];
} else {
datak= ellipsis_field(data, 64);
}
share_link = buildShareLink(row['ioc_id']);
data = '<a href="' + share_link + '" data-selector="true" title="IOC ID #'+ row['ioc_id'] +'" onclick="edit_ioc(\'' + row['ioc_id'] + '\');return false;">' + datak +'</a>';
}
return data;
}
},
{ "data": "ioc_type",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
}
return data;
}
},
{ "data": "ioc_description",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover" style="cursor: pointer;" title="Info" data-trigger="hover" href="#" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{ "data": "ioc_tags",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
tags = "";
de = data.split(',');
for (tag in de) {
tags += '<span class="badge badge-light ml-2">' + sanitizeHTML(de[tag]) + '</span>';
}
return tags;
}
return data;
}
},
{ "data": "link",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
links = "";
for (link in data) {
links += '<span data-toggle="popover" style="cursor: pointer;" data-trigger="hover" class="text-primary mr-3" href="#" title="Case info" data-content="' + sanitizeHTML(data[link]['case_name']) +
' (' + sanitizeHTML(data[link]['client_name']) + ')' + '">#' + data[link]['case_id'] + '</span>'
}
return links;
} else if (type === 'export' && data != null) {
return data.map(ds => sanitizeHTML(ds['case_name'])).join(',');
}
return data;
}
},
{
"data": "tlp_name",
"render": function(data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
data = '<span class="badge badge-'+ row['tlp_bscolor'] +' ml-2">tlp:' + data + '</span>';
}
return data;
}
}
],
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.childRow,
renderer: $.fn.dataTable.Responsive.renderer.tableAll()
}
},
buttons: [],
orderCellsTop: true,
initComplete: function () {
tableFiltering(this.api(), 'ioc_table');
},
select: true
});
$("#ioc_table").css("font-size", 12);
Table.on( 'responsive-resize', function ( e, datatable, columns ) {
hide_table_search_input( columns );
});
var buttons = new $.fn.dataTable.Buttons(Table, {
buttons: [
{ "extend": 'csvHtml5', "text":'<i class="fas fa-cloud-download-alt"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Download as CSV', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } } ,
{ "extend": 'copyHtml5', "text":'<i class="fas fa-copy"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Copy', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } },
{ "extend": 'colvis', "text":'<i class="fas fa-eye-slash"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Toggle columns' }
]
}).container().appendTo($('#tables_button'));
get_case_ioc();
setInterval(function() { check_update('ioc/state'); }, 3000);
shared_id = getSharedLink();
if (shared_id) {
edit_ioc(shared_id);
}
});

View File

@ -0,0 +1,179 @@
function buildShareLink(lookup_id) {
current_path = location.protocol + '//' + location.host + location.pathname;
current_path = current_path + case_param() + '&shared=' + lookup_id;
return current_path;
}
function getSharedLink(){
queryString = window.location.search;
urlParams = new URLSearchParams(queryString);
if (Number.isInteger(parseInt(urlParams.get('shared')))) {
return urlParams.get('shared')
}
return null;
}
function edit_case_info() {
$('#case_gen_info_content').hide();
$('#case_gen_info_edit').show();
$('#cancel_case_info').show();
$('#save_case_info').show();
$('#case_info').hide();
}
function cancel_case_edit() {
$('#case_gen_info_content').show();
$('#case_gen_info_edit').hide();
$('#cancel_case_info').hide();
$('#save_case_info').hide();
$('#case_info').show();
}
function save_case_edit(case_id) {
var data_sent = $('form#form_update_case').serializeObject();
var map_protagonists = Object();
for (e in data_sent) {
if (e.startsWith('protagonist_role_')) {
map_protagonists[e.replace('protagonist_role_', '')] = {
'role': data_sent[e]
};
delete data_sent[e];
}
if (e.startsWith('protagonist_name_')) {
map_protagonists[e.replace('protagonist_name_', '')]['name'] = data_sent[e];
delete data_sent[e];
}
if (e.startsWith('protagonist_contact_')) {
map_protagonists[e.replace('protagonist_contact_', '')]['contact'] = data_sent[e];
delete data_sent[e];
}
if (e.startsWith('protagonist_id_')) {
map_protagonists[e.replace('protagonist_id_', '')]['id'] = data_sent[e];
delete data_sent[e];
}
}
data_sent['protagonists'] = [];
for (e in map_protagonists) {
data_sent['protagonists'].push(map_protagonists[e]);
}
data_sent['case_tags'] = $('#case_tags').val();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('/manage/cases/update/' + case_id, JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
case_detail(case_id);
}
});
}
/* Remove case function */
function remove_case(id) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this !\nAll associated data will be deleted",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/cases/delete/' + id)
.done((data) => {
if (notify_auto_api(data)) {
$('#modal_case_detail').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}
/* Reopen case function */
function reopen_case(id) {
post_request_api('/manage/cases/reopen/' + id)
.done((data) => {
window.location.reload();
$('#modal_case_detail').modal('hide');
});
}
/* Close case function */
function close_case(id) {
swal({
title: "Are you sure?",
text: "Case ID " + id + " will be closed",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, close it!'
})
.then((willClose) => {
if (willClose) {
post_request_api('/manage/cases/close/' + id)
.done((data) => {
window.location.reload();
$('#modal_case_detail').modal('hide');
});
}
});
}
function add_protagonist() {
random_string = Math.random().toString(36).substring(7);
prota_html = $('#protagonist_list_edit_template').html();
prota_html = prota_html.replace(/__PROTAGONIST_ID__/g, random_string);
$('#protagonist_list_edit').append(prota_html);
}
function remove_protagonist(id) {
$('#protagonist_' + id).remove();
}
$(document).ready(function(){
$(function(){
var current = location.pathname;
$('#h_nav_tab li').each(function(){
var $this = $(this);
var child = $this.children();
// if the current path is like this link, make it active
if(child.attr('href') !== undefined && child.attr('href').split("?")[0] == current){
$this.addClass('active');
return;
}
})
});
$('#case_quick_status').change(function(){
post_request_api('/case/update-status', JSON.stringify({
'status_id': $('#case_quick_status').val(),
'csrf_token': $('#csrf_token').val()
}))
.done((data) => {
if (notify_auto_api(data)) {
window.location.reload();
}
})
});
});

View File

@ -0,0 +1,761 @@
/* Defines the kanban board */
let note_editor;
let session_id = null ;
let collaborator = null ;
let collaborator_socket = null ;
let buffer_dumped = false ;
let last_applied_change = null ;
let just_cleared_buffer = null ;
let from_sync = null;
let is_typing = "";
let ppl_viewing = new Map();
let timer_socket = 0;
let note_id = null;
let map_notes = Object();
let last_ping = 0;
let forceModalClose = false;
let wasMiniNote = false;
const preventFormDefaultBehaviourOnSubmit = (event) => {
event.preventDefault();
return false;
};
var boardNotes = {
init: function init() {
this.bindUIActions();
},
bindUIActions: function bindUIActions() {
// event handlers
this.handleBoardStyle();
this.handleSortable();
},
byId: function byId(id) {
return document.getElementById(id);
},
handleBoardStyle: function handleBoardStyle() {
$(document).on('mouseenter mouseleave', '.kanban-board-header', function (e) {
var isHover = e.type === 'mouseenter';
$(this).parent().toggleClass('hover', isHover);
});
},
handleSortable: function handleSortable() {
var board = this.byId('myKanban');
// Multi groups
Sortable.create(board, {
animation: 150,
draggable: '.kanban-board',
handle: '.kanban-board-header',
filter: '.ignore-sort',
forceFallback: true
});
[].forEach.call(board.querySelectorAll('.kanban-drag'), function (el) {
Sortable.create(el, {
group: 'tasks',
animation: 150,
filter: '.ignore-sort',
forceFallback: true
});
});
}
};
function Collaborator( session_id, note_id ) {
this.collaboration_socket = collaborator_socket;
this.channel = "case-" + session_id + "-notes";
this.collaboration_socket.on( "change-note", function(data) {
if ( data.note_id !== note_id ) return ;
let delta = JSON.parse( data.delta ) ;
last_applied_change = delta ;
$("#content_typing").text(data.last_change + " is typing..");
if ( delta !== null && delta !== undefined ) {
note_editor.session.getDocument().applyDeltas([delta]);
}
}.bind()) ;
this.collaboration_socket.on( "clear_buffer-note", function() {
if ( data.note_id !== note_id ) return ;
just_cleared_buffer = true ;
note_editor.setValue( "" ) ;
}.bind() ) ;
this.collaboration_socket.on( "save-note", function(data) {
if ( data.note_id !== note_id ) return ;
sync_note(note_id)
.then(function () {
$("#content_last_saved_by").text("Last saved by " + data.last_saved);
$('#btn_save_note').text("Saved").addClass('btn-success').removeClass('btn-danger').removeClass('btn-warning');
$('#last_saved').removeClass('btn-danger').addClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-check");
});
}.bind());
this.collaboration_socket.on('leave-note', function(data) {
ppl_viewing.delete(data.user);
refresh_ppl_list(session_id, note_id);
});
this.collaboration_socket.on('join-note', function(data) {
if ( data.note_id !== note_id ) return ;
if ((data.user in ppl_viewing)) return;
ppl_viewing.set(filterXSS(data.user), 1);
refresh_ppl_list(session_id, note_id);
collaborator.collaboration_socket.emit('ping-note', { 'channel': collaborator.channel, 'note_id': note_id });
});
this.collaboration_socket.on('ping-note', function(data) {
if ( data.note_id !== note_id ) return ;
collaborator.collaboration_socket.emit('pong-note', { 'channel': collaborator.channel, 'note_id': note_id });
});
this.collaboration_socket.on('disconnect', function(data) {
ppl_viewing.delete(data.user);
refresh_ppl_list(session_id, note_id);
});
}
function set_notes_follow(data) {
if (data.note_id !== null) {
if (data.note_id in map_notes ) {
map_notes[data.note_id][data.user] = 2;
} else {
map_notes[data.note_id] = Object();
map_notes[data.note_id][data.user] = 2;
}
}
for (let notid in map_notes) {
for (let key in map_notes[notid]) {
if (key !== data.user && data.note_id !== note_id || data.note_id === null) {
map_notes[notid][key] -= 1;
}
if (map_notes[notid][key] < 0) {
delete map_notes[notid][key];
}
}
$(`#badge_${notid}`).empty();
for (let key in map_notes[notid]) {
$(`#badge_${notid}`).append(get_avatar_initials(filterXSS(key), false, undefined, true));
}
}
}
Collaborator.prototype.change = function( delta, note_id ) {
this.collaboration_socket.emit( "change-note", { 'delta': delta, 'channel': this.channel, 'note_id': note_id } ) ;
}
Collaborator.prototype.clear_buffer = function( note_id ) {
this.collaboration_socket.emit( "clear_buffer-note", { 'channel': this.channel, 'note_id': note_id } ) ;
}
Collaborator.prototype.save = function( note_id ) {
this.collaboration_socket.emit( "save-note", { 'channel': this.channel, 'note_id': note_id } ) ;
}
Collaborator.prototype.close = function( note_id ) {
this.collaboration_socket.emit( "leave-note", { 'channel': this.channel, 'note_id': note_id } ) ;
}
function auto_remove_typing() {
if ($("#content_typing").text() == is_typing) {
$("#content_typing").text("");
} else {
is_typing = $("#content_typing").text();
}
}
/* Generates a global sequence id for subnotes */
let current_id = 0;
function nextSubNote(element, _item, title) {
var newElement = element.clone();
var id = current_id + 1;
current_id = id;
if (id < 10) id = "0" + id;
newElement.attr("id", element.attr("id").split("_")[0] + "_" + id);
var field = $(newElement).attr("id");
$(newElement).attr("id", field.split("_")[0] + "_" + id);
$(newElement).find('iris_note').attr('id', 'xqx' + id + 'qxq');
$(newElement).find('iris_note').text("New note");
var va = $(newElement).find('a');
$(newElement).find(va[1]).attr("onclick", 'delete_note("_' + id + '")');
newElement.appendTo($('#group-' + _item + "_main"));
newElement.show();
}
/* Generates a global sequence id for groups */
var current_gid = 0;
async function get_remote_note(note_id) {
return get_request_api("/case/notes/" + note_id);
}
async function sync_note(node_id) {
return;
}
function nextGroupNote(title="", rid=0) {
if (rid == 0) {
console.log("RID is needed to create group");
return;
}
var element = $('#group_');
var newElement = element.clone();
if (title == "") {
title = "Untitled group";
}
newElement.attr("id", "group-" + rid);
newElement.attr("title", "New group note");
var fa = $(newElement).find('button')[0];
var fb = $(newElement).find('button')[1];
var va = $(newElement).find('a');
$(newElement).find('div.kanban-title-board').text(title);
$(newElement).find('div.kanban-title-board').attr("onclick", 'edit_add_save(' + rid + ')');
$(newElement).find(fa).attr("onclick", 'edit_remote_groupnote(' + rid + ')');
$(newElement).find(fb).attr("onclick", 'add_remote_note(' + rid + ')');
$(newElement).find(va[0]).attr("onclick", 'delete_remote_groupnote(' + rid + ')');
$(newElement).find('main').attr("id", "group-" + rid + "-main");
newElement.appendTo($('#myKanban'));
newElement.show();
return rid;
}
/* Add a subnote to an item */
function add_subnote(_item, tr=0, title='', last_up, user) {
if (tr != 0) {
let element = $('#_subnote_');
var newElement = element.clone();
var id = tr;
current_id = id;
let info = user + " on " + last_up.replace('GMT', '');
newElement.attr("id", element.attr("id").split("_")[0] + "_" + id);
var field = $(newElement).attr("id");
$(newElement).attr("id", field.split("_")[0] + "_" + id);
$(newElement).attr("title", 'Note #' + id);
$(newElement).find('iris_note').attr('id', tr);
$(newElement).find('iris_note').text(title);
$(newElement).find('a.kanban-title').text(title);
$(newElement).find('small.kanban-info').text(info);
$(newElement).find('div.kanban-badge').attr('id', 'badge_' + id);
newElement.appendTo($('#group-' + _item + "-main"));
newElement.show();
}
}
/* Add a group to the dashboard */
function add_groupnote(title="", rid=0) {
return nextGroupNote(title, rid=rid);
}
/* Add a remote note to a group */
function add_remote_note(group_id) {
let data = Object();
data['note_title'] = "Untitled note";
data['note_content'] = "";
data['group_id'] = group_id;
data['csrf_token'] = $('#csrf_token').val();
post_request_api('/case/notes/add', JSON.stringify(data), false)
.done((data) => {
if (data.status == 'success') {
draw_kanban();
} else {
if (data.message != "No data to load for dashboard") {
swal("Oh no !", data.message, "error");
}
}
})
}
/* Add a group note remotely */
function add_remote_groupnote() {
let data = Object();
data['csrf_token'] = $('#csrf_token').val();
post_request_api('/case/notes/groups/add', JSON.stringify(data), false)
.done((data) => {
if (data.status == 'success') {
nextGroupNote(data.data.group_title, data.data.group_id);
draw_kanban();
} else {
if (data.message != "No data to load for dashboard") {
swal("Oh no !", data.message, "error");
}
}
})
}
/* Delete a group of the dashboard */
function delete_remote_groupnote(group_id) {
swal({
title: "Attention ",
text: "All the notes in this group will be deleted !\nThis cannot be reverted, notes will not be recoverable",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
var data = Object();
data['group_id'] = group_id;
data['csrf_token'] = $('#csrf_token').val();
post_request_api('/case/notes/groups/delete/'+ group_id)
.done((data) => {
if (data.status == 'success') {
swal("Done !", data.message, "success");
draw_kanban();
} else {
if (data.message != "No data to load for dashboard") {
swal("Oh no !", data.message, "error");
}
}
})
} else {
swal("Pfew, that was close");
}
});
}
/* Add a button to save group name */
function edit_add_save(group_id) {
btn = $("#group-" + group_id).find('button')[0];
$(btn).show();
}
/* Delete a group of the dashboard */
function edit_remote_groupnote(group_id) {
var data = Object();
data['group_title'] = $("#group-" + group_id).find('div.kanban-title-board').text();
data["csrf_token"] = $('#csrf_token').val();
post_request_api('/case/notes/groups/update/'+ group_id, JSON.stringify(data))
.done((data) => {
notify_auto_api(data);
draw_kanban();
})
}
/* Delete a group of the dashboard */
function delete_note(_item, cid) {
var n_id = $("#info_note_modal_content").find('iris_notein').text();
do_deletion_prompt("You are about to delete note #" + n_id)
.then((doDelete) => {
if (doDelete) {
post_request_api('/case/notes/delete/' + n_id, null, null, cid)
.done((data) => {
$('#modal_note_detail').modal('hide');
notify_auto_api(data);
})
.fail(function (error) {
draw_kanban();
swal( 'Oh no :(', error.message, 'error');
});
}
});
}
/* List all the notes on the dashboard */
function list_notes() {
output = {};
$("#myKanban").children().each(function () {
gid = $(this).attr('id');
output[gid] = [];
$(this).find('iris_note').each(function () {
output[gid].push(
[$(this).attr('id'),
$(this).text()
]);
})
});
return output;
}
/* Edit one note */
function edit_note(event) {
var nval = $(event).find('iris_note').attr('id');
collaborator = null;
note_detail(nval);
}
/* Fetch the edit modal with content from server */
function note_detail(id, cid) {
if (cid === undefined ) {
cid = case_param()
} else {
cid = '?cid=' + cid;
}
url = '/case/notes/' + id + "/modal" + cid;
$('#info_note_modal_content').load(url, function (response, status, xhr) {
$('#form_note').on("submit", preventFormDefaultBehaviourOnSubmit);
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
let timer;
let timeout = 10000;
$('#form_note').keyup(function(){
if(timer) {
clearTimeout(timer);
}
if (ppl_viewing.size <= 1) {
timer = setTimeout(save_note, timeout);
}
});
note_id = id;
collaborator = new Collaborator( get_caseid(), id );
note_editor = get_new_ace_editor('editor_detail', 'note_content', 'targetDiv', function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
$('#btn_save_note').text("Save").removeClass('btn-success').addClass('btn-warning').removeClass('btn-danger');
}, save_note);
note_editor.focus();
note_editor.on( "change", function( e ) {
// TODO, we could make things more efficient and not likely to conflict by keeping track of change IDs
if( last_applied_change != e && note_editor.curOp && note_editor.curOp.command.name) {
collaborator.change( JSON.stringify(e), id ) ;
}
}, false
);
last_applied_change = null ;
just_cleared_buffer = false ;
load_menu_mod_options_modal(id, 'note', $("#note_modal_quick_actions"));
$('#modal_note_detail').modal({ show: true, backdrop: 'static'});
$('#modal_note_detail').off('hide.bs.modal').on("hide.bs.modal", function (e) {
forceModalClose = false;
return handle_note_close(id, e);
});
collaborator_socket.emit('ping-note', { 'channel': 'case-' + get_caseid() + '-notes', 'note_id': note_id });
});
}
async function handle_note_close(id, e) {
note_id = null;
if ($("#minimized_modal_box").is(":visible")) {
forceModalClose = true;
wasMiniNote = true;
save_note(null, get_caseid());
}
if ($('#btn_save_note').text() === "Save" && !forceModalClose) {
e.preventDefault();
e.stopPropagation();
swal({
title: "Are you sure?",
text: "You have unsaved changes!",
icon: "warning",
buttons: {
cancel: {
text: "Cancel",
value: null,
visible: true,
},
confirm: {
text: "Discard changes",
value: true,
}
},
dangerMode: true,
closeOnEsc: false,
allowOutsideClick: false,
allowEnterKey: false
})
.then((willDiscard) => {
if (willDiscard) {
location.reload();
} else {
return false;
}
})
} else {
forceModalClose = false;
if (!wasMiniNote) {
if (collaborator) {
collaborator.close();
}
if (note_editor) {
note_editor.destroy();
}
if (ppl_viewing) {
ppl_viewing.clear();
}
}
collaborator_socket.off('save-note');
collaborator_socket.off('leave-note');
collaborator_socket.off('join-note');
collaborator_socket.off('ping-note');
collaborator_socket.off('disconnect');
collaborator_socket.off('clear_buffer-note');
collaborator_socket.off('change-note');
collaborator_socket.emit('ping-note', {'channel': 'case-' + get_caseid() + '-notes', 'note_id': null});
wasMiniNote = false;
await draw_kanban();
return true;
}
}
function refresh_ppl_list() {
$('#ppl_list_viewing').empty();
for (let [key, value] of ppl_viewing) {
$('#ppl_list_viewing').append(get_avatar_initials(key, false, undefined, true));
}
}
function handle_ed_paste(event) {
let filename = null;
const { items } = event.originalEvent.clipboardData;
for (let i = 0; i < items.length; i += 1) {
const item = items[i];
if (item.kind === 'string') {
item.getAsString(function (s){
filename = $.trim(s.replace(/\t|\n|\r/g, '')).substring(0, 40);
});
}
if (item.kind === 'file') {
console.log(item.type);
const blob = item.getAsFile();
if (blob !== null) {
const reader = new FileReader();
reader.onload = (e) => {
notify_success('The file is uploading in background. Don\'t leave the page');
if (filename === null) {
filename = random_filename(25);
}
upload_interactive_data(e.target.result, filename, function(data){
url = data.data.file_url + case_param();
event.preventDefault();
note_editor.insertSnippet(`\n![${filename}](${url} =40%x40%)\n`);
});
};
reader.readAsDataURL(blob);
} else {
notify_error('Unsupported direct paste of this item. Use datastore to upload.');
}
}
}
}
/* Delete a group of the dashboard */
function search_notes() {
var data = Object();
data['search_term'] = $("#search_note_input").val();
data['csrf_token'] = $("#csrf_token").val();
post_request_api('/case/notes/search', JSON.stringify(data))
.done((data) => {
if (data.status == 'success') {
$('#notes_search_list').empty();
for (e in data.data) {
li = `<li class="list-group-item list-group-item-action">
<span class="name" style="cursor:pointer" title="Click to open note" onclick="note_detail(`+ data.data[e]['note_id'] +`);">`+ data.data[e]['note_title'] +`</span>
</li>`
$('#notes_search_list').append(li);
}
$('#notes_search_list').show();
} else {
if (data.message != "No data to load for dashboard") {
swal("Oh no !", data.message, "error");
}
}
})
}
function toggle_max_editor() {
if ($('#container_note_content').hasClass('col-md-12')) {
$('#container_note_content').removeClass('col-md-12').addClass('col-md-6');
$('#ctrd_notesum').removeClass('d-none');
$('#btn_max_editor').html('<i class="fa-solid fa-minimize"></i>');
} else {
$('#container_note_content').removeClass('col-md-6').addClass('col-md-12');
$('#ctrd_notesum').addClass('d-none');
$('#btn_max_editor').html('<i class="fa-solid fa-maximize"></i>');
}
}
/* Save a note into db */
function save_note(this_item, cid) {
clear_api_error();
var n_id = $("#info_note_modal_content").find('iris_notein').text();
var data_sent = $('#form_note').serializeObject();
data_sent['note_content'] = $('#note_content').val();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
post_request_api('/case/notes/update/'+ n_id, JSON.stringify(data_sent), false, undefined, cid, function() {
$('#btn_save_note').text("Error saving!").removeClass('btn-success').addClass('btn-danger').removeClass('btn-danger');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-xmark");
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
})
.done((data) => {
if (data.status == 'success') {
$('#btn_save_note').text("Saved").addClass('btn-success').removeClass('btn-danger').removeClass('btn-warning');
$('#last_saved').removeClass('btn-danger').addClass('btn-success');
$("#content_last_saved_by").text('Last saved by you');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-check");
collaborator.save(n_id);
}
});
}
/* Span for note edition */
function edit_innote() {
return edit_inner_editor('notes_edition_btn', 'container_note_content', 'ctrd_notesum');
}
/* Load the kanban case data and build the board from it */
async function draw_kanban() {
/* Empty board */
$('#myKanban').empty();
show_loader();
return get_request_api('/case/notes/groups/list')
.done((data) => {
if (notify_auto_api(data, true)) {
gidl = [];
if (data.data.groups.length > 0) {
$('#empty-set-notes').hide();
} else {
$('#empty-set-notes').show();
}
for (idx in data.data.groups) {
group = data.data.groups[idx];
if (!gidl.includes(group.group_id)) {
nextGroupNote(group.group_title, group.group_id);
gidl.push(group.group_id);
}
for (ikd in group.notes) {
note = group.notes[ikd];
add_subnote(group.group_id,
note.note_id,
note.note_title,
note.note_lastupdate,
note.user
);
}
}
set_last_state(data.data.state);
hide_loader();
}
});
}
function note_interval_pinger() {
if (new Date() - last_ping > 2000) {
collaborator_socket.emit('ping-note',
{ 'channel': 'case-' + get_caseid() + '-notes', 'note_id': note_id });
last_ping = new Date();
}
}
$(document).ready(function(){
shared_id = getSharedLink();
if (shared_id) {
note_detail(shared_id);
}
let cid = get_caseid();
collaborator_socket = io.connect();
collaborator_socket.emit('join-notes-overview', { 'channel': 'case-' + cid + '-notes' });
collaborator_socket.on('ping-note', function(data) {
last_ping = new Date();
if ( data.note_id === null || data.note_id !== note_id) {
set_notes_follow(data);
return;
}
ppl_viewing.set(data.user, 1);
for (let [key, value] of ppl_viewing) {
if (key !== data.user) {
ppl_viewing.set(key, value-1);
}
if (value < 0) {
ppl_viewing.delete(key);
}
}
refresh_ppl_list(session_id, note_id);
});
timer_socket = setInterval( function() {
note_interval_pinger();
}, 2000);
collaborator_socket.emit('ping-note', { 'channel': 'case-' + cid + '-notes', 'note_id': note_id });
setInterval(auto_remove_typing, 1500);
});

View File

@ -0,0 +1,149 @@
/*************************
* Case update section
*************************/
/* Dropzone creation for update */
Dropzone.autoDiscover = false;
Dropzone.prototype.getErroredFiles = function () {
var file, _i, _len, _ref, _results;
_ref = this.files;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
if (file.status === Dropzone.ERROR) {
_results.push(file);
}
}
return _results;
};
var dropUpdate = new Dropzone("div#files_drop_1", {
url: "/manage/cases/upload_files" + case_param(),
addRemoveLinks: true,
autoProcessQueue: false,
parallelUploads: 40,
maxFiles: 40,
maxFilesize: 10000,
timeout: 0,
complete: function () {
if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0 && this.getErroredFiles().length === 0) {
$('#submit_update_case').text('Notifying for new import')
send_update_case_data();
}
},
error: function(jqXHR, error) {
if(error !== null || error !== undefined) {
notify_error(error.message);
} else {
notify_error(jqXHR);
ajax_notify_error(jqXHR, this.url);
}
}
});
/* Add of field for file upload */
dropUpdate.on('sending', function (file, xhr, formData) {
formData.append('is_update', true);
formData.append('pipeline', $('#update_pipeline_selector').val() );
formData.append('csrf_token', $('#csrf_token').val());
});
/* Update case function. start the update task */
function send_update_case_data() {
/* Get the pipeline args */
var args = Object();
$.each($(".update-" + $('#update_pipeline_selector').val()), function(el, k) {
args['args_' + k.id] = k.value;
});
args['pipeline'] = $('#update_pipeline_selector').val();
args['csrf_token'] = $('#csrf_token').val();
post_request_api('/manage/cases/trigger-pipeline', JSON.stringify(args), true, function () {
$('#submit_update_case').text('Starting pipeline');
$('#submit_update_case')
.attr("disabled", true)
.addClass('bt-outline-success')
.removeClass('btn-success', 'text-dark');
})
.done((data) => {
if (notify_auto_api(data, true)) {
$('#submit_update_case').text('Saved');
swal("That's done !",
"Files are being processed in background.\nYou can follow the progress in DIM Tasks",
"success",
{
buttons: {
again: {
text: "Import files again",
value: "again"
},
dash: {
text: "Go to dashboard",
value: "dash",
}
}
}
).then((value) => {
switch (value) {
case "dash":
window.location.replace("/dashboard" + case_param());
break;
case "again":
window.location.replace("/case" + case_param());
break;
default:
window.location.replace("/case" + case_param());
}
});
} else {
$('#submit_update_case').text('Save');
mdata = ""
for (element in data.data) {
mdata += data.data[element]
}
$.notify({
icon: 'flaticon-error',
title: data.message,
message: mdata
}, {
type: 'danger',
placement: {
from: 'top',
align: 'right'
},
time: 5000,
});
swal("Oh no !", data.message, "error")
}
})
.fail(() => {
$('#submit_new_case_btn').text('Save');
})
.always(() => {
$('#submit_update_case')
.attr("disabled", false)
.addClass('bt-outline-success')
.removeClass('btn-success', 'text-dark');
});
}
/* Event listener to process update queue */
function submit_update_casefn() {
var dse = $(".update-" + $('#update_pipeline_selector').val());
for (var elm=0; elm < $(dse).length; elm++) {
if($(dse[elm]).find('input').attr('required')) {
if ( ! $(dse[elm]).find('input').val() ) {
notify_error("Required fields are not set");
return false;
}
}
}
dropUpdate.processQueue();
}

View File

@ -0,0 +1,367 @@
/* reload the rfiles table */
function reload_rfiles(notify) {
get_case_rfiles();
if (notify !== undefined) {
notify_success("Refreshed");
}
}
function edit_in_evidence_desc() {
if($('#container_evidence_desc_content').is(':visible')) {
$('#container_evidence_description').show(100);
$('#container_evidence_desc_content').hide(100);
$('#evidence_edition_btn').hide(100);
$('#evidence_preview_button').hide(100);
} else {
$('#evidence_preview_button').show(100);
$('#evidence_edition_btn').show(100);
$('#container_evidence_desc_content').show(100);
$('#container_evidence_description').hide(100);
}
}
function get_hash() {
if (document.getElementById("input_autofill").files[0] === undefined) {
$('#btn_rfile_proc').text("Please select a file");
return;
}
getMD5(
document.getElementById("input_autofill").files[0],
prog => $('#btn_rfile_proc').text("Processing "+ (prog * 100).toFixed(2) + "%")
).then(
res => on_done_hash(res),
err => console.error(err)
);
}
function on_done_hash(result) {
$('#btn_rfile_proc').text('Done processing');
$('form#form_edit_rfile #file_hash').val(result);
$('form#form_edit_rfile #filename').val(document.getElementById("input_autofill").files[0].name);
$('form#form_edit_rfile #file_size').val(document.getElementById("input_autofill").files[0].size);
}
function add_modal_rfile() {
url = 'evidences/add/modal' + case_param();
$('#modal_add_rfiles_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_evidence_desc_editor = get_new_ace_editor('evidence_description', 'evidence_desc_content', 'target_evidence_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null);
g_evidence_desc_editor.setOption("minLines", "10");
edit_in_evidence_desc();
headers = get_editor_headers('g_evidence_desc_editor', null, 'evidence_edition_btn');
$('#evidence_edition_btn').append(headers);
$('#modal_add_rfiles').modal({ show: true });
$('#filename').focus();
});
}
function add_rfile() {
var data_sent = $('form#form_edit_rfile').serializeObject();
data_sent['csrf_token'] = $('#csrf_token').val();
data_sent['file_description'] = g_evidence_desc_editor.getValue();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
post_request_api('/case/evidences/add', JSON.stringify(data_sent), true)
.done((data) => {
notify_auto_api(data);
get_case_rfiles();
$('#modal_add_rfiles').modal("hide");
});
return false;
}
function readChunked(file, chunkCallback, endCallback) {
var fileSize = file.size;
var chunkSize = 4 * 1024 * 1024; // 4MB
var offset = 0;
var reader = new FileReader();
reader.onload = function() {
if (reader.error) {
endCallback(reader.error || {});
return;
}
offset += reader.result.length;
// callback for handling read chunk
// TODO: handle errors
chunkCallback(reader.result, offset, fileSize);
if (offset >= fileSize) {
endCallback(null);
return;
}
readNext();
};
reader.onerror = function(err) {
endCallback(err || {});
};
function readNext() {
var fileSlice = file.slice(offset, offset + chunkSize);
reader.readAsBinaryString(fileSlice);
}
readNext();
}
function getMD5(blob, cbProgress) {
return new Promise((resolve, reject) => {
var md5 = CryptoJS.algo.MD5.create();
readChunked(blob, (chunk, offs, total) => {
md5.update(CryptoJS.enc.Latin1.parse(chunk));
if (cbProgress) {
cbProgress(offs / total);
}
}, err => {
if (err) {
reject(err);
} else {
// TODO: Handle errors
var hash = md5.finalize();
var hashHex = hash.toString(CryptoJS.enc.Hex);
resolve(hashHex);
}
});
});
}
/* Retrieve the list of rfiles and build a datatable for each type of rfiles */
function get_case_rfiles() {
get_request_api("/case/evidences/list")
.done(function (response) {
if (response.status == 'success') {
if (response.data != null) {
jsdata = response.data;
Table.clear();
Table.rows.add(jsdata.evidences);
Table.columns.adjust().draw();
load_menu_mod_options('evidence', Table, delete_rfile);
set_last_state(jsdata.state);
hide_loader();
$('#rfiles_table_wrapper').show();
Table.responsive.recalc();
} else {
Table.clear().draw();
swal("Oh no !", data.message, "error")
}
} else {
Table.clear().draw()
}
});
}
/* Edit an rfiles */
function edit_rfiles(rfiles_id) {
url = 'evidences/' + rfiles_id + '/modal' + case_param();
$('#modal_add_rfiles_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_evidence_id = rfiles_id;
g_evidence_desc_editor = get_new_ace_editor('evidence_description', 'evidence_desc_content', 'target_evidence_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
$('#submit_new_evidence').text("Unsaved").removeClass('btn-success').addClass('btn-outline-warning').removeClass('btn-outline-danger');
}, null);
g_evidence_desc_editor.setOption("minLines", "6");
preview_evidence_description(true);
headers = get_editor_headers('g_evidence_desc_editor', null, 'evidence_edition_btn');
$('#evidence_edition_btn').append(headers);
load_menu_mod_options_modal(rfiles_id, 'evidence', $("#evidence_modal_quick_actions"));
$('#modal_add_rfiles').modal({ show: true });
edit_in_evidence_desc();
});
}
function preview_evidence_description(no_btn_update) {
if(!$('#container_evidence_description').is(':visible')) {
evidence_desc = g_evidence_desc_editor.getValue();
converter = get_showdown_convert();
html = converter.makeHtml(do_md_filter_xss(evidence_desc));
evidence_desc_html = do_md_filter_xss(html);
$('#target_evidence_desc').html(evidence_desc_html);
$('#container_evidence_description').show();
if (!no_btn_update) {
$('#evidence_preview_button').html('<i class="fa-solid fa-eye-slash"></i>');
}
$('#container_evidence_desc_content').hide();
}
else {
$('#container_evidence_description').hide();
if (!no_btn_update) {
$('#evidence_preview_button').html('<i class="fa-solid fa-eye"></i>');
}
$('#evidence_preview_button').html('<i class="fa-solid fa-eye"></i>');
$('#container_evidence_desc_content').show();
}
}
/* Update an rfiles */
function update_rfile(rfiles_id) {
var data_sent = $('form#form_edit_rfile').serializeObject();
data_sent['csrf_token'] = $('#csrf_token').val();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
data_sent['file_description'] = g_evidence_desc_editor.getValue();
post_request_api('evidences/update/' + rfiles_id, JSON.stringify(data_sent), true)
.done((data) => {
notify_auto_api(data);
reload_rfiles();
});
}
/* Delete an rfiles */
function delete_rfile(rfiles_id) {
do_deletion_prompt("You are about to delete evidence #" + rfiles_id)
.then((doDelete) => {
if (doDelete) {
post_request_api('evidences/delete/' + rfiles_id)
.done(function(data){
reload_rfiles();
$('#modal_add_rfiles').modal('hide');
notify_auto_api(data);
});
}
});
}
/* Page is ready, fetch the rfiles of the case */
$(document).ready(function(){
/* add filtering fields for each table of the page (must be done before datatable initialization) */
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
Table = $("#rfiles_table").DataTable({
dom: '<"container-fluid"<"row"<"col"l><"col"f>>>rt<"container-fluid"<"row"<"col"i><"col"p>>>',
fixedHeader: true,
aaData: [],
aoColumns: [
{
"data": "filename",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
if (isWhiteSpace(data)) {
data = '#' + row['id'];
} else {
data = sanitizeHTML(data);
}
share_link = buildShareLink(row['id']);
data = '<a data-toggle="tooltip" data-selector="true" href="' + share_link + '" title="Evidence ID #' + row['id'] + '" onclick="edit_rfiles(\'' + row['id'] + '\');return false;">' + data +'</a>';
}
return data;
}
},
{ "data": "date_added" },
{ "data": "file_hash",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{ "data": "file_size",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}},
{ "data": "file_description",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}},
{ "data": "username",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}}
],
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
buttons: [
],
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.childRow,
renderer: $.fn.dataTable.Responsive.renderer.tableAll()
}
},
orderCellsTop: true,
initComplete: function () {
tableFiltering(this.api(), 'rfiles_table');
},
select: true
});
$("#rfiles_table").css("font-size", 12);
var buttons = new $.fn.dataTable.Buttons(Table, {
buttons: [
{ "extend": 'csvHtml5', "text":'<i class="fas fa-cloud-download-alt"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Download as CSV', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } } ,
{ "extend": 'copyHtml5', "text":'<i class="fas fa-copy"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Copy', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } },
{ "extend": 'colvis', "text":'<i class="fas fa-eye-slash"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Toggle columns' }
]
}).container().appendTo($('#tables_button'));
Table.on( 'responsive-resize', function ( e, datatable, columns ) {
hide_table_search_input( columns );
});
get_case_rfiles();
setInterval(function() { check_update('evidences/state'); }, 3000);
/* Modal to add rfiles is closed, clear its contents */
$('.modal').on('hidden.bs.modal', function () {
$(this).find('form').trigger('reset');
$('#btn_rfile_proc').text('Process');
})
shared_id = getSharedLink();
if (shared_id) {
edit_rfiles(shared_id);
}
});

View File

@ -0,0 +1,514 @@
var session_id = null ;
var collaborator = null ;
var buffer_dumped = false ;
var last_applied_change = null ;
var just_cleared_buffer = null ;
var from_sync = null;
var editor = ace.edit("editor_summary",
{
autoScrollEditorIntoView: true,
minLines: 4
});
var textarea = $('#case_summary');
function Collaborator( session_id ) {
this.collaboration_socket = io.connect() ;
this.channel = "case-" + session_id;
this.collaboration_socket.emit('join', { 'channel': this.channel });
this.collaboration_socket.on( "change", function(data) {
delta = JSON.parse( data.delta ) ;
console.log(delta);
last_applied_change = delta ;
$("#content_typing").text(data.last_change + " is typing..");
editor.getSession().getDocument().applyDeltas( [delta] ) ;
}.bind() ) ;
this.collaboration_socket.on( "clear_buffer", function() {
just_cleared_buffer = true ;
console.log( "setting editor empty" ) ;
editor.setValue( "" ) ;
}.bind() ) ;
this.collaboration_socket.on( "save", function(data) {
$("#content_last_saved_by").text("Last saved by " + data.last_saved);
sync_editor(true);
}.bind() ) ;
}
Collaborator.prototype.change = function( delta ) {
this.collaboration_socket.emit( "change", { 'delta': delta, 'channel': this.channel } ) ;
}
Collaborator.prototype.clear_buffer = function() {
this.collaboration_socket.emit( "clear_buffer", { 'channel': this.channel } ) ;
}
Collaborator.prototype.save = function() {
this.collaboration_socket.emit( "save", { 'channel': this.channel } ) ;
}
function body_loaded() {
collaborator = new Collaborator( get_caseid() ) ;
// registering change callback
from_sync = true;
editor.on( "change", function( e ) {
// TODO, we could make things more efficient and not likely to conflict by keeping track of change IDs
if( last_applied_change!=e && editor.curOp && editor.curOp.command.name) {
collaborator.change( JSON.stringify(e) ) ;
}
}, false );
editor.$blockScrolling = Infinity ;
document.getElementsByTagName('textarea')[0].focus() ;
last_applied_change = null ;
just_cleared_buffer = false ;
}
function handle_ed_paste(event) {
filename = null;
const { items } = event.originalEvent.clipboardData;
for (let i = 0; i < items.length; i += 1) {
const item = items[i];
if (item.kind === 'string') {
item.getAsString(function (s){
filename = $.trim(s.replace(/\t|\n|\r/g, '')).substring(0, 40);
});
}
if (item.kind === 'file') {
const blob = item.getAsFile();
if (blob !== null) {
const reader = new FileReader();
reader.onload = (e) => {
notify_success('The file is uploading in background. Don\'t leave the page');
if (filename === null) {
filename = random_filename(25);
}
upload_interactive_data(e.target.result, filename, function(data){
url = data.data.file_url + case_param();
event.preventDefault();
editor.insertSnippet(`\n![${filename}](${url} =40%x40%)\n`);
});
};
reader.readAsDataURL(blob);
} else {
notify_error('Unsupported direct paste of this item. Use datastore to upload.');
}
}
}
}
function report_template_selector() {
$('#modal_select_report').modal({ show: true });
}
function gen_report(safe) {
url = '/case/report/generate-investigation/' + $("#select_report option:selected").val() + case_param();
if (safe === true) {
url += '&safe=true';
}
window.open(url, '_blank');
}
function gen_act_report(safe) {
url = '/case/report/generate-activities/' + $("#select_report_act option:selected").val() + case_param();
if (safe === true) {
url += '&safe=true';
}
window.open(url, '_blank');
}
function act_report_template_selector() {
$('#modal_select_report_act').modal({ show: true });
}
function edit_case_summary() {
$('#container_editor_summary').toggle();
if ($('#container_editor_summary').is(':visible')) {
$('#ctrd_casesum').removeClass('col-md-12').addClass('col-md-6');
$('#summary_edition_btn').show(100);
$("#sum_refresh_btn").html('Save');
$("#sum_edit_btn").html('Close editor');
} else {
$('#ctrd_casesum').removeClass('col-md-6').addClass('col-md-12');
$('#summary_edition_btn').hide();
$("#sum_refresh_btn").html('Refresh');
$("#sum_edit_btn").html('Edit');
}
}
/* sync_editor
* Save the editor state.
* Check if there are external changes first.
* Copy local changes if conflict
*/
function sync_editor(no_check) {
$('#last_saved').text('Syncing..').addClass('badge-danger').removeClass('badge-success');
get_request_api('/case/summary/fetch')
.done((data) => {
if (data.status == 'success') {
if (no_check) {
// Set the content from remote server
from_sync = true;
editor.getSession().setValue(data.data.case_description);
// Set the CRC in page
$('#fetched_crc').val(data.data.crc32.toString());
$('#last_saved').text('Changes saved').removeClass('badge-danger').addClass('badge-success');
$('#content_last_sync').text("Last synced: " + new Date().toLocaleTimeString());
}
else {
// Check if content is different
st = editor.getSession().getValue();
if (data.data.crc32 != $('#fetched_crc').val()) {
// Content has changed remotely
// Check if we have changes locally
local_crc = crc32(st).toString();
console.log('Content changed. Local CRC is ' + local_crc);
console.log('Saved CRC is ' + $('#fetched_crc').val());
console.log('Remote CRC is ' + data.data.crc32);
if (local_crc == $('#fetched_crc').val()) {
// No local change, we can sync and update local CRC
editor.getSession().setValue(data.data.case_description);
$('#fetched_crc').val(data.data.crc32);
$('#last_saved').text('Changes saved').removeClass('badge-danger').addClass('badge-success');
$('#content_last_sync').text("Last synced: " + new Date().toLocaleTimeString());
} else {
// We have a conflict
$('#last_saved').text('Conflict !').addClass('badge-danger').removeClass('badge-success');
swal ( "Oh no !" ,
"We have a conflict with the remote content.\nSomeone may just have changed the description at the same time.\nThe local content will be copied into clipboard and content will be updated with remote." ,
"error"
).then((value) => {
// Old fashion trick
editor.selectAll();
editor.focus();
document.execCommand('copy');
editor.getSession().setValue(data.data.desc);
$('#fetched_crc').val(data.data.crc32);
notify_success('Content updated with remote. Local changes copied to clipboard.');
$('#content_last_sync').text("Last synced: " + new Date().toLocaleTimeString());
});
}
} else {
// Content did not change remotely
// Check local change
local_crc = crc32(st).toString();
if (local_crc != $('#fetched_crc').val()) {
console.log('Local change. Old CRC is ' + local_crc);
console.log('New CRC is ' + $('#fetched_crc').val());
var data = Object();
data['case_description'] = st;
data['csrf_token'] = $('#csrf_token').val();
// Local change detected. Update to remote
$.ajax({
url: '/case/summary/update' + case_param(),
type: "POST",
dataType: "json",
contentType: "application/json;charset=UTF-8",
data: JSON.stringify(data),
success: function (data) {
if (data.status == 'success') {
collaborator.save();
$('#content_last_sync').text("Last synced: " + new Date().toLocaleTimeString());
$('#fetched_crc').val(data.data);
$('#last_saved').text('Changes saved').removeClass('badge-danger').addClass('badge-success');
} else {
notify_error("Unable to save content to remote server");
$('#last_saved').text('Error saving !').addClass('badge-danger').removeClass('badge-success');
}
},
error: function(error) {
notify_error(error.responseJSON.message);
('#last_saved').text('Error saving !').addClass('badge-danger').removeClass('badge-success');
}
});
}
$('#content_last_sync').text("Last synced: " + new Date().toLocaleTimeString());
$('#last_saved').text('Changes saved').removeClass('badge-danger').addClass('badge-success');
}
}
}
});
}
is_typing = "";
function auto_remove_typing() {
if ($("#content_typing").text() == is_typing) {
$("#content_typing").text("");
} else {
is_typing = $("#content_typing").text();
}
}
function case_pipeline_popup() {
url = '/case/pipelines-modal' + case_param();
$('#info_case_modal_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_case_detail').modal({ show: true });
$("#update_pipeline_selector").selectpicker({
liveSearch: true,
style: "btn-outline-white"
})
$('#update_pipeline_selector').selectpicker("refresh");
$(".control-update-pipeline-args ").hide();
$('.control-update-pipeline-'+ $('#update_pipeline_selector').val() ).show();
$('#update_pipeline_selector').on('change', function(e){
$(".control-update-pipeline-args ").hide();
$('.control-update-pipeline-'+this.value).show();
});
$('[data-toggle="popover"]').popover();
});
}
async function do_case_review(action, reviewer_id) {
let data = Object();
data['csrf_token'] = $('#csrf_token').val();
data['action'] = action;
if (reviewer_id) {
data['reviewer_id'] = reviewer_id;
}
return post_request_api('/case/review/update', JSON.stringify(data));
}
function case_detail(case_id, edit_mode=false) {
url = '/case/details/' + case_id + case_param();
$('#info_case_modal_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_case_detail').modal({ show: true });
if (edit_mode) {
edit_case_info();
}
});
}
function manage_case(case_id) {
window.location = '/manage/cases?cid='+ case_id +'#view';
}
$(document).ready(function() {
if ($("#editor_summary").attr("data-theme") !== "dark") {
editor.setTheme("ace/theme/tomorrow");
} else {
editor.setTheme("ace/theme/iris_night");
}
editor.session.setMode("ace/mode/markdown");
editor.renderer.setShowGutter(true);
editor.setOption("showLineNumbers", true);
editor.setOption("showPrintMargin", false);
editor.setOption("displayIndentGuides", true);
editor.setOption("indentedSoftWrap", false);
editor.session.setUseWrapMode(true);
editor.setOption("maxLines", "Infinity")
editor.renderer.setScrollMargin(8, 5)
editor.setOption("enableBasicAutocompletion", true);
editor.commands.addCommand({
name: 'save',
bindKey: {win: "Ctrl-S", "mac": "Cmd-S"},
exec: function(editor) {
sync_editor(false);
}
})
editor.commands.addCommand({
name: 'bold',
bindKey: {win: "Ctrl-B", "mac": "Cmd-B"},
exec: function(editor) {
editor.insertSnippet('**${1:$SELECTION}**');
}
});
editor.commands.addCommand({
name: 'italic',
bindKey: {win: "Ctrl-I", "mac": "Cmd-I"},
exec: function(editor) {
editor.insertSnippet('*${1:$SELECTION}*');
}
});
editor.commands.addCommand({
name: 'head_1',
bindKey: {win: "Ctrl-Shift-1", "mac": "Cmd-Shift-1"},
exec: function(editor) {
editor.insertSnippet('# ${1:$SELECTION}');
}
});
editor.commands.addCommand({
name: 'head_2',
bindKey: {win: "Ctrl-Shift-2", "mac": "Cmd-Shift-2"},
exec: function(editor) {
editor.insertSnippet('## ${1:$SELECTION}');
}
});
editor.commands.addCommand({
name: 'head_3',
bindKey: {win: "Ctrl-Shift-3", "mac": "Cmd-Shift-3"},
exec: function(editor) {
editor.insertSnippet('### ${1:$SELECTION}');
}
});
editor.commands.addCommand({
name: 'head_4',
bindKey: {win: "Ctrl-Shift-4", "mac": "Cmd-Shift-4"},
exec: function(editor) {
editor.insertSnippet('#### ${1:$SELECTION}');
}
});
$('#editor_summary').on('paste', (event) => {
event.preventDefault();
handle_ed_paste(event);
});
var timer;
var timeout = 10000;
$('#editor_summary').keyup(function(){
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(sync_editor, timeout);
});
//var textarea = $('#case_summary');
editor.getSession().on("change", function () {
//textarea.val(do_md_filter_xss(editor.getSession().getValue()));
$('#last_saved').text('Changes not saved').addClass('badge-danger').removeClass('badge-success');
let target = document.getElementById('targetDiv');
let converter = get_showdown_convert();
let html = converter.makeHtml(do_md_filter_xss(editor.getSession().getValue()));
target.innerHTML = do_md_filter_xss(html);
});
edit_case_summary();
body_loaded();
sync_editor(true);
setInterval(auto_remove_typing, 2000);
let review_state = $('#caseReviewState');
if (review_state.length > 0) {
let current_review_state = review_state.data('review-state');
if (current_review_state === 'Review in progress') {
$(".btn-start-review").hide();
$(".btn-confirm-review").show();
$(".btn-cancel-review").show();
$('#reviewSubtitle').text('You started this review. Press "Confirm review" when you are done.');
} else if (current_review_state === 'Review completed') {
$(".btn-start-review").hide();
$(".btn-confirm-review").hide();
$(".btn-cancel-review").hide();
} else if (current_review_state === 'Pending review') {
$(".btn-start-review").show();
$(".btn-confirm-review").hide();
$(".btn-cancel-review").hide();
}
$('.review-card').show();
}
$('.btn-start-review').on('click', function(e){
do_case_review('start').then(function(data) {
if (notify_auto_api(data)) {
location.reload();
}
});
});
$('.btn-confirm-review').on('click', function(e){
do_case_review('done').then(function(data) {
if (notify_auto_api(data)) {
location.reload();
}
});
});
$('.btn-cancel-review').on('click', function(e){
do_case_review('cancel').then(function(data) {
if (notify_auto_api(data)) {
location.reload();
}
});
});
$('#request_review').on('click', function(e){
let reviewer_id = $('#caseReviewState').data('reviewer-id');
let reviewer_name = $('#caseReviewState').data('reviewer-name');
if (reviewer_id !== "None") {
swal({
title: "Request review",
text: "Request a case review from " + reviewer_name + "?",
icon: "info",
buttons: true,
dangerMode: false,
}).then((willRequest) => {
if (willRequest) {
do_case_review('request', reviewer_id).then(function (data) {
if (notify_auto_api(data)) {
location.reload();
}
});
}
});
} else {
$('#reviewer_id').selectpicker({
liveSearch: true,
size: 10,
width: '100%'
});
get_request_api('/case/users/list')
.done((data) => {
if (notify_auto_api(data)) {
let users = data.data;
let options = '';
for (let i = 0; i < users.length; i++) {
if (users[i].user_access_level === 4) {
options += '<option value="' + users[i].user_id + '">' + filterXSS(users[i].user_name) + '</option>';
}
}
$('#reviewer_id').html(options);
$('#reviewer_id').selectpicker('refresh');
$('#modal_choose_reviewer').modal('show');
$('#submit_set_reviewer').off('click').on('click', function(e){
let reviewer_id = $('#reviewer_id').val();
do_case_review('request', reviewer_id).then(function (data) {
if (notify_auto_api(data)) {
location.reload();
}
});
});
}
});
}
});
});

View File

@ -0,0 +1,466 @@
var current_users_list = [];
var g_task_id = null;
var g_task_desc_editor = null;
function edit_in_task_desc() {
if($('#container_task_desc_content').is(':visible')) {
$('#container_task_description').show(100);
$('#container_task_desc_content').hide(100);
$('#task_edition_btn').hide(100);
$('#task_preview_button').hide(100);
} else {
$('#task_preview_button').show(100);
$('#task_edition_btn').show(100);
$('#container_task_desc_content').show(100);
$('#container_task_description').hide(100);
}
}
/* Fetch a modal that allows to add an event */
function add_task() {
url = 'tasks/add/modal' + case_param();
$('#modal_add_task_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_task_desc_editor = get_new_ace_editor('task_description', 'task_desc_content', 'target_task_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null);
g_task_desc_editor.setOption("minLines", "10");
edit_in_task_desc();
headers = get_editor_headers('g_task_desc_editor', null, 'task_edition_btn');
$('#task_edition_btn').append(headers);
$('#submit_new_task').on("click", function () {
clear_api_error();
if(!$('form#form_new_task').valid()) {
return false;
}
var data_sent = $('#form_new_task').serializeObject();
data_sent['task_tags'] = $('#task_tags').val();
data_sent['task_assignees_id'] = $('#task_assignees_id').val();
data_sent['task_status_id'] = $('#task_status_id').val();
data_sent['task_description'] = g_task_desc_editor.getValue();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
post_request_api('tasks/add', JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
get_tasks();
$('#modal_add_task').modal('hide');
}
});
return false;
})
$('#modal_add_task').modal({ show: true });
$('#task_title').focus();
});
}
function save_task() {
$('#submit_new_task').click();
}
function update_task(task_id) {
update_task_ext(task_id, true);
}
function update_task_ext(task_id, do_close) {
clear_api_error();
if(!$('form#form_new_task').valid()) {
return false;
}
if (task_id === undefined || task_id === null) {
task_id = g_task_id;
}
var data_sent = $('#form_new_task').serializeObject();
data_sent['task_tags'] = $('#task_tags').val();
data_sent['task_assignees_id'] = $('#task_assignees_id').val();
data_sent['task_status_id'] = $('#task_status_id').val();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
data_sent['task_description'] = g_task_desc_editor.getValue();
$('#update_task_btn').text('Updating..');
post_request_api('tasks/update/' + task_id, JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
get_tasks();
$('#submit_new_task').text("Saved").addClass('btn-outline-success').removeClass('btn-outline-danger').removeClass('btn-outline-warning');
$('#last_saved').removeClass('btn-danger').addClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-check");
if (do_close !== undefined && do_close === true) {
$('#modal_add_task').modal('hide');
}
}
})
.always(() => {
$('#update_task_btn').text('Update');
});
}
/* Delete an event from the timeline thank to its id */
function delete_task(id) {
do_deletion_prompt("You are about to delete task #" + id)
.then((doDelete) => {
if (doDelete) {
post_request_api("tasks/delete/" + id)
.done((data) => {
if(notify_auto_api(data)) {
get_tasks();
$('#modal_add_task').modal('hide');
}
});
}
});
}
/* Edit and event from the timeline thanks to its ID */
function edit_task(id) {
url = '/case/tasks/'+ id + '/modal' + case_param();
$('#modal_add_task_content').load(url, function (response, status, xhr) {
hide_minimized_modal_box();
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
g_task_id = id;
g_task_desc_editor = get_new_ace_editor('task_description', 'task_desc_content', 'target_task_desc',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null);
g_task_desc_editor.setOption("minLines", "6");
preview_task_description(true);
headers = get_editor_headers('g_task_desc_editor', null, 'task_edition_btn');
$('#task_edition_btn').append(headers);
load_menu_mod_options_modal(id, 'task', $("#task_modal_quick_actions"));
$('#modal_add_task').modal({show:true});
edit_in_task_desc();
});
}
function preview_task_description(no_btn_update) {
if(!$('#container_task_description').is(':visible')) {
task_desc = g_task_desc_editor.getValue();
converter = get_showdown_convert();
html = converter.makeHtml(do_md_filter_xss(task_desc));
task_desc_html = do_md_filter_xss(html);
$('#target_task_desc').html(task_desc_html);
$('#container_task_description').show();
if (!no_btn_update) {
$('#task_preview_button').html('<i class="fa-solid fa-eye-slash"></i>');
}
$('#container_task_desc_content').hide();
}
else {
$('#container_task_description').hide();
if (!no_btn_update) {
$('#task_preview_button').html('<i class="fa-solid fa-eye"></i>');
}
$('#task_preview_button').html('<i class="fa-solid fa-eye"></i>');
$('#container_task_desc_content').show();
}
}
/* Fetch and draw the tasks */
function get_tasks() {
$('#tasks_list').empty();
show_loader();
get_request_api("tasks/list")
.done((data) => {
if (data.status == 'success') {
Table.MakeCellsEditable("destroy");
tasks_list = data.data.tasks;
options_l = data.data.tasks_status;
options = [];
for (index in options_l) {
option = options_l[index];
options.push({ "value": option.id, "display": option.status_name })
}
Table.clear();
Table.rows.add(tasks_list);
Table.MakeCellsEditable({
"onUpdate": callBackEditTaskStatus,
"inputCss": 'form-control col-12',
"columns": [2],
"allowNulls": {
"columns": [2],
"errorClass": 'error'
},
"confirmationButton": {
"confirmCss": 'my-confirm-class',
"cancelCss": 'my-cancel-class'
},
"inputTypes": [
{
"column": 2,
"type": "list",
"options": options
}
]
});
Table.columns.adjust().draw();
load_menu_mod_options('task', Table, delete_task);
$('[data-toggle="popover"]').popover();
Table.responsive.recalc();
set_last_state(data.data.state);
hide_loader();
}
});
}
function refresh_users(on_finish, cur_assignees_id_list) {
get_request_api('/case/users/list')
.done((data) => {
if(notify_auto_api(data, true)) {
current_users_list = data.data;
if (on_finish !== undefined) {
on_finish(current_users_list, cur_assignees_id_list);
}
}
});
}
function do_list_users(list_users, cur_assignees_id_list) {
$('#task_assignees_id').selectpicker({
liveSearch: true,
title: "Select assignee(s)"
});
for (let user in list_users) {
if (list_users[user].user_access_level === 4) {
$('#task_assignees_id').append(new Option(`${filterXSS(list_users[user].user_login)} (${filterXSS(list_users[user].user_name)})`,
list_users[user].user_id));
}
}
if (cur_assignees_id_list !== undefined) {
$('#task_assignees_id').selectpicker('val', cur_assignees_id_list);
}
$('#task_assignees_id').selectpicker('refresh');
}
function callBackEditTaskStatus(updatedCell, updatedRow, oldValue) {
data_send = updatedRow.data();
data_send['csrf_token'] = $('#csrf_token').val();
tid = data_send['task_id'];
post_request_api("tasks/status/update/" + tid, JSON.stringify(data_send))
.done(function (data){
if(notify_auto_api(data)) {
get_tasks();
}
});
}
/* Page is ready, fetch the assets of the case */
$(document).ready(function(){
/* add filtering fields for each table of the page (must be done before datatable initialization) */
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
Table = $("#tasks_table").DataTable({
dom: '<"container-fluid"<"row"<"col"l><"col"f>>>rt<"container-fluid"<"row"<"col"i><"col"p>>>',
aaData: [],
fixedHeader: true,
aoColumns: [
{
"data": "task_title",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
if (isWhiteSpace(data)) {
data = '#' + row['task_id'];
} else {
data = sanitizeHTML(data);
}
share_link = buildShareLink(row['task_id']);
data = '<a href="'+ share_link + '" data-selector="true" title="Task ID #'+ row['task_id'] +'" onclick="edit_task(\'' + row['task_id'] + '\');return false;">' + data +'</a>';
}
return data;
}
},
{ "data": "task_description",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover" style="cursor: pointer;" title="Info" data-trigger="hover" href="#" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{
"data": "task_status_id",
"render": function(data, type, row) {
if (type === 'display') {
data = sanitizeHTML(data);
data = '<span class="badge ml-2 badge-'+ row['status_bscolor'] +'">' + row['status_name'] + '</span>';
}
else if (type === 'filter' || type === 'sort'){
data = row['status_name']
} else if (type === 'export') {
data = row['status_name']
}
return data;
}
},
{
"data": "task_assignees",
"render": function (data, type, row, meta) {
if (data != null) {
names = "";
if (data.length > 0) {
lst = [];
data.forEach(function (item, index) { lst.push(item['name']); });
if (type === 'display') {
names = list_to_badges(lst, 'primary', 10, 'users');
}
else {
lst.forEach(function (item, index) {
names += `${sanitizeHTML(item)}`;
});
}
}
else {
if (type === 'display') {
names = '<span class="badge badge-light ml-2">' + "Unassigned" + '</span>';
}
else {
names = "Unassigned";
}
}
return names;
}
return data;
}
},
{
"data": "task_open_date",
"render": function (data, type, row, meta) { return sanitizeHTML(data);}
},
{ "data": "task_tags",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
tags = "";
de = data.split(',');
for (tag in de) {
tags += '<span class="badge badge-primary ml-2">' + sanitizeHTML(de[tag]) + '</span>';
}
return tags;
}
return data;
}
}
],
rowCallback: function (nRow, data) {
nRow = '<span class="badge ml-2 badge-'+ sanitizeHTML(data['status_bscolor']) +'">' + sanitizeHTML(data['status_name']) + '</span>';
},
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
pageLength: 50,
order: [[ 2, "asc" ]],
buttons: [
],
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.childRow,
renderer: $.fn.dataTable.Responsive.renderer.tableAll()
}
},
orderCellsTop: true,
initComplete: function () {
tableFiltering(this.api(), 'tasks_table');
},
select: true
});
$("#tasks_table").css("font-size", 12);
Table.on( 'responsive-resize', function ( e, datatable, columns ) {
hide_table_search_input( columns );
});
var buttons = new $.fn.dataTable.Buttons(Table, {
buttons: [
{ "extend": 'csvHtml5', "text":'<i class="fas fa-cloud-download-alt"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Download as CSV', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } } ,
{ "extend": 'copyHtml5', "text":'<i class="fas fa-copy"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Copy', "exportOptions": { "columns": ':visible', 'orthogonal': 'export' } },
{ "extend": 'colvis', "text":'<i class="fas fa-eye-slash"></i>',"className": 'btn btn-link text-white'
, "titleAttr": 'Toggle columns' }
]
}).container().appendTo($('#tables_button'));
get_tasks();
setInterval(function() { check_update('tasks/state'); }, 3000);
shared_id = getSharedLink();
if (shared_id) {
edit_task(shared_id);
}
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
function visualizeTimeline(group) {
ggr = ['asset', 'category']
if (group == 'asset') {
src = '/case/timeline/visualize/data/by-asset';
} else {
src = '/case/timeline/visualize/data/by-category';
}
get_request_api(src)
.done((data) => {
if (data.status == 'success') {
var items = new vis.DataSet();
groups = new vis.DataSet();
groups_l = []
if (data.data.events.length == 0) {
$('#card_main_load').show();
$('#visualization').text('No events in summary');
hide_loader();
return true;
}
for (index in data.data.events) {
event = data.data.events[index];
if (!groups_l.includes(event.group)){
groups.add({
id: groups_l.length,
content: event.group
})
groups_l.push(event.group);
}
items.add({
id: index,
group: groups_l.indexOf(event.group),
start: event.date,
content: event.content,
style: event.style,
title: event.title
})
}
// specify options
var options = {
stack: true,
minHeight: '400px',
maxHeight: $(window).height() - 250,
start: data.data.events[0].date,
end: data.data.events[data.data.events.length - 1].date,
};
// create a Timeline
var container = document.getElementById('visualization');
container.innerHTML = '';
$('#card_main_load').show();
timeline = new vis.Timeline(container, null, options);
if (ggr.includes(group)) {
timeline.setGroups(groups);
}
timeline.setItems(items);
hide_loader();
}
});
}
function refresh_timeline_graph(){
show_loader();
queryString = window.location.search;
urlParams = new URLSearchParams(queryString);
group = urlParams.get('group-by');
visualizeTimeline(group);
}

View File

@ -0,0 +1,261 @@
var g_comment_desc_editor = null;
function comment_element(element_id, element_type, is_alert=false) {
const prefix = is_alert ? '/alerts' : `/case/${element_type}`;
const url = `${prefix}/${element_id}/comments/modal`;
$('#modal_comment_content').load(url + case_param(),
function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_comment_content').resizable({
minHeight: 300,
minWidth: 300,
handles: "n, e, s, w, ne, se, sw, nw"
});
$('.modal-comment').draggable({
cursor: 'move'
});
$('#modal_comment').modal('show');
g_comment_desc_editor = get_new_ace_editor('comment_message', 'comment_content', 'target_comment_content',
function() {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
}, null, false, false);
headers = get_editor_headers('g_comment_desc_editor', null, 'comment_edition_btn');
$('#comment_edition_btn').append(headers);
load_comments(element_id, element_type, undefined, undefined, is_alert);
}
);
}
function preview_comment() {
if(!$('#container_comment_preview').is(':visible')) {
let comment_text = g_comment_desc_editor.getValue();
let converter = get_showdown_convert();
let html = converter.makeHtml(comment_text);
let comment_html = do_md_filter_xss(html);
$('#target_comment_content').html(comment_html);
$('#container_comment_preview').show();
$('#comment_preview_button').html('<i class="fa-solid fa-eye-slash"></i> Edit');
$('#container_comment_content').hide();
}
else {
$('#container_comment_preview').hide();
$('#comment_preview_button').html('<i class="fa-solid fa-eye"></i> Preview');
$('#container_comment_content').show();
}
}
function save_comment(element_id, element_type) {
save_comment_ext(element_id, element_type, false);
}
function save_comment_ext(element_id, element_type, do_close){
data = Object();
data['comment_text'] = g_comment_desc_editor.getValue();
data['csrf_token'] = $('#csrf_token').val();
const is_alert = element_type === 'alerts';
const prefix = is_alert ? '/alerts' : `/case/${element_type}`;
post_request_api(`${prefix}/${element_id}/comments/add`, JSON.stringify(data), true)
.done((data) => {
if(notify_auto_api(data)) {
load_comments(element_id, element_type, undefined, undefined, is_alert);
g_comment_desc_editor.setValue('');
increase_modal_comments_count(element_type, element_id);
}
});
}
function decrease_modal_comments_count(element_type, element_id) {
let tid = '#object_comments_number';
if (element_type === 'timeline/events' || element_type === 'alerts') {
tid = '#object_comments_number_' + element_id;
}
let curr_count = $(tid).text();
if (curr_count > 0) {
$(tid).text(curr_count - 1);
if (element_type === 'timeline/events' || element_type === 'alerts') {
$('#object_comments_number').text(parseInt(curr_count) - 1);
}
}
}
function increase_modal_comments_count(element_type, element_id) {
let tid = '#object_comments_number';
if (element_type === 'timeline/events' || element_type === 'alerts') {
tid = '#object_comments_number_' + element_id;
}
let curr_count = $(tid).text();
if (curr_count === '') {
curr_count = 0;
}
$(tid).text(parseInt(curr_count) + 1);
if (element_type === 'timeline/events' || element_type === 'alerts') {
$('#object_comments_number').text(parseInt(curr_count) + 1);
}
}
function delete_comment(comment_id, element_id, element_type) {
do_deletion_prompt("You are about to delete comment #" + comment_id)
.then((doDelete) => {
if (doDelete) {
data = Object();
data['csrf_token'] = $('#csrf_token').val();
const is_alert = element_type === 'alerts';
const prefix = is_alert ? '/alerts' : `/case/${element_type}`;
post_request_api(`${prefix}/${element_id}/comments/${comment_id}/delete`, JSON.stringify(data))
.done((data) => {
if(notify_auto_api(data)) {
load_comments(element_id, element_type, undefined, undefined, is_alert);
decrease_modal_comments_count(element_type, element_id);
}
});
}
});
}
function edit_comment(comment_id, element_id, element_type) {
const is_alert = element_type === 'alerts';
const prefix = is_alert ? '/alerts' : `/case/${element_type}`;
get_request_api(`${prefix}/${element_id}/comments/${comment_id}`)
.done((data) => {
if(notify_auto_api(data, true)) {
$('#comment_'+comment_id).addClass('comment_editing');
$('#comment_'+comment_id).data('comment_id', comment_id);
g_comment_desc_editor.setValue(data.data.comment_text);
$('#comment_edition').show();
$('#comment_submit').hide();
$('#cancel_edition').show();
}
});
}
function save_edit_comment(element_id, element_type) {
data = Object();
data['comment_text'] = g_comment_desc_editor.getValue();
comment_id = $('.comment_editing').data('comment_id');
data['csrf_token'] = $('#csrf_token').val();
const is_alert = element_type === 'alerts';
const prefix = is_alert ? '/alerts' : `/case/${element_type}`;
post_request_api(`${prefix}/${element_id}/comments/${comment_id}/edit`, JSON.stringify(data), true)
.done((data) => {
if(notify_auto_api(data)) {
cancel_edition(comment_id);
load_comments(element_id, element_type, comment_id, undefined, is_alert);
}
});
}
function cancel_edition(comment_id) {
$('.comment_editing').css('background-color', '');
$('.comment_editing').css('border-radius', '');
$('.comment_editing').removeClass('comment_editing');
$('.comment_editing').data('comment_id', '');
$('#comment_edition').hide();
$('#cancel_edition').hide();
$('#comment_submit').show();
g_comment_desc_editor.setValue('');
}
function load_comments(element_id, element_type, comment_id, do_notification, is_alert=false) {
if (do_notification !== undefined) {
silent_success = !do_notification;
} else {
silent_success = true;
}
const prefix = is_alert || element_type === 'alerts' ? '/alerts' : `/case/${element_type}`;
get_request_api(`${prefix}/${element_id}/comments/list`)
.done((data) => {
if (notify_auto_api(data, silent_success)) {
$('#comments_list').empty();
var names = Object;
for (var i = 0; i < data['data'].length; i++) {
comment_text = data['data'][i].comment_text;
converter = get_showdown_convert();
html = converter.makeHtml(do_md_filter_xss(comment_text));
comment_html = do_md_filter_xss(html);
const username = data['data'][i].user.user_name;
if (names.hasOwnProperty(username)) {
avatar = names[username];
} else {
avatar = get_avatar_initials(username);
names[username] = avatar;
}
can_edit = "";
current_user = $('#current_username').text();
if (current_user === data['data'][i].user.user_login) {
can_edit = '<a href="#" class="btn btn-sm comment-edition-hidden" title="Edit comment" onclick="edit_comment(\'' + data['data'][i].comment_id + '\', \'' + element_id + '\',\''+ element_type +'\'); return false;"><i class="fa-solid fa-edit text-dark"></i></a>';
can_edit += '<a href="#" class="btn btn-sm comment-edition-hidden" title="Delete comment" onclick="delete_comment(\'' + data['data'][i].comment_id + '\', \'' + element_id + '\',\''+ element_type +'\'); return false;"><i class="fa-solid fa-trash text-dark"></i></a>';
}
comment = `
<div class="row mb-2 mr-1" >
<div class="col-12" id="comment_${data['data'][i].comment_id}">
<div class="row mt-2">
<div class="col">
<div class="row mr-2">
<div class="col">
<div class="ml-2 row">
${avatar}
<h6 class="text-uppercase fw-bold mb-1 ml-1 mt-2">${filterXSS(data['data'][i].name)}</h6>
<div class="ml-auto">
${can_edit} <small class="text-muted text-wrap">${data['data'][i].comment_date}</small>
</div>
</div>
<div class="row" style="border-left: 3px solid #eaeaea;margin-left:30px;">
<span class="text-muted ml-2">${comment_html}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
$('#comments_list').append(comment);
}
$('#comments_list').append('<div id="last-comment"><div>');
if (data['data'].length === 0) {
$('#comments_list').html('<div class="text-center">No comments yet</div>');
} else if (comment_id === undefined || comment_id === null) {
offset = document.getElementById("last-comment").offsetTop;
if (offset > 20) {
$('.comments-listing').animate({ scrollTop: offset});
}
} else {
if (document.getElementById('#comment_'+comment_id) !== null) {
offset = document.getElementById('#comment_'+comment_id).offsetTop;
if (offset > 20) {
$('.comments-listing').animate({ scrollTop: offset});
}
}
}
}
});
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
var makeCRCTable = function(){
var c;
var crcTable = [];
for(var n =0; n < 256; n++){
c = n;
for(var k =0; k < 8; k++){
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
}
crcTable[n] = c;
}
return crcTable;
}
var crc32 = function(str) {
var crcTable = window.crcTable || (window.crcTable = makeCRCTable());
var crc = 0 ^ (-1);
for (var i = 0; i < str.length; i++ ) {
crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF];
}
return (crc ^ (-1)) >>> 0;
};

View File

@ -0,0 +1,535 @@
let UserReviewsTable;
let UserCasesTable;
let UserTaskTable;
function check_page_update(){
update_gtasks_list();
update_utasks_list();
}
function task_status(id) {
url = 'tasks/status/human/'+id + case_param();
$('#info_task_modal_body').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_task_detail').modal({show:true});
});
}
async function update_ucases_list(show_all=false) {
$('#ucases_list').empty();
get_raw_request_api("/user/cases/list" + case_param() + "&show_closed=" + show_all)
.done((data) => {
if (notify_auto_api(data, true)) {
UserCasesTable.clear();
UserCasesTable.rows.add(data.data);
UserCasesTable.columns.adjust().draw();
UserCasesTable.buttons().container().appendTo($('#ucases_table_info'));
$('[data-toggle="popover"]').popover();
$('#ucases_last_updated').text("Last updated: " + new Date().toLocaleTimeString());
}
});
}
async function update_ureviews_list() {
get_raw_request_api("/user/reviews/list" + case_param())
.done((data) => {
if (notify_auto_api(data, true)) {
if (data.data.length == 0) {
$('#rowPendingCasesReview').hide();
return;
}
UserReviewsTable.clear();
UserReviewsTable.rows.add(data.data);
UserReviewsTable.columns.adjust().draw();
$('[data-toggle="popover"]').popover();
$('#ureviews_last_updated').text("Last updated: " + new Date().toLocaleTimeString());
$('#rowPendingCasesReview').show();
}
});
}
async function update_utasks_list() {
$('#utasks_list').empty();
return get_request_api("/user/tasks/list")
.done((data) => {
if (notify_auto_api(data, true)) {
UserTaskTable.MakeCellsEditable("destroy");
tasks_list = data.data.tasks;
$('#user_attr_count').text(tasks_list.length);
if (tasks_list.length != 0){
$('#icon_user_task').removeClass().addClass('flaticon-alarm text-danger');
} else {
$('#icon_user_task').removeClass().addClass('flaticon-success text-success');
}
options_l = data.data.tasks_status;
options = [];
for (index in options_l) {
option = options_l[index];
options.push({ "value": option.id, "display": option.status_name })
}
UserTaskTable.clear();
UserTaskTable.rows.add(tasks_list);
UserTaskTable.MakeCellsEditable({
"onUpdate": callBackEditUserTaskStatus,
"inputCss": 'form-control col-12',
"columns": [2],
"allowNulls": {
"columns": [2],
"errorClass": 'error'
},
"confirmationButton": {
"confirmCss": 'my-confirm-class',
"cancelCss": 'my-cancel-class'
},
"inputTypes": [
{
"column": 2,
"type": "list",
"options": options
}
]
});
UserTaskTable.columns.adjust().draw();
UserTaskTable.buttons().container().appendTo($('#utasks_table_info'));
$('[data-toggle="popover"]').popover();
$('#utasks_last_updated').text("Last updated: " + new Date().toLocaleTimeString());
}
});
}
function callBackEditUserTaskStatus(updatedCell, updatedRow, oldValue) {
data_send = updatedRow.data()
data_send['csrf_token'] = $('#csrf_token').val();
post_request_api("user/tasks/status/update", JSON.stringify(data_send))
.done((data) => {
if (notify_auto_api(data)) {
update_utasks_list();
UserTaskTable.columns.adjust().draw();
}
});
}
/**** GTASKS ****/
/* Fetch a modal that allows to add an event */
function add_gtask() {
url = '/global/tasks/add/modal' + case_param();
$('#modal_add_gtask_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_gtask').on("click", function () {
var data_sent = $('#form_new_gtask').serializeObject();
data_sent['task_tags'] = $('#task_tags').val();
data_sent['task_assignees_id'] = $('#task_assignees_id').val();
data_sent['task_status_id'] = $('#task_status_id').val();
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('/global/tasks/add', JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
update_gtasks_list();
$('#modal_add_gtask').modal('hide');
}
});
return false;
})
});
$('#modal_add_gtask').modal({ show: true });
}
function update_gtask(id) {
var data_sent = $('#form_new_gtask').serializeObject();
data_sent['task_tags'] = $('#task_tags').val();
data_sent['task_assignee_id'] = $('#task_assignee_id').val();
data_sent['task_status_id'] = $('#task_status_id').val();
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('/global/tasks/update/' + id, JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
update_gtasks_list();
$('#modal_add_gtask').modal('hide');
}
});
}
/* Delete an event from the timeline thank to its id */
function delete_gtask(id) {
post_request_api("/global/tasks/delete/" + id)
.done((data) => {
if(notify_auto_api(data)) {
update_gtasks_list();
$('#modal_add_gtask').modal('hide');
}
});
}
/* Edit and event from the timeline thanks to its ID */
function edit_gtask(id) {
url = '/global/tasks/update/'+ id + "/modal" + case_param();
$('#modal_add_gtask_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_add_gtask').modal({show:true});
});
}
/* Fetch and draw the tasks */
async function update_gtasks_list() {
$('#gtasks_list').empty();
return get_request_api("/global/tasks/list")
.done((data) => {
if(notify_auto_api(data, true)) {
Table.MakeCellsEditable("destroy");
tasks_list = data.data.tasks;
options_l = data.data.tasks_status;
options = [];
for (index in options_l) {
option = options_l[index];
options.push({ "value": option.id, "display": option.status_name })
}
Table.clear();
Table.rows.add(tasks_list);
Table.columns.adjust().draw();
Table.buttons().container().appendTo($('#gtasks_table_info'));
$('[data-toggle="popover"]').popover();
load_menu_mod_options('global_task', Table, delete_gtask);
$('#tasks_last_updated').text("Last updated: " + new Date().toLocaleTimeString());
}
});
}
$(document).ready(function() {
UserReviewsTable = $("#ureview_table").DataTable({
dom: 'frtip',
aaData: [],
aoColumns: [
{
"data": "name",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = `<a href="/case?cid=${row['case_id']}">${sanitizeHTML(data)}</a>`;
}
return data;
}
},
{
"data": "status_name",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = `<span class="badge badge-light">${sanitizeHTML(data)}</span>`;
}
return data;
}
}
],
ordering: false,
processing: true,
retrieve: true,
lengthChange: false,
pageLength: 10,
order: [[ 1, "asc" ]],
select: true
});
UserCasesTable = $("#ucases_table").DataTable({
dom: 'Blfrtip',
aaData: [],
aoColumns: [
{
"data": "name",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = `<a rel="noopener" target="_blank" href="/case?cid=${row['case_id']}">${sanitizeHTML(data)}</a>`;
}
return data;
}
},
{
"data": "description",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover" style="cursor: pointer;" title="Info" data-trigger="hover" href="#" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{
"data": "client",
"render": function(data, type, row, meta) {
if (type === 'display') {
//data = sanitizeHTML(data);
data = sanitizeHTML(row['client']['customer_name']);
}
return data;
}
},
{
"data": "open_date",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
}
return data;
}
},
{
"data": "tags",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
datas = '';
for (index in data) {
datas += '<span class="badge badge-primary">' + sanitizeHTML(data[index]['tag_title']) + '</span> ';
}
return datas;
}
return data;
}
}
],
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
lengthChange: false,
pageLength: 10,
order: [[ 2, "asc" ]],
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
],
select: true
});
$("#ucases_table").css("font-size", 12);
UserTaskTable = $("#utasks_table").DataTable({
dom: 'Blfrtip',
aaData: [],
aoColumns: [
{
"data": "task_title",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (isWhiteSpace(data)) {
data = '#' + row['task_id'];
} else {
data = sanitizeHTML(data);
}
data = '<a target="_blank" rel="noopener" href="case/tasks?cid='+ row['case_id'] + '&shared=' + row['task_id'] + '">' + data +'</a>';
}
return data;
}
},
{ "data": "task_description",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover" style="cursor: pointer;" title="Info" data-trigger="hover" href="#" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{
"data": "task_status_id",
"render": function(data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
data = '<span class="badge ml-2 badge-'+ row['status_bscolor'] +'">' + row['status_name'] + '</span>';
}
return data;
}
},
{
"data": "task_case",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
data = '<a href="/case?cid='+ row['case_id'] +'">' + data +'</a>';
}
return data;
}
},
{
"data": "task_last_update",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
data = sanitizeHTML(data);
data = data.replace(/GMT/g, "");
}
return data;
}
},
{ "data": "task_tags",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
tags = "";
de = data.split(',');
for (tag in de) {
tags += '<span class="badge badge-primary ml-2">' + sanitizeHTML(de[tag]) + '</span>';
}
return tags;
}
return data;
}
}
],
rowCallback: function (nRow, data) {
data = sanitizeHTML(data);
nRow = '<span class="badge ml-2 badge-'+ sanitizeHTML(data['status_bscolor']) +'">' + sanitizeHTML(data['status_name']) + '</span>';
},
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
lengthChange: false,
pageLength: 10,
order: [[ 2, "asc" ]],
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
],
select: true
});
$("#utasks_table").css("font-size", 12);
Table = $("#gtasks_table").DataTable({
dom: 'Blfrtip',
aaData: [],
aoColumns: [
{
"data": "task_title",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (isWhiteSpace(data)) {
data = '#' + row['task_id'];
} else {
data = sanitizeHTML(data);
}
data = '<a href="#" onclick="edit_gtask(\'' + row['task_id'] + '\');">' + data +'</a>';
}
return data;
}
},
{ "data": "task_description",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover" style="cursor: pointer;" title="Info" data-trigger="hover" href="#" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{
"data": "task_status_id",
"render": function(data, type, row, meta) {
if (type === 'display' && data != null) {
data = sanitizeHTML(data);
data = '<span class="badge ml-2 badge-'+ row['status_bscolor'] +'">' + row['status_name'] + '</span>';
}
return data;
}
},
{
"data": "user_name",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "task_last_update",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
data = sanitizeHTML(data);
data = data.replace(/GMT/g, "");
}
return data;
}
},
{ "data": "task_tags",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
tags = "";
de = data.split(',');
for (tag in de) {
tags += '<span class="badge badge-primary ml-2">' + sanitizeHTML(de[tag]) + '</span>';
}
return tags;
}
return data;
}
}
],
rowCallback: function (nRow, data) {
nRow = '<span class="badge ml-2 badge-'+ sanitizeHTML(data['status_bscolor']) +'">' + sanitizeHTML(data['status_name']) + '</span>';
},
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
lengthChange: false,
pageLength: 10,
order: [[ 2, "asc" ]],
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
],
select: true
});
$("#gtasks_table").css("font-size", 12);
update_utasks_list();
update_ucases_list();
update_ureviews_list();
setInterval(check_page_update,30000);
});

View File

@ -0,0 +1,639 @@
var ds_filter;
function load_datastore() {
ds_filter = ace.edit("ds_file_search",
{
autoScrollEditorIntoView: true,
minLines: 1,
maxLines: 5
});
ds_filter.setTheme("ace/theme/tomorrow");
ds_filter.session.setMode("ace/mode/json");
ds_filter.renderer.setShowGutter(false);
ds_filter.setShowPrintMargin(false);
ds_filter.renderer.setScrollMargin(10, 10);
ds_filter.setOption("displayIndentGuides", true);
ds_filter.setOption("indentedSoftWrap", true);
ds_filter.setOption("showLineNumbers", false);
ds_filter.setOption("placeholder", "Search files");
ds_filter.setOption("highlightActiveLine", false);
ds_filter.commands.addCommand({
name: "Do filter",
bindKey: { win: "Enter", mac: "Enter" },
exec: function (editor) {
filter_ds_files();
}
});
get_request_api('/datastore/list/tree')
.done(function (data){
if(notify_auto_api(data, true)){
$('#ds-tree-root').empty();
build_ds_tree(data.data, 'ds-tree-root');
reparse_activate_tree();
show_datastore();
}
});
}
function build_ds_tree(data, tree_node) {
var standard_files_filters = [
{value: 'name: ', score: 10, meta: 'Match filename'},
{value: 'storage_name: ', score: 10, meta: 'Match local storage filename'},
{value: 'tag: ', score: 10, meta: 'Match tag of file'},
{value: 'description: ', score: 10, meta: 'Match description of file'},
{value: 'is_ioc: ', score: 10, meta: "Match file is IOC"},
{value: 'is_evidence: ', score: 10, meta: "Match file is evidence"},
{value: 'has_password: ', score: 10, meta: "Match file is password protected"},
{value: 'id: ', score: 10, meta: "Match ID of the file"},
{value: 'uuid: ', score: 10, meta: "Match UUID of the file"},
{value: 'sha256: ', score: 10, meta: "Match sha256 of the file"},
{value: 'AND ', score: 10, meta: 'AND operator'}
]
for (node in data) {
if (data[node] === null) {
break;
}
if (data[node].type == 'directory') {
data[node].name = sanitizeHTML(data[node].name);
can_delete = '';
if (!data[node].is_root) {
can_delete = `<div class="dropdown-divider"></div><a href="#" class="dropdown-item text-danger" onclick="delete_ds_folder('${node}');"><small class="fa fa-trash mr-2"></small>Delete</a>`;
}
jnode = `<li>
<span id='${node}' title='Folder ID ${node}' data-node-id="${node}"><i class="fa-regular fa-folder"></i> ${sanitizeHTML(data[node].name)}</span> <i class="fas fa-plus ds-folder-menu" role="menu" style="cursor:pointer;" data-toggle="dropdown" aria-expanded="false"></i>
<div class="dropdown-menu" role="menu">
<a href="#" class="dropdown-item" onclick="add_ds_folder('${node}');return false;"><small class="fa-solid fa-folder mr-2"></small>Add subfolder</a>
<a href="#" class="dropdown-item" onclick="add_ds_file('${node}');return false;"><small class="fa-solid fa-file mr-2"></small>Add file</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item" onclick="move_ds_folder('${node}');return false;"><small class="fa fa-arrow-right-arrow-left mr-2"></small>Move</a>
<a href="#" class="dropdown-item" onclick="rename_ds_folder('${node}', '${sanitizeHTML(data[node].name)}');return false;"><small class="fa-solid fa-pencil mr-2"></small>Rename</a>
${can_delete}
</div>
<ul id='tree-${node}'></ul>
</li>`;
$('#'+ tree_node).append(jnode);
build_ds_tree(data[node].children, 'tree-' + node);
} else {
data[node].file_original_name = sanitizeHTML(data[node].file_original_name);
data[node].file_password = sanitizeHTML(data[node].file_password);
data[node].file_description = sanitizeHTML(data[node].file_description);
standard_files_filters.push({
value: data[node].file_original_name,
score: 1,
meta: data[node].file_description
});
icon = '';
if (data[node].file_is_ioc) {
icon += '<i class="fa-solid fa-virus-covid text-danger mr-1" title="File is an IOC"></i>';
}
if (data[node].file_is_evidence) {
icon += '<i class="fa-solid fa-file-shield text-success mr-1" title="File is an evidence"></i>';
}
if (icon.length === 0) {
icon = '<i class="fa-regular fa-file mr-1" title="Regular file"></i>';
}
icon_lock = '';
has_password = data[node].file_password !== null && data[node].file_password.length > 0;
if (has_password) {
icon_lock = '<i title="Password protected" class="fa-solid fa-lock text-success mr-1"></i>'
}
icn_content = btoa(icon + icon_lock);
jnode = `<li>
<span id='${node}' data-file-id="${node}" title="ID : ${data[node].file_id}\nUUID : ${data[node].file_uuid}" class='tree-leaf'>
<span role="menu" style="cursor:pointer;" data-toggle="dropdown" aria-expanded="false">${icon}${icon_lock} ${sanitizeHTML(data[node].file_original_name)}</span>
<i class="fa-regular fa-circle ds-file-selector" style="cursor:pointer;display:none;" onclick="ds_file_select('${node}');"></i>
<div class="dropdown-menu" role="menu">
<a href="#" class="dropdown-item" onclick="get_link_ds_file('${node}');return false;"><small class="fa fa-link mr-2"></small>Link</a>
<a href="#" class="dropdown-item" onclick="get_mk_link_ds_file('${node}', '${toBinary64(data[node].file_original_name)}', '${icn_content}', '${has_password}');return false;"><small class="fa-brands fa-markdown mr-2"></small>Markdown link</a>
<a href="#" class="dropdown-item" onclick="download_ds_file('${node}');return false;"><small class="fa-solid fa-download mr-2"></small>Download</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item" onclick="info_ds_file('${node}');return false;"><small class="fa fa-eye mr-2"></small>Info</a>
<a href="#" class="dropdown-item" onclick="edit_ds_file('${node}');return false;"><small class="fa fa-pencil mr-2"></small>Edit</a>
<a href="#" class="dropdown-item" onclick="move_ds_file('${node}');return false;"><small class="fa fa-arrow-right-arrow-left mr-2"></small>Move</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item text-danger" onclick="delete_ds_file('${node}');"><small class="fa fa-trash mr-2"></small>Delete</a>
</div>
</span>
</li>`;
$('#'+ tree_node).append(jnode);
}
}
ds_filter.setOptions({
enableBasicAutocompletion: [{
getCompletions: (editor, session, pos, prefix, callback) => {
callback(null, standard_files_filters);
},
}],
enableLiveAutocompletion: true,
});
}
function show_datastore() {
$('html').addClass('ds_sidebar_open');
$('.ds-sidebar-toggler').addClass('toggled');
}
function hide_datastore() {
$('html').removeClass('ds_sidebar_open');
$('.ds-sidebar-toggler').removeClass('toggled');
}
function reparse_activate_tree() {
$('.tree li:has(ul)').addClass('parent_li').find(' > span').attr('title', 'Collapse this branch');
$('.tree li.parent_li > span').on('click', function (e) {
var children = $(this).parent('li.parent_li').find(' > ul > li');
if (children.is(":visible")) {
children.hide('fast');
$(this).attr('title', 'Expand this branch').find(' > i').addClass('icon-plus-sign').removeClass('icon-minus-sign');
} else {
children.show('fast');
$(this).attr('title', 'Collapse this branch').find(' > i').addClass('icon-minus-sign').removeClass('icon-plus-sign');
}
e.stopPropagation();
});
}
function add_ds_folder(parent_node) {
$('#ds_mod_folder_name').data('parent-node', parent_node);
$('#ds_mod_folder_name').data('node-update', false);
$('#ds_mod_folder_name').val('');
$('#modal_ds_folder').modal("show");
}
function rename_ds_folder(parent_node, name) {
$('#ds_mod_folder_name').data('parent-node', parent_node);
$('#ds_mod_folder_name').data('node-update', true);
$('#ds_mod_folder_name').val(name);
$('#modal_ds_folder').modal("show");
}
function delete_ds_folder(node) {
node = node.replace('d-', '');
swal({
title: "Are you sure?",
text: "This will delete all files included and sub-folders",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
var data_sent = {
"csrf_token": $('#csrf_token').val()
}
post_request_api('/datastore/folder/delete/' + node, JSON.stringify(data_sent))
.done((data) => {
if (notify_auto_api(data)) {
reset_ds_file_view();
load_datastore();
}
});
} else {
swal("Pfew, that was close");
}
});
}
function save_ds_mod_folder() {
var data = Object();
data['parent_node'] = $('#ds_mod_folder_name').data('parent-node').replace('d-', '');
data['folder_name'] = $('#ds_mod_folder_name').val();
data['csrf_token'] = $('#csrf_token').val();
if ($('#ds_mod_folder_name').data('node-update')) {
uri = '/datastore/folder/rename/' + data['parent_node'];
} else {
uri = '/datastore/folder/add';
}
post_request_api(uri, JSON.stringify(data))
.done(function (data){
if(notify_auto_api(data)){
$('#modal_ds_folder').modal("hide");
load_datastore();
}
});
}
function add_ds_file(node) {
node = node.replace('d-', '');
url = '/datastore/file/add/'+ node +'/modal' + case_param();
$('#modal_ds_file_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_ds_file').modal("show");
});
}
function edit_ds_file(node) {
node = node.replace('f-', '');
url = '/datastore/file/update/'+ node +'/modal' + case_param();
$('#modal_ds_file_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_ds_file').modal("show");
});
}
function info_ds_file(node) {
node = node.replace('f-', '');
url = '/datastore/file/info/'+ node +'/modal' + case_param();
$('#modal_ds_file_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_ds_file').modal("show");
});
}
function save_ds_file(node, file_id) {
var formData = new FormData($('#form_new_ds_file')[0]);
formData.append('file_content', $('#input_upload_ds_file').prop('files')[0]);
if (file_id === undefined) {
uri = '/datastore/file/add/' + node;
} else {
uri = '/datastore/file/update/' + file_id;
}
post_request_data_api(uri, formData, true, function() {
window.swal({
title: "File is uploading",
text: "Please wait. This window will close automatically when the file is uploaded.",
icon: "/static/assets/img/loader.gif",
button: false,
allowOutsideClick: false
});
})
.done(function (data){
if(notify_auto_api(data)){
$('#modal_ds_file').modal("hide");
reset_ds_file_view();
load_datastore();
}
})
.always((data) => {
window.swal.close();
});
}
function refresh_ds(){
reset_ds_file_view();
load_datastore();
notify_success('Datastore refreshed');
}
function upload_interactive_data(data_blob, filename, completion_callback) {
var data_sent = Object()
data_sent["csrf_token"] = $('#csrf_token').val();
data_sent["file_content"] = data_blob.split(';base64,')[1];
data_sent["file_original_name"] = filename;
post_request_api('/datastore/file/add-interactive', JSON.stringify(data_sent), true)
.done(function (data){
if(notify_auto_api(data)) {
if (completion_callback !== undefined) {
completion_callback(data);
}
}
});
}
function toggle_select_file() {
if ($('.btn-ds-bulk-selector').hasClass('active')) {
reset_ds_file_view();
load_datastore();
} else {
$('.ds-file-selector').show(250);
$('.btn-ds-bulk').show(250);
$('.btn-ds-bulk-selector').addClass('active');
}
}
function move_ds_file(file_id) {
reparse_activate_tree_selection();
$('.ds-file-selector').show();
$('#msg_mv_dst_folder').text('unselected destination');
$('#msg_select_destination_folder').show();
ds_file_select(file_id);
}
function reset_ds_file_view() {
$(".node-selected").removeClass("node-selected");
$(".file-selected").removeClass("file-selected");
$('.ds-file-selector').hide();
$('#msg_select_destination_folder').attr("data-file-id", '');
$('#msg_select_destination_folder').hide();
$('#msg_select_destination_folder_folder').hide();
$('.ds-file-selector').hide();
$('.btn-ds-bulk').hide();
$('.btn-ds-bulk-selector').removeClass('active');
}
function ds_file_select(file_id) {
file_id = '#'+ file_id;
if ($(file_id).hasClass('file-selected')) {
$(file_id + '> i').removeClass('fa-circle-check');
$(file_id + '> i').addClass('fa-circle');
$(file_id).removeClass('file-selected');
} else {
$(file_id+ '> i').removeClass('fa-circle');
$(file_id+ '> i').addClass('fa-circle-check');
$(file_id).addClass('file-selected');
}
$('#msg_mv_files').text($('.file-selected').length);
}
function validate_ds_file_move() {
var data_sent = Object();
if ($(".node-selected").length === 0) {
notify_error('No destination folder selected');
return false;
}
if ($(".file-selected").length === 0) {
notify_error('No file to move selected');
return false;
}
data_sent['destination-node'] = $(".node-selected").data('node-id').replace('d-', '');
data_sent['csrf_token'] = $('#csrf_token').val();
index = 0;
selected_files = $(".file-selected");
selected_files.each((index) => {
file_id = $(selected_files[index]).data('file-id').replace('f-', '');
post_request_api('/datastore/file/move/' + file_id, JSON.stringify(data_sent))
.done((data) => {
if (notify_auto_api(data)) {
if (index == $(".file-selected").length - 1) {
reset_ds_file_view();
load_datastore();
}
index +=1;
}
});
});
}
function move_ds_folder(node_id) {
reset_ds_file_view();
$('#msg_mv_folder').text($('#' + node_id).text());
$('#msg_mv_dst_folder_folder').text('unselected destination');
$('#msg_select_destination_folder_folder').show();
reparse_activate_tree_selection();
$('#' + node_id).addClass('node-source-selected');
}
function validate_ds_folder_move() {
var data_sent = Object();
if ($(".node-selected").length === 0) {
notify_error('No destination folder selected');
return false;
}
if ($(".node-source-selected").length === 0) {
notify_error('No initial folder to move');
return false;
}
data_sent['destination-node'] = $(".node-selected").data('node-id').replace('d-', '');
data_sent['csrf_token'] = $('#csrf_token').val();
node_id = $(".node-source-selected").data('node-id').replace('d-', '');
post_request_api('/datastore/folder/move/' + node_id, JSON.stringify(data_sent))
.done((data) => {
if (notify_auto_api(data)) {
reset_ds_file_view();
load_datastore();
}
});
}
function delete_ds_file(file_id) {
file_id = file_id.replace('f-', '');
swal({
title: "Are you sure?",
text: "This will delete the file on the server and any manual reference will become invalid",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
var data_sent = {
"csrf_token": $('#csrf_token').val()
}
post_request_api('/datastore/file/delete/' + file_id, JSON.stringify(data_sent))
.done((data) => {
if (notify_auto_api(data)) {
reset_ds_file_view();
load_datastore();
}
});
} else {
swal("Pfew, that was close");
}
});
}
function delete_bulk_ds_file() {
selected_files = $(".file-selected");
swal({
title: "Are you sure?",
text: `Yu are about to delete ${selected_files.length} files\nThis will delete the files on the server and any manual reference will become invalid`,
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
selected_files.each((index) => {
file_id = $(selected_files[index]).data('file-id').replace('f-', '');
var data_sent = {
"csrf_token": $('#csrf_token').val()
}
post_request_api('/datastore/file/delete/' + file_id, JSON.stringify(data_sent))
.done((data) => {
if (notify_auto_api(data)) {
if (index == $(".file-selected").length - 1) {
reset_ds_file_view();
load_datastore();
}
index +=1;
}
});
});
} else {
swal("Pfew, that was close");
}
});
}
function get_link_ds_file(file_id) {
file_id = file_id.replace('f-', '');
link = location.protocol + '//' + location.host + '/datastore/file/view/' + file_id;
link = link + case_param();
navigator.clipboard.writeText(link).then(function() {
notify_success('File link copied')
}, function(err) {
notify_error('Unable to copy link. Error ' + err);
console.error('File link link', err);
});
}
function build_dsfile_view_link(file_id) {
file_id = file_id.replace('f-', '');
link = '/datastore/file/view/' + file_id;
link = link + case_param();
return link;
}
function get_mk_link_ds_file(file_id, filename, file_icon, has_password) {
let link = build_dsfile_view_link(file_id);
filename = sanitizeHTML(fromBinary64(filename));
if (has_password == 'false' && ['png', 'svg', 'jpeg', 'jpg', 'webp', 'bmp', 'gif'].includes(filename.split('.').pop())) {
mk_link = `![${filename}](${link} =40%x40%)`;
} else {
file_icon = atob(file_icon);
mk_link = `[${file_icon} [DS] ${filename}](${link})`;
}
navigator.clipboard.writeText(mk_link).then(function() {
notify_success('Markdown file link copied')
}, function(err) {
notify_error('Unable to copy link. Error ' + err);
console.error(`Markdown file link ${md_link}`, err);
});
}
function download_ds_file(file_id) {
let link = build_dsfile_view_link(file_id);
downloadURI(link, name);
}
function reparse_activate_tree_selection() {
$('.tree li.parent_li > span').on('click', function (e) {
if ($(this).hasClass('node-selected')) {
$(this).removeClass('node-selected');
$('#msg_mv_dst_folder').text('unselected destination');
$('#msg_mv_dst_folder_folder').text('unselected destination');
} else {
$(".node-selected").removeClass("node-selected");
$(this).addClass('node-selected');
$('#msg_mv_dst_folder').text($(".node-selected").text());
$('#msg_mv_dst_folder_folder').text($(".node-selected").text());
}
});
}
var parsed_filter_ds = {};
var ds_keywords = ['storage_name', 'name', 'tag', 'description', 'is_ioc', 'is_evidence', 'has_password', 'uuid', 'id', 'sha256'];
function parse_filter(str_filter, keywords) {
for (var k = 0; k < keywords.length; k++) {
keyword = keywords[k];
items = str_filter.split(keyword + ':');
ita = items[1];
if (ita === undefined) {
continue;
}
item = split_bool(ita);
if (item != null) {
if (!(keyword in parsed_filter_ds)) {
parsed_filter_ds[keyword] = [];
}
if (!parsed_filter_ds[keyword].includes(item)) {
parsed_filter_ds[keyword].push(item.trim());
}
if (items[1] != undefined) {
str_filter = str_filter.replace(keyword + ':' + item, '');
if (parse_filter(str_filter, keywords)) {
keywords.shift();
}
}
}
}
return true;
}
function filter_ds_files() {
ds_keywords = ['storage_name', 'name', 'tag', 'description', 'is_ioc', 'is_evidence', 'has_password', 'uuid', 'id', 'sha256'];
parsed_filter_ds = {};
parse_filter(ds_filter.getValue(), ds_keywords);
filter_query = encodeURIComponent(JSON.stringify(parsed_filter_ds));
$('#btn_filter_ds_files').text('Searching..');
get_request_data_api("/datastore/list/filter",{ 'q': filter_query })
.done(function (data){
if(notify_auto_api(data, true)){
$('#ds-tree-root').empty();
build_ds_tree(data.data, 'ds-tree-root');
reparse_activate_tree();
show_datastore();
}
})
.always(() => {
$('#btn_filter_ds_files').text('Search');
});
}
function reset_ds_files_filter() {
ds_filter.setValue("");
load_datastore();
}
function show_ds_filter_help() {
$('#modal_help').load('/datastore/filter-help/modal' + case_param(), function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, '/datastore/filter-help/modal');
return false;
}
$('#modal_help').modal('show');
});
}

View File

@ -0,0 +1,66 @@
/* remove user provided filter */
function removeFilter(clickedObject) {
console.log("removeFilter")
let inputObject = $(clickedObject)
.parents("table")
.find("input")[$(clickedObject).parents("th").index()]
inputObject.value=""; // Clear input
$(inputObject).trigger("change"); // trigger change event
}
/* add a text input to each column of a given datatable to allow filtering */
function addFilterFields(tableId){
$('#' + tableId + ' thead tr')
.clone(true)
.addClass('filters')
.appendTo('#' + tableId + ' thead');
}
/* callback function to activate filtering on a datatable */
function tableFiltering(api, table_anchor, exclude_columns=[]) {
// For each column
api
.columns()
.eq(0)
.each(function (colIdx) {
// Set the header cell to contain the input element
var cell = $('#'+table_anchor+' .filters th').eq(
$(api.column(colIdx).header()).index()
);
if (exclude_columns.includes(colIdx)) {
$(cell).html('<div class="form-group has-feedback" style="display: none;"><input type="text" class="form-control" placeholder="Filter"><i class="fas fa-times-circle form-control-feedback" onclick="removeFilter(this);"></i></div>');
return;
}
$(cell).html('<div class="form-group has-feedback"><input type="text" class="form-control" placeholder="Filter"><i class="fas fa-times-circle form-control-feedback" onclick="removeFilter(this);"></i></div>');
// On every keypress in this input
$(
'input',
$('#'+table_anchor+' .filters th').eq($(api.column(colIdx).header()).index())
)
.off('keyup change')
.on('keyup change', function (e) {
e.stopPropagation();
// Get the search value
$(this).attr('title', $(this).val());
var regexr = '({search})';
var cursorPosition = this.selectionStart;
// Search the column for that value
api
.column(colIdx)
.search(
this.value != ''
? regexr.replace('{search}', '(((' + this.value + ')))')
: '',
this.value != '',
this.value == ''
)
.draw();
$(this)
.focus()[0]
.setSelectionRange(cursorPosition, cursorPosition);
});
});
}

View File

@ -0,0 +1,86 @@
function get_activities () {
get_request_api('/dim/tasks/list/1000')
.done((data) => {
if (notify_auto_api(data, true)) {
content = data.data;
Table.clear();
Table.rows.add(content);
Table.columns.adjust().draw();
$('#feed_last_updated').text("Last updated: " + new Date().toLocaleTimeString());
hide_loader();
}
});
}
$(document).ready(function(){
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
Table = $("#activities_table").DataTable({
dom: 'Blfrtip',
aaData: [],
bSort: false,
aoColumns: [
{ "data": "task_id",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
data = "<a href='#' onclick=\"dim_task_status('"+ data +"');return false;\">"+ data +"</a>"
}
return data;
} },
{ "data": "state",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (data == 'success'){
data = "<i class='fas fa-check text-success' title='success'></i>";
} else {
data = "<i class='fas fa-times text-danger' title='failure'></i>";
}
}
return data;
} },
{ "data": "date_done",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ "data": "case",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ "data": "module",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ "data": "user",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} }
],
filter: true,
info: true,
processing: true,
retrieve: true,
initComplete: function () {
tableFiltering(this.api(), 'activities_table');
},
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
]
});
$("#activities_table").css("font-size", 12);
get_activities();
});

View File

@ -0,0 +1,188 @@
function add_object_attribute() {
url = '/manage/attributes/add/modal' + case_param();
$('#modal_add_attribute_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_attribute').on("click", function () {
var form = $('#form_new_attribute').serializeObject();
post_request_api('/manage/attributes/add', JSON.stringify(form), true)
.done((data) => {
if (notify_auto_api(data, true)) {
refresh_attribute_table();
$('#modal_add_attribute').modal('hide');
}
});
return false;
})
});
$('#modal_add_type').modal({ show: true });
}
$('#attributes_table').dataTable( {
"ajax": {
"url": "/manage/attributes/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"order": [[ 0, "desc" ]],
"autoWidth": false,
"columns": [
{
"data": "attribute_id",
"render": function ( data, type, row ) {
return '<a href="#" onclick="attribute_detail(\'' + row['attribute_id'] + '\');">' + sanitizeHTML(data) +'</a>';
}
},
{
"data": "attribute_display_name",
"render": function ( data, type, row ) {
return '<a href="#" onclick="attribute_detail(\'' + row['attribute_id'] + '\');">' + sanitizeHTML(data) +'</a>';
}
},
{
"data": "attribute_description"
}
]
}
);
function refresh_attribute_table() {
$('#attributes_table').DataTable().ajax.reload();
notify_success("Refreshed");
}
function attribute_detail(attr_id) {
url = '/manage/attributes/' + attr_id + '/modal' + case_param();
$('#modal_add_attribute_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
var editor = ace.edit("editor_detail",
{
autoScrollEditorIntoView: true,
minLines: 30,
});
editor.setTheme("ace/theme/tomorrow");
editor.session.setMode("ace/mode/json");
editor.renderer.setShowGutter(true);
editor.setOption("showLineNumbers", true);
editor.setOption("showPrintMargin", false);
editor.setOption("displayIndentGuides", true);
editor.setOption("maxLines", "Infinity");
editor.session.setUseWrapMode(true);
editor.setOption("indentedSoftWrap", true);
editor.renderer.setScrollMargin(8, 5)
editor.setOptions({
enableBasicAutocompletion: [{
getCompletions: (editor, session, pos, prefix, callback) => {
callback(null, [
{value: 'mandatory', score: 1, meta: 'mandatory tag'},
{value: 'type', score: 1, meta: 'type tag'},
{value: 'input_string', score: 1, meta: 'An input string field type'},
{value: 'input_checkbox', score: 1, meta: 'An input checkbox field type'},
{value: 'input_textfield', score: 1, meta: 'An input textfield field type'},
{value: 'input_date', score: 1, meta: 'An input date field type'},
{value: 'input_datetime', score: 1, meta: 'An input datetime field type'},
{value: 'input_select', score: 1, meta: 'An input select field type'},
{value: 'raw', score: 1, meta: 'A raw field type'},
{value: 'html', score: 1, meta: 'An html field type'},
{value: 'value', score: 1, meta: 'default value'},
]);
},
}],
enableLiveAutocompletion: true,
enableSnippets: true
});
$('#preview_attribute').on("click", function () {
var data_sent = Object();
data_sent['attribute_content'] = editor.getSession().getValue();
data_sent['csrf_token'] = $("#csrf_token").val();
post_request_api('/manage/attributes/preview', JSON.stringify(data_sent), true)
.done((data) => {
if (notify_auto_api(data, true)) {
$('#modal_preview_attribute_content').html(data.data);
$('#modal_preview_attribute').modal({ show: true });
}
});
});
$('#submit_new_attribute').on("click", function () {
update_attribute(attr_id, editor, false, false);
})
$('#submit_partial_overwrite').on("click", function () {
update_attribute(attr_id, editor, true, false);
})
$('#submit_complete_overwrite').on("click", function () {
update_attribute(attr_id, editor, false, true);
})
});
$('#modal_add_attribute').modal({ show: true });
}
function update_attribute(attr_id, editor, partial, complete){
event.preventDefault();
var data_sent = Object();
data_sent['attribute_content'] = editor.getSession().getValue();
data_sent['csrf_token'] = $("#csrf_token").val();
data_sent['partial_overwrite'] = partial;
data_sent['complete_overwrite'] = complete;
$('#alert_attributes_edit').empty();
$('#alert_attributes_details').hide();
$('#attributes_err_details_list').empty();
post_request_api('/manage/attributes/update/' + attr_id, JSON.stringify(data_sent), false, function() {
window.swal({
title: "Updating and migrating...",
text: "Please wait",
icon: "/static/assets/img/loader.gif",
button: false,
allowOutsideClick: false
});
})
.done((data) => {
notify_auto_api(data);
})
.fail((error) => {
data = error.responseJSON;
$('#submit_new_attribute').text('Save');
$('#alert_attributes_edit').text(data.message);
if (data.data && data.data.length > 0) {
for(var i in data.data)
{
var output='<li>'+ sanitizeHTML(data.data[i]) +'</li>';
$('#attributes_err_details_list').append(output);
}
$('#alert_attributes_details').show();
}
$('#alert_attributes_edit').show();
$('#submit_new_module').text("Retry");
})
.always((data) => {
window.swal.close();
});
return false;
}

View File

@ -0,0 +1,66 @@
function get_case_audit_page() {
us_val = $('#cases_audit_select').val();
if (!us_val) {
notify_error('I really wanna help you but I still can\'t read your mind');
return false;
}
$('#get_case_audit_btn').text('Auditing case..');
url = '/manage/access-control/audit/cases/'+ us_val +'/modal' + case_param();
$('#case_audit_content').load(url, function (response, status, xhr) {
$('#get_case_audit_btn').text('Audit');
if (status !== "success") {
$('#get_case_audit_btn').text('Audit');
ajax_notify_error(xhr, url);
return false;
}
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
$('#case_audit_access_table').dataTable({
order: [[ 1, "asc" ]],
info: true,
filter: true,
processing: true,
orderCellsTop: true,
initComplete: function () {
tableFiltering(this.api(), 'case_audit_access_table');
}
});
});
}
function refresh_cases_list_audit() {
get_request_api('/manage/cases/list')
.done((data) => {
if(notify_auto_api(data, true)) {
$('#cases_audit_select').selectpicker({
liveSearch: true,
title: "Select case to audit",
style: "btn-outline-white",
size: 10
});
data_select = [];
for (caseid in data.data) {
label = `${sanitizeHTML(data.data[caseid].case_name)}`;
$("#cases_audit_select").append('<option value="'+data.data[caseid].case_id+'">'+label+'</option>');
}
$("#cases_audit_select").selectpicker("refresh");
$("#cases_audit_select").show();
}
});
}
$(document).ready(function () {
refresh_cases_list_audit();
});

View File

@ -0,0 +1,78 @@
function get_user_audit_page() {
us_val = $('#users_audit_select').val();
if (!us_val) {
notify_error('I really wanna help you but I still can\'t read your mind');
return false;
}
$('#get_user_audit_btn').text('Auditing user..');
url = '/manage/access-control/audit/users/'+ us_val +'/modal' + case_param();
$('#user_audit_content').load(url, function (response, status, xhr) {
$('#get_user_audit_btn').text('Audit');
if (status !== "success") {
$('#get_user_audit_btn').text('Audit');
ajax_notify_error(xhr, url);
return false;
}
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
$('#user_audit_access_table').dataTable({
order: [[ 1, "asc" ]],
info: true,
filter: true,
processing: true,
orderCellsTop: true,
initComplete: function () {
tableFiltering(this.api(), 'user_audit_access_table');
}
});
$('#user_audit_permissions_table').dataTable({
order: [[ 1, "asc" ]],
info: true,
filter: true,
processing: true,
orderCellsTop: true,
initComplete: function () {
tableFiltering(this.api(), 'user_audit_permissions_table');
}
});
});
}
function refresh_users_list_audit() {
get_request_api('/manage/users/list')
.done((data) => {
if(notify_auto_api(data, true)) {
$('#users_audit_select').selectpicker({
liveSearch: true,
title: "Select user to audit",
style: "btn-outline-white",
size: 10
});
data_select = [];
for (user in data.data) {
label = `${sanitizeHTML(data.data[user].user_login)} (${sanitizeHTML(data.data[user].user_name)} - ${sanitizeHTML(data.data[user].user_email)})`;
$("#users_audit_select").append('<option value="'+data.data[user].user_id+'">'+label+'</option>');
}
$("#users_audit_select").selectpicker("refresh");
$("#users_audit_select").show();
}
});
}
$(document).ready(function () {
refresh_users_list_audit();
});

View File

@ -0,0 +1,336 @@
function add_case_template() {
let url = '/manage/case-templates/add/modal' + case_param();
$('#modal_case_template_json').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
let editor = ace.edit("editor_detail",
{
autoScrollEditorIntoView: true,
minLines: 30,
});
editor.setTheme("ace/theme/tomorrow");
editor.session.setMode("ace/mode/json");
editor.renderer.setShowGutter(true);
editor.setOption("showLineNumbers", true);
editor.setOption("showPrintMargin", false);
editor.setOption("displayIndentGuides", true);
editor.setOption("maxLines", "Infinity");
editor.session.setUseWrapMode(true);
editor.setOption("indentedSoftWrap", true);
editor.renderer.setScrollMargin(8, 5)
editor.setOptions({
enableBasicAutocompletion: [{
getCompletions: (editor, session, pos, prefix, callback) => {
callback(null, [
{value: 'name', score: 1, meta: 'name of the template'},
{value: 'display', score: 1, meta: 'display name of the template'},
{value: 'description', score: 1, meta: 'description of the template'},
{value: 'author', score: 1, meta: 'author of the template'},
{value: 'title_prefix', score: 1, meta: 'prefix of instantiated cases'},
{value: 'summary', score: 1, meta: 'summary of the case'},
{value: 'tags', score: 1, meta: 'tags of the case or the tasks'},
{value: 'tasks', score: 1, meta: 'tasks of the case'},
{value: 'note_groups', score: 1, meta: 'groups of notes'},
{value: 'title', score: 1, meta: 'title of the task or the note group or the note'},
{value: 'content', score: 1, meta: 'content of the note'},
]);
},
}],
enableLiveAutocompletion: true,
enableSnippets: true
});
$('#submit_new_case_template').on("click", function () {
let data_sent = Object();
data_sent['case_template_json'] = editor.getSession().getValue();
data_sent['csrf_token'] = $("#csrf_token").val();
post_request_api('/manage/case-templates/add', JSON.stringify(data_sent), false, function() {
window.swal({
title: "Adding...",
text: "Please wait",
icon: "/static/assets/img/loader.gif",
button: false,
allowOutsideClick: false
});
})
.done((data) => {
if (notify_auto_api(data)) {
refresh_case_template_table();
$('#modal_case_template').modal('hide');
}
})
.fail((error) => {
let data = error.responseJSON;
$('#submit_new_case_template').text('Save');
$('#alert_case_template_edit').text(data.message);
if (data.data && data.data.length > 0) {
let output='<li>'+ sanitizeHTML(data.data) +'</li>';
$('#case_template_err_details_list').append(output);
$('#alert_case_template_details').show();
}
$('#alert_case_template_edit').show();
})
.always((data) => {
window.swal.close();
});
return false;
})
});
$('#modal_case_template').modal({ show: true });
}
$('#case_templates_table').dataTable( {
"ajax": {
"url": "/manage/case-templates/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return JSON.stringify([]);
}
}
},
"order": [[ 0, "desc" ]],
"autoWidth": false,
"columns": [
{
"data": "id",
"render": function ( data, type, row ) {
return '<a href="#" onclick="case_template_detail(\'' + row['id'] + '\');">' + sanitizeHTML(data) +'</a>';
}
},
{
"data": "display_name",
"render": function ( data, type, row ) {
return '<a href="#" onclick="case_template_detail(\'' + row['id'] + '\');">' + sanitizeHTML(data) +'</a>';
}
},
{
"data": "description"
},
{
"data": "added_by"
},
{
"data": "created_at"
},
{
"data": "updated_at"
}
]
}
);
function refresh_case_template_table() {
$('#case_templates_table').DataTable().ajax.reload();
notify_success("Refreshed");
}
function delete_case_template(id) {
swal({
title: "Are you sure ?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/case-templates/delete/' + id)
.done((data) => {
if(notify_auto_api(data)) {
window.location.href = '/manage/case-templates' + case_param();
}
});
} else {
swal("Pfew, that was close");
}
});
}
function case_template_detail(ctempl_id) {
let url = '/manage/case-templates/' + ctempl_id + '/modal' + case_param();
$('#modal_case_template_json').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
let editor = ace.edit("editor_detail",
{
autoScrollEditorIntoView: true,
minLines: 30,
});
editor.setTheme("ace/theme/tomorrow");
editor.session.setMode("ace/mode/json");
editor.renderer.setShowGutter(true);
editor.setOption("showLineNumbers", true);
editor.setOption("showPrintMargin", false);
editor.setOption("displayIndentGuides", true);
editor.setOption("maxLines", "Infinity");
editor.session.setUseWrapMode(true);
editor.setOption("indentedSoftWrap", true);
editor.renderer.setScrollMargin(8, 5)
editor.setOptions({
enableBasicAutocompletion: [{
getCompletions: (editor, session, pos, prefix, callback) => {
callback(null, [
{value: 'name', score: 1, meta: 'name of the template'},
{value: 'display_name', score: 1, meta: 'display name of the template'},
{value: 'description', score: 1, meta: 'description of the template'},
{value: 'author', score: 1, meta: 'author of the template'},
{value: 'title_prefix', score: 1, meta: 'prefix of instantiated cases'},
{value: 'summary', score: 1, meta: 'summary of the case'},
{value: 'tags', score: 1, meta: 'tags of the case or the tasks'},
{value: 'tasks', score: 1, meta: 'tasks of the case'},
{value: 'note_groups', score: 1, meta: 'groups of notes'},
{value: 'title', score: 1, meta: 'title of the task or the note group or the note'},
{value: 'content', score: 1, meta: 'content of the note'},
]);
},
}],
enableLiveAutocompletion: true,
enableSnippets: true
});
$('#submit_new_case_template').on("click", function () {
update_case_template(ctempl_id, editor, false, false);
});
$('#submit_delete_case_template').on("click", function () {
delete_case_template(ctempl_id);
});
});
$('#modal_case_template').modal({ show: true });
}
function update_case_template(ctempl_id, editor, partial, complete){
event.preventDefault();
let data_sent = Object();
data_sent['case_template_json'] = editor.getSession().getValue();
data_sent['csrf_token'] = $("#csrf_token").val();
$('#alert_case_template_edit').empty();
$('#alert_case_template_details').hide();
$('#case_template_err_details_list').empty();
post_request_api('/manage/case-templates/update/' + ctempl_id, JSON.stringify(data_sent), false, function() {
window.swal({
title: "Updating...",
text: "Please wait",
icon: "/static/assets/img/loader.gif",
button: false,
allowOutsideClick: false
});
})
.done((data) => {
notify_auto_api(data);
})
.fail((error) => {
let data = error.responseJSON;
$('#submit_new_case_template').text('Update');
$('#alert_case_template_edit').text(data.message);
if (data.data && data.data.length > 0) {
let output='<li>'+ sanitizeHTML(data.data) +'</li>';
$('#case_template_err_details_list').append(output);
$('#alert_case_template_details').show();
}
$('#alert_case_template_edit').show();
})
.always((data) => {
window.swal.close();
});
return false;
}
function fire_upload_case_template() {
let url = '/manage/case-templates/upload/modal' + case_param();
$('#modal_upload_case_template_json').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
});
$('#modal_upload_case_template').modal({ show: true });
}
function upload_case_template() {
if ($("#input_upload_case_template").val() !== "")
{
var file = $("#input_upload_case_template").get(0).files[0];
var reader = new FileReader();
reader.onload = function (e) {
fileData = e.target.result
var data = new Object();
data['csrf_token'] = $('#csrf_token').val();
data['case_template_json'] = fileData;
post_request_api('/manage/case-templates/add', JSON.stringify(data), false, function() {
window.swal({
title: "Adding...",
text: "Please wait",
icon: "/static/assets/img/loader.gif",
button: false,
allowOutsideClick: false
});
})
.done((data) => {
notify_auto_api(data);
jsdata = data;
if (jsdata.status == "success") {
refresh_case_template_table();
$('#modal_upload_case_template').modal('hide');
}
})
.fail((error) => {
let data = error.responseJSON;
$('#alert_upload_case_template').text(data.message);
if (data.data && data.data.length > 0) {
let output='<li>'+ sanitizeHTML(data.data) +'</li>';
$('#upload_case_template_err_details_list').append(output);
$('#alert_upload_case_template_details').show();
}
$('#alert_upload_case_template').show();
})
.always((data) => {
$("#input_upload_case_template").val("");
window.swal.close();
});
};
reader.readAsText(file);
}
return false;
}
function downloadCaseTemplateDefinition() {
event.preventDefault();
let editor = ace.edit("editor_detail");
let data = editor.getSession().getValue();
let filename = "case_template.json";
download_file(filename, 'text/json' , data);
}

View File

@ -0,0 +1,404 @@
function add_protagonist() {
prota_html = $('#protagonist_list_edit_template').html();
$('#protagonist_list_edit').append(prota_html);
}
function refresh_case_table() {
if ($('#cases_table').length === 0) {
return false;
}
$('#cases_table').DataTable().ajax.reload();
$('#cases_table').DataTable().columns.adjust().draw();
notify_success('Cases list refreshed');
return true;
}
/* Create detail modal function */
function case_detail(id) {
url = 'cases/details/' + id + case_param();
$('#info_case_modal_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_case_detail').modal({ show: true });
});
}
/* Remove case function */
function remove_case(id) {
swal({
title: "Are you sure?",
text: "You are about to delete this case forever. This cannot be reverted.\nAll associated data will be deleted",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/cases/delete/' + id)
.done((data) => {
if (notify_auto_api(data)) {
if (!refresh_case_table()) {
swal({
title: "Done!",
text: "You will be redirected in 5 seconds",
icon: "success",
buttons: false,
dangerMode: false
})
setTimeout(function () {
window.location.href = '/dashboard?cid=1';
}, 4500);
} else {
refresh_case_table();
$('#modal_case_detail').modal('hide');
}
}
});
} else {
swal("Pfew, that was close");
}
});
}
/* Reopen case function */
function reopen_case(id) {
post_request_api('/manage/cases/reopen/' + id)
.done((data) => {
if (!refresh_case_table()) {
window.location.reload();
}
$('#modal_case_detail').modal('hide');
});
}
/* Close case function */
function close_case(id) {
swal({
title: "Are you sure?",
text: "Case ID " + id + " will be closed and will not appear in contexts anymore",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, close it!'
})
.then((willClose) => {
if (willClose) {
post_request_api('/manage/cases/close/' + id)
.done((data) => {
if (!refresh_case_table()) {
window.location.reload();
}
});
}
});
}
function edit_case_info() {
$('#case_gen_info_content').hide();
$('#case_gen_info_edit').show();
$('#cancel_case_info').show();
$('#save_case_info').show();
$('#case_info').hide();
}
function cancel_case_edit() {
$('#case_gen_info_content').show();
$('#case_gen_info_edit').hide();
$('#cancel_case_info').hide();
$('#case_info').show();
$('#save_case_info').hide();
}
function save_case_edit(case_id) {
var data_sent = $('form#form_update_case').serializeObject();
var map_protagonists = Object();
for (e in data_sent) {
if (e.startsWith('protagonist_role_')) {
map_protagonists[e.replace('protagonist_role_', '')] = {
'role': data_sent[e]
};
delete data_sent[e];
}
if (e.startsWith('protagonist_name_')) {
map_protagonists[e.replace('protagonist_name_', '')]['name'] = data_sent[e];
delete data_sent[e];
}
if (e.startsWith('protagonist_contact_')) {
map_protagonists[e.replace('protagonist_contact_', '')]['contact'] = data_sent[e];
delete data_sent[e];
}
if (e.startsWith('protagonist_id_')) {
map_protagonists[e.replace('protagonist_id_', '')]['id'] = data_sent[e];
delete data_sent[e];
}
}
data_sent['protagonists'] = [];
for (e in map_protagonists) {
data_sent['protagonists'].push(map_protagonists[e]);
}
data_sent['case_tags'] = $('#case_tags').val();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('/manage/cases/update/' + case_id, JSON.stringify(data_sent), true, undefined, case_id)
.done((data) => {
if(notify_auto_api(data)) {
case_detail(case_id);
}
});
}
function remove_case_access_from_user(user_id, case_id, on_finish) {
swal({
title: "Are you sure?",
text: "This user might not be able access this case anymore",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, remove it!'
})
.then((willDelete) => {
if (willDelete) {
url = '/manage/users/' + user_id + '/case-access/delete';
var data_sent = Object();
data_sent['case'] = case_id;
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api(url, JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
if (on_finish !== undefined) {
on_finish();
}
}
}).always(() => {
window.swal.close();
});
}
});
}
var access_levels = [
{ "id": 1, "name": "Deny all" },
{ "id": 2, "name": "Read only" },
{ "id": 4, "name": "Full access" }
]
function get_access_level_options(data) {
var options = "";
for (var i = 0; i < access_levels.length; i++) {
options += `<option value="${access_levels[i].id}" ${data == access_levels[i].id ? 'selected' : ''}>${access_levels[i].name}</option>`;
}
return options;
}
function update_user_case_access_level(user_id, case_id, access_level) {
var data = {
"case_id": parseInt(case_id),
"user_id": parseInt(user_id),
"access_level": parseInt(access_level),
"csrf_token": $('#csrf_token').val()
};
post_request_api('/case/access/set-user', JSON.stringify(data), false, null, case_id)
.done((data) => {
notify_auto_api(data);
});
}
function view_case_access_via_group(case_id) {
url = '/case/groups/access/modal' + case_param();
$('#modal_ac_additional').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_ac_additional').modal({ show: true });
});
}
function set_case_access_via_group(case_id) {
var data = {
"case_id": parseInt(case_id),
"access_level": parseInt($('#group_case_ac_select').val()),
"group_id": parseInt($('#group_case_access_select').val()),
"csrf_token": $('#csrf_token').val()
};
post_request_api('/case/access/set-group', JSON.stringify(data))
.done((data) => {
notify_auto_api(data);
access_case_info_reload(case_id);
$('#modal_ac_additional').modal('hide');
});
}
function access_case_info_reload(case_id, owner_id, reviewer_id) {
var req_users = [];
get_request_api('/case/users/list')
.done((data) => {
has_table = $.fn.dataTable.isDataTable( '#case_access_users_list_table' );
if (!notify_auto_api(data, !has_table)) {
return;
}
req_users = data.data;
if ( has_table ) {
table = $('#case_access_users_list_table').DataTable();
table.clear();
table.rows.add(req_users);
table.draw();
} else {
addFilterFields($('#case_access_users_list_table').attr("id"));
$("#case_access_users_list_table").DataTable({
dom: '<"container-fluid"<"row"<"col"l><"col"f>>>rt<"container-fluid"<"row"<"col"i><"col"p>>>',
aaData: req_users,
aoColumns: [
{
"data": "user_id",
"className": "dt-center"
},
{
"data": "user_name",
"className": "dt-center",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "user_login",
"className": "dt-center",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "user_access_level",
"className": "dt-center",
"render": function ( data, type, row ) {
return `<select class="form-control" onchange="update_user_case_access_level('${row.user_id}',${case_id},this.value)">${get_access_level_options(data)}</select>`;
}
}
],
filter: true,
info: true,
ordering: true,
processing: true,
initComplete: function () {
tableFiltering(this.api(), 'case_access_users_list_table');
}
});
}
let quick_owner = $('#case_quick_owner');
let quick_reviewer = $('#case_quick_reviewer');
quick_reviewer.append($('<option>'));
for (let i = 0; i < req_users.length; i++) {
$('#username-list').append($('<option>', {
value: req_users[i].user_name
}));
$('#emails-list').append($('<option>', {
value: req_users[i].user_email
}));
quick_owner.append($('<option>', {
value: req_users[i].user_id,
text: req_users[i].user_name
}));
if (req_users[i].user_id == owner_id) {
quick_owner.val(req_users[i].user_id);
}
quick_owner.selectpicker('refresh');
quick_reviewer.append($('<option>', {
value: req_users[i].user_id,
text: req_users[i].user_name
}));
if (req_users[i].user_id == reviewer_id) {
quick_reviewer.val(req_users[i].user_id);
}
quick_reviewer.selectpicker('refresh');
}
});
$('#case_tags').amsifySuggestags({
printValues: false,
suggestions: []
});
}
function remove_cases_access_user(user_id, cases, on_finish) {
swal({
title: "Are you sure?",
text: "This user might not be able access these cases anymore",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, remove it!'
})
.then((willDelete) => {
if (willDelete) {
url = '/manage/users/' + user_id + '/cases-access/delete';
var data_sent = Object();
data_sent['cases'] = cases;
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api(url, JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_user_cac(user_id);
if (on_finish !== undefined) {
on_finish();
}
}
}).always(() => {
window.swal.close();
});
}
});
}

View File

@ -0,0 +1,239 @@
/*************************
* Case creation section
*************************/
/* create the select picker for customer */
$('#case_customer').selectpicker({
liveSearch: true,
title: "Select customer *",
style: "btn-outline-white",
size: 8
});
$('#case_template_id').selectpicker({
liveSearch: true,
title: "Select case template",
style: "btn-outline-white",
size: 8
});
$('#case_template_id').prepend(new Option('', ''));
$('#classification_id').selectpicker({
liveSearch: true,
title: "Select classification",
style: "btn-outline-white",
size: 8
});
$('#classification_id').prepend(new Option('', ''));
/* Submit event handler for new case */
function submit_new_case() {
if(!$('form#form_new_case').valid()) {
return false;
}
var data_sent = $('form#form_new_case').serializeObject();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
data_sent['custom_attributes'] = attributes;
send_add_case(data_sent);
return false;
};
function send_add_case(data_sent) {
post_request_api('/manage/cases/add', JSON.stringify(data_sent), true, function () {
$('#submit_new_case_btn').text('Checking data..')
.attr("disabled", true)
.removeClass('bt-outline-success')
.addClass('btn-success', 'text-dark');
})
.done((data) => {
if (notify_auto_api(data, true)) {
case_id = data.data.case_id;
swal("That's done !",
"Case has been successfully created",
"success",
{
buttons: {
again: {
text: "Create a case again",
value: "again",
dangerMode: true,
color: '#d33'
},
dash: {
text: "Go to dashboard",
value: "dash",
color: '#d33'
},
go_case: {
text: "Switch to newly created case",
value: "go_case"
}
}
}
).then((value) => {
switch (value) {
case "dash":
window.location.replace("/dashboard" + case_param());
break;
case "again":
window.location.replace("/manage/cases" + case_param());
break;
case 'go_case':
window.location.replace("/case?cid=" + case_id);
default:
window.location.replace("/case?cid=" + case_id);
}
});
}
})
.always(() => {
$('#submit_new_case_btn')
.attr("disabled", false)
.addClass('bt-outline-success')
.removeClass('btn-success', 'text-dark');
})
.fail(() => {
$('#submit_new_case_btn').text('Save');
})
}
/*************************
* Case list section
*************************/
/* case table creation */
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
$('#cases_table').dataTable({
"ajax": {
"url": "cases/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function (d) {
if (d.status == 'success') {
return JSON.stringify(d.data);
} else {
return [];
}
}
},
"columns": [
{
"render": function (data, type, row) {
data = sanitizeHTML(data);
return '<a href="#" onclick="case_detail(\'' + row['case_id'] + '\');">' + data + '</a>';
},
"data": "case_name"
},
{
"data": "case_description",
"render": function (data, type, row) {
if (type === 'display' && data != null) {
if (row["case_description"].length > 50){
return sanitizeHTML(row["case_description"].slice(0,50)) + " ... " ;
}
else {
return sanitizeHTML(row["case_description"]);
}
}
return data;
},
},
{
"data": "client_name",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "state_name",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "case_open_date",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
},
"type": "date"
},
{
"data": "case_close_date",
"type": "date",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "case_soc_id",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "opened_by",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
}
],
dom: '<"container-fluid"<"row"<"col"l><"col"f>>>rt<"container-fluid"<"row"<"col"i><"col"p>>>',
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
lengthChange: true,
pageLength: 25,
select: true,
sort: true,
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.childRow,
renderer: $.fn.dataTable.Responsive.renderer.tableAll()
}
},
initComplete: function () {
tableFiltering(this.api(), 'cases_table');
}
}
);
$(document).ready(function() {
if ($('.nav-tabs').length > 0) { // if .nav-tabs exists
var hashtag = window.location.hash;
if (hashtag!='') {
$('.nav-item > a').removeClass('active').removeClass('show');
$('.nav-item > a[href="'+hashtag+'"]').addClass('active');
$('.nav-item > a[href="'+hashtag+'"]').addClass('show');
$('.tab-content > div').removeClass('active');
$(hashtag).addClass('active'); $(hashtag).addClass('show');
}
}
});

View File

@ -0,0 +1,148 @@
const preventFormDefaultBehaviourOnSubmit = (event) => {
event.preventDefault();
return false;
};
function add_customer() {
const url = 'customers/add/modal' + case_param();
$('#modal_add_customer_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#form_new_customer').on("submit", preventFormDefaultBehaviourOnSubmit);
$('#submit_new_customer').on("click", function () {
const form = $('#form_new_customer').serializeObject();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
form['custom_attributes'] = attributes;
post_request_api('customers/add', JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_customer_table();
$('#modal_add_customer').modal('hide');
}
});
return false;
})
});
$('#modal_add_customer').modal({show: true});
}
$(document).ready(function() {
cid = case_param();
$('#customers_table').dataTable({
"ajax": {
"url": "customers/list" + cid,
"contentType": "application/json",
"type": "GET",
"data": function (d) {
if (d.status == 'success') {
return JSON.stringify(d.data);
} else {
return [];
}
}
},
"order": [[0, "desc"]],
"autoWidth": false,
"columns": [
{
"data": "customer_name",
"render": function (data, type, row) {
if (type === 'display') {
data = sanitizeHTML(data);
return '<a href="/manage/customers/' + row['customer_id'] + '/view'+ cid +'">' + data + '</a>';
}
return data;
}
},
{
"data": "customer_description",
"render": function (data, type, row) {
if (type === 'display') {
return sanitizeHTML(data);
}
return data;
}
}
]
}
);
});
function refresh_customer_table(do_notify) {
$('#customers_table').DataTable().ajax.reload();
if (do_notify !== undefined) {
notify_success("Refreshed");
}
}
/* Fetch the details of an asset and allow modification */
function customer_detail(customer_id) {
url = '/manage/customers/update/' + customer_id + '/modal' + case_param();
$('#modal_add_customer_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#form_new_customer').on("submit", preventFormDefaultBehaviourOnSubmit);
$('#submit_new_customer').on("click", function () {
const form = $('#form_new_customer').serializeObject();
ret = get_custom_attributes_fields();
has_error = ret[0].length > 0;
attributes = ret[1];
if (has_error){return false;}
form['custom_attributes'] = attributes;
post_request_api('/manage/customers/update/' + customer_id, JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
window.location.reload();
}
});
return false;
})
});
$('#modal_add_customer').modal({show: true});
}
function delete_customer(id) {
swal({
title: "Are you sure ?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/customers/delete/' + id)
.done((data) => {
if(notify_auto_api(data)) {
window.location.href = '/manage/customers' + case_param();
}
});
} else {
swal("Pfew, that was close");
}
});
}

View File

@ -0,0 +1,349 @@
var modal_group_table;
var current_groups_list;
manage_groups_table = $('#groups_table').dataTable( {
"order": [[ 1, "asc" ]],
"autoWidth": true,
"columns": [
{
"data": "group_id",
"render": function ( data, type, row ) {
if (type === 'display') {
data = sanitizeHTML(data)
return '<a href="#" onclick="group_detail(\'' + row["group_id"] + '\');">' + data +'</a>';
}
return data;
}
},
{ "data": "group_name",
"render": function ( data, type, row ) {
if (type === 'display') {
data = sanitizeHTML(data)
return '<a href="#" onclick="group_detail(\'' + row["group_id"] + '\');">' + data +'</a>';
}
return data;
}
},
{ "data": "group_description",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{ "data": "group_permissions_list",
"render": function (data, type, row, meta) {
if (type === 'display') {
tags = "";
for (perm in data) {
permstr = sanitizeHTML(data[perm].name);
tags += '<span class="badge badge-pill badge-light" title="Value 0x'+ data[perm].value.toString(16) +'">'+ permstr + '</span> ';
}
return tags;
}
return data;
}
},
{ "data": "group_members",
"render": function ( data, type, row ) {
if (type === 'display') {
return data.length;
}
return data;
}
}
]
}
);
function refresh_groups(do_notify) {
get_request_api('groups/list')
.done((data) => {
if(notify_auto_api(data, true)) {
current_groups_list = data.data;
manage_groups_table.api().clear().rows.add(data.data).draw();
if (do_notify !== undefined) {
notify_success("Refreshed");
}
}
});
}
/* Fetch the details of an user and allow modification */
function group_detail(group_id) {
url = 'groups/' + group_id + '/modal' + case_param();
$('#modal_access_control').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_group').on("click", function () {
clear_api_error();
var data_sent = $('#form_new_group').serializeObject();
post_request_api('/manage/groups/update/' + group_id, JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_groups();
$('#modal_access_control').modal('hide');
}
});
return false;
})
});
$('#modal_access_control').modal({ show: true });
}
function add_group() {
url = '/manage/groups/add/modal' + case_param();
$('#modal_access_control').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_group').on("click", function () {
clear_api_error();
var data_sent = $('#form_new_group').serializeObject();
post_request_api('/manage/groups/add', JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_groups();
$('#modal_access_control').modal('hide');
}
});
});
$('#modal_access_control').modal({ show: true });
});
}
function delete_group(id) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this!\nPlease make sure a group remains with enough rights to avoid a lockdown!",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
var data_sent = {
"csrf_token": $('#csrf_token').val()
}
post_request_api('/manage/groups/delete/' + id, JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_groups();
$('#modal_access_control').modal('hide');
}
});
}
});
}
function remove_members_from_group(group_id, user_id, on_finish) {
swal({
title: "Are you sure?",
text: "This will remove the user from the group",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, remove it!'
})
.then((willDelete) => {
if (willDelete) {
url = '/manage/groups/' + group_id + '/members/delete/' + user_id;
var data_sent = {
"csrf_token": $('#csrf_token').val()
}
post_request_api(url, JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_groups();
refresh_group_members(group_id);
if (on_finish !== undefined) {
on_finish();
}
}
});
}
});
}
function add_members_to_group(group_id) {
url = 'groups/' + group_id + '/members/modal' + case_param();
$('#modal_ac_additional').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#save_group_members').on("click", function () {
clear_api_error();
var data_sent = Object();
data_sent['group_members'] = $('#group_members').val();
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('groups/' + group_id + '/members/update', JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_groups();
refresh_group_members(group_id);
$('#modal_ac_additional').modal('hide');
}
});
return false;
});
$('#modal_ac_additional').modal({ show: true });
});
}
function refresh_group_members(group_id) {
if (modal_group_table !== undefined) {
get_request_api('/manage/groups/' + group_id)
.done((data) => {
if(notify_auto_api(data)) {
modal_group_table.clear();
modal_group_table.rows.add(data.data.group_members).draw();
}
});
}
}
function refresh_group_cac(group_id) {
if (modal_group_cac_table !== undefined) {
get_request_api('/manage/groups/' + group_id)
.done((data) => {
if(notify_auto_api(data)) {
current_group_cases_access_list = data.data.group_cases_access;
modal_group_cac_table.clear();
modal_group_cac_table.rows.add(current_group_cases_access_list).draw();
}
});
}
}
function manage_group_cac(group_id) {
url = 'groups/' + group_id + '/cases-access/modal' + case_param();
$('#manage_group_cac_button').text('Loading manager...');
$('#modal_ac_additional').load(url, function (response, status, xhr) {
$('#manage_group_cac_button').text('Set case access');
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#grant_case_access_to_group').on("click", function () {
clear_api_error();
var data_sent = Object();
data_sent['access_level'] = parseInt($('#group_case_ac_select').val());
data_sent['cases_list'] = $('#group_case_access_select').val();
data_sent['auto_follow_cases'] = $('#enable_auto_follow_cases').is(':checked');
data_sent['csrf_token'] = $('#csrf_token').val();
window.swal({
title: "Updating access",
text: "Please wait. We are updating users access.",
icon: "/static/assets/img/loader_cubes.gif",
button: false,
allowOutsideClick: false
});
post_request_api('groups/' + group_id + '/cases-access/update', JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_group_cac(group_id);
$('#modal_ac_additional').modal('hide');
}
})
.always(() => {
window.swal.close();
});
return false;
});
$('#modal_ac_additional').modal({ show: true });
});
}
function remove_case_access_from_group(group_id, case_id, on_finish) {
remove_cases_access_group(group_id, [case_id], on_finish);
}
function remove_group_cases_from_group_table(group_id, rows) {
cases = [];
for (cid in rows) {
cases.push(rows[cid].case_id);
}
remove_cases_access_group(group_id, cases);
}
function remove_cases_access_group(group_id, cases, on_finish) {
swal({
title: "Are you sure?",
text: "Members of this group won't be able to access these cases anymore",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, remove them!'
}).then((willDelete) => {
if (willDelete) {
url = '/manage/groups/' + group_id + '/cases-access/delete';
window.swal({
title: "Updating access",
text: "Please wait. We are updating users access.",
icon: "/static/assets/img/loader_cubes.gif",
button: false,
allowOutsideClick: false
});
var data_sent = Object();
data_sent['cases'] = cases;
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api(url, JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_group_cac(group_id);
if (on_finish !== undefined) {
on_finish();
}
}
})
.always(() => {
window.swal.close();
});
}
});
}
$(document).ready(function () {
refresh_groups();
});

View File

@ -0,0 +1,371 @@
$('#form_new_module').submit(function () {
post_request_api('/manage/modules/add', $('form#form_new_module').serializeArray(), function() {
$('#submit_new_module').text('Saving..')
.attr("disabled", true)
.removeClass('bt-outline-success')
.addClass('btn-success', 'text-dark');
})
.done((data) => {
notify_auto_api(data);
})
.always(() => {
$('#submit_new_module')
.attr("disabled", false)
.addClass('bt-outline-success')
.removeClass('btn-success', 'text-dark');
});
return false;
});
function add_module() {
url = 'modules/add/modal' + case_param();
$('#modal_add_module_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_module').on("click", function () {
post_request_api('modules/add', JSON.stringify($('#form_new_module').serializeObject()), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_modules(true);
refresh_modules_hooks(true);
$('#modal_add_module').modal('hide');
} else {
$('#alert_mod_add').text(data.message);
if (data.data) {
$('#details_list').empty();
for(var i in data.data)
{
var output='<li>'+data.data[i]+'</li>';
$('#details_list').append(output);
}
$('#alert_mod_details').show();
}
$('#alert_mod_add').show();
$('#submit_new_module').text("Retry");
}
})
.fail((error) => {
data = error.responseJSON;
$('#submit_new_module').text('Save');
$('#alert_mod_add').text(data.message);
if (data.data && data.data.length > 0) {
$('#details_list').empty();
for(var i in data.data)
{
var output='<li>'+data.data[i]+'</li>';
$('#details_list').append(output);
}
$('#alert_mod_details').show();
}
$('#alert_mod_add').show();
$('#submit_new_module').text("Retry");
});
return false;
})
});
$('#modal_add_module').modal({ show: true });
}
$('#modules_table').dataTable( {
"ajax": {
"url": "modules/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"order": [[ 1, "asc" ]],
"autoWidth": false,
"columns": [
{ 'data': 'id'},
{ 'data': 'module_human_name'},
{ 'data': 'has_pipeline',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'module_version',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'interface_version',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'date_added',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'name',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'is_active'},
],
"columnDefs": [
{
"render": function ( data, type, row ) {
data = sanitizeHTML(data);
return '<a href="#" onclick="module_detail(\'' + row['id'] + '\');">' + data +'</a>';
},
"targets": [0, 1]
},
{
"render": function ( data, type, row ) {
if (data == true) {
data = '<i class="fas fa-check text-success"></i>';
} else {
data = '<i class="fas fa-times text-warning"></i>';
}
if (row['configured'] == false) {
return data + ' <i class="fas fa-exclamation-triangle text-warning" data-toggle="tooltip" data-placement="top" title="Module was disabled because mandatory settings are not set. Please configure to activate."></i>'
} else { return data; }
},
"targets": [7]
}
]
}
);
function refresh_modules(silent) {
$('#modules_table').DataTable().ajax.reload();
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
if (silent === undefined || silent !== true) {
notify_success("Modules refreshed");
}
}
$('#hooks_table').dataTable( {
"ajax": {
"url": "modules/hooks/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"order": [[ 1, "asc" ]],
"autoWidth": false,
"columns": [
{ 'data': 'id'},
{ 'data': 'module_name',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'hook_name',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'hook_description',
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ 'data': 'is_manual_hook',
"render": function (data, type, row, meta) {
if (data == false) {
data = "<i class='fas fa-check text-success'></i>";
} else {
data = "<i class='fas fa-times text-muted'></i>";
}
return data;
}
},
{ 'data': 'is_active',
"render": function (data, type, row, meta) {
if (data == true) {
data = "<i class='fas fa-check text-success'></i>";
} else {
data = "<i class='fas fa-times text-muted'></i>";
}
return data;
}
}
]
}
);
function refresh_modules_hooks(silent) {
$('#hooks_table').DataTable().ajax.reload();
if (silent === undefined || silent !== true) {
notify_success("Hooks refreshed");
}
}
function export_mod_config(module_id) {
get_request_api('/manage/modules/export-config/' + module_id)
.done((data) => {
if(notify_auto_api(data, true)) {
download_file(data.data.module_name + "_configuration_export.json", "text/json",
JSON.stringify(data.data.module_configuration, null, 4));
}
});
}
function import_mod_config(module_id){
var file = $("#input_configuration_file").get(0).files[0];
var reader = new FileReader();
reader.onload = function (e) {
fileData = e.target.result
var data = new Object();
data['csrf_token'] = $('#csrf_token').val();
data['module_configuration'] = fileData;
post_request_api('/manage/modules/import-config/'+ module_id, JSON.stringify(data), true)
.done((data) => {
if(notify_auto_api(data, true)) {
module_detail(module_id);
$('#modal_input_config').modal('hide');
swal("Got news for you", data.message, "success");
} else {
swal("Got bad news for you", data.data, "error");
}
});
};
reader.readAsText(file)
return false;
}
/* Update the param of a module */
function update_param(module_id, param_name) {
url = 'modules/get-parameter/' + decodeURIComponent(escape(window.btoa(param_name))) + case_param();
$('#modal_update_param_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_save_parameter').on("click", function () {
var data = Object();
if ($('#editor_detail').length != 0) {
editor = ace.edit("editor_detail");
data['parameter_value'] = editor.getSession().getValue();
data['csrf_token'] = $('#csrf_token').val();
} else {
data = $('#form_update_param').serializeObject();
if ($('#parameter_value').attr('type') == "checkbox") {
data['parameter_value'] = $('#parameter_value').prop('checked');
}
}
post_request_api('modules/set-parameter/' + decodeURIComponent(escape(window.btoa(param_name))), JSON.stringify(data))
.done((data) => {
if(notify_auto_api(data)) {
module_detail(module_id);
refresh_modules(true);
$('#modal_update_param').modal('hide');
}
})
return false;
})
});
$('#modal_update_param').modal({ show: true });
}
/* Fetch the details of an module and allow modification */
function module_detail(module_id) {
url = 'modules/update/' + module_id + '/modal' + case_param();
$('#modal_add_module_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_module').on("click", function () {
post_request_api('modules/update/' + module_id, $('#form_new_module').serializeArray())
.done((data) => {
if(notify_auto_api(data)) {
module_detail(module_id);
$('#modal_update_param').modal('hide');
}
});
return false;
})
});
$('#modal_add_module').modal({ show: true });
}
function remove_module(id) {
swal({
title: "Are you sure?",
text: "Please note this will only remove the reference of the module in Iris. The module will stay installed on the server.",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, remove it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/modules/remove/' + id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_modules(true);
refresh_modules_hooks(true);
$('#modal_add_module').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}
function enable_module(module_id) {
post_request_api('modules/enable/' + module_id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_modules(true);
refresh_modules_hooks(true);
module_detail(module_id);
}
});
}
function disable_module(module_id) {
post_request_api('modules/disable/' + module_id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_modules(true);
refresh_modules_hooks(true);
module_detail(module_id);
}
});
}

View File

@ -0,0 +1,538 @@
function add_asset_type() {
url = '/manage/asset-type/add/modal' + case_param();
$('#modal_add_type_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#form_new_asset_type').submit("click", function (event) {
event.preventDefault();
var formData = new FormData(this);
url = '/manage/asset-type/add' + case_param();
$.ajax({
url: url,
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
if(notify_auto_api(data, true)) {
refresh_asset_table();
$('#modal_add_type').modal('hide');
}
},
error: function (error) {
$('#modal_add_type').text('Save');
propagate_form_api_errors(error.responseJSON.data);
}
});
return false;
});
$('#modal_add_type').modal({ show: true });
})};
$('#assets_table').dataTable( {
"ajax": {
"url": "/manage/asset-type/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"order": [[ 0, "desc" ]],
"autoWidth": false,
"columns": [
{
"data": "asset_name",
"render": function ( data, type, row ) {
return '<a href="#" onclick="assettype_detail(\'' + row['asset_id'] + '\');">' + sanitizeHTML(data) +'</a>';
}
},
{
"data": "asset_description",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "asset_icon_not_compromised_path",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return '<img style="width:2em;height:2em" src=\'' + data + '\'>';
}
},
{
"data": "asset_icon_compromised_path",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return '<img style="width:2em;height:2em" src=\'' + data + '\'>';
}
}
]
}
);
function refresh_asset_table() {
$('#assets_table').DataTable().ajax.reload();
notify_success("Refreshed");
}
/* Fetch the details of an asset and allow modification */
function assettype_detail(asset_id) {
url = '/manage/asset-type/update/' + asset_id + '/modal' + case_param();
$('#modal_add_type_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#form_new_asset_type').submit("click", function (event) {
event.preventDefault();
var formData = new FormData(this);
url = '/manage/asset-type/update/' + asset_id + case_param();
$.ajax({
url: url,
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
if(notify_auto_api(data, true)) {
refresh_asset_table();
$('#modal_add_type').modal('hide');
}
},
error: function (jqXHR) {
if(jqXHR.responseJSON && jqXHR.status == 400) {
propagate_form_api_errors(jqXHR.responseJSON.data);
} else {
ajax_notify_error(jqXHR, this.url);
}
}
});
return false;
});
$('#modal_add_type').modal({ show: true });
});
}
function delete_asset_type(id) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/asset-type/delete/' + id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_asset_table();
$('#modal_add_type').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}
/*** IOC Type ***/
function add_ioc_type() {
let url = '/manage/ioc-types/add/modal' + case_param();
$('#modal_add_type_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_ioc_type').on("click", function () {
var form = $('form#form_new_ioc_type').serializeObject();
post_request_api('/manage/ioc-types/add', JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_ioc_table();
$('#modal_add_type').modal('hide');
}
});
return false;
})
$('#modal_add_type').modal({ show: true });
});
}
$('#ioc_table').dataTable({
"ajax": {
"url": "/manage/ioc-types/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"order": [[ 0, "asc" ]],
"autoWidth": false,
"columns": [
{
"data": "type_name",
"render": function ( data, type, row ) {
return '<a href="#" onclick="ioc_type_detail(\'' + row['type_id'] + '\');">' + sanitizeHTML(data) +'</a>';
}
},
{
"data": "type_description",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "type_taxonomy",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "type_validation_regex",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
}
]
});
function refresh_ioc_table() {
$('#ioc_table').DataTable().ajax.reload();
notify_success("Refreshed");
}
/* Fetch the details of an asset and allow modification */
function ioc_type_detail(ioc_id) {
url = '/manage/ioc-types/update/' + ioc_id + '/modal' + case_param();
$('#modal_add_type_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_ioc_type').on("click", function () {
var form = $('form#form_new_ioc_type').serializeObject();
post_request_api('/manage/ioc-types/update/' + ioc_id, JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_ioc_table();
$('#modal_add_type').modal('hide');
}
});
return false;
})
});
$('#modal_add_type').modal({ show: true });
}
function delete_ioc_type(id) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/ioc-types/delete/' + id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_ioc_table();
$('#modal_add_type').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}
/*** Classification ***/
function add_classification() {
url = '/manage/case-classifications/add/modal' + case_param();
$('#modal_add_type_content').load(url, function () {
$('#submit_new_case_classification').on("click", function () {
var form = $('form#form_new_case_classification').serializeObject();
post_request_api('/manage/case-classifications/add', JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_classification_table();
$('#modal_add_type').modal('hide');
}
});
return false;
})
});
$('#modal_add_type').modal({ show: true });
}
$('#classification_table').dataTable({
"ajax": {
"url": "/manage/case-classifications/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"order": [[ 0, "asc" ]],
"autoWidth": false,
"columns": [
{
"data": "name",
"render": function ( data, type, row ) {
return '<a href="#" onclick="classification_detail(\'' + row['id'] + '\');">' + sanitizeHTML(data) +'</a>';
}
},
{
"data": "name_expanded",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{
"data": "description",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
}
]
});
function refresh_classification_table() {
$('#classification_table').DataTable().ajax.reload();
notify_success("Refreshed");
}
/* Fetch the details of an classification and allow modification */
function classification_detail(ioc_id) {
url = '/manage/case-classifications/update/' + ioc_id + '/modal' + case_param();
$('#modal_add_type_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_case_classification').on("click", function () {
var form = $('form#form_new_case_classification').serializeObject();
post_request_api('/manage/case-classifications/update/' + ioc_id, JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_classification_table();
$('#modal_add_type').modal('hide');
}
});
return false;
})
});
$('#modal_add_type').modal({ show: true });
}
function delete_case_classification(id) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/case-classifications/delete/' + id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_classification_table();
$('#modal_add_type').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}
/*** State ***/
function add_state() {
url = '/manage/case-states/add/modal' + case_param();
$('#modal_add_type_content').load(url, function () {
$('#submit_new_case_state').on("click", function () {
var form = $('form#form_new_case_state').serializeObject();
post_request_api('/manage/case-states/add', JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_state_table();
$('#modal_add_type').modal('hide');
}
});
return false;
})
});
$('#modal_add_type').modal({ show: true });
}
$('#state_table').dataTable({
"ajax": {
"url": "/manage/case-states/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"order": [[ 0, "asc" ]],
"autoWidth": false,
"columns": [
{
"data": "state_name",
"render": function ( data, type, row ) {
if (type === 'display') {
if (row['protected'] === true) {
return '<span href="#" "><i class="fa fa-lock mr-2" title="Protected state"></i>' + sanitizeHTML(data) + '</span>';
}
return '<a href="#" onclick="state_detail(\'' + row['state_id'] + '\');">' + sanitizeHTML(data) + '</a>';
}
return data;
}
},
{
"data": "state_description",
"render": function ( data, type, row ) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
}
]
});
function refresh_state_table() {
$('#state_table').DataTable().ajax.reload();
notify_success("Refreshed");
}
/* Fetch the details of an state and allow modification */
function state_detail(ioc_id) {
url = '/manage/case-states/update/' + ioc_id + '/modal' + case_param();
$('#modal_add_type_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_case_state').on("click", function () {
var form = $('form#form_new_case_state').serializeObject();
post_request_api('/manage/case-states/update/' + ioc_id, JSON.stringify(form))
.done((data) => {
if(notify_auto_api(data)) {
refresh_state_table();
$('#modal_add_type').modal('hide');
}
});
return false;
})
});
$('#modal_add_type').modal({ show: true });
}
function delete_case_state(id) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/case-states/delete/' + id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_state_table();
$('#modal_add_type').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}

View File

@ -0,0 +1,41 @@
function update_settings() {
var data_sent = $('form#form_srv_settings').serializeObject();
data_sent['prevent_post_mod_repush'] = $('#prevent_post_mod_repush').is(":checked");
data_sent['prevent_post_objects_repush'] = $('#prevent_post_objects_repush').is(":checked");
data_sent['password_policy_upper_case'] = $('#password_policy_upper_case').is(":checked");
data_sent['password_policy_lower_case'] = $('#password_policy_lower_case').is(":checked");
data_sent['password_policy_digit'] = $('#password_policy_digit').is(":checked");
post_request_api('/manage/settings/update', JSON.stringify(data_sent), true)
.done((data) => {
notify_auto_api(data);
});
}
function init_db_backup() {
get_request_api('/manage/server/backups/make-db')
.done((data) => {
msg = ""
for (idx in data.data) {
msg += data.data[idx] + '\n';
}
swal("Done",
msg,
{
icon: "success"
});
})
.fail((error) => {
for (idx in error.responseJSON.data) {
msg += data.data[idx] + '\n';
}
swal("Error",
msg,
{
icon: "error"
});
});
}

View File

@ -0,0 +1,179 @@
function add_report_template() {
url = 'templates/add/modal' + case_param();
$('#modal_report_template_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
/* create the select picker for language */
$('#report_language').selectpicker({
liveSearch: true,
title: "Language",
style: "Bootstrap 4: 'btn-outline-primary'"
});
$('#report_type').selectpicker({
liveSearch: true,
title: "Report type",
style: "Bootstrap 4: 'btn-outline-primary'"
});
$('#form_new_report_template').submit("click", function (event) {
event.preventDefault();
var formData = new FormData(this);
$.ajax({
url: 'templates/add' + case_param(),
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
if (notify_auto_api(data)) {
refresh_template_table();
$('#modal_add_report_template').modal('hide');
}
},
error: function (error) {
if(error.responseJSON) {
notify_error(error.responseJSON.message);
} else {
ajax_notify_error(error, this.url);
}
}
});
return false;
})
});
$('#modal_add_report_template').modal({ show: true });
}
$('#reports_table').dataTable( {
"ajax": {
"url": "templates/list" + case_param(),
"contentType": "application/json",
"type": "GET",
"data": function ( d ) {
if (d.status == 'success') {
return JSON.stringify( d.data );
} else {
return [];
}
}
},
"autoWidth": false,
"columns": [
{
"data": "name",
"render": function ( data, type, row ) {
data = sanitizeHTML(data);
return '<a href="#" onclick="delete_report(\'' + row['id'] + '\');">' + data +'</a>';
}
},
{
"render": function ( data, type, row ) {return sanitizeHTML(data);},
"data": "description",
},
{
"render": function ( data, type, row ) {return sanitizeHTML(data);},
"data": "naming_format",
},
{
"render": function ( data, type, row ) {return sanitizeHTML(data);},
"data": "date_created",
},
{
"render": function ( data, type, row ) {return sanitizeHTML(data);},
"data": "created_by",
},
{
"render": function ( data, type, row ) {return sanitizeHTML(data);},
"data": "code",
},
{
"render": function ( data, type, row ) {return sanitizeHTML(data);},
"data": "type_name",
},
{
"render": function ( data, type, row ) {
data = sanitizeHTML(data);
return '<a href="templates/download/' + row["id"] + case_param() + '"><i class="fas fa-download"></i></a>';
},
"data": "id",
}
]
}
);
function refresh_template_table() {
$('#reports_table').DataTable().ajax.reload();
notify_success("Refreshed");
}
/* Fetch the details of an asset and allow modification */
function report_detail(report_id) {
url = 'templates/update/' + report_id + case_param();
$('#modal_report_template_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_report_template').on("click", function () {
$.ajax({
url: url,
type: "POST",
data: $('#form_new_report_template').serializeArray(),
dataType: "json",
success: function (data) {
if (notify_auto_api(data)) {
refresh_template_table();
$('#modal_add_report_template').modal('hide');
}
},
error: function (error) {
if(error.responseJSON) {
notify_error(error.responseJSON.message);
} else {
ajax_notify_error(error, this.url);
}
}
});
return false;
})
});
$('#modal_report_template').modal({ show: true });
}
function delete_report(id) {
swal({
title: "This will delete the report template\nAre you sure?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
post_request_api('/manage/templates/delete/' + id)
.done((data) => {
if(notify_auto_api(data)) {
refresh_template_table();
$('#modal_add_report_template').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}

View File

@ -0,0 +1,337 @@
var current_users_list = [];
function add_user() {
url = 'users/add/modal' + case_param();
$('#modal_access_control').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_user').on("click", function () {
var data_sent = $('#form_new_user').serializeObject()
clear_api_error();
post_request_api('users/add', JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_users();
$('#modal_access_control').modal('hide');
}
});
return false;
})
});
$('#modal_access_control').modal({ show: true });
}
manage_users_table = $('#users_table').dataTable( {
"order": [[ 1, "asc" ]],
"autoWidth": false,
"language": {
"emptyTable": "Loading users..."
},
"columns": [
{
"data": "user_id",
"render": function ( data, type, row ) {
if (type === 'display') {
data = sanitizeHTML(data)
return '<a href="#" onclick="user_detail(\'' + row["user_id"] + '\');">' + data +'</a>';
}
return data;
}
},
{ "data": "user_name",
"render": function ( data, type, row ) {
if (type === 'display') {
data = sanitizeHTML(data)
return '<a href="#" onclick="user_detail(\'' + row["user_id"] + '\');">' + data +'</a>';
}
return data;
}
},
{ "data": "user_login",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{ "data": "user_email",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
},
{ "data": "user_active",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (data == true) {
data = '<span class="badge ml-2 badge-success">Active</span>';
} else {
data = '<span class="badge ml-2 badge-warning">Disabled</span>';
}
}
return data;
}
},
{ "data": "user_is_service_account",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (data == true) {
data = '<i class="fa fa-check text-success"></i>';
} else {
data = '<i class="fa fa-xmark text-danger"></i>';
}
}
return data;
}
}
]
}
);
function refresh_users(do_notify) {
get_request_api('users/list')
.done((data) => {
if(notify_auto_api(data, true)) {
current_users_list = data.data;
manage_users_table.api().clear().rows.add(data.data).draw();
if (do_notify !== undefined) {
notify_success("Refreshed");
}
}
});
}
/* Fetch the details of an user and allow modification */
function user_detail(user_id, goto_tab) {
url = 'users/' + user_id + '/modal' + case_param();
$('#modal_access_control').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#submit_new_user').on("click", function () {
clear_api_error();
var data_sent = $('#form_new_user').serializeObject();
post_request_api('/manage/users/update/' + user_id, JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
refresh_users();
$('#modal_access_control').modal('hide');
}
});
return false;
})
if (goto_tab !== undefined) {
$('.nav-pills a[href="#'+ goto_tab +'"]').tab('show');
}
$('#modal_access_control').modal({ show: true });
});
}
function refresh_user_ac(user_id) {
var ori_txt = $('#users_refresh_ac_btn').text();
$('#users_refresh_ac_btn').text('Refreshing..');
get_request_api('/manage/access-control/recompute-effective-user-ac/' + user_id)
.done((data) => {
notify_auto_api(data);
}).always(() => {
$('#users_refresh_ac_btn').text(ori_txt);
});
}
function delete_user(id) {
swal({
title: "Are you sure?",
text: "You won't be able to revert this !",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
})
.then((willDelete) => {
if (willDelete) {
var data_sent = {
'csrf_token': $('#csrf_token').val()
}
post_request_api('/manage/users/delete/' + id, JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_users();
$('#modal_access_control').modal('hide');
}
});
} else {
swal("Pfew, that was close");
}
});
}
function activate_user(user_id) {
get_request_api('/manage/users/activate/' + user_id)
.done((data) => {
if(notify_auto_api(data)) {
user_detail(user_id);
refresh_users();
}
});
}
function deactivate_user(user_id) {
get_request_api('/manage/users/deactivate/' + user_id)
.done((data) => {
if(notify_auto_api(data)) {
user_detail(user_id);
refresh_users();
}
});
}
function remove_member_from_org_wrap(org_id, user_id) {
remove_members_from_org(org_id, user_id, function() {
user_detail(user_id, 'user_orgs_tab');
});
}
function remove_member_from_group_wrap(group_id, user_id) {
remove_members_from_group(group_id, user_id, function() {
user_detail(user_id, 'user_groups_tab');
});
}
function manage_user_groups(user_id) {
url = 'users/' + user_id + '/groups/modal' + case_param();
$('#modal_ac_additional').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_ac_additional').modal({ show: true });
$('#save_user_groups_membership').on("click", function () {
clear_api_error();
var data_sent = Object();
data_sent['groups_membership'] = $('#user_groups_membership').val();
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('/manage/users/' + user_id + '/groups/update', JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_groups();
user_detail(user_id, 'user_groups_tab');
}
});
});
});
}
function manage_user_organisations(user_id) {
url = 'users/' + user_id + '/organisations/modal' + case_param();
$('#modal_ac_additional').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#modal_ac_additional').modal({ show: true });
$('#save_user_orgs_membership').on("click", function () {
clear_api_error();
var data_sent = Object();
data_sent['orgs_membership'] = $('#user_orgs_membership').val();
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('/manage/users/' + user_id + '/organisations/update', JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
user_detail(user_id, 'user_orgs_tab');
}
});
});
});
}
function refresh_user_cac(user_id) {
if (modal_user_cac_table !== undefined) {
get_request_api('/manage/users/' + user_id)
.done((data) => {
if(notify_auto_api(data)) {
current_user_cases_access_list = data.data.user_cases_access;
modal_user_cac_table.clear();
modal_user_cac_table.rows.add(current_user_cases_access_list).draw();
}
});
}
}
function manage_user_cac(user_id) {
url = 'users/' + user_id + '/cases-access/modal' + case_param();
$('#manage_user_cac_button').text('Loading manager...');
$('#modal_ac_additional').load(url, function (response, status, xhr) {
$('#manage_user_cac_button').text('Set case access');
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#grant_case_access_to_user').on("click", function () {
clear_api_error();
var data_sent = Object();
data_sent['cases_list'] = $('#user_case_access_select').val();
data_sent['access_level'] = parseInt($('#user_case_ac_select').val());
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('users/' + user_id + '/cases-access/update', JSON.stringify(data_sent))
.done((data) => {
if(notify_auto_api(data)) {
refresh_user_cac(user_id);
$('#modal_ac_additional').modal('hide');
}
});
return false;
});
$('#modal_ac_additional').modal({ show: true });
});
}
function remove_cases_access_from_user_table(org_id, rows) {
cases = [];
for (cid in rows) {
cases.push(rows[cid].case_id);
}
remove_cases_access_user(org_id, cases);
}
$(document).ready(function () {
refresh_users();
});

View File

@ -0,0 +1,363 @@
$.each($.find("table"), function(index, element){
addFilterFields($(element).attr("id"));
});
var OverviewTable = $("#overview_table").DataTable({
dom: '<"container-fluid"<"row"<"col"l><"col"f>>>rt<"container-fluid"<"row"<"col"i><"col"p>>>',
aaData: [],
aoColumns: [
{
data: "case_id",
render: function (data, type, row, meta) {
if (type === 'display') {
data = `<span title="Quick look" class="bg-transparent btn-quick-view" style="cursor: pointer;" data-index="${meta.row}" ><i class="fa-solid fa-eye"></i></span>`;
} else if (type === 'sort' || type === 'filter') {
data = parseInt(row['case_id']);
}
return data;
}
},
{
"data": "name",
"render": function (data, type, row, meta) {
if (type === 'display') {
if (isWhiteSpace(data)) {
data = '#' + row['case_id'];
} else {
data = sanitizeHTML(data);
}
data = '<a rel="noopener" title="Open case in new tab" target="_blank" href="case?cid='+ row['case_id'] + '">' + data +'</a>';
} else if (type === 'sort' || type === 'filter') {
data = sanitizeHTML(data);
}
return data;
}
},
{ "data": "client",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data.customer_name);
} else if (type === 'sort' || type === 'filter') {
data = sanitizeHTML(data.customer_name);
}
return data;
}
},
{
"data": "classification",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
data = sanitizeHTML(data.name);
} else if (data != null && (type === 'sort' || type === 'filter')) {
data = data.name;
}
return data;
}
},
{
"data": "state",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
let datar = sanitizeHTML(data.state_name);
let review_status = row['review_status'] ? row['review_status'].status_name : 'Not reviewed';
datar = `${datar} ${review_status === "Not reviewed"? '' : ' - ' + review_status}`;
if (data.state_name === 'Closed') {
datar = `<span class="badge badge-light"> Closed - ${review_status}</span>`;
}
return datar;
} else if (data != null && (type === 'sort' || type === 'filter')) {
let datar = sanitizeHTML(data.state_name);
let review_status = row['review_status'] ? row['review_status'].status_name : 'Not reviewed';
datar = `${datar} ${review_status === "Not reviewed"? '' : ' - ' + review_status}`;
if (data.state_name === 'Closed') {
datar = `Closed - ${review_status}`;
}
return datar;
} else {
return data;
}
}
},
{
"data": "tags",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
let output = '';
for (let index in data) {
let tag = sanitizeHTML(data[index].tag_title);
output += `<span class="badge badge-pill badge-light">${tag}</span> `;
}
return output;
} else if (type === 'sort' || type === 'filter') {
let output = [];
for (let index in data) {
let tag = sanitizeHTML(data[index].tag_title);
output.push(tag);
}
return output;
}
return data;
}
},
{
"data": "case_open_since_days",
"render": function(data, type, row, meta) {
if (type === 'display') {
title = "You\'re not forgetting me, are you?";
if (data <= 1) {
data = `<i title="Sounds good" class="text-success fw-bold fa-solid fa-stopwatch mr-1"></i>${data} day`;
}
else if (data <= 7) {
data = `<i title="Sounds good" class="text-success fw-bold fa-solid fa-stopwatch mr-1"></i>${data} days`;
} else if (7 < data && data < 14) {
data = `<i title="${title}" class="text-warning fw-bold fa-solid fa-stopwatch mr-1"></i>${data} days</div>`;
} else {
data = `<i title="${title}" class="text-danger fw-bold fa-solid fa-stopwatch mr-1"></i>${data} days</div>`;
}
} else if (type === 'sort' || type === 'filter') {
data = parseInt(data);
}
return data;
}
},
{
"data": "open_date",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
data = sanitizeHTML(data);
}
return data;
}
},
{
"data": "tasks_status",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
now = (data.closed_tasks / (data.closed_tasks + data.open_tasks))*100;
if (data.closed_tasks + data.open_tasks > 1) {
tasks_text = `tasks`;
} else {
tasks_text = `task`;
}
data = `<div class="progress progress-sm">
<div class="progress-bar bg-success" style="width:${now}%" role="progressbar" aria-valuenow="${now}" aria-valuemin="0" aria-valuemax="100"></div>
</div><small class="float-right">${data.closed_tasks} / ${data.closed_tasks + data.open_tasks} ${tasks_text} done</small>`;
} else if (data != null && (type === 'sort' || type === 'filter')) {
data = data.closed_tasks / (data.closed_tasks + data.open_tasks);
}
return data;
}
},
{
"data": "owner",
"render": function (data, type, row, meta) {
if (type === 'display' && data != null) {
sdata = sanitizeHTML(data.user_name);
data = `<div class="row">${get_avatar_initials(sdata, false, null, true)} <span class="ml-1">${sdata}</span></div>`;
} else if (type === 'filter' || type === 'sort') {
data = data.user_name;
}
return data;
}
}
],
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
lengthChange: true,
pageLength: 25,
searchBuilder: {
},
language: {
searchBuilder: {
add: "Add filter",
title: {
_: 'Filters (%d)',
0: '',
}
}
},
order: [[ 1, "asc" ]],
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
],
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.childRow,
renderer: $.fn.dataTable.Responsive.renderer.tableAll()
}
},
select: true,
initComplete: function () {
tableFiltering(this.api(), 'overview_table', [0]);
},
drawCallback: function () {
$('.btn-quick-view').off('click').on('click', function() {
show_case_view($(this).data('index'));
});
}
});
OverviewTable.searchBuilder.container().appendTo($('#table_buttons'));
function get_cases_overview(silent, show_full=false) {
show_full = show_full || $('#overviewLoadClosedCase').prop('checked');
$('#overviewTableTitle').text(show_full ? 'All cases' : 'Open cases');
get_raw_request_api('/overview/filter?cid=' + get_caseid() + (show_full ? '&show_closed=true' : ''))
.done((data) => {
if(notify_auto_api(data, silent)) {
overview_list = data.data;
OverviewTable.clear();
OverviewTable.rows.add(overview_list);
OverviewTable.columns.adjust().draw();
$(".truncate").on("click", function() {
var index = $(this).index() + 1;
$('table tr td:nth-child(' + index + ')').toggleClass("truncate");
});
}
});
}
function show_case_view(row_index) {
let case_data = OverviewTable.row(row_index).data();
$('#caseViewModal').find('.modal-title').text(case_data.name);
$('#caseViewModal').find('.modal-subtitle').text(case_data.case_uuid);
let body = $('#caseViewModal').find('.modal-body .container');
body.empty();
// Owner Card
let owner_card = $('<div/>').addClass('card mb-3');
let owner_body = $('<div/>').addClass('card-body');
owner_body.append($('<h2/>').addClass('card-title mb-2').text('Metadata'));
let owner_row = $('<div/>').addClass('row');
let owner_col1 = $('<div/>').addClass('col-md-6');
let owner_col2 = $('<div/>').addClass('col-md-6');
let timeSinceLastUpdateStr = '';
let modifications = case_data.modification_history;
if (modifications != null) {
let timestamps = Object.keys(modifications).map(parseFloat);
let lastUpdatedTimestamp = Math.max(...timestamps);
let currentTime = Date.now() / 1000; // convert to seconds
let timeSinceLastUpdate = currentTime - lastUpdatedTimestamp;
let timeSinceLastUpdateInSeconds = currentTime - lastUpdatedTimestamp;
let timeSinceLastUpdateInMinutes = timeSinceLastUpdate / 60;
let timeSinceLastUpdateInHours = timeSinceLastUpdateInMinutes / 60;
let timeSinceLastUpdateInDays = timeSinceLastUpdateInHours / 24;
if (timeSinceLastUpdateInSeconds < 60) {
timeSinceLastUpdateStr = `${Math.round(timeSinceLastUpdateInSeconds)} second(s) ago`;
} else if (timeSinceLastUpdateInMinutes < 60) {
timeSinceLastUpdateStr = `${Math.round(timeSinceLastUpdateInMinutes)} minute(s) ago`;
} else if (timeSinceLastUpdateInHours < 24) {
timeSinceLastUpdateStr = `${Math.round(timeSinceLastUpdateInHours)} hour(s) ago`;
} else {
timeSinceLastUpdateStr = `${Math.round(timeSinceLastUpdateInDays)} day(s) ago`;
}
} else {
timeSinceLastUpdateStr = 'Never';
}
let tagsStr = '';
for (let index in case_data.tags) {
let tag = sanitizeHTML(case_data.tags[index].tag_title);
tagsStr += `<span class="badge badge-pill badge-light">${tag}</span> `;
}
let owner_dl1 = $('<dl class="row"/>');
owner_dl1.append($('<dt class="col-sm-3"/>').text('Owner:'));
owner_dl1.append($('<dd class="col-sm-8"/>').text(case_data.owner.user_name));
owner_dl1.append($('<dt class="col-sm-3"/>').text('Opening User:'));
owner_dl1.append($('<dd class="col-sm-8"/>').text(case_data.user.user_name));
owner_dl1.append($('<dt class="col-sm-3"/>').text('Open Date:'));
owner_dl1.append($('<dd class="col-sm-8"/>').text(case_data.open_date));
if (case_data.close_date != null) {
owner_dl1.append($('<dt class="col-sm-3"/>').text('Close Date:'));
owner_dl1.append($('<dd class="col-sm-8"/>').text(case_data.close_date))
}
owner_dl1.append($('<dt class="col-sm-3"/>').text('Tags:'));
owner_dl1.append($('<dd class="col-sm-8"/>').html(tagsStr !== ''? tagsStr : 'No tags'));
owner_dl1.append($('<dt class="col-sm-3"/>').text('State:'));
owner_dl1.append($('<dd class="col-sm-8"/>').text(case_data.state ? case_data.state.state_description: 'None'));
owner_dl1.append($('<dt class="col-sm-3"/>').text('Last update:'));
owner_dl1.append($('<dd class="col-sm-8"/>').text(timeSinceLastUpdateStr));
owner_col1.append(owner_dl1);
let owner_dl2 = $('<dl class="row"/>');
owner_dl2.append($('<dt class="col-sm-3"/>').text('Customer Name:'));
owner_dl2.append($('<dd class="col-sm-8"/>').text(case_data.client.customer_name));
owner_dl2.append($('<dt class="col-sm-3"/>').text('Classification:'));
owner_dl2.append($('<dd class="col-sm-8"/>').text(case_data.classification ? case_data.classification.name: 'None'));
owner_dl2.append($('<dt class="col-sm-3"/>').text('SOC ID:'));
owner_dl2.append($('<dd class="col-sm-8"/>').text(case_data.soc_id !== '' ? case_data.soc_id : 'None'));
owner_dl2.append($('<dt class="col-sm-3"/>').text('Related alerts:'));
owner_dl2.append($('<dd class="col-sm-8"/>').html(`<a target="_blank" rel="noopener" href='/alerts?case_id=${case_data.case_id}'>${case_data.alerts.length} related alert(s) <i class="fa-solid fa-up-right-from-square ml-2"></i></a>`));
owner_dl2.append($('<dt class="col-sm-3"/>').text('Tasks:'));
if (case_data.tasks_status != null) {
owner_dl2.append($('<dd class="col-sm-8"/>').html(`<a target="_blank" rel="noopener" href='/case/tasks?cid=${case_data.case_id}'>${case_data.tasks_status.closed_tasks}/${case_data.tasks_status.open_tasks + case_data.tasks_status.closed_tasks} task(s) <i class="fa-solid fa-up-right-from-square ml-2"></i></a>`));
} else {
owner_dl2.append($('<dd class="col-sm-8"/>').text('No tasks'));
}
owner_dl2.append($('<dt class="col-sm-3"/>').text('Review:'));
if (case_data.review_status != null) {
owner_dl2.append($('<dd class="col-sm-8"/>').text(case_data.review_status.status_name));
} else {
owner_dl2.append($('<dd class="col-sm-8"/>').text('No review'));
}
owner_dl2.append($('<dt class="col-sm-3"/>').text('Reviewer:'));
if (case_data.reviewer != null) {
owner_dl2.append($('<dd class="col-sm-8"/>').text(case_data.reviewer.user_name));
} else {
owner_dl2.append($('<dd class="col-sm-8"/>').text('No reviewer'));
}
owner_col2.append(owner_dl2);
owner_row.append(owner_col1);
owner_row.append(owner_col2);
owner_body.append(owner_row);
owner_body.append(`<a type="button" class="btn btn-sm btn-dark float-right" target="_blank" rel="noopener" href='/case?cid=${case_data.case_id}'><i class="fa-solid fa-up-right-from-square mr-2"></i> View case</a>`);
owner_card.append(owner_body);
body.append(owner_card);
// Description Card
let desc_card = $('<div/>').addClass('card mb-3');
let desc_body = $('<div/>').addClass('card-body');
desc_body.append($('<h2/>').addClass('card-title mb-3').text('Summary'));
let converter = get_showdown_convert();
let html = converter.makeHtml(case_data.description);
desc_body.append($('<div/>').addClass('card-text').html(html));
desc_card.append(desc_body);
body.append(desc_card);
$('#caseViewModal').modal('show');
}
$(document).ready(function() {
get_cases_overview(true);
$('#overviewLoadClosedCase').change(function() {
get_cases_overview(true, this.checked);
});
});

View File

@ -0,0 +1,209 @@
$('#search_value').keypress(function(event){
var keycode = (event.keyCode ? event.keyCode : event.which);
if(keycode == '13'){
jQuery(this).blur();
jQuery('#submit_search').focus().click();
event.stopPropagation();
return false;
}
});
Table_1 = $("#file_search_table_1").DataTable({
dom: 'Bfrtip',
aaData: [],
aoColumns: [
{ "data": "ioc_name",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
if (row['ioc_misp'] != null) {
jse = JSON.parse(row['ioc_misp']);
data += `<i class="fas fa-exclamation-triangle ml-2 text-warning" style="cursor: pointer;" data-html="true"
data-toggle="popover" data-trigger="hover" title="Seen on MISP" data-content="Has been seen on <a href='` + row['misp_link'] + `/events/view/` + jse.misp_id +`'>this event</a><br/><br/><b>Description: </b>`+ jse.misp_desc +`"></i>`;
}
}
return data;
}
},
{ "data": "ioc_description",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover" style="cursor: pointer;" data-trigger="hover" title="Description" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{ "data": "type_name",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}},
{ "data": "case_name",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
data = '<a target="_blank" href="case?cid='+ row["case_id"] +'">' + data + '</a>';
}
return data;
}},
{ "data": "customer_name",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
} },
{ "data": "tlp_name",
"render": function(data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
data = '<span class="badge badge-'+ row['tlp_bscolor'] +' ml-2">tlp:' + data + '</span>';
}
return data;
}
}
],
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
]
});
$("#file_search_table_1").css("font-size", 12);
Table_comments = $("#comments_search_table").DataTable({
dom: 'Bfrtip',
aaData: [],
aoColumns: [
{ "data": "comment_id",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
if (row['ioc_misp'] != null) {
jse = JSON.parse(row['ioc_misp']);
data += `<i class="fas fa-exclamation-triangle ml-2 text-warning" style="cursor: pointer;" data-html="true"
data-toggle="popover" data-trigger="hover" title="Seen on MISP" data-content="Has been seen on <a href='` + row['misp_link'] + `/events/view/` + jse.misp_id +`'>this event</a><br/><br/><b>Description: </b>`+ jse.misp_desc +`"></i>`;
}
}
return data;
}
},
{ "data": "comment_text",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
datas = '<span data-toggle="popover" style="cursor: pointer;" data-trigger="hover" title="Description" data-content="' + data + '">' + data.slice(0, 70);
if (data.length > 70) {
datas += ' (..)</span>';
} else {
datas += '</span>';
}
return datas;
}
return data;
}
},
{ "data": "case_name",
"render": function (data, type, row, meta) {
if (type === 'display') {
data = sanitizeHTML(data);
data = '<a target="_blank" href="case?cid='+ row["case_id"] +'">' + data + '</a>';
}
return data;
}},
{ "data": "customer_name",
"render": function (data, type, row, meta) {
if (type === 'display') { data = sanitizeHTML(data);}
return data;
}
}
],
filter: true,
info: true,
ordering: true,
processing: true,
retrieve: true,
buttons: [
{ "extend": 'csvHtml5', "text":'Export',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
{ "extend": 'copyHtml5', "text":'Copy',"className": 'btn btn-primary btn-border btn-round btn-sm float-left mr-4 mt-2' },
]
});
$("#comments_search_table").css("font-size", 12);
$('#submit_search').click(function () {
search();
});
function search() {
var data_sent = $('form#form_search').serializeObject();
data_sent['csrf_token'] = $('#csrf_token').val();
post_request_api('/search', JSON.stringify(data_sent), true, function (data) {
$('#submit_search').text("Searching...");
})
.done((data) => {
if(notify_auto_api(data, true)) {
$('#notes_msearch_list').empty();
Table_1.clear();
Table_comments.clear();
$('#search_table_wrapper_1').hide();
$('#search_table_wrapper_2').hide();
$('#search_table_wrapper_3').hide();
val = $("input[type='radio']:checked").val();
if (val == "ioc") {
Table_1.rows.add(data.data);
Table_1.columns.adjust().draw();
$('#search_table_wrapper_1').show();
$('#search_table_wrapper_1').on('click', function(e){
if($('.popover').length>1)
$('.popover').popover('hide');
$(e.target).popover('toggle');
});
}
else if (val == "notes") {
for (e in data.data) {
li = `<li class="list-group-item">
<span class="name" style="cursor:pointer" title="Click to open note" onclick="note_in_details(${data.data[e]['note_id']}, ${data.data[e]['case_id']});">`+ sanitizeHTML(data.data[e]['note_title']) + ` - ` + sanitizeHTML(data.data[e]['case_name']) + ` - ` + sanitizeHTML(data.data[e]['client_name']) +`</span>
</li>`
$('#notes_msearch_list').append(li);
}
$('#search_table_wrapper_2').show();
} else if (val == "comments") {
Table_comments.rows.add(data.data);
Table_comments.columns.adjust().draw();
$('#search_table_wrapper_3').show();
$('#search_table_wrapper_3').on('click', function(e){
if($('.popover').length>1)
$('.popover').popover('hide');
$(e.target).popover('toggle');
});
}
}
})
.always(() => {
$('#submit_search').text("Search");
});
}
function note_in_details(note_id, case_id) {
window.open("/case/notes?cid=" + case_id + "&shared=" + note_id);
}
$(document).ready(function(){
$('#search_value').focus();
});

View File

@ -0,0 +1,174 @@
channel = 'iris_update_status';
function log_error(message) {
add_update_log(message, true);
}
function log_msg(message) {
add_update_log(message, false)
}
function add_update_log(message, is_error) {
html_wrap = `<h4><i class="mt-2 fas fa-check text-success"></i> `
if (is_error) {
html_wrap = `<h4><i class="mt-2 fas fa-times text-danger"></i> `
}
$("#updates_log").append(html_wrap + message + '</h4><br/>')
$('html, body').animate({
scrollTop: $("#updates_log_end").offset().top
}, 50);
}
function get_caseid() {
queryString = window.location.search;
urlParams = new URLSearchParams(queryString);
return urlParams.get('cid')
}
function case_param() {
var params = {
cid: get_caseid
}
return '?'+ $.param(params);
}
function initiate_update() {
$.ajax({
url: '/manage/server/start-update' + case_param(),
type: "GET",
dataType: "json",
beforeSend : function () {
log_msg('Update order sent. Expecting feedback anytime soon');
},
success: function (data) {},
error: function (data) {
log_error('Unexpected error starting update');
}
});
}
var intervalId = null;
var ios = io('/server-updates');
var update_socket = null;
var current_version = null;
var updated_version = null;
var steps = 0;
var no_resp_time = 0;
function check_server_version() {
$.ajax({
url: '/api/versions' + case_param(),
type: "GET",
dataType: "json",
timeout: 1000,
success: function (data) {
server_version = data.data.iris_current;
if (server_version == current_version) {
add_update_log('Something was wrong - server is still in the same version', true);
add_update_log('Please check server logs', true);
clearInterval(intervalId);
$('#tag_bottom').hide();
$('#update_return_button').show();
} else {
add_update_log('Successfully updated from ' + current_version + ' to ' + server_version, false);
add_update_log('You can now leave this page', false);
clearInterval(intervalId);
$('#tag_bottom').hide();
$('#update_return_button').show();
}
},
error: function (error) {
log_error('Something\'s wrong, server is not answering');
log_error('Please check server logs')
clearInterval(intervalId);
$('#tag_bottom').hide();
$('#update_return_button').show();
}
});
}
function ping_check_server_online() {
$.ajax({
url: '/api/ping' + case_param(),
type: "GET",
dataType: "json",
timeout: 1000,
success: function (data) {
$("#offline_time").hide();
log_msg('Server is back online');
clearInterval(intervalId);
check_server_version();
},
error: function (error) {
no_resp_time += 1;
if (no_resp_time > 29) {
log_error('Something\'s wrong, server is not answering');
log_error('Please check server logs')
clearInterval(intervalId);
$('#tag_bottom').hide();
$('#update_return_button').show();
}
$("#offline_time").html('<h4 id="offline_time"><i class="fas fa-clock"></i> Attempt '+ no_resp_time +' / 30</h4><br/>');
$("#offline_time").show();
}
});
}
function start_updates(){
$('#update_start_btn').hide();
$('.update_start_txt').hide();
$('#container-updates').show();
update_socket.emit('update_get_current_version', { 'channel': channel });
update_socket.emit('update_ping', { 'channel': channel });
// index = 0;
// while(index < 20) {
// add_update_log('ping');
// index += 1;
// }
}
$(document).ready(function(){
update_socket = ios.connect();
update_socket.on( "update_status", function(data) {
add_update_log(data.message, data.is_error)
}.bind() );
update_socket.on( "update_ping", function(data) {
log_msg('Server connection verified');
log_msg('Starting update');
initiate_update();
}.bind() );
update_socket.on( "server_has_updated", function(data) {
log_msg('Server reported updates applied. Checking . . .');
check_server_version();
}.bind() );
update_socket.on('disconnect', function () {
add_update_log('Server is offline, waiting for connection', false);
intervalId = window.setInterval(function(){
ping_check_server_online();
}, 1000);
});
update_socket.on('update_current_version', function (data) {
add_update_log('Server reported version ' + data.version , false);
if (current_version == null) {
current_version = data.version;
}
});
update_socket.on('update_has_fail', function () {
$('#tag_bottom').hide();
$('#update_return_button').show();
});
update_socket.emit('join-update', { 'channel': channel });
});

View File

@ -0,0 +1,104 @@
function renew_api() {
swal({
title: "Are you sure?",
text: "The current key will be revoked and cannot be used anymore",
icon: "warning",
buttons: true,
dangerMode: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Go for it'
})
.then((willDelete) => {
if (willDelete) {
get_request_api('/user/token/renew')
.done((data) => {
if(notify_auto_api(data)) {
location.reload(true);
}
})
} else {
swal("Pfew, that was close");
}
});
}
function save_user_password() {
clear_api_error();
if ( $('#user_password').val() != $('#user_password_v').val()) {
$('#user_password').addClass('is-invalid');
$('#user_password').after("<div class='invalid-feedback' id='user_password-invalid-msg'>Password and verification are not the same</div>");
$('#user_password').show();
return False;
}
var data_sent = $('#form_update_pwd').serializeObject();
data_sent['user_password'] = $('#user_password').val();
post_request_api('update', JSON.stringify(data_sent), true)
.done((data) => {
if(notify_auto_api(data)) {
$('#modal_pwd_user').modal('hide');
}
});
}
/* Fetch the details of an user and allow modification */
function update_password(user_id) {
url = 'update/modal' + case_param();
$('#modal_pwd_user_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
});
$('#modal_pwd_user').modal({ show: true });
}
function refresh_user_permissions() {
var ori_txt = $('#user_refresh_perms_btn').text();
$('#user_refresh_perms_btn').text('Refreshing..');
get_request_api('refresh-permissions')
.done((data) => {
notify_auto_api(data);
}).always(() => {
$('#user_refresh_perms_btn').text(ori_txt);
});
}
$('input[type=radio][name=iris-theme]').change(function() {
if (this.value == 'false') {
theme = 'light'
}
else if (this.value == 'true') {
theme = 'dark';
} else {
return;
}
get_request_api('theme/set/'+ theme)
.done((data) => {
if (notify_auto_api(data, true)) {
location.reload(true);
}
});
});
$('input[type=radio][name=user-has-deletion-prompt]').change(function() {
if (this.value == 'false') {
do_prompt = false;
}
else if (this.value == 'true') {
do_prompt = true;
} else {
return;
}
get_request_api('deletion-prompt/set/'+ do_prompt)
.then((data) => {
if (notify_auto_api(data)) {
userWhoamiRequest(true);
}
});
});

View File

@ -0,0 +1,117 @@
function delete_contact(contact_id, customer_id) {
post_request_api('/manage/customers/' + customer_id + '/contacts/' + contact_id + '/delete', null, true)
.done((data) => {
if(notify_auto_api(data)) {
window.location.reload();
}
});
}
function edit_contact(contact_id, customer_id) {
url = '/manage/customers/' + customer_id + '/contacts/' + contact_id + '/modal' + case_param();
$('#modal_add_contact_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#form_new_contact').on("submit", preventFormDefaultBehaviourOnSubmit);
$('#submit_new_contact').on("click", function () {
const form = $('#form_new_contact').serializeObject();
post_request_api('/manage/customers/' + customer_id + '/contacts/' + contact_id + '/update', JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
window.location.reload();
}
});
return false;
});
$('#submit_delete_contact').on("click", function () {
post_request_api('/manage/customers/' + customer_id + '/contacts/' + contact_id + '/delete')
.done((data) => {
if(notify_auto_api(data)) {
window.location.reload();
}
});
return false;
});
});
$('#modal_add_contact').modal({show: true});
}
function add_new_contact(customer_id) {
url = '/manage/customers/' + customer_id + '/contacts/add/modal' + case_param();
$('#modal_add_contact_content').load(url, function (response, status, xhr) {
if (status !== "success") {
ajax_notify_error(xhr, url);
return false;
}
$('#form_new_contact').on("submit", preventFormDefaultBehaviourOnSubmit);
$('#submit_new_contact').on("click", function () {
const form = $('#form_new_contact').serializeObject();
post_request_api('/manage/customers/' + customer_id + '/contacts/add', JSON.stringify(form), true)
.done((data) => {
if(notify_auto_api(data)) {
window.location.reload();
}
});
return false;
})
});
$('#modal_add_contact').modal({show: true});
}
function load_customer_stats(customer_id) {
get_request_api('/manage/customers/' + customer_id + '/cases')
.done((data) => {
if(notify_auto_api(data, true)) {
$('#last_month_cases').text(data.data.stats.cases_last_month);
$('#last_year_cases').text(data.data.stats.cases_last_year);
$('#cases_last_month').text(data.data.stats.cases_last_month);
$('#cases_current_month').text(data.data.stats.cases_current_month);
$('#cases_current_year').text(data.data.stats.cases_current_year);
$('#current_open_cases').text(data.data.stats.open_cases);
$('#cases_total').text(data.data.stats.cases_total);
$('#ratio_year').text(data.data.stats.ratio_year);
$('#average_case_duration').text(data.data.stats.average_case_duration);
if (data.data.stats.ratio_year > 0) {
$('#ratio_year').addClass('text-warning');
$('#ratio_year').html(`+${data.data.stats.ratio_year}% <i class="ml-1 fa fa-chevron-up"></i>`);
} else if (data.data.stats.ratio_year < 0) {
$('#ratio_year').addClass('text-success');
$('#ratio_year').html(`${data.data.stats.ratio_year}% <i class="ml-1 fa fa-chevron-down"></i>`);
}
if (data.data.stats.ratio_month > 0) {
$('#ratio_month').addClass('text-warning');
$('#ratio_month').html(`+${data.data.stats.ratio_month}% <i class="ml-1 fa fa-chevron-up"></i>`);
} else if (data.data.stats.ratio_month < 0) {
$('#ratio_month').addClass('text-success');
$('#ratio_month').html(`${data.data.stats.ratio_month}% <i class="ml-1 fa fa-chevron-down"></i>`);
}
$('#last_year').text(data.data.stats.last_year);
}
});
}
$(document).ready(function() {
customer_id = $('#customer_id').val();
load_customer_stats(customer_id);
});