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,125 @@
{% extends "layouts/default.html" %}
{% block title %} Access Control {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
<link rel="stylesheet" href="/static/assets/css/bootstrap-multiselect.min.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-heading collapsed" href="#collapse_user_mgmt" title="Click to unfold" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_user_mgmt">
<span class="accicon float-left mr-3"><i class="fas fa-angle-right rotate-icon"></i></span>
<div class="card-title">Users</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_users(true);">Refresh</button>
<a class="btn btn-sm btn-dark float-right ml-2" href="access-control/audit/users?cid={{ session['current_case'].case_id }}">Audit users</a>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_user();">Add user</button>
</div>
</div>
</div>
<div class="card-body collapse" id="collapse_user_mgmt">
<div class="table-responsive" id="users_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="users_table">
<thead>
<tr>
<th>#ID</th>
<th>Name</th>
<th>Login Name</th>
<th>Email</th>
<th>Active</th>
<th>Service Account</th>
</tr>
</thead>
<tfoot>
<tr>
<th>#ID</th>
<th>Name</th>
<th>Login Name</th>
<th>Email</th>
<th>Active</th>
<th>Service Account</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-heading collapsed" href="#collapse_groups_mgmt" title="Click to unfold" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_groups_mgmt">
<span class="accicon float-left mr-3"><i class="fas fa-angle-right rotate-icon"></i></span>
<div class="card-title">Groups</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_groups(true);">Refresh</button>
<button class="btn btn-sm btn-dark float-right" onclick="add_group();">Add group</button>
</div>
</div>
</div>
<div class="card-body collapse" id="collapse_groups_mgmt">
<div class="table-responsive" id="groups_table_wrapper">
<div class="selectgroup">
<span id="groups_table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="groups_table">
<thead>
<tr>
<th>#ID</th>
<th>Name</th>
<th>Description</th>
<th>Permissions</th>
<th>#Members</th>
</tr>
</thead>
<tfoot>
<tr>
<th>#ID</th>
<th>Name</th>
<th>Description</th>
<th>Permissions</th>
<th>#Members</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
{% endif %}
</div>
<div class="modal" tabindex="-1" role="dialog" id="modal_access_control" data-backdrop="true">
</div>
<div class="modal bg-shadow-gradient" tabindex="-1" role="dialog" id="modal_ac_additional" data-backdrop="true">
</div>
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/plugin/select/bootstrap-multiselect.min.js"></script>
<script src="/static/assets/js/plugin/datatables/dataTables.select.min.js"></script>
<script src="/static/assets/js/plugin/datatables/dataTables.contextualActions.min.js"></script>
<script src="/static/assets/js/iris/manage.users.js"></script>
<script src="/static/assets/js/iris/manage.cases.common.js"></script>
<script src="/static/assets/js/iris/manage.groups.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,58 @@
{% extends "layouts/default.html" %}
{% block title %} Access Control {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
<link rel="stylesheet" href="/static/assets/css/bootstrap-select.min.css">
<link rel="stylesheet" href="/static/assets/css/select2.css">
{% endblock stylesheets %}
{% block content %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<a class="mb-2 ml-1 text-dark" href="/manage/access-control?cid={{ session['current_case'].case_id }}"><i class="fa-solid fa-arrow-left"></i> Back</a>
<div class="card mt-2">
<div class="card-header">
<div class="row">
<div class="col col-heading">
<div class="card-title">Users audit</div>
</div>
</div>
</div>
<div class="card-body" id="">
<div class="row">
<div class="col-12">
<div class="input-group mb-3">
<select id="users_audit_select" name="users_audit_select" class="form-control ml-12"
tabindex="-1" style="width: 50%"></select>
<div class="input-group-append">
<button type="button" class="btn btn-outline-success" id="get_user_audit_btn"
onclick="get_user_audit_page();">Audit</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
</div>
</div>
</div>
</div>
<div id="user_audit_content">
</div>
</div>
</div>
</div>
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/plugin/datatables/dataTables.select.min.js"></script>
<script src="/static/assets/js/iris/manage.audit.users.js"></script>
<script src="/static/assets/js/iris/datatablesUtils.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,292 @@
<div class="modal-xl modal-dialog" role="document">
<div class="modal-content" id="modal_access_control_content">
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">{% if not group.group_id %}Add Group {% else %} Edit {{ group.group_name }} {% endif %}</h4>
<div class="row text-center mr-4">
{% if group.group_id %}
<ul class="nav nav-pills nav-default mr-4" role="tablist">
<li class="nav-item">
<a class="nav-link active show" data-toggle="pill" href="#group_details_tab" role="tab" aria-controls="group_details_tab" aria-selected="false">Info</a>
</li>
<li class="nav-item submenu">
<a class="nav-link" data-toggle="pill" href="#group_members_tab" role="tab" aria-controls="group_members_tab" aria-selected="false">Members</a>
</li>
<li class="nav-item submenu">
<a class="nav-link" data-toggle="pill" href="#group_cac_tab" role="tab" aria-controls="group_cac_tab" aria-selected="false">Cases access</a>
</li>
</ul>
{% endif %}
</div>
<div class="row text-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
<div class="modal-body">
<div role="tabpanel">
<div class="tab-content">
<div class="tab-pane active" id="group_details_tab">
<div class="container col-md-12" >
<form method="post" action="" id="form_new_group">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
{% if not group.group_id %}
<p class="ml-3"><i class="fa-solid fa-circle-info mr-2"></i>Members can be added once the group is created.</p>
{% endif %}
<div class="form-group">
<label for="group_name" class="mr-4">Group name *
</label>
{{ form.group_name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="group_description" class="placeholder">Description *</label>
{{ form.group_description(class='form-control', autocomplete="off") }}
</div>
<div class="form-group" data-select2-id="7">
<label>Permissions *</label>
<div class="select2-input ml-12" data-select2-id="6">
<select id="group_permissions" name="group_permissions" class="form-control select2-hidden-accessible ml-12" multiple="" data-select2-id="group_permissions" tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
</div>
</div>
</div>
{% if group.group_id %}
<button type="button" class="btn btn-danger mt-5"
onclick="delete_group('{{ group.group_id }}');">Delete</button>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_group">Update</button>
{% else %}
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_group">Save</button>
{% endif %}
</form>
</div>
</div>
<div class="tab-pane" id="group_members_tab">
<div class="container col-md-12" >
<div class="row d-flex">
<div class="col pull-right">
<button class="btn btn-dark btn-sm pull-right" onclick="refresh_group_members({{ group.group_id }});">
<span class="menu-title">Refresh</span>
</button>
<button class="btn btn-dark btn-sm pull-right mr-2" onclick="add_members_to_group({{ group.group_id }});">
<span class="menu-title">Manage</span>
</button>
</div>
</div>
<div class="row">
<table class="table display table-bordered table-striped table-hover responsive" width="100%" cellspacing="0" id="group_members_table" >
<thead>
<tr>
<th>User ID</th>
<th>User login</th>
<th>User display name</th>
</tr>
</thead>
<tfoot>
<tr>
<th>User ID</th>
<th>User login</th>
<th>User display name</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<div class="tab-pane" id="group_cac_tab">
<div class="container col-md-12" >
<div class="row d-flex mb-2">
<div class="col">
{% if group.group_auto_follow %}
<b><i class="fa fa-triangle-exclamation text-warning mr-2"></i>This group is set to automatically include all new cases.</b>
{% endif %}
</div>
<div class="col pull-right">
<button class="btn btn-dark btn-sm pull-right" onclick="refresh_group_cac({{ group.group_id }});">
<span class="menu-title">Refresh</span>
</button>
<button class="btn btn-dark btn-sm pull-right mr-2" onclick="manage_group_cac({{ group.group_id }});">
<span class="menu-title" id="manage_group_cac_button">Set case access</span>
</button>
</div>
</div>
<div class="row mt-2">
<table class="table display table-bordered table-striped table-hover responsive" width="100%" cellspacing="0" id="group_cac_table" >
<thead>
<tr>
<th>Case ID</th>
<th>Case Name</th>
<th>Access</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Case ID</th>
<th>Case Name</th>
<th>Access</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
<script>
var data = [
{% for e in all_perms %}
{
value: {{ e.value }},
label: "{{ e.name }}"
}
{% if not loop.last %},{% endif %}
{% endfor %}
];
$('#group_permissions').multiselect({
buttonWidth: 400,
nonSelectedText: 'Select permissions',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#group_permissions').multiselect('dataprovider', data );
{% if group.group_permissions_list %}
$('#group_permissions').multiselect('select', [
{% for perm in group.group_permissions_list %} {{ perm.value }}, {% endfor %}
]);
$('#org_members').multiselect('refresh')
{% endif %}
var modal_group_table = $("#group_members_table").DataTable({
dom: 'Blfrtip',
aaData: [],
aoColumns: [
{
"data": "id",
"render": function ( data, type, row ) {
return `<i class="fa-solid fa-trash-can mr-2 text-danger" style="cursor:pointer;" title="Remove from group" href="javascript:void(0)" onclick="remove_members_from_group('{{ group.group_id }}',${data})"></i>${data}`;
},
"className": "dt-center"
},
{
"data": "user",
"className": "dt-center",
"render": function (data, type, row) {
return sanitizeHTML(data);
}
},
{
"data": "name",
"className": "dt-center",
"render": function (data, type, row) {
return sanitizeHTML(data);
}
}
],
filter: true,
info: true,
ordering: true,
processing: true
});
{% if group.group_id %}
modal_group_table.rows.add({{ group.group_members|tojson }});
modal_group_table.columns.adjust().draw();
{% endif %}
var modal_group_cac_table = $("#group_cac_table").DataTable({
dom: 'Blfrtip',
aaData: [],
aoColumns: [
{
"data": "case_id",
"render": function ( data, type, row ) {
return `<i class="fa-solid fa-trash-can mr-2 text-danger" style="cursor:pointer;" title="Remove access to case" href="javascript:void(0)" onclick="remove_case_access_from_group('{{ group.group_id }}',${data})"></i>${data}`;
},
"className": "dt-center"
},
{
"data": "case_name",
"className": "dt-center",
"render": function (data, type, row) {
return `<a target="_blank" rel="noopener" href="/case?cid=${row.case_id}">${sanitizeHTML(data)}</a>`;
}
},
{
"data": "access_level_list",
"render": function ( data, type, row ) {
ret_data = "";
for (acc in data) {
ret_data += `<span class="badge ml-2 badge-light">${data[acc].name}</span>`
}
return ret_data;
},
"className": "dt-center"
}
],
filter: true,
info: true,
ordering: true,
processing: true,
select: true
});
var actionOptionsGroup = {
classes: [],
contextMenu: {
enabled: true,
isMulti: true,
xoffset: -10,
yoffset: -10,
headerRenderer: function (rows) {
if (rows.length > 1) {
return rows.length + ' items selected';
} else {
let row = rows[0];
return 'Quick action';
}
},
},
buttonList: {
enabled: false,
},
deselectAfterAction: true,
items: [],
};
{% if group.group_id %}
actionOptionsGroup.items.push({
type: 'option',
title: 'Remove access',
multi: true,
iconClass: 'fas fa-trash',
buttonClasses: ['btn', 'btn-outline-primary'],
action: function(rows){
remove_group_cases_from_group_table({{ group.group_id }}, rows);
}
});
modal_group_cac_table.contextualActions(actionOptionsGroup);
current_group_cases_access_list = {{ group.group_cases_access|tojson }};
modal_group_cac_table.rows.add(current_group_cases_access_list);
modal_group_cac_table.columns.adjust().draw();
{% endif %}
</script>

View File

@@ -0,0 +1,90 @@
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">Set case access</h4>
<div class="row text-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
<div class="modal-body">
<div class="container col-md-12" >
<div class="row">
<div class="form-group" data-select2-id="7">
<label>Set cases access of group <i>{{ group.group_name }}</i> *</label>
<div class="row">
<div class="col-12">
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="enable_auto_follow_cases" name="enable_auto_follow_cases" {% if group.group_auto_follow %}checked{% endif %}>
<span class="form-check-sign">Apply to currents and futures cases</span>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<select id="group_case_access_select" name="org_case_access_select" class="form-control select2-hidden-accessible ml-12" multiple="multiple"
tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
<select id="group_case_ac_select" name="org_case_ac_select" class="form-control select2-hidden-accessible ml-12"
tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="grant_case_access_to_group">Set access</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
<script>
var data = [];
$('#group_case_access_select').multiselect({
buttonWidth: 400,
nonSelectedText: 'Select case',
emptyText: 'No case available to add',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#group_case_access_select').multiselect('dataprovider', [{% for ocs in outer_cases %}
{ label: "{{ ocs.case_name }}", value: {{ ocs.case_id }} }, {% endfor %}]);
$('#group_case_access_select').multiselect('refresh')
$('#group_case_ac_select').multiselect({
nonSelectedText: 'Select access level',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#group_case_ac_select').multiselect('dataprovider', [{% for acc in access_levels %}
{ label: "{{ acc.name }}", value: {{ acc.value }} }, {% endfor %}]);
$('#group_case_ac_select').multiselect('refresh');
$('#enable_auto_follow_cases').on('change', function() {
if (this.checked) {
$('#group_case_access_select').multiselect('disable');
} else {
$('#group_case_access_select').multiselect('enable');
}
});
if ($('#enable_auto_follow_cases').is(':checked')) {
$('#group_case_access_select').multiselect('disable');
}
</script>

View File

@@ -0,0 +1,62 @@
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">Manage members of group {{ group.group_name }}</h4>
<div class="row text-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
<div class="modal-body">
<div class="container col-md-12" >
<div class="row">
<div class="form-group" data-select2-id="7">
<label>Members *</label>
<div class="select2-input ml-12" data-select2-id="6">
<select id="group_members" name="group_members" class="form-control select2-hidden-accessible ml-12" multiple=""
data-select2-id="group_members" tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
</div>
</div>
</div>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="save_group_members">Save</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
<script>
var data = [];
if (current_users_list.length === 0) {
refresh_users();
}
for (user in current_users_list) {
data.push({
label: `${current_users_list[user].user_login} (${current_users_list[user].user_name} - ${current_users_list[user].user_email})`,
value: current_users_list[user].user_id
});
}
$('#group_members').multiselect({
buttonWidth: 400,
nonSelectedText: 'Select members',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#group_members').multiselect('dataprovider', data );
{% if group.group_members %}
$('#group_members').multiselect('select', [
{% for member in group.group_members %} {{ member.id }}, {% endfor %}
]);
$('#group_members').multiselect('refresh')
{% endif %}
</script>

View File

@@ -0,0 +1,343 @@
<div class="modal-xl modal-dialog" role="document">
<div class="modal-content" id="modal_access_control_content">
<div class="modal-header">
<div class="row w-100 d-flex justify-content-center">
<h4 class="modal-title ml-4 mt-3">{% if not user.user_id %}Add User{% else %} Edit user {% endif %}</h4>
<div class="col">
{% if user.user_id %}
<ul class="nav nav-pills nav-default justify-content-center" role="tablist">
<li class="nav-item">
<a class="nav-link active show" data-toggle="pill" href="#user_details_tab" role="tab" aria-controls="user_details_tab" aria-selected="false">Info</a>
</li>
<li class="nav-item submenu">
<a class="nav-link" data-toggle="pill" href="#user_permissions_tab" role="tab" aria-controls="user_permissions_tab" aria-selected="false">Permissions</a>
</li>
<li class="nav-item submenu">
<a class="nav-link" data-toggle="pill" href="#user_groups_tab" role="tab" aria-controls="user_groups_tab" aria-selected="false">Groups</a>
</li>
<li class="nav-item submenu">
<a class="nav-link" data-toggle="pill" href="#user_cac_tab" role="tab" aria-controls="user_cac_tab" aria-selected="false">Cases access</a>
</li>
</ul>
{% endif %}
</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
</div>
<div class="modal-body">
<div role="tabpanel">
<div class="tab-content">
<div class="tab-pane active" id="user_details_tab">
<div class="container col-md-12">
<form method="post" action="" id="form_new_user">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
{% if not user.user_id %}
<p class="ml-3"><i class="fa-solid fa-circle-info mr-2"></i>Permissions and groups memberships can be set once the user is created.</p>
{% endif %}
{% if user.user_is_service_account %}
<p class="ml-3 text-warning-high"><i class="fa-solid fa-circle-info mr-2"></i>This is a service account. It cannot login interactively nor have a password.</p>
{% endif %}
<div class="form-group">
<label for="user_name" class="mr-4">Full name
</label>
{{ form.user_name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="user_login" class="placeholder">Login</label>
{{ form.user_login(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="user_email" class="placeholder">Email</label>
{{ form.user_email(class='form-control', autocomplete="off") }}
</div>
{% if not user.user_is_service_account %}
<div class="form-group mt-3" id="formGroupUserPassword">
<label for="user_pwd" class="placeholder">Password (optional for service accounts)</label>
<ul>
<li><small>Must contain at least {{ server_settings.password_policy_min_length }} chars</small></li>
{% if server_settings.password_policy_upper_case %}
<li class="text-sm"><small>Must contain at least an upper case</small></li>
{% endif %}
{% if server_settings.password_policy_lower_case %}
<li class="text-sm"><small>Must contain at least a lower case</small></li>
{% endif %}
{% if server_settings.password_policy_digit %}
<li class="text-sm"><small>Must contain at least a digit</small></li>
{% endif %}
{% if server_settings.password_policy_special_chars %}
<li class="text-sm"><small>Must contain at least one of : {{ server_settings.password_policy_special_chars }}</small></li>
{% endif %}
</ul>
<div class="input-group mb-3">
{{ form.user_password(class='form-control', autocomplete="off") }}
<div class="input-group-append">
<span class="input-group-text">
<div class="user_show_password" id="toggle_user_password"><i class="fa-solid fa-eye"></i></div>
</span>
</div>
</div>
</div>
{% endif %}
{% if not user.user_id %}
<div class="form-group mt-3">
<div class="form-check">
<label class="form-check-label mt-3" >
{{ form.user_is_service_account(class="form-check-input", type="checkbox") }}
<span class="form-check-sign" id="formCheckIsServiceAccount"> Use as service account
<i class="ml-1 mt-1 fa-regular fa-circle-question" title="If checked, the user won't appear in the attribution suggestions and won't be able to connect on the UI" style="cursor:pointer;"></i>
</span>
</label>
</div>
</div>
{% endif %}
{% if user.user_id %}
<div class="form-group mt-3">
<label for="user_id" class="placeholder">User ID</label>
<input autocomplete="off" class="form-control" type="text" value="{{ user.user_id }}" disabled>
</div>
<div class="form-group mt-3">
<label for="user_uuid" class="placeholder">User UUID</label>
<input autocomplete="off" class="form-control" type="text" value="{{ user.user_uuid }}" disabled>
</div>
<div class="form-group mt-3">
<label for="user_uuid" class="placeholder">User API Key</label>
<input autocomplete="off" class="form-control" type="text" value="{{ user.user_api_key }}" disabled>
</div>
{% endif %}
</div>
{% if user.user_id %}
<button type="button" class="btn btn-danger mt-5"
onclick="delete_user('{{ user.user_id }}');">Delete</button>
{% if user.user_active %}
<button type="button" class="btn btn-outline-danger mt-5"
onclick="deactivate_user('{{ user.user_id }}');">Deactivate</button>
{% else %}
<button type="button" class="btn btn-outline-success mt-5"
onclick="activate_user('{{ user.user_id }}');">Activate</button>
{% endif %}
<button type="button" class="btn btn-outline-success ml-1 mt-5 float-right"
id="submit_new_user">Update</button>
<button type="button" class="btn btn-dark mt-5 float-right"
onclick="refresh_user_ac('{{ user.user_id }}');" id="users_refresh_ac_btn">Refresh access</button>
{% else %}
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_user">Save</button>
{% endif %}
</form>
</div>
</div>
<div class="tab-pane" id="user_permissions_tab">
<div class="container col-md-12">
<p class="mb-4"><i class="fa-solid fa-circle-info mr-2"></i>Permissions are inherited from the groups the user belongs to. The table shows the effective permissions the user has on the platform.</p>
<table class="table table-striped" id="user_permissions_table">
<thead>
<tr>
<th>Permission</th>
<th>Value</th>
<th>Inherited from groups</th>
</tr>
</thead>
<tbody>
{% for perm in user.user_permissions %}
<tr>
<td>{{ user.user_permissions[perm].name }}</td>
<td>0x{{ perm | int(perm,16) }}</td>
<td>{% for group in user.user_permissions[perm].inherited_from %}<span class="badge ml-2 badge-light">{{ group }}</span>{% endfor %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="tab-pane" id="user_groups_tab">
<div class="row">
<div class="container col-md-12">
<span class="ml-2 mt-3">Groups the user is member of.</span>
<button class="btn btn-dark btn-sm pull-right mr-2" onclick="manage_user_groups({{ user.user_id }});">
<span class="menu-title">Manage</span>
</button>
</div>
</div>
<div class="row mt-4">
<div class="container col-md-12">
<table class="table table-striped" id="user_groups_table">
<thead>
<tr>
<th>Group name</th>
<th>Group ID</th>
<th>Group UUID</th>
</tr>
</thead>
<tbody>
{% for group in user.user_groups %}
<tr>
<td>{{ group.group_name }}</td>
<td>{{ group.group_id }}</td>
<td>{{ group.group_uuid }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="tab-pane" id="user_cac_tab">
<div class="container col-md-12" >
<div class="row d-flex mb-4">
<div class="col-8">
<span>Cases accesses are usually inherited from groups memberships. These are not displayed here. This tab allows to add granular case access if necessary.</span>
</div>
<div class="col-4 pull-right">
<button class="btn btn-dark btn-sm pull-right" onclick="refresh_user_cac({{ user.user_id }});">
<span class="menu-title">Refresh</span>
</button>
<button class="btn btn-dark btn-sm pull-right mr-2" onclick="manage_user_cac({{ user.user_id }});">
<span class="menu-title" id="manage_user_cac_button">Set case access</span>
</button>
</div>
</div>
<div class="row mt-4">
<table class="table display table-striped table-hover responsive" width="100%" cellspacing="0" id="user_cac_table" >
<thead>
<tr>
<th>Case ID</th>
<th>Case Name</th>
<th>Access</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Case ID</th>
<th>Case Name</th>
<th>Access</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$('#toggle_user_password').on('click', function (e) {
const type = $('#user_password').attr('type') === 'password' ? 'text' : 'password';
$('#user_password').attr('type', type);
$('#toggle_user_password > i').attr('class', type === 'password' ? 'fa-solid fa-eye' : 'fa-solid fa-eye-slash');
});
$('#user_permissions_table').dataTable({
"order": [[ 1, "asc" ]]});
$('#user_groups_table').dataTable({
"order": [[ 1, "asc" ]],
"columns": [{
"title": "Group name",
"render": function ( data, type, row, meta ) {
if (type === 'display' ) {
return `<i class="fa-solid fa-trash-can mr-2 text-danger" style="cursor:pointer;" title="Remove from group" href="javascript:void(0)" onclick="remove_member_from_group_wrap('${row[1]}','{{ user.user_id }}')"></i>${sanitizeHTML(data)}`;
}
return data;
}},
{"title": "Group ID"},
{"title": "Group UUID"}
]
});
var modal_user_cac_table = $("#user_cac_table").DataTable({
dom: 'Blfrtip',
aaData: [],
aoColumns: [
{
"data": "case_id",
"render": function ( data, type, row ) {
return `<i class="fa-solid fa-trash-can mr-2 text-danger" style="cursor:pointer;" title="Remove access to case" href="javascript:void(0)" onclick="remove_case_access_from_user('{{ user.user_id }}',${data})"></i>${data}`;
},
"className": "dt-center"
},
{
"data": "case_name",
"className": "dt-center",
"render": function (data, type, row) {
return `<a target="_blank" rel="noopener" href="/case?cid=${row.case_id}">${sanitizeHTML(data)}</a>`;
}
},
{
"data": "access_level_list",
"render": function ( data, type, row ) {
ret_data = "";
for (acc in data) {
ret_data += `<span class="badge ml-2 badge-light">${data[acc].name}</span>`
}
return ret_data;
},
"className": "dt-center"
}
],
filter: true,
info: true,
ordering: true,
processing: true,
select: true
});
var actionOptionsUser = {
classes: [],
contextMenu: {
enabled: true,
isMulti: true,
xoffset: -10,
yoffset: -10,
headerRenderer: function (rows) {
if (rows.length > 1) {
return rows.length + ' items selected';
} else {
let row = rows[0];
return 'Quick action';
}
},
},
buttonList: {
enabled: false,
},
deselectAfterAction: true,
items: [],
};
actionOptionsUser.items.push({
type: 'option',
title: 'Remove access',
multi: true,
iconClass: 'fas fa-trash',
buttonClasses: ['btn', 'btn-outline-primary'],
action: function(rows){
remove_cases_access_from_user_table('{{ user.user_id }}', rows);
}
});
modal_user_cac_table.contextualActions(actionOptionsUser);
{% if user.user_id %}
current_user_cases_access_list = {{ user.user_cases_access|tojson }};
modal_user_cac_table.rows.add(current_user_cases_access_list);
modal_user_cac_table.columns.adjust().draw();
{% endif %}
</script>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->

View File

@@ -0,0 +1,66 @@
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">Set case access</h4>
<div class="row text-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
<div class="modal-body">
<div class="container col-md-12" >
<div class="row">
<div class="form-group" data-select2-id="7">
<label>Set cases access of user <i>{{ user.user_name }}</i> *</label>
<div class="col-12">
<select id="user_case_access_select" name="org_case_access_select" class="form-control ml-12" multiple="multiple"
tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
<select id="user_case_ac_select" name="org_case_ac_select" class="form-control ml-12"
tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
</div>
</div>
</div>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="grant_case_access_to_user">Set access</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
<script>
var data = [];
$('#user_case_access_select').multiselect({
buttonWidth: 400,
nonSelectedText: 'Select case',
emptyText: 'No case available to add',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#user_case_access_select').multiselect('dataprovider', [{% for ocs in outer_cases %}
{ label: "{{ ocs.case_name }}", value: {{ ocs.case_id }} }, {% endfor %}]);
$('#user_case_access_select').multiselect('refresh')
$('#user_case_ac_select').multiselect({
nonSelectedText: 'Select access level',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#user_case_ac_select').multiselect('dataprovider', [{% for acc in access_levels %}
{ label: "{{ acc.name }}", value: {{ acc.value }} }, {% endfor %}]);
$('#user_case_ac_select').multiselect('refresh');
</script>

View File

@@ -0,0 +1,68 @@
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">Set case access via groups</h4>
<div class="row text-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
<div class="modal-body">
<div class="container col-md-12" >
<div class="row">
<div class="form-group" data-select2-id="7">
<label>Set groups case access</label>
<div class="row">
<div class="col-12">
<select id="group_case_access_select" name="group_case_access_select" class="form-control select2-hidden-accessible ml-12" multiple="multiple"
tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
<select id="group_case_ac_select" name="group_case_ac_select" class="form-control select2-hidden-accessible ml-12"
tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
onclick="set_case_access_via_group('{{ caseid }}')">Set access</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
<script>
var data = [];
$('#group_case_access_select').multiselect({
buttonWidth: 400,
nonSelectedText: 'Select group(s)',
emptyText: 'No groups available to set',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#group_case_access_select').multiselect('dataprovider', [{% for ocs in groups %}
{ label: "{{ ocs.group_name }}", value: {{ ocs.group_id }} }, {% endfor %}]);
$('#group_case_access_select').multiselect('refresh')
$('#group_case_ac_select').multiselect({
nonSelectedText: 'Select access level',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#group_case_ac_select').multiselect('dataprovider', [{% for acc in access_levels %}
{ label: "{{ acc.name }}", value: {{ acc.value }} }, {% endfor %}]);
$('#group_case_ac_select').multiselect('refresh');
</script>

View File

@@ -0,0 +1,65 @@
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-heading">
<div class="card-title">Case access</div>
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-12">
<p>Click on a user to unveil access control path</p>
<table class="table table-striped table-bordered" id="case_audit_access_table">
<thead>
<tr>
<th>User ID</th>
<th>User Name</th>
<th>User UUID</th>
<th>Access</th>
</tr>
</thead>
<tbody>
{% for user_id in access_audit %}
<tr>
<td>
{% if access_audit[user_id].user_effective_access_list|length == 0 %}
<i class="mr-2 fa-solid text-danger fa-circle-xmark" title="No access"></i>
{% elif access_audit[user_id].user_effective_access_list|length == 1 %}
<i class="mr-2 fa-solid text-warning fa-circle-minus" title="Partial access"></i>
{% else %}
<i class="mr-2 fa-solid fa-circle-check text-success" title="All access"></i>
{% endif %}
{{ user_id }}
</td>
<td>{{ access_audit[user_id].user_info.user_name }}</td>
<td>{{ access_audit[user_id].user_info.user_uuid }}</td>
<td>{% if access_audit[user_id].user_effective_access_list|length == 0 %}
<span class="badge badge-pill badge-light" title="Click to show trace" href="#collapse_cac_{{user_id}}" style="cursor:pointer;" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_cac_{{user_id}}">No access</span>
{% else %}
{% for uac in access_audit[user_id].user_effective_access_list %}
<span class="badge badge-pill badge-light" title="Click to show trace" href="#collapse_cac_{{user_id}}" style="cursor:pointer;" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_cac_{{user_id}}">{{ uac }}</span>
{% endfor %}
<i class="fa-solid fa-eye ml-2" title="Click to show trace" href="#collapse_cac_{{user_id}}" style="cursor:pointer;" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_cac_{{user_id}}"></i>
{% endif %}
<ol class="activity-feed collapse" id="collapse_cac_{{user_id}}">
{% if access_audit[user_id].user_effective_access_list|length == 0 %}
The user is neither in a group nor an organisation who has access to this case
{% endif %}
{% for uac in access_audit[user_id].access_trace %}
<li class="feed-item {% if uac.state == 'Effective' %} feed-item-success {% else %} feed-item-danger {% endif %}" title="{{ uac.state }}">
<span class="text"><span class="badge badge-pill badge-light">{{ uac.name }}</span> ({{ uac.state }})</span><br />
<span class="text">Inherited from {{ uac.inherited_from.object_type }} <i class="fa-solid fa-right-long"></i> {{ uac.inherited_from.object_name }} (ID {{ uac.inherited_from.object_id }} :: UUID {{ uac.inherited_from.object_uuid }})</span>
</li>
{% endfor %}
</ol>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,62 @@
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">Manage user groups</h4>
<div class="row text-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
<div class="modal-body">
<div class="container col-md-12" >
<div class="row">
<div class="form-group" data-select2-id="7">
<label>Groups membership *</label>
<div class="select2-input ml-12" data-select2-id="6">
<select id="user_groups_membership" name="user_groups_membership" class="form-control select2-hidden-accessible ml-12" multiple=""
tabindex="-1" aria-hidden="true" style="width: 100%">
</select>
</div>
</div>
</div>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="save_user_groups_membership">Save</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
<script>
var data = [];
if (current_groups_list.length === 0) {
refresh_groups();
}
for (group in current_groups_list) {
data.push({
label: `${current_groups_list[group].group_name}`,
value: current_groups_list[group].group_id
});
}
$('#user_groups_membership').multiselect({
buttonWidth: 400,
nonSelectedText: 'Select groups',
includeSelectAllOption: true,
enableFiltering: true,
enableCaseInsensitiveFiltering: true,
filterPlaceholder: 'Search',
filterBehavior: 'both',
widthSynchronizationMode: 'ifPopupIsSmaller'
});
$('#user_groups_membership').multiselect('dataprovider', data );
{% if user.user_groups %}
$('#user_groups_membership').multiselect('select', [
{% for group in user.user_groups %} {{ group.group_id }}, {% endfor %}
]);
$('#user_groups_membership').multiselect('refresh')
{% endif %}
</script>

View File

@@ -0,0 +1,94 @@
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-heading">
<div class="card-title">User permissions</div>
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-12">
<p class="mb-4">Permissions are inherited from the groups the user belongs to. The table shows the effective permissions the user has on the platform.</p>
<table class="table table-striped table-bordered" id="user_audit_permissions_table">
<thead>
<tr>
<th>Permission</th>
<th>Value</th>
<th>Inherited from groups</th>
</tr>
</thead>
<tbody>
{% for perm in permissions_audit['details'] %}
<tr>
<td>{{ permissions_audit['details'][perm].name }}</td>
<td>0x{{ perm | int(perm,16) }}</td>
<td>{% for group_id in permissions_audit['details'][perm].inherited_from %}<span class="badge ml-2 badge-light">{{ permissions_audit['details'][perm].inherited_from[group_id].group_name }}</span>{% endfor %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-heading">
<div class="card-title">User cases access</div>
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-12">
<p>Click on a case to unveil access control path</p>
<table class="table table-striped table-bordered" id="user_audit_access_table">
<thead>
<tr>
<th>Case name</th>
<th>Access</th>
</tr>
</thead>
<tbody>
{% for case_id in access_audit %}
<tr>
<td>
{% if access_audit[case_id].user_effective_access|length == 0 or 'deny_all' in access_audit[case_id].user_effective_access[0].name %}
<i class="mr-2 fa-solid text-danger fa-eye-slash" title="No access"></i>
{% elif 'read_only' in access_audit[case_id].user_effective_access[0].name %}
<i class="mr-2 fa-solid text-warning fa-lock" title="Read only access"></i>
{% else %}
<i class="mr-2 fa-solid fa-circle-check text-success" title="Full access"></i>
{% endif %}
{{ access_audit[case_id].case_info.case_name }}
</td>
<td>{% if access_audit[case_id].user_effective_access|length == 0 %}
<span class="badge badge-pill badge-light" title="Click to show trace" href="#collapse_cac_{{case_id}}" style="cursor:pointer;" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_cac_{{case_id}}">No access</span>
{% else %}
{% for uac in access_audit[case_id].user_effective_access %}
<span class="badge badge-pill badge-light" title="Click to show trace" href="#collapse_cac_{{case_id}}" style="cursor:pointer;" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_cac_{{case_id}}">{{ uac.name }}</span>
{% endfor %}
<i class="fa-solid fa-eye ml-2" title="Click to show trace" href="#collapse_cac_{{case_id}}" style="cursor:pointer;" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_cac_{{case_id}}"></i>
{% endif %}
<ol class="activity-feed collapse" id="collapse_cac_{{case_id}}">
{% if access_audit[case_id].user_effective_access|length == 0 %}
The user is neither in a group nor an organisation who has access to this case
{% endif %}
{% for uac in access_audit[case_id].user_access %}
<li class="feed-item {% if uac.state == 'Effective' %} feed-item-success {% else %} feed-item-danger {% endif %}" title="{{ uac.state }}">
<span class="text">{% for ac in uac.access_list %}<span class="badge badge-pill badge-light">{{ ac.name }}</span>{% endfor %} ({{ uac.state }})</span><br />
<span class="text">Inherited from {{ uac.inherited_from.object_type }} <i class="fa-solid fa-right-long"></i> {{ uac.inherited_from.object_name }} (ID {{ uac.inherited_from.object_id }} :: UUID {{ uac.inherited_from.object_uuid }})</span>
</li>
{% endfor %}
</ol>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,82 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Attributes {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<div class="card-title">Objects Attributes</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_attribute_table();">
Refresh
</button>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive" id="hooks_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="attributes_table">
<thead>
<tr>
<th>#ID</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tfoot>
<tr>
<th>#ID</th>
<th>Name</th>
<th>Description</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal" tabindex="-1" id="modal_add_attribute" data-backdrop="true">
<div class="modal-xxl modal-dialog" role="document">
<div class="modal-content" id="modal_add_attribute_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<div class="modal bg-primary-gradient" tabindex="-1" id="modal_preview_attribute" data-backdrop="true">
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content" id="modal_preview_attribute_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
{% endif %}
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/plugin/ace/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/assets/js/plugin/ace/src-noconflict/ext-language_tools.js" type="text/javascript"
charset="utf-8"></script>
<script src="/static/assets/js/iris/manage.attributes.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,93 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Case Templates {% endblock title %}
{% block stylesheets %}
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<div class="card-title">Case Templates</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_case_template_table();">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_case_template();">
Add case template
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="fire_upload_case_template();">
Upload case template
</button>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive" id="hooks_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table aria-describedby="Case template list"
class="table display table table-striped table-hover"
style="width: 100%; border-spacing: 0;" id="case_templates_table">
<thead>
<tr>
<th scope="col">#ID</th>
<th scope="col">Name</th>
<th scope="col">Description</th>
<th scope="col">Added by</th>
<th scope="col">Created at</th>
<th scope="col">Updated at</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="col">#ID</th>
<th scope="col">Name</th>
<th scope="col">Description</th>
<th scope="col">Added by</th>
<th scope="col">Created at</th>
<th scope="col">Updated at</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal" tabindex="-1" id="modal_case_template" data-backdrop="true">
<div class="modal-xxl modal-dialog" role="document">
<div class="modal-content" id="modal_case_template_json">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<div class="modal" tabindex="-1" role="dialog" id="modal_upload_case_template" data-backdrop="true">
<div class="modal-xl modal-dialog" role="document">
<div class="modal-content" id="modal_upload_case_template_json">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
{% endif %}
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/plugin/ace/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/assets/js/plugin/ace/src-noconflict/ext-language_tools.js" type="text/javascript"
charset="utf-8"></script>
<script src="/static/assets/js/iris/manage.case.templates.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,184 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Cases {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/dataTables.select.min.css">
<link rel="stylesheet" href="/static/assets/css/bootstrap-select.min.css">
<link rel="stylesheet" href="/static/assets/css/bootstrap-multiselect.min.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="card-title">Cases management</div>
</div>
<div class="card-body">
<div class="col-md-12">
<div class="row">
<div class="col d-flex justify-content-center">
<ul class="nav nav-pills nav-dark" id="pills-tabs-manage-case"
role="tablist">
<li class="nav-item submenu">
<a class="nav-link active show" id="add-tab" data-toggle="pill" href="#add" role="tab"
aria-controls="pills-home-nobd" aria-selected="true">New</a>
</li>
<li class="nav-item submenu">
<a class="nav-link" id="view-tab" data-toggle="pill" href="#view" role="tab"
aria-controls="view-tab" aria-selected="false">Cases list</a>
</li>
</ul>
</div>
</div>
<div id="myTab1Content" class="tab-content col-md-12">
<div id="add" role="tabpanel" aria-labelledby="add-tab"
class="tab-pane fade px-4 py-5 show active">
<div class="row">
<div class="col-md-12 col-lg-6 col-sm-12">
<h4 class="border-bottom pb-3">General info</h4>
Fields with an asterix are required.
<form method="post" action='' id="form_new_case" autocomplete="off">
{{ form.hidden_tag() }}
<div class="mt-4 col-md-12 col-lg-12 col-sm-12">
<div class="input-group mb-4">
{{ form.case_customer(class="selectpicker form-control") }}
</div>
<div class="input-group mb-4">
{{ form.case_template_id(class="selectpicker form-control", data_actions_box="true") }}
</div>
<div class="input-group mb-4">
{{ form.classification_id(class="selectpicker form-control") }}
</div>
<div class="input-group mb-4">
<div class="input-group-prepend">
<span class="input-group-text">Case name *</span>
</div>
{{ form.case_name(class="form-control", type="text") }}
</div>
<div class="input-group mb-4">
<div class="input-group-prepend">
<span class="input-group-text">Short description *</span>
</div>
{{ form.case_description(class="form-control", type="text") }}
</div>
<div class="input-group mb-4">
<div class="input-group-prepend">
<span class="input-group-text">SOC ticket ID</span>
</div>
{{ form.case_soc_id(class="form-control", type="text") }}
</div>
</div>
</form>
</div>
<div class="col-md-12 col-lg-6 col-sm-12">
{% if attributes and attributes|length > 0 %}
<h4><ul class="nav nav-tabs nav-lines mr-4" role="tablist">
{% for ca in attributes %}
<li class="nav-item submenu">
<a class="nav-link {% if loop.index == 1 %}{{"active show"}}{% endif %}" data-toggle="tab" href="#itab_{{ loop.index }}_{{ ca.lower() | replace(' ', '_' ) }}"
role="tab" aria-selected="false">{{ca}}</a>
</li>
{% endfor %}
</ul></h4>
<div role="tabpanel">
<div class="tab-content">
{% set is_case_page = True %}
{% include 'modals/modal_attributes_tabs.html' %}
</div>
</div>
{% endif %}
</div>
</div>
<button class="btn btn-outline-success ml-4 mt-5 float-right" id="submit_new_case_btn" onclick="submit_new_case();">Create</button>
</div>
<div id="view" role="tabpanel" aria-labelledby="view-tab" class="tab-pane fade px-4 py-5">
<button type="button" class="btn btn-sm btn-outline-dark float-right mr-3"
onclick="refresh_case_table();">
Refresh
</button>
<div class="table-responsive" id="cases_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display wrap col-border table-striped table-hover" width="100%"
cellspacing="0" id="cases_table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Customer</th>
<th>State</th>
<th>Open date</th>
<th>Close date</th>
<th>SOC Ticket</th>
<th>Opening user</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Description</th>
<th>Customer</th>
<th>State</th>
<th>Open date</th>
<th>Close date</th>
<th>SOC Ticket</th>
<th>Opening user</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<!-- End bordered tabs -->
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal " tabindex="-1" role="dialog" id="modal_case_detail" data-backdrop="true">
<div class="modal-xl modal-dialog" role="document">
<div class="modal-content" id="info_case_modal_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<div class="modal bg-shadow-gradient" tabindex="-1" role="dialog" id="modal_ac_additional" data-backdrop="true">
</div>
{% endif %}
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/core/jquery.validate.js"></script>
<script src="/static/assets/js/plugin/datatables/dataTables.cellEdit.js"></script>
<script src="/static/assets/js/plugin/datatables/dataTables.buttons.min.js"></script>
<script src="/static/assets/js/plugin/datatables/dataTables.select.min.js"></script>
<script src="/static/assets/js/plugin/datatables/dataTables.responsive.min.js"></script>
<script src="/static/assets/js/plugin/datatables/buttons.html5.min.js"></script>
<script src="/static/assets/js/plugin/datatables/buttons.print.min.js"></script>
<script src="/static/assets/js/plugin/datatables/buttons.print.min.js"></script>
<script src="/static/assets/js/plugin/select/bootstrap-select.min.js"></script>
<script src="/static/assets/js/plugin/select/bootstrap-multiselect.min.js"></script>
<script src="/static/assets/js/iris/datatablesUtils.js"></script>
<script src="/static/assets/js/iris/manage.cases.common.js"></script>
<script src="/static/assets/js/iris/manage.cases.js"></script>
<script>
$('form#form_new_case').validate();
</script>
{% endblock javascripts %}

View File

@@ -0,0 +1,191 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Customers {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
{{ form.hidden_tag() }}
<div class="page-inner">
<a class="mb-2 ml-1 text-dark" href="/manage/customers?cid={{ session['current_case'].case_id }}"><i class="fa-solid fa-arrow-left"></i> Back</a>
<div class="mt-2 mb-4">
<div class="row ml-2 mr-2">
<h2 class="pb-2">Customer > {{ customer.customer_name }}</h2>
<button class="btn btn-light btn-sm ml-auto" onclick="customer_detail('{{ customer.customer_id }}');">Edit customer</button>
</div>
</div>
<input id="customer_id" style="display:none;" value="{{ customer.customer_id }}"/>
<div class="row">
<div class="col-md-2">
<div class="card card-dark bg-success-gradient">
<div class="card-body pb-0">
<div class="h1 fw-bold float-right"></div>
<h2 id="current_open_cases" class="mb-2">0</h2>
<p>Current open cases</p>
<div class="pull-in sparkline-fix chart-as-background">
<div id="chart_current_open_cases"></div>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="card card-dark bg-info-gradient">
<div class="card-body pb-0">
<div class="h5 fw-bold float-right"><span id="ratio_month"></span></div>
<h2 id="cases_current_month" class="mb-2"></h2>
<p>Current month</p>
<div class="pull-in sparkline-fix chart-as-background">
<div id="chart_month_cases"></div>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="card card-dark bg-info-gradient">
<div class="card-body pb-0">
<div class="h1 fw-bold float-right"></div>
<h2 id="cases_last_month" class="mb-2">0</h2>
<p>Last month</p>
<div class="pull-in sparkline-fix chart-as-background">
<div id=""></div>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="card card-dark bg-info-gradient">
<div class="card-body pb-0">
<div class="h5 fw-bold float-right"><span id="ratio_year"></span></div>
<h2 id="cases_current_year" class="mb-2">0</h2>
<p>Current year </p>
<div class="pull-in sparkline-fix chart-as-background">
<div id="chart_year_cases"></div>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="card card-dark bg-info-gradient">
<div class="card-body pb-0">
<div class="h3 fw-bold float-right"></div>
<h2 id="cases_last_year" class="mb-2">0</h2>
<p>Last year (<span id="last_year"></span>)</p>
<div class="pull-in sparkline-fix chart-as-background">
<div></div>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="card card-dark bg-close-gradient">
<div class="card-body pb-0">
<div class="h1 fw-bold float-right"></div>
<h2 id="cases_total" class="mb-2">0</h2>
<p>Total</p>
<div class="pull-in sparkline-fix chart-as-background">
<div></div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card card-customer">
<div class="card-body">
<div class="row">
<div class="col-md-3 info-customer">
<h5 class="sub"><b>Customer name</b></h5>
<p>{{ customer.customer_name }}</p>
</div>
<div class="col-md-3 info-customer">
<h5 class="sub"><b>Customer Description</b></h5>
<p>{{ customer.customer_description }}</p>
</div>
<div class="col-md-3 info-customer">
<h5 class="sub text-bold"><b>Customer SLAs</b></h5>
<p>{{ customer.customer_sla }}</p>
</div>
<div class="col-md-3 info-customer">
<h5 class="sub text-bold"><b>Average case duration</b></h5>
<p><span id="average_case_duration"></span> days</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card card-customer">
<div class="card-header">
<div class="row">
<div class="col-12">
<div class="row">
<h3><strong><i class="ml-1 fa-regular fa-address-book mr-1"></i> Contacts</strong></h3>
<button class="btn btn-light btn-sm ml-auto" onclick="add_new_contact({{ customer.customer_id }});">Add Contact</button>
</div>
</div>
</div>
</div>
<div class="card-body">
<div class="customer-list">
{% for contact in contacts %}
<div class="contact-list-item">
<div class="contact-list-detail">
<span class="date float-right"><button class="btn btn-light btn-sm" onclick="edit_contact('{{ contact.id }}','{{ customer.customer_id }}');">Edit</button></span>
<span class="h4">{{ contact.contact_name }}</span>
<p class="ml-2">
{% if contact.contact_role %}
<b>Role: </b>{{ contact.contact_role }}<br/>
{% endif %}
{% if contact.contact_email %}
<b>Email: </b>{{ contact.contact_email }}<br/>
{% endif %}
{% if contact.contact_work_phone %}
<b>Work phone: </b>{{ contact.contact_work_phone }}<br/>
{% endif %}
{% if contact.contact_mobile_phone %}
<b>Mobile phone: </b>{{ contact.contact_mobile_phone }}<br/>
{% endif %}
{% if contact.contact_note %}
<b>Notes: </b>{{ contact.contact_note }}<br/>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<div class="modal" tabindex="-1" role="dialog" id="modal_add_customer" data-backdrop="true">
<div class="modal-xl modal-dialog" role="document">
<div class="modal-content" id="modal_add_customer_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<div class="modal" tabindex="-1" role="dialog" id="modal_add_contact" data-backdrop="true">
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content" id="modal_add_contact_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/iris/manage.customers.js"></script>
<script src="/static/assets/js/iris/view.customers.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,74 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Customers {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<div class="card-title">Customers management</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_customer_table(true);">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_customer();">Add customer</button>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive" id="customers_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="customers_table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="modal" tabindex="-1" role="dialog" id="modal_add_customer" data-backdrop="true">
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content" id="modal_add_customer_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
</div>
{% endif %}
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/iris/manage.customers.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,120 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>IRIS - Server updates</title>
<meta content='width=device-width, initial-scale=1.0, shrink-to-fit=no' name='viewport' />
<link rel="icon" href="/static/assets/img/logo.ico" type="image/x-icon"/>
<!-- Fonts and icons -->
<script src="/static/assets/js/plugin/webfont/webfont.min.js"></script>
<script>
WebFont.load({
custom: {"families":["Lato:300,400,700,900", "Flaticon", "Font Awesome 5 Solid", "Font Awesome 5 Regular", "Font Awesome 5 Brands", "simple-line-icons"],
urls: ['/static/assets/css/fonts.css']},
active: function() {
sessionStorage.fonts = true;
}
});
</script>
<!-- CSS Files -->
<link rel="stylesheet" href="/static/assets/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/assets/css/atlantis.css">
<link rel="stylesheet" href="/static/assets/css/bootstrap-select.min.css">
</head>
<body class="bg-dark-gradient p-4" style="height: 100vh;">
<div class="container bg-white shadow-lg p-3 rounded mb-4">
<div class="mt-2 row">
<div class="col d-flex justify-content-center">
<a href="/" class="logo ml-2 text-center">
<img src="/static/assets/img/logo-alone-2-black.png" alt="navbar brand" class='image-update navbar-brand' width="50">
</a>
</div>
</div>
<div class="mt-2 row">
<div class="col d-flex justify-content-center">
<h1 class="text-dark text-center">Server Updates</h1>
</div>
</div>
<div class="row ">
<div class="col d-flex justify-content-center">
<i class="text-dark">Some great improvements are hopefully on their way, hang tight</i>
</div>
</div>
<div class="row mt-4">
<div class="col d-flex justify-content-center">
<h4 class="text-danger text-center">Please do not leave or refresh the page once updates have started</h4>
</div>
</div>
<div class="row mt-4 update_start_txt">
<div class="col pl-4 justify-content-center">
<p class="text-center">Ensure users are disconnected. Any unsaved work might be lost.</p>
</div>
</div>
<div class="row mt-4 justify-content-center update_start_txt">
<div class="col-6">
<p class="text-center">The following steps might occur during updates, depending on the updates scope : </p>
<ul>
<li>Fetch of updates information from github.com</li>
<li>Download of updates assets from github</li>
<li>Signatures verification</li>
<li>Compatibility verifications</li>
<li>Back up of the current server code to backup storage defined in <code>BACKUP_PATH</code></li>
<li>Server stop and update of application</li>
<li>Server restarts</li>
<li>Version check</li>
</ul>
</div>
</div>
<div class="row mt-4">
<div class="col d-flex justify-content-center ">
<a href='#' onclick="start_updates();" class="btn btn-outline-success text-center" id="update_start_btn">Start updates</a>
</div>
</div>
<div id="container-updates" class="row shadow-lg ml-4 mr-4 rounded" style="display:none;">
<div class="col justify-content-left text-dark pl-4 pb-4 pt-4 pr-4 mh-100">
<div class="col">
<div id="updates_log">
</div>
<div id="updates_log_end"></div>
</div>
</div>
</div>
<div class="row text-dark">
<div class="col d-flex justify-content-center">
<div id="offline_time" style="display:none;"></div>
</div>
</div>
<div class="row mt-4">
<div class="col d-flex justify-content-center">
<div id="tag_bottom" style="display:none;" class="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
<a href='/manage/settings' class="btn btn-dark ml-mr-auto" style="display:none;" id="update_return_button">Go back to server</a>
</div>
</div>
</div>
<!-- Core JS Files -->
<script src="/static/assets/js/core/jquery.3.2.1.min.js"></script>
<script src="/static/assets/js/core/popper.min.js"></script>
<script src="/static/assets/js/core/bootstrap.min.js"></script>
<!-- jQuery UI -->
<script src="/static/assets/js/plugin/jquery-ui-1.12.1.custom/jquery-ui.min.js"></script>
<script src="/static/assets/js/plugin/jquery-ui-touch-punch/jquery.ui.touch-punch.min.js"></script>
<!-- jQuery Scrollbar -->
<script src="/static/assets/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js"></script>
<!-- Atlantis JS -->
<script src="/static/assets/js/atlantis.min.js"></script>
{% if current_user.in_dark_mode %}<script src="/static/assets/js/dark-mode.js"></script>{% endif %}
<script src="/static/assets/js/core/socket.io.js"></script>
<script src="/static/assets/js/iris/updates.handler.js"></script>
</body>
</html>

View File

@@ -0,0 +1,143 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Modules {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
<link rel="stylesheet" href="/static/assets/css/dataTables.group.min.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<div class="card-title">Modules management</div>
{{ form.hidden_tag() }}
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_modules();">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_module();">Add module</button>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive" id="module_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="modules_table">
<thead>
<tr>
<th>#ID</th>
<th>Module name</th>
<th>Has pipeline</th>
<th>Module version</th>
<th>Interface version</th>
<th>Date added</th>
<th>Added by</th>
<th>Active</th>
</tr>
</thead>
<tfoot>
<tr>
<th>#ID</th>
<th>Module name</th>
<th>Has pipeline</th>
<th>Module version</th>
<th>Interface version</th>
<th>Date added</th>
<th>Added by</th>
<th>Active</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<div class="card-title">Registered hooks</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-icon btn-round btn-outline-black float-right" onclick="refresh_modules_hooks();">
<i class="fas fa-sync rotate"></i>
</button>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive" id="hooks_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="hooks_table">
<thead>
<tr>
<th>#ID</th>
<th>Registrant module</th>
<th>Hook name</th>
<th>Hook description</th>
<th>Automatic trigger</th>
<th>Active</th>
</tr>
</thead>
<tfoot>
<tr>
<th>#ID</th>
<th>Registrant module</th>
<th>Hook name</th>
<th>Hook description</th>
<th>Automatic trigger</th>
<th>Active</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="modal" tabindex="-1" role="dialog" id="modal_add_module" data-backdrop="true">
<div class="modal-xl modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-content" id="modal_add_module_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<div class="modal bg-shadow-gradient" tabindex="-1" role="dialog" id="modal_update_param" data-backdrop="true">
<div class="modal-xl modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
<div class="modal-content shadow-lg p-3 mb-5 rounded" id="modal_update_param_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
</div>
{% endif %}
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/plugin/ace/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/assets/js/plugin/ace/src-noconflict/ext-language_tools.js" type="text/javascript"
charset="utf-8"></script>
<script src="/static/assets/js/plugin/datatables/dataTables.group.min.js"></script>
<script src="/static/assets/js/iris/manage.modules.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,209 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Objects {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-heading collapsed" href="#collapse_assets" title="Click to unfold" data-toggle="collapse" aria-expanded="false" role="button" aria-controls="collapse_assets">
<span class="accicon float-left mr-3"><i class="fas fa-angle-right rotate-icon"></i></span>
<div class="card-title">Assets types</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_asset_table();">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_asset_type();">Add new</button>
</div>
</div>
</div>
<div class="card-body collapse" id="collapse_assets">
<div class="table-responsive" id="assets_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="assets_table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Icon - not compromised</th>
<th>Icon - compromised</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Description</th>
<th>Icon - not compromised</th>
<th>Icon - compromised</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header" >
<div class="row">
<div class="col col-heading collapsed" href="#collapse_ioc" title="Click to unfold" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_ioc">
<span class="accicon float-left mr-3"><i class="fas fa-angle-right rotate-icon"></i></span>
<div class="card-title">IOC types</div>
</div>
<div class="col float-right">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_ioc_table();">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_ioc_type();">Add new</button>
</div>
</div>
</div>
<div class="card-body collapse" id="collapse_ioc">
<div class="table-responsive" id="ioc_table_wrapper">
<div class="selectgroup">
<span id="ioc_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="ioc_table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Taxonomy</th>
<th>Validation regex</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Description</th>
<th>Taxonomy</th>
<th>Validation regex</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header" >
<div class="row">
<div class="col col-heading collapsed" href="#collapse_classifications" title="Click to unfold" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_classifications">
<span class="accicon float-left mr-3"><i class="fas fa-angle-right rotate-icon"></i></span>
<div class="card-title">Case classifications</div>
</div>
<div class="col float-right">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_classification_table();">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_classification();">Add new</button>
</div>
</div>
</div>
<div class="card-body collapse" id="collapse_classifications">
<div class="table-responsive" id="classification_table_wrapper">
<div class="selectgroup">
<span id="classification_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="classification_table">
<thead>
<tr>
<th>Name</th>
<th>Expanded name</th>
<th>Description</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Expanded name</th>
<th>Description</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header" >
<div class="row">
<div class="col col-heading collapsed" href="#collapse_state" title="Click to unfold" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapse_state">
<span class="accicon float-left mr-3"><i class="fas fa-angle-right rotate-icon"></i></span>
<div class="card-title">Case state</div>
</div>
<div class="col float-right">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_state_table();">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_state();">Add new</button>
</div>
</div>
</div>
<div class="card-body collapse" id="collapse_state">
<div class="table-responsive" id="state_table_wrapper">
<div class="selectgroup">
<span id="state_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="state_table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal" tabindex="-1" id="modal_add_type" data-backdrop="true">
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content" id="modal_add_type_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
{% endif %}
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/iris/manage.objects.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,218 @@
{% extends "layouts/default.html" %}
{% block title %} Server Settings {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
{% endblock stylesheets %}
{% block content %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row ">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="card-title">Server versions</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-12">
<div class="col-12 mb-4">
<dl class="row">
<dt class="col-sm-3">IRIS server version:</dt>
<dd class="col-sm-8">{{ versions.iris_current }}</dd>
<dt class="col-sm-3">Database revision:</dt>
<dd class="col-sm-8">{{ versions.db_revision }}</dd>
<dt class="col-sm-3">Min. API version supported:</dt>
<dd class="col-sm-8">{{ versions.api_min }}</dd>
<dt class="col-sm-3">Max. API version supported:</dt>
<dd class="col-sm-8">{{ versions.api_current }}</dd>
<dt class="col-sm-3">Min. module interface version supported:</dt>
<dd class="col-sm-8">{{ versions.interface_min }}</dd>
<dt class="col-sm-3">Max. module interface version supported:</dt>
<dd class="col-sm-8">{{ versions.interface_current }}</dd>
</dl>
</div>
</div>
</div>
<!-- <div class="row">-->
<!-- <div class="col-12">-->
<!-- <div class="float-right mt-4">-->
<!-- <button class="btn btn-outline-primary" id="check_updates" type="button" onclick="check_updates()">Check for updates</button>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="card-title">Global settings</div>
</div>
<div class="card-body">
<div class="row mt-2">
<div class="col-12">
<form id="form_srv_settings">
{{ form.hidden_tag() }}
<h2>Proxy</h2>
<div class="mb-4">
<p>Proxy settings can be used by modules to access external resources.</p>
<div class="row mb-4">
<div class="col-6">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">
HTTP Proxy
</span>
</div>
<input class="form-control" name="http_proxy" placeholder="HTTP Proxy" value="{{ settings.http_proxy }}">
</div>
</div>
<div class="col-6">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">
HTTP Proxy
</span>
</div>
<input class="form-control" name="https_proxy" placeholder="HTTPS Proxy" value="{{ settings.http_proxy }}">
</div>
</div>
</div>
</div>
<h2 class="mt-4">Post-init Behavior</h2>
<div class="col-12 mb-4">
<!-- <div class="form-check">-->
<!-- <label class="form-check-label">-->
<!-- <input class="form-check-input" type="checkbox" id="enable_updates_check" name="enable_updates_check" {% if settings.enable_updates_check %}checked{% endif %}>-->
<!-- <span class="form-check-sign">Enable automatic daily check for updates</span>-->
<!-- </label>-->
<!-- </div>-->
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="prevent_post_mod_repush" name="prevent_post_mod_repush" {% if settings.prevent_post_mod_repush %}checked{% endif %}>
<span class="form-check-sign">Prevent post-init step to register default modules again during boot</span>
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="prevent_post_objects_repush" name="prevent_post_objects_repush" {% if settings.prevent_post_objects_repush %}checked{% endif %}>
<span class="form-check-sign">Prevent post-init step to register default case objects again during boot</span>
</label>
</div>
</div>
<h2 class="mt-4">Password Policy</h2>
<p>A password policy change applies to new or updated passwords.</p>
<div class="row mb-2">
<div class="col-4">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">
Minimum Password Length
</span>
</div>
<input class="form-control" name="password_policy_min_length" placeholder="12" type="number" value="{{ settings.password_policy_min_length }}">
</div>
</div>
<div class="col-8">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">
Include Special chars
</span>
</div>
<input class="form-control" name="password_policy_special_chars" placeholder="Set empty to disable" type="text" value="{{ settings.password_policy_special_chars }}">
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="password_policy_upper_case" name="password_policy_upper_case" {% if settings.password_policy_upper_case %}checked{% endif %}>
<span class="form-check-sign">Must include uppercase char</span>
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="password_policy_lower_case" name="password_policy_lower_case" {% if settings.password_policy_lower_case %}checked{% endif %}>
<span class="form-check-sign">Must include lowercase char</span>
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="password_policy_digit" name="password_policy_digit" {% if settings.password_policy_digit %}checked{% endif %}>
<span class="form-check-sign">Must include digits</span>
</label>
</div>
</div>
</div>
</form>
<div class="float-right mt-4">
<button class="btn btn-outline-primary float-right" id="save_srv_settings" type="button" onclick="update_settings()">Save changes</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="card-title">Backups</div>
</div>
<div class="card-body">
<div class="row mt-2">
<div class="col-12">
<h2>Database</h2>
<p>Initiate a database backup. The backup file is stored on the configured path <code>BACKUP_PATH</code></p>
<div class="float-right mt-4">
<button class="btn btn-outline-primary" id="init_db_backup" type="button" onclick="init_db_backup()">Backup database</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal " tabindex="-1" role="dialog" id="modal_updates" data-backdrop="true">
<div class="modal-xl modal-dialog" role="document">
<div class="modal-content" id="modal_updates_content">
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">Server Updates</h4>
<button type="button" class="pull-right btn btn-white" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<div class="row">
<h3>Please wait while we look for updates</h3>
</div>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/plugin/showdown/showdown.min.js"></script>
<script src="/static/assets/js/iris/manage.server.settings.js"></script>
<script>
</script>
{% endblock javascripts %}

View File

@@ -0,0 +1,82 @@
{% extends "layouts/default.html" %}
{% block title %} Manage Templates {% endblock title %}
{% block stylesheets %}
<link rel="stylesheet" href="/static/assets/css/suggestags.css">
{% endblock stylesheets %}
{% block content %}
{% if current_user.is_authenticated %}
{{ form.hidden_tag() }}
<div class="page-inner">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<div class="card-title">Report Templates Management</div>
</div>
<div class="col">
<button type="button" class="btn btn-sm btn-dark float-right ml-2" onclick="refresh_template_table();">
Refresh
</button>
<button class="btn btn-sm btn-dark float-right ml-2" onclick="add_report_template();">Add template</button>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive" id="assets_table_wrapper">
<div class="selectgroup">
<span id="table_buttons"></span>
</div>
<table class="table display table table-striped table-hover" width="100%"
cellspacing="0" id="reports_table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Naming format</th>
<th>Date created</th>
<th>Created by</th>
<th>Language</th>
<th>Type</th>
<th>Download</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Description</th>
<th>Naming format</th>
<th>Date created</th>
<th>Created by</th>
<th>Language</th>
<th>Type</th>
<th>Download</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade " tabindex="-1" role="dialog" id="modal_add_report_template" data-backdrop="true">
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content" id="modal_report_template_content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
{% endif %}
{% endblock content %}
{% block javascripts %}
<script src="/static/assets/js/iris/manage.templates.js"></script>
{% endblock javascripts %}

View File

@@ -0,0 +1,80 @@
<div class="modal-header">
<h4>Add Asset Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_asset_type" enctype="multipart/form-data">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="asset_type" class="mr-4">Asset Type
</label>
{{ form.asset_name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="asset_description" class="placeholder">Asset Type description</label>
{{ form.asset_description(class='form-control', autocomplete="off") }}
</div>
<div class="row ml-2">
{% if assettype.asset_icon_not_compromised %}
<div class="form-group col-2">
<label for="asset_icon_not_compromised" class="mr-4">Preview</label>
<div id="asset_icon_not_compromised">
<img style="width:2em;height:2em" src="{{ assettype.asset_icon_not_compromised_path }}">
</div>
</div>
<div class="form-group col">
<label for="asset_icon_compromised" class="mr-4">Asset Icon - not compromised
</label>
{{ form.asset_icon_not_compromised(class='form-control',type='file', accept='.svg, .png') }}
</div>
{% else %}
<div class="form-group col">
<label for="asset_icon_compromised" class="mr-4">Asset Icon - not compromised
</label>
{{ form.asset_icon_not_compromised(class='form-control',type='file', required='false', value=assettype.asset_icon_not_compromised, accept='.svg, .png') }}
</div>
{% endif %}
</div>
<div class="row ml-2">
{% if assettype.asset_icon_compromised %}
<div class="form-group col-2">
<label for="asset_icon_compromised" class="mr-4">Preview</label>
<div id="asset_icon_compromised">
<img style="width:2em;height:2em" src="{{ assettype.asset_icon_compromised_path }}">
</div>
</div>
<div class="form-group col">
<label for="asset_icon_compromised" class="mr-4">Asset Icon - compromised
</label>
{{ form.asset_icon_compromised(class='form-control',type='file', accept='.svg, .png') }}
</div>
{% else %}
<div class="form-group col">
<label for="asset_icon_compromised" class="mr-4">Asset Icon - compromised
</label>
{{ form.asset_icon_compromised(class='form-control', type='file', required='false', value=assettype.asset_icon_compromised, accept='.svg, .png') }}
</div>
{% endif %}
</div>
{% if assettype.asset_id %}
<button type="button" class="btn btn-outline-danger mt-5"
onclick="delete_asset_type('{{ assettype.asset_id }}');">Delete</button>
<button type="submit" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_assettype">Update</button>
{% else %}
<button type="submit" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_assettype">Save</button>
{% endif %}
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,154 @@
<div class="modal-header">
<h4>Edit attribute {{ attribute.attribute_display_name }}</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_attribute" enctype="multipart/form-data">
<div class="row">
<div class="col-6">
<div class="accordion accordion-primary">
<h2>{{ attribute.attribute_display_name }} attributes</h2>
<p>Attributes allow to extend the fields available for analysts when they add or edit {{ attribute.attribute_display_name }}.</p>
<div class="alert-std alert-warning" role="alert">
Attributes can be added by administrator in this UI, or they can be pushed by modules.<br/>
This means each {{ attribute.attribute_display_name }} object may have a different set of attributes.
Updating the default objects here will result in an update of every existing object, which might take a huge amount of time.
<p>Typing wrong attributes here might result in UI breaks. IRIS will attempt to validate the attributes' taxonomy before committing.</p>
<b>To avoid this, use the Preview button before saving. It displays a 1-to-1 UI representation of the attributes</b>
</div>
<div class="card">
<div class="card-header collapsed" id="drop_attr_description" data-toggle="collapse" data-target="#drop_attr_desc" aria-expanded="false" aria-controls="drop_attr_desc" role="button">
<div class="span-icon">
<div class="flaticon-tea-cup"></div>
</div>
<div class="span-title">
More details
</div>
<div class="span-mode"></div>
</div>
<div id="drop_attr_desc" class="collapse" aria-labelledby="drop_tax_attr" style="">
<div class="card-body">
<p>These attributes are stored in each {{ attribute.attribute_display_name }} object in the form of a JSON structure.</p>
<p>Attributes in this page represent the default attributes of each new {{ attribute.attribute_display_name }} objects. Existing object are updated if they
don't hold the specified attributes. <b>Other existing attributes are not deleted.</b></p>
Attributes can have the following purposes:
<ul>
<li><b>Inputs</b>: Offer analysts the possibility to fill additional details. Multiple types of inputs are supported. See taxonomy for more details</li>
<li><b>Raw</b>: A static content rendered in raw text. HTML is not interpreted.</li>
<li><b>HTML</b>: A static content rendered as HTML for infinite possibilities. <b>Careful, this is by nature prone to vulnerabilities.</b></li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header collapsed" id="drop_attr_taxonomy" data-toggle="collapse" data-target="#drop_tax_attr" aria-expanded="false" aria-controls="drop_tax_attr" role="button">
<div class="span-icon">
<div class="flaticon-pencil"></div>
</div>
<div class="span-title">
Attributes taxonomy
</div>
<div class="span-mode"></div>
</div>
<div id="drop_tax_attr" class="collapse" aria-labelledby="drop_tax_attr" style="">
<div class="card-body">
Attributes are defined as below.
<pre>
{
"Tab Name 1": { // Defines a new tab in the {{ attribute.attribute_display_name }} modal
"Field 1": { // Defines a new field within the Tab Name 1
"type": "input_string", // Defines the type of field, here a standard string input
"mandatory": true, // Indicates whether the field is mandatory upon saving
"value": "" // Default value if any, else empty
},
"Field 2": { // Defines a second field within the tab Tab Name 1
"type": "input_checkbox", // Defines an input checkbox
"mandatory": false, // Indicates whether the field is mandatory upon saving
"value": true // Default value
}
},
"VT report": { // Defines a second tab named VT report
"Content": { // Defines a new field Content within the VT Report
"type": "html", // Defines an HTML interpreted content
"value": "" // Default value if any, else empty
}
}
}
</pre>
<h4>Field types</h4>
The supported fields types are:
<ul>
<li>input_string: Standard input text</li>
<li>input_textfield: Standard input textfield</li>
<li>input_checkbox: Standard checkbox</li>
<li>input_date: Standard date input</li>
<li>input_datetime: Standard date and time input</li>
<li>input_select: Standard select input. Need "options" tag to describe the available options</li>
<li>raw: A static content rendered in raw text. HTML is not interpreted.</li>
<li>html: A static content rendered as HTML. <b>Careful, this is by nature prone to vulnerabilities.</b></li>
</ul>
</div>
</div>
</div>
<div class="card">
<div class="card-header collapsed" id="drop_attr_over" data-toggle="collapse" data-target="#drop_attr_overwrite" aria-expanded="false" aria-controls="drop_attr_overwrite" role="button">
<div class="span-icon">
<div class="flaticon-exclamation"></div>
</div>
<div class="span-title">
Overwrite features
</div>
<div class="span-mode"></div>
</div>
<div id="drop_attr_overwrite" class="collapse" aria-labelledby="drop_tax_attr" style="">
<div class="card-body">
<p>Changing types of fields in attributes might result in incompatibles types and existing objects being unable to be migrated.</p>
<p>When this happens, IRIS will not update the fields of these objects and let them as is to prevent any data loss.</p>
<p>This behavior can however be changed by using the <kbd>Complete overwrite</kbd> and <kbd>Partial overwrite</kbd> buttons.</p>
<p><kbd>Partial overwrite</kbd> basically resets the attributes values of every {{ attribute.attribute_display_name }} objects that matches the current ones, and then applies the current attributes.
All associated values are lost. This does not impact attributes pushed by modules.</p>
<p><kbd>Complete overwrite</kbd> resets all attributes of every {{ attribute.attribute_display_name }} objects, including the ones created by modules, and then applies the current attributes.
All associated values are lost.</p>
<b>In any case, none of the native values of the {{ attribute.attribute_display_name }} objects are modified. This only concerns custom attributes.</b>
</div>
</div>
</div>
</div>
</div>
<div class="col-6">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="Attribute content" class="mr-4">Attribute definition
</label>
<div id="editor_detail">{{ attribute.attribute_content|tojsonsafe }}</div>
</div>
</div>
</div>
</form>
</div>
<div class="alert alert-warning" style="display:none;" role="alert" id="alert_attributes_details">
<span id="alert_attributes_edit"></span><br/>
<b>Logs:</b>
<ul id="attributes_err_details_list">
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-danger float-right" id="submit_complete_overwrite">Complete overwrite</button>
<button type="button" class="btn btn-outline-danger mr-auto" id="submit_partial_overwrite">Partial overwrite</button>
<button type="button" class="btn btn-outline-black float-right" id="preview_attribute">Preview</button>
<button type="button" class="btn btn-outline-success float-right" id="submit_new_attribute">Update</button>
</div>

View File

@@ -0,0 +1,72 @@
<div class="modal-header">
<div class="col md-12">
<div class="row">
<div class="col">
<h4 class="modal-title mt-1 mr-4">{% if customer.client_id %}Edit customer #{{ customer.client_id }}{% else %}Add customer{% endif %}</h4>
<small><a class="text-muted">{% if customer.client_uuid %}#{{ customer.client_uuid }}{% endif %}</a></small>
</div>
{% include 'modals/modal_attributes_nav.html' %}
<div class="col ">
<div class="row float-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
</div>
</div>
</div>
<div class="modal-body">
<div role="tabpanel">
<div class="tab-content">
<div class="tab-pane active" id="details">
<div class="container col-md-12">
<form method="post" action="" id="form_new_customer" enctype="multipart/form-data">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="customer" class="mr-4">Name *</label>
{{ form.customer_name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group">
<label for="description" class="mr-4">Description</label>
{{ form.customer_description(class='form-control', autocomplete="off") }}
</div>
<div class="form-group">
<label for="sla" class="mr-4">SLAs</label>
{{ form.customer_sla(class='form-control', autocomplete="off") }}
</div>
</div>
</form>
</div>
</div>
{% include 'modals/modal_attributes_tabs.html' %}
</div>
{% if customer.client_id %}
<button
type="button"
class="btn btn-outline-danger mt-5"
onclick="delete_customer('{{ customer.client_id }}');"
>
Delete
</button>
<button
type="button"
class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_customer"
>
Update
</button>
{% else %}
<button
type="button"
class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_customer"
>
Save
</button>
{% endif %}
</div>
</div>

View File

@@ -0,0 +1,49 @@
<div class="modal-header">
<h4>Add IOC Type</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_ioc_type" enctype="multipart/form-data">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="type_name" class="mr-4">Type name
</label>
{{ form.type_name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="type_description" class="placeholder">Type description</label>
{{ form.type_description(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="type_taxonomy" class="placeholder">Type taxonomy</label>
{{ form.type_taxonomy(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="type_description" class="placeholder">Type validation regex</label>
{{ form.type_validation_regex(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="type_description" class="placeholder">Type validation expect explanation</label>
{{ form.type_validation_expect(class='form-control', autocomplete="off") }}
</div>
{% if ioc_type.type_id %}
<button type="button" class="btn btn-outline-danger mt-5"
onclick="delete_ioc_type('{{ ioc_type.type_id }}');">Delete</button>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_ioc_type">Update</button>
{% else %}
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_ioc_type">Save</button>
{% endif %}
</form>
</div>
</div>

View File

@@ -0,0 +1,40 @@
<div class="modal-header">
<h4>Add Module</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_module">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group">
<h3>Module extensions</h3>
<p>Iris can be extended with compatible modules. Modules are pip packages providing a specific interface which allows
Iris and the module to communicate. Enter below a pip package name already installed.</p>
<p>Ex: iris_evtx</p>
<i class="">Tips: you can develop your own module by following <a target=”_blank” href="https://docs.dfir-iris.org/development/modules/" >this link</a></i>
<div class="mt-4">
<strong class="text-danger">Note :</strong> Modules are running as the same trust level as Iris. They can thus access all the information
stored on Iris as well as run code on the server. Please be cautious and review modules before installing them.
</div>
<label for="module_name" class="mr-4 mt-3">Module name</label>
{{ form.module_name(class='form-control', autocomplete="off") }}
<div class="alert-std alert-warning" style="display:none;" role="alert" id="alert_mod_add">
</div>
<div class="alert-std alert-warning" style="display:none;" role="alert" id="alert_mod_details">
<b>Logs</b>
<ul id="details_list">
</ul>
</div>
</div>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_module">Validate module</button>
</form>
</div>
</div>

View File

@@ -0,0 +1,75 @@
<div class="modal-header">
<h4>Add Report Template</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_report_template" enctype="multipart/form-data">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group mt-3">
<label for="report_name" class="placeholder">Template name</label>
{{ form.report_name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="report_type" class="mr-4">Template type
</label>
{{ form.report_type(class='form-control', autocomplete="off") }}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="report_language" class="mr-4">Template language
</label>
{{ form.report_language(class="selectpicker pl--6 col-md-12") }}
</div>
</div>
</div>
</div>
<div class="form-group mt-3">
<label for="report_description" class="placeholder">Template description</label>
{{ form.report_description(class='form-control', autocomplete="off") }}
</div>
<div class="form-group ml--2">
{{ form.report_language(class="selectpicker pl--6") }}
</div>
<div class="form-group mt-3">
<label for="report_name_format" class="placeholder">Template name format</label>
<br/>This is the name of the generated report file. Do not input extension.
Available tags:
<ul>
<li>%date% : date of generation</li>
<li>%customer% : customer name</li>
<li>%case_name% : name of the case</li>
<li>%code_name%: autogenerated enterprise code name</li>
</ul>
Example: <i>analysis_%customer%_%date%</i>
{{ form.report_name_format(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="report_name_format" class="placeholder">Template file : </label>
<input type=file name=file>
</div>
{% if report_template.asset_id %}
<button type="button" class="btn btn-outline-danger mt-5"
onclick="delete_report_template('{{ assettype.asset_id }}');">Delete</button>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_report_template">Update</button>
{% else %}
<button type="submit" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_report_template">Save</button>
{% endif %}
</form>
</div>
</div>

View File

@@ -0,0 +1,42 @@
<div class="modal-header">
<h4>Case classification</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_case_classification" enctype="multipart/form-data">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="name" class="mr-4">Classification name
</label>
{{ form.name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="name_expanded" class="placeholder">Classification expanded name</label>
{{ form.name_expanded(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="description" class="placeholder">Classification description</label>
{{ form.description(class='form-control', autocomplete="off") }}
</div>
{% if case_classification.id %}
<button type="button" class="btn btn-outline-danger mt-5"
onclick="delete_case_classification('{{ case_classification.id }}');">Delete</button>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_case_classification">Update</button>
{% else %}
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_case_classification">Save</button>
{% endif %}
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,421 @@
{% set attributes = data.custom_attributes %}
<div class="modal-header">
<div class="col md-12">
<div class="row">
<div class="col align-self-center">
<h4 class="modal-title mr-4">{{ data.case_name|unquote }}
{% if data.modification_history %}
<i class="fa-solid fa-clock-rotate-left ml-3 mt-2" data-toggle="popover" data-html="true" id="pop_history" style="cursor: pointer;"
title="Modifications history"
data-content="<small>{% for mod in data.modification_history %}<code>{{ mod|format_datetime('%Y-%m-%d %H:%M') }}</code> - {{ data.modification_history[mod].action }} by {{ data.modification_history[mod].user }}<br/>{% endfor %}</small>">
</i>
{% endif %}
</h4>
</div>
<div class="row text-center">
<ul class="nav nav-pills nav-default mr-4" id="pills-tab-custom-attr" role="tablist">
<li class="nav-item">
<a class="nav-link active show" id="pills-home-tab-nobd" data-toggle="pill" href="#details" role="tab" aria-controls="pills-home-nobd" aria-selected="false">Info</a>
</li>
<li class="nav-item submenu">
<a class="nav-link" data-toggle="pill" href="#case-info-access" role="tab" aria-controls="case-info-access" aria-selected="false">Access</a>
</li>
{% if attributes and attributes|length > 0 %}
{% for ca in attributes %}
<li class="nav-item submenu">
<a class="nav-link" data-toggle="pill" href="#{{page_uid}}{{ loop.index }}_{{ ca.lower() | replace(' ', '_' ) }}" role="tab" aria-controls="{{page_uid}}{{ loop.index }}_{{ ca.lower() | replace(' ', '_' ) }}" aria-selected="false">{{ca}}</a>
</li>
{% endfor %}
{% endif %}
</ul>
</div>
<div class="col ">
<div class="row float-right">
<button type="button" class="float-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
</div>
</div>
</div>
<div class="modal-body">
<div class="container col-md-12">
<div role="tabpanel">
<div class="tab-content">
<div class="tab-pane active" id="details">
<div id="case_gen_info_content">
<h4>General info <button class="ml-2 btn btn-sm float-right" onclick="edit_case_info();">Edit</button></h4>
<div class="row">
<div class="col-6 col-xs-12 col-md-6">
<div class="form-group">
<label>Case name :</label>
<span type="text" class="">{{ data.case_name|unquote }}</span>
</div>
<div class="form-group mt--3">
<label>Case description :</label>
<span type="text" class="">{{ data.case_description[0:50] }}</span>
</div>
<div class="form-group mt--3">
<label>Customer :</label>
<span type="text" class="text-faded">{{ data.customer_name }}</span>
</div>
<div class="form-group mt--3">
<label>Case tags :</label>
<span type="text" class="text-faded">{% if data.case_tags %} {% for tag in data.case_tags.split(',') %}
<span class="badge badge-pill badge-light ml-1"><i class="fa fa-tag mr-1"></i>{{ tag }}</span> {% endfor %}{% endif %}</span>
</div>
<div class="form-group mt--3">
<label>SOC ID :</label>
<span type="text" class="text-faded">{{ data.case_soc_id }}</span>
</div>
<div class="form-group mt--3">
<label>Case ID :</label>
<span type="text" class="text-faded">{{ data.case_id }}</span>
</div>
<div class="form-group mt--3">
<label>Case UUID :</label>
<span type="text" class="text-faded">{{ data.case_uuid }}</span>
</div>
</div>
<div class="col-6 col-xs-12 col-md-6">
<div class="form-group mt--3">
<label>Classification :</label>
{% if data.classification %}
<span type="text" class="text-faded">{{ data.classification }}</span>
{% else %}
<span type="text" class="text-faded">Unknown</span>
{% endif %}
</div>
<div class="form-group mt--3">
<label>State :</label>
<span type="text" class="text-faded">{{ data.state_name }}</span>
</div>
<div class="form-group mt--3">
<label>Open date :</label>
<span type="text" class="">{{ data.open_date }}</span>
</div>
<div class="form-group mt--3">
<label>Opening user :</label>
<span type="text" class="">{{ data.open_by_user }}</span>
</div>
<div class="form-group mt--3">
<label>Owner :</label>
<span type="text" class="">{{ data.owner }}</span>
</div>
{% if data.reviewer %}
<div class="form-group mt--3">
<label>Reviewer :</label>
<span type="text" class="">{{ data.reviewer }}</span>
</div>
{% endif %}
{% if data.review_status %}
<div class="form-group mt--3">
<label>Reviewer :</label>
<span type="text" class="">{{ data.review_status.status_name }}</span>
</div>
{% endif %}
{% if data.close_date %}
<div class="form-group mt--3">
<label>Close date :</label>
<span type="text" class="">{{ data.close_date }}</span>
</div>
{% endif %}
{% if protagonists %}
{% for protagonist in protagonists %}
<div class="form-group mt--3">
<label>{{ protagonist.role }}: </label>
<span type="text" class="">{{ protagonist.name }} ({{protagonist.contact}})</span>
</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
<div id="case_gen_info_edit" style="display:none;">
<form method="post" action='' id="form_update_case" autocomplete="off">
<h4 class=" pb-3">Edit case information</h4>
<div class="col-12">
{{ form.hidden_tag() }}
<div class="mt-4">
<div class="row">
<div class="col-xs-12 col-6">
<div class="input-group mb-4">
<div class="input-group-prepend">
<span class="input-group-text">Case name <i class="ml-2">{{"#{} - ".format(data.case_id)}}</i></span>
</div>
<input type="text" class="form-control" name="case_name" value="{{ data.case_name.replace('#{} - '.format(data.case_id), '')}}">
</div>
</div>
<div class="col-xs-12 col-6">
<div class="input-group mb-4">
<div class="input-group-prepend">
<span class="input-group-text">SOC ticket ID</span>
</div>
<input type="text" class="form-control" name="case_soc_id" value="{{ data.case_soc_id }}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-6">
<div class="input-group mb-4">
<div class="input-group-prepend fix-label-item">
<span class="input-group-text">Classification</span>
</div>
<select class="selectpicker form-control"
id="case_quick_classification" name="classification_id">
{% for clc in case_classifications %}
<option value="{{ clc.id }}" {% if data.classification_id == clc.id %}selected{% endif %} class="badge-text">{{ clc.name_expanded }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-xs-12 col-6">
<div class="input-group mb-4">
<div class="input-group-prepend fix-label-item">
<span class="input-group-text">Owner</span>
</div>
<select class="selectpicker form-control"
id="case_quick_owner" name="owner_id">
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-6">
<div class="input-group mb-4">
<div class="input-group-prepend fix-label-item">
<span class="input-group-text">State</span>
</div>
<select class="selectpicker form-control"
id="case_state" name="state_id">
{% for clc in case_states %}
<option value="{{ clc.state_id }}" {% if data.state_id == clc.state_id %}selected{% endif %} class="badge-text">{{ clc.state_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-xs-12 col-6">
<div class="input-group mb-4">
<div class="input-group-prepend fix-label-item">
<span class="input-group-text">Outcome</span>
</div>
<select class="form-control selectpicker"
id="case_quick_status" name="status_id">
<option value="0" {% if data.status_id == 0 %}selected{% endif %} class="badge-text">Unknown</option>
<option value="1" {% if data.status_id == 1 %}selected{% endif %} class="badge-text">False Positive</option>
<option value="2" {% if data.status_id == 2 %}selected{% endif %} class="badge-text">True Positive with impact</option>
<option value="4" {% if data.status_id == 4 %}selected{% endif %} class="badge-text">True Positive without impact</option>
<option value="3" {% if data.status_id == 3 %}selected{% endif %} class="badge-text">Not applicable</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-6">
<div class="input-group mb-2">
<div class="input-group-prepend fix-label-item">
<span class="input-group-text">Customer</span>
</div>
<select class="selectpicker form-control"
id="case_quick_customer" name="case_customer">
{% for cst in customers %}
<option value="{{ cst.customer_id }}" {% if data.customer_id == cst.customer_id %}selected{% endif %} class="badge-text">{{ cst.customer_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-xs-12 col-6">
<div class="input-group mb-4">
<div class="input-group-prepend fix-label-item">
<span class="input-group-text">Reviewer</span>
</div>
<select class="selectpicker form-control"
id="case_quick_reviewer" name="reviewer_id">
</select>
</div>
</div>
</div>
<div class="form-group px-0">
<label for="asset_tags">Case tags
</label>
<input type="text" id="case_tags"
class="form-control col-md-12" {% if data.case_tags %} value="{{ data.case_tags }}" {% endif %}/>
</div>
<div class="form-group px-4 py-4 mt-3" id="protagonists_form_group">
{% if protagonists %}
<label>Protagonists
</label>
{% for iprota in protagonists %}
<div class="input-group mb-2 mt-2" id="protagonist_{{loop.index}}">
<div class="col-6">
<h6># {{loop.index}}</h6>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="ingrole_{{loop.index}}">Role</span>
</div>
<input type="text" aria-describedby="ingrole_{{loop.index}}" list="roles-list" class="form-control" name="protagonist_role_{{loop.index}}" value="{{ iprota.role }}" placeholder="Role">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="ingname_{{loop.index}}">Name</span>
</div>
<input type="text" aria-describedby="ingname_{{loop.index}}" class="form-control" name="protagonist_name_{{loop.index}}" placeholder="Name" list="username-list" value="{{ iprota.name }}">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="ingp_{{loop.index}}">Contact</span>
</div>
<input type="text" aria-describedby="ingp_{{loop.index}}" class="form-control" name="protagonist_contact_{{loop.index}}" value="{{ iprota.contact }}" placeholder="Contact" list="emails-list">
</div>
<button type="button" class="btn btn-sm btn-outline-dark mr-2 mt-1" onclick="remove_protagonist('{{loop.index}}');">
Remove
</button>
<hr/>
</div>
</div>
{% endfor %}
{% endif %}
<div id="protagonist_list_edit">
</div>
<button type="button" class="btn btn-sm btn-outline-dark mt-2 mr-2" id="add_protagonist_btn" onclick="add_protagonist();">Add protagonist</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="tab-pane" id="case-info-access">
<div class="row">
<div class="col">
<div class="card-title">Case access</div>
</div>
<div class="col">
<button class="btn btn-dark btn-sm ml-3 float-right" onclick="access_case_info_reload('{{ data.case_id }}');">Refresh</button>
<button class="btn btn-dark btn-sm ml-2 float-right" onclick="view_case_access_via_group('{{ data.case_id }}');">Set access via group</button>
</div>
</div>
<div class="row mt-4">
<div class="col">
<table class="table display table-striped table-hover responsive" width="100%" cellspacing="0" id="case_access_users_list_table" >
<thead>
<tr>
<th>User ID</th>
<th>User Name</th>
<th>User Login</th>
<th>User Access</th>
</tr>
</thead>
<tfoot>
<tr>
<th>User ID</th>
<th>User Name</th>
<th>User Login</th>
<th>User Access</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
{% include 'modals/modal_attributes_tabs.html' %}
</div>
</div>
</div>
</div>
<div id="protagonist_list_edit_template" style="display:none;">
<div class="input-group mb-2 mt-2" id="protagonist___PROTAGONIST_ID__">
<div class="col-6">
<h5>Protagonist</h5>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="ingrole___PROTAGONIST_ID__">Role</span>
</div>
<input type="text" aria-describedby="ingrole___PROTAGONIST_ID__" list="roles-list" class="form-control" name="protagonist_role___PROTAGONIST_ID__" value="" placeholder="Role">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="ingname___PROTAGONIST_ID__">Name</span>
</div>
<input type="text" aria-describedby="ingname___PROTAGONIST_ID__" class="form-control" name="protagonist_name___PROTAGONIST_ID__" placeholder="Name" list="username-list" value="">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="ingp___PROTAGONIST_ID__">Contact</span>
</div>
<input type="text" aria-describedby="ingp___PROTAGONIST_ID__" class="form-control" name="protagonist_contact___PROTAGONIST_ID__" value="" list="emails-list" placeholder="Contact">
</div>
<button type="button" class="btn btn-sm btn-outline-dark mr-2 mt-1" onclick="remove_protagonist('__PROTAGONIST_ID__');">
Remove
</button>
<hr/>
</div>
</div>
</div>
<datalist id="roles-list">
<option value="Analyst">
<option value="Lead">
<option value="Communication">
<option value="Customer contact">
</datalist>
<datalist id="username-list">
</datalist>
<datalist id="emails-list">
</datalist>
<div class="modal-footer">
<button type="button" class="btn btn-outline-danger " onclick="remove_case('{{ data.case_id }}');"
id="delete_case_info">Delete case</button>
{% if not data.close_date %}
<button type="button" class="btn btn-outline-warning mr-auto" onclick="close_case('{{ data.case_id }}');"
id="close_case_info">Close case</button>
{% else %}
<button type="button" class="btn btn-success" onclick="reopen_case('{{ data.case_id }}');"
id="reopen_case_info">Reopen case</button>
{% endif %}
<button type="button" class="btn btn-outline-dark mr-2" style="display:none;" id="cancel_case_info" onclick="cancel_case_edit();">Cancel</button>
<button type="button" class="btn btn-outline-success mr-2" style="display:none;" id="save_case_info" onclick="save_case_edit({{ data.case_id }});">Save</button>
</div>
<script>
$('[data-toggle="popover"]').popover();
$('#case_quick_classification').selectpicker({
liveSearch: true,
title: "Classification",
style: "btn-outline-white"
});
$('#case_quick_owner').selectpicker({
liveSearch: true,
title: "Owner",
style: "btn-outline-white"
});
$('#case_quick_reviewer').selectpicker({
liveSearch: true,
title: "Reviewer",
style: "btn-outline-white"
});
$('#case_state').selectpicker({
liveSearch: true,
title: "Case state",
style: "btn-outline-white"
});
$('#case_quick_status').selectpicker({
liveSearch: true,
title: "Outcome",
style: "btn-outline-white"
});
$('#case_quick_customer').selectpicker({
liveSearch: true,
title: "Customer",
style: "btn-outline-white"
});
access_case_info_reload('{{ data.case_id }}', '{{ data.owner_id }}', '{{ data.reviewer_id }}');
</script>

View File

@@ -0,0 +1,42 @@
<div class="modal-header">
<h4>Case state</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_case_state" enctype="multipart/form-data">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group">
<label for="name" class="mr-4">State name
</label>
{{ form.state_name(class='form-control', autocomplete="off") }}
</div>
<div class="form-group mt-3">
<label for="description" class="placeholder">State description</label>
{{ form.state_description(class='form-control', autocomplete="off") }}
</div>
{% if not case_state.protected %}
{% if case_state.state_id %}
<button type="button" class="btn btn-outline-danger mt-5"
onclick="delete_case_state('{{ case_state.state_id }}');">Delete</button>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_case_state">Update</button>
{% else %}
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_case_state">Save</button>
{% endif %}
{% else %}
<i class="fa fa-lock mt-4 mr-2 ml-3 text-danger mb-4" aria-hidden="true"></i> This state is protected and cannot be deleted or updated.
{% endif %}
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,177 @@
<div class="modal-header">
{% if case_template.id %}
<h4>Edit case template {{ case_template.display_name }}</h4>
{% else %}
<h4>Add case template</h4>
{% endif %}
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_new_case_template" enctype="multipart/form-data">
<div class="row">
<div class="col-6">
<div class="accordion accordion-primary">
{% if case_template.id %}
<h2>{{ case_template.display_name }} template</h2>
{% else %}
<h2>New template</h2>
{% endif %}
<p>Case templates allow to prefill case objects such as tasks, tags, and notes.<br/>
It can be used to add procedures defining how to react against a specific kind of incident (phishing, ransomware, APT...)</p>
<div class="alert-std alert-warning" role="alert">
Case templates can be added and edited in this UI, or they can be uploaded as JSON files.<br/>
<p>IRIS will attempt to validate the contents of the case template before committing.</p>
</div>
<div class="card">
<div class="card-header collapsed" id="drop_case_template_taxonomy" data-toggle="collapse" data-target="#drop_tax_case_template" aria-expanded="false" aria-controls="drop_tax_attr" role="button">
<div class="span-icon">
<div class="flaticon-pencil"></div>
</div>
<div class="span-title">
Case Template taxonomy
</div>
<div class="span-mode"></div>
</div>
<div id="drop_tax_case_template" class="collapse" aria-labelledby="drop_tax_case_template" style="">
<div class="card-body">
<h4>Field types</h4>
The supported fields types are:
<ul>
<li>name: The name of the case template (required).</li>
<li>display_name: The displayed name of the case template.</li>
<li>description: The description of the case template.</li>
<li>author: The author of the case template (not related to the current user).</li>
<li>classification: The classification of the case template. Should be a lowercase name matching an existing classification in IRIS.</li>
<li>title_prefix: A prefix to add to case title.</li>
<li>summary: content to prefill the summary.</li>
<li>tags: A list of case tags.</li>
<li>tasks: A list of dictionaries defining tasks. Tasks are defined by title (required), description, and list of tags.</li>
<li>note_groups: A list of dictionaries defining note groups. Note groups are defined by title (required), and list of notes. Notes have title (required) and content</li>
</ul>
</div>
</div>
</div>
<div class="card mt-4">
<div class="card-header collapsed" id="drop__template_example" data-toggle="collapse" data-target="#drop_case_template_example" aria-expanded="false" aria-controls="drop_tax_attr" role="button">
<div class="span-icon">
<div class="flaticon-pencil"></div>
</div>
<div class="span-title">
Case Template Example
</div>
<div class="span-mode"></div>
</div>
<div id="drop_case_template_example" class="collapse" aria-labelledby="drop_tax_case_template" style="">
<div class="card-body">
A case template is defined as below.
<pre>
{
"name": "ransomware_infection",
"display_name": "Ransomware Infection Template",
"description": "This case template describes first-response tasks to handle information system compromised by a ransomware.",
"author": "DFIR-IRIS",
"classification": "malicious-code:ransomware",
"title_prefix": "[RANS]",
"summary": "# Context \n\n\n# Contact \n\n\n# Actions \n\n\n",
"tags": ["ransomware","malware"],
"tasks": [
{
"title": "Identify the perimeter",
"description": "The perimeter of compromise must be identified",
"tags": ["identify"]
},
{
"title": "Collect compromised hosts",
"description": "Deploy Velociraptor and start collecting evidence",
"tags": ["collect", "velociraptor"]
},
{
"title": "Containment"
}
],
"note_groups": [
{
"title": "Identify",
"notes": [
{
"title": "Identify the compromised accounts",
"content": "# Observations\n\n"
}
]
},
{
"title": "Collect",
"notes": [
{
"title": "Velociraptor deployment"
},
{
"title": "Assets collected",
"content": "# Assets collected\n\n# Assets not collected"
}
]
}
]
}
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="col-6">
{{ form.hidden_tag() }}
<div class="form-group">
<div class="row">
<label for="editor_detail" class="mr-4">Case template definition
</label><button type="button" class="btn btn-sm ml-auto" onclick="downloadCaseTemplateDefinition();">Download definition</button>
</div>
<div id="editor_detail">{{ form.case_template_json.data|tojsonsafe }}</div>
</div>
</div>
</div>
</form>
</div>
<div class="alert alert-warning" style="display:none;" role="alert" id="alert_case_template_details">
<span id="alert_case_template_edit"></span><br/>
<b>Logs:</b>
<ul id="case_template_err_details_list">
</ul>
</div>
</div>
<div class="modal-footer">
{% if case_template.id %}
<button
type="button"
class="btn btn-outline-danger mr-auto"
id="submit_delete_case_template"
>
Delete
</button>
<button
type="button"
class="btn btn-outline-success ml-4 float-right"
id="submit_new_case_template"
>
Update
</button>
{% else %}
<button
type="button"
class="btn btn-outline-success ml-4 float-right"
id="submit_new_case_template"
>
Save
</button>
{% endif %}
</div>

View File

@@ -0,0 +1,101 @@
<div class="modal-header">
<div class="col md-12">
<div class="row">
<div class="col">
<h4 class="modal-title mt-2 mr-4">{% if contact.id %}Edit contact #{{ contact.id }}{% else %}Add contact{% endif %}</h4>
<small><a class="text-muted">{% if contact.contact_uuid %}#{{ contact.contact_uuid }}{% endif %}</a></small>
</div>
<div class="col ">
<div class="row float-right">
<button type="button" class="pull-right btn bg-transparent" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
</div>
</div>
</div>
<div class="modal-body">
<div role="tabpanel">
<div class="tab-content">
<div class="tab-pane active" id="details">
<div class="container col-md-12">
<form method="post" action="" id="form_new_contact" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<div class="form-group row">
<label for="contact_name" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2 text-right">Contact name *</label>
<div class="col-lg-8 col-md-9 col-sm-8">
{{ form.contact_name(class='form-control', autocomplete="off") }}
</div>
</div>
<div class="form-group row">
<label for="contact_role" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2 text-right">Contact Role</label>
<div class="col-lg-8 col-md-9 col-sm-8">
{{ form.contact_role(class='form-control', autocomplete="off", list="contact_roles_list") }}
</div>
<datalist id="contact_roles_list">
<option value="CISO">
<option value="CEO">
<option value="Manager">
<option value="Sales">
<option value="Support">
<option value="Billing">
<option value="Other">
</datalist>
</div>
<div class="form-group row">
<label for="email" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2 text-right">Contact email</label>
<div class="col-lg-8 col-md-9 col-sm-8">
{{ form.contact_email(class='form-control', autocomplete="off") }}
</div>
</div>
<div class="form-group row">
<label for="work_phone" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2 text-right">Contact work phone</label>
<div class="col-lg-8 col-md-9 col-sm-8">
{{ form.contact_work_phone(class='form-control', autocomplete="off") }}
</div>
</div>
<div class="form-group row">
<label for="mobile_phone" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2 text-right">Contact mobile phone</label>
<div class="col-lg-8 col-md-9 col-sm-8">
{{ form.contact_mobile_phone(class='form-control', autocomplete="off") }}
</div>
</div>
<div class="form-group row">
<label for="notes" class="col-lg-3 col-md-3 col-sm-4 mt-sm-2 text-right">Additional notes</label>
<div class="col-lg-8 col-md-9 col-sm-8">
{{ form.contact_note(class='form-control', autocomplete="off") }}
</div>
</div>
</form>
</div>
</div>
</div>
{% if contact.id %}
<button
type="button"
class="btn btn-outline-danger mt-5"
id="submit_delete_contact"
>
Delete
</button>
<button
type="button"
class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_contact"
>
Update
</button>
{% else %}
<button
type="button"
class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_new_contact"
>
Save
</button>
{% endif %}
</div>
</div>

View File

@@ -0,0 +1,130 @@
<div class="modal-header">
<h4>{{ data.module_human_name|unquote }} - Module Information</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="row">
<div class="container col-6">
<div class="form-group">
<label>Name :</label>
<span type="text" class="">{{ data.module_human_name|unquote }}</span>
</div>
<div class="form-group mt--3">
<label>Description :</label>
<span type="text" class="">{{ data.module_description }}</span>
</div>
<div class="form-group mt--3">
<label>Target package :</label>
<span type="text" class="text-faded">{{ data.module_name }}</span>
</div>
<div class="form-group mt--3">
<label>Date added :</label>
<span type="text" class="text-faded">{{ data.date_added }}</span>
</div>
{% if not is_configured %}
<div class="form-group">
<b class="text-danger">The module was automatically disabled because mandatory parameters are not set.</b>
</div>
{% endif %}
</div>
<div class="container col-6">
<div class="form-group">
<label>Module version :</label>
<span type="text" class="text-faded">{{ data.module_version }}</span>
</div>
<div class="form-group mt--3">
<label>Interface version :</label>
<span type="text" class="text-faded">{{ data.interface_version }}</span>
</div>
<div class="form-group mt--3">
<label>Is active :</label>
<span type="text" class="text-faded">{{ data.is_active }} </span>
</div>
<div class="form-group mt--3">
<label>Provides pipeline :</label>
<span type="text" class="text-faded">{{ data.has_pipeline }}</span>
</div>
</div>
</div>
<div class="container col-12">
<hr/>
<div class="form-group mt-3">
<label>Configuration (click on a setting to edit)</label>
<button type="button" class="btn btn-sm btn-outline-dark float-right" onclick="export_mod_config('{{ data.id }}');">Export configuration</button>
<button type="button" class="btn btn-sm btn-outline-dark float-right mr-2" data-toggle="modal" data-target="#modal_input_config">Import configuration</button>
</div>
<div class="form-group mt-3">
<table id="datatable_db_list" class="table display table-bordered table-striped table-hover mt-4" width="100%"
cellspacing="0">
<thead>
<tr role="row">
<th>Section</th>
<th>Parameter</th>
<th>Value</th>
<th>Mandatory</th>
</tr>
</thead>
<tbody>
{% for id in config %}
<tr role="row">
<td>{{ id["section"] or "Main" }}</td>
<td><a href="#" onclick="update_param({{ data.id }}, '{{ data.id }}##{{ id['param_name'] }}');">
{% if (id['param_name'] in missing_params) %}
<i class="fa-solid fa-triangle-exclamation text-danger" title="Mandatory parameter not set"></i>
{% endif %}
{{ id["param_human_name"] }}
</a></td>
<td>{% if id["value"] is not none %}{% if id["type"] != "sensitive_string" %} {% if id["value"] is string %}{{ id["value"][0:20] }}{% else %}{{id["value"]}}{% endif %} {% else %} *************** {% endif %}{% endif %}</td>
<td>{{ id["mandatory"] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-danger mr-auto" onclick="remove_module('{{ data.id }}');">Remove module</button>
{% if is_configured and not data.is_active %}
<button type="button" class="btn btn-outline-success" onclick="enable_module('{{ data.id }}');">Enable module</button>
{% elif is_configured and data.is_active %}
<button type="button" class="btn btn-outline-warning" onclick="disable_module('{{ data.id }}');">Disable module</button>
{% endif %}
<button type="button" class="btn btn-default" data-dismiss="modal">Dismiss</button>
</div>
<div class="modal bg-shadow-gradient" tabindex="-1" role="dialog" id="modal_input_config" data-backdrop="true">
<div class="modal-lg modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5>Import module configuration from file</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="form-group">
<p>Select a configuration file to upload. Existing configuration for this module will be overwritten.</p>
<label class="placeholder">Configuration file : </label>
<input id="input_configuration_file" type="file" accept="text/json">
<button type="button" class="btn btn-outline-success float-right mr-2" onclick="import_mod_config('{{ data.id }}');">Import</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<script>
$(document).ready(function(){
$("#datatable_db_list").DataTable({
filter: true,
order: [[0, 'asc']],
rowGroup: {
dataSrc: 0
}
});
});
</script>

View File

@@ -0,0 +1,22 @@
<div class="modal-header">
<h4 class="modal-title mt-1">Attribute preview
</h4>
{% include 'modals/modal_attributes_nav.html' %}
<div class="row text-right">
<button type="button" class="pull-right btn btn-white" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
</div>
<div class="modal-body">
<div role="tabpanel">
<div class="tab-content">
<div class="tab-pane active text-center" id="details">
<h2>Base object information</h2>
<b>This is for preview purpose only. Standard object information will be rendered here.</b><br/>
Don't mind the background, it's for preview also
</div>
{% include 'modals/modal_attributes_tabs.html' %}
</div>
</div>
</div>

View File

@@ -0,0 +1,21 @@
<div class="modal-header">
<h4 class="modal-title mt-2 mr-4">Server Updates</h4>
<button type="button" class="pull-right btn btn-white" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true"><i class="fa fa-times"></i></span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<div class="col-md-12" id="updates_content_md">
{{ updates_content }}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Dismiss</button>
{% if has_updates %}
<a type="button" class="btn btn-success" href="/manage/server/make-update?cid={{session['current_case'].case_id}}">Update server</a>
{% endif %}
</div>

View File

@@ -0,0 +1,74 @@
<div class="modal-header">
<h4>Update {{ parameter["param_human_name"] }} of {{ mod_name }} </h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_update_param">
<div class="col-md-12 col-lg-12 col-sm-12">
{{ form.hidden_tag() }}
<div class="form-group">
<b>Description :</b> {{ parameter["param_description"] }}<br/>
<b>Default :</b> {{ parameter["default"] }} <br/>
<b>Mandatory :</b> {{ parameter["mandatory"] }}<br/>
<b>Expected type :</b> {{ parameter["type"] }}<br/>
</div>
<div class="form-group mt-3">
{% if parameter["type"].startswith("textfield_") %}
<label class="placeholder"><b>Value</b></label>
<div id="editor_detail">{{ parameter["value"] }}</div>
{% elif parameter["type"] == 'bool' %}
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" id="parameter_value"
class="form-control"
{% if parameter["value"] == True %} checked {% endif %}
/>
<span class="form-check-sign">Check to set to true</span>
</label>
</div>
{% else %}
<label class="placeholder"><b>Value</b></label>
<input class="form-control required" name="parameter_value" type="text" value="{{ parameter["value"] }}">
{% endif %}
</div>
<button type="button" class="btn btn-outline-success ml-4 mt-5 float-right"
id="submit_save_parameter">Save</button>
</div>
</form>
</div>
</div>
<script>
$(document).ready(function(){
if ($('#editor_detail').length != 0) {
var editor = ace.edit("editor_detail",
{
autoScrollEditorIntoView: true,
minLines: 30,
});
editor.setTheme("ace/theme/tomorrow");
{% if parameter["type"].endswith("json") %}
editor.session.setMode("ace/mode/json");
{% elif parameter["type"].endswith("html") %}
editor.session.setMode("ace/mode/html");
{% elif parameter["type"].endswith("markdown") %}
editor.session.setMode("ace/mode/markdown");
{% endif %}
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);
}
});
</script>

View File

@@ -0,0 +1,121 @@
<div class="modal-header">
<h4>Upload case template</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="container col-md-12">
<form method="post" action="" id="form_upload_case_template">
<div class="modal-content">
<div class="modal-body">
<div class="accordion accordion-primary">
<p>Case templates allow to prefill case objects such as tasks, tags, and notes.<br/>
It could be used to add procedures defining how to react against a specific kind of incident (phishing, ransomware, APT...)</p>
<div class="alert-std alert-warning" role="alert">
Case templates can be uploaded as JSON files, or they can be added and edited in the Add/Edit case template UI.<br/>
</div>
<label class="placeholder">JSON File format example</label>
<div class="card">
<div class="card-header collapsed" id="drop_up_case_template_taxonomy" data-toggle="collapse" data-target="#drop_up_tax_case_template" aria-expanded="false" aria-controls="drop_up_tax_attr" role="button">
<div class="span-icon">
<div class="flaticon-pencil"></div>
</div>
<div class="span-title">
Case Template taxonomy
</div>
<div class="span-mode"></div>
</div>
<div id="drop_up_tax_case_template" class="collapse" aria-labelledby="drop_up_tax_case_template" style="">
<div class="card-body">
A case template is defined as below.
<pre>
{
"name": "ransomware_infection",
"display_name": "Ransomware Infection Template",
"description": "This case template describes first-response tasks to handle information system compromised by a ransomware.",
"author": "DFIR-IRIS",
"title_prefix": "RANS",
"summary": "# Context \n\n\n # Contact \n\n\n # Actions \n\n\n",
"tags": ["ransomware","malware"],
"tasks": [
{
"title": "Identify the perimeter",
"description": "The perimeter of compromise must be identified",
"tags": ["identify"]
},
{
"title": "Collect compromised hosts",
"description": "Deploy Velociraptor and start collecting evidence",
"tags": ["collect", "velociraptor"]
},
{
"title": "Contain"
}
],
"note_groups": [
{
"title": "Identify",
"notes": [
{
"title": "Identify the compromised accounts",
"content": "# Observations\n\n"
}
]
},
{
"title": "Collect",
"notes": [
{
"title": "Velociraptor deployment"
},
{
"title": "Assets collected",
"content": "# Assets collected\n\n# Assets not collected"
}
]
}
]
}
</pre>
<h4>Field types</h4>
The supported fields types are:
<ul>
<li>name: The name of the case template (required).</li>
<li>display_name: The displayed name of the case template.</li>
<li>description: The description of the case template.</li>
<li>author: The author of the case template (not related to the current user).</li>
<li>title_prefix: A prefix to add to case title.</li>
<li>summary: content to prefill the summary.</li>
<li>tags: A list of case tags.</li>
<li>tasks: A list of dictionaries defining tasks. Tasks are defined by title (required), description, and list of tags.</li>
<li>note_groups: A list of dictionaries defining note groups. Note groups are defined by title (required), and list of notes. Notes have title (required) and content</li>
</ul>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="placeholder">Choose JSON file to import : </label>
<input id="input_upload_case_template" type="file" accept="text/json">
</div>
</div>
<div class='invalid-feedback' id='ctempl-invalid-msg'></div>
</div><!-- /.modal-content -->
</form>
</div>
<div class="alert alert-warning" style="display:none;" role="alert" id="alert_upload_case_template_details">
<span id="alert_upload_case_template"></span><br/>
<b>Logs:</b>
<ul id="upload_case_template_err_details_list">
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-success" onclick="upload_case_template();">Upload</button>
</div>