This commit is contained in:
@ -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 %}
|
@ -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 %}
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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">×</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 -->
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
Reference in New Issue
Block a user