Skip to content

Commit

Permalink
BF:security on users mgt with CSRF token fix #369
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin BALET committed Jun 6, 2022
1 parent bc0b5d4 commit 299b5a3
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 55 deletions.
4 changes: 1 addition & 3 deletions application/config/routes.php
Expand Up @@ -58,10 +58,8 @@
$route['users/reset/(:num)'] = 'users/reset/$1';
$route['users/create'] = 'users/create';
$route['users/edit/(:num)'] = 'users/edit/$1';
$route['users/delete/(:num)'] = 'users/delete/$1';
$route['users/check/login'] = 'users/checkLoginByAjax';
$route['users/enable/(:num)'] = 'users/enable/$1';
$route['users/disable/(:num)'] = 'users/disable/$1';
$route['users/account']['POST'] = 'users/account';
$route['users'] = 'users';

//_______________________________________________
Expand Down
69 changes: 25 additions & 44 deletions application/controllers/Users.php
Expand Up @@ -46,34 +46,34 @@ public function index() {
}

/**
* Set a user as active (TRUE) or inactive (FALSE)
* @param int $id User identifier
* @param bool $active active (TRUE) or inactive (FALSE)
* Account management (activate/disable/delete) is done by a
* POST request with a CSRF token for an improved security
* @author Benjamin BALET <benjamin.balet@gmail.com>
*/
public function active($id, $active) {
public function account() {
$this->auth->checkIfOperationIsAllowed('list_users');
$this->users_model->setActive($id, $active);
$this->session->set_flashdata('msg', lang('users_edit_flash_msg_success'));
redirect('users');
}

/**
* Enable a user
* @param int $id User identifier
* @author Benjamin BALET <benjamin.balet@gmail.com>
*/
public function enable($id) {
$this->active($id, TRUE);
}

/**
* Disable a user
* @param int $id User identifier
* @author Benjamin BALET <benjamin.balet@gmail.com>
*/
public function disable($id) {
$this->active($id, FALSE);
$id = $this->input->post('id');
$operation = $this->input->post('operation');
//Test if user exists
$data['users_item'] = $this->users_model->getUsers($id);
if (empty($data['users_item'])) {
redirect('notfound');
} else {
switch ($operation) {
case 'enable':
$this->users_model->setActive($id, TRUE);
log_message('error', 'User #' . $id . ' has been enabled by user #' . $this->session->userdata('id'));
break;
case 'disable':
$this->users_model->setActive($id, FALSE);
log_message('error', 'User #' . $id . ' has been disabled by user #' . $this->session->userdata('id'));
break;
case 'delete':
$this->auth->checkIfOperationIsAllowed('delete_user');
$this->users_model->deleteUser($id);
log_message('error', 'User #' . $id . ' has been deleted by user #' . $this->session->userdata('id'));
}
}
}

/**
Expand Down Expand Up @@ -194,25 +194,6 @@ public function edit($id) {
}
}

/**
* Delete a user. Log it as an error.
* @param int $id User identifier
* @author Benjamin BALET <benjamin.balet@gmail.com>
*/
public function delete($id) {
$this->auth->checkIfOperationIsAllowed('delete_user');
//Test if user exists
$data['users_item'] = $this->users_model->getUsers($id);
if (empty($data['users_item'])) {
redirect('notfound');
} else {
$this->users_model->deleteUser($id);
}
log_message('error', 'User #' . $id . ' has been deleted by user #' . $this->session->userdata('id'));
$this->session->set_flashdata('msg', lang('users_delete_flash_msg_success'));
redirect('users');
}

/**
* Reset the password of a user
* Can be accessed by the user itself or by admin
Expand Down
73 changes: 65 additions & 8 deletions application/views/users/index.php
Expand Up @@ -28,20 +28,24 @@
</thead>
<tbody>
<?php foreach ($users as $users_item): ?>
<tr>
<tr data-id="<?php echo $users_item['id']; ?>">
<td data-order="<?php echo $users_item['id']; ?>">
<?php echo $users_item['id'] ?>&nbsp;
<div class="pull-right">
<?php if ($users_item['id'] != $this->session->userdata('id')) { ?>
<?php if ($users_item['active']) { ?>
<a href="<?php echo base_url();?>users/disable/<?php echo $users_item['id'] ?>" title="<?php echo lang('users_index_thead_tip_active');?>"><i class="mdi mdi-account-off nolink"></i></a>
<a href="#" class="action-disable" data-id="<?php echo $users_item['id'];?>" title="<?php echo lang('users_index_thead_tip_active');?>"><i class="mdi mdi-account-off nolink"></i></a>
<?php } else { ?>
<a href="<?php echo base_url();?>users/enable/<?php echo $users_item['id'] ?>" title="<?php echo lang('users_index_thead_tip_inactive');?>"><i class="mdi mdi-account mdi-dark mdi-inactive"></i></a>
<a href="#" class="action-enable" data-id="<?php echo $users_item['id'];?>" title="<?php echo lang('users_index_thead_tip_inactive');?>"><i class="mdi mdi-account mdi-dark mdi-inactive"></i></a>
<?php } ?>
<?php } ?>
&nbsp;
<a href="<?php echo base_url();?>users/edit/<?php echo $users_item['id'] ?>" title="<?php echo lang('users_index_thead_tip_edit');?>"><i class="mdi mdi-account-edit nolink"></i></a>
&nbsp;
<?php if ($users_item['id'] != $this->session->userdata('id')) { ?>
<a href="#" class="confirm-delete" data-id="<?php echo $users_item['id'];?>" title="<?php echo lang('users_index_thead_tip_delete');?>"><i class="mdi mdi-delete nolink"></i></a>
&nbsp;
<?php } ?>
<a href="<?php echo base_url();?>users/reset/<?php echo $users_item['id'] ?>" title="<?php echo lang('users_index_thead_tip_reset');?>" data-target="#frmResetPwd" data-toggle="modal"><i class="mdi mdi-lock nolink"></i></a>
</div>
</td>
Expand Down Expand Up @@ -79,7 +83,7 @@
<p><?php echo lang('users_index_popup_delete_question');?></p>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-danger" id="lnkDeleteUser"><?php echo lang('users_index_popup_delete_button_yes');?></a>
<a href="#" class="btn btn-danger" id="action-delete"><?php echo lang('users_index_popup_delete_button_yes');?></a>
<a href="#" onclick="$('#frmConfirmDelete').modal('hide');" class="btn"><?php echo lang('users_index_popup_delete_button_no');?></a>
</div>
</div>
Expand Down Expand Up @@ -119,11 +123,34 @@

<link href="<?php echo base_url();?>assets/datatable/DataTables-1.10.11/css/jquery.dataTables.min.css" rel="stylesheet">
<script type="text/javascript" src="<?php echo base_url();?>assets/datatable/DataTables-1.10.11/js/jquery.dataTables.min.js"></script>
<script src="<?php echo base_url();?>assets/js/bootbox.min.js"></script>

<script type="text/javascript">
$(document).ready(function() {

<?php if ($this->config->item('csrf_protection') == TRUE) {?>
$.ajaxSetup({
data: {
<?php echo $this->security->get_csrf_token_name();?>: "<?php echo $this->security->get_csrf_hash();?>",
}
});
<?php }?>

//Global Ajax error handling mainly used for session expiration
$( document ).ajaxError(function(event, jqXHR, settings, errorThrown) {
$('#frmModalAjaxWait').modal('hide');
if (jqXHR.status == 401) {
bootbox.alert("<?php echo lang('global_ajax_timeout');?>", function() {
//After the login page, we'll be redirected to the current page
location.reload();
});
} else { //Oups
bootbox.alert("<?php echo lang('global_ajax_error');?>");
}
});

//Transform the HTML table in a fancy datatable
$('#users').dataTable({
oTable = $('#users').DataTable({
stateSave: true,
language: {
decimal: "<?php echo lang('datatable_sInfoThousands');?>",
Expand Down Expand Up @@ -152,10 +179,9 @@
$("#frmResetPwd").alert();
$("#frmImportUsers").alert();

//On showing the confirmation pop-up, add the user id at the end of the delete url action
//On showing the confirmation pop-up, add the user id as an attribute of the delete url link
$('#frmConfirmDelete').on('show', function() {
var link = "<?php echo base_url();?>users/delete/" + $(this).data('id');
$("#lnkDeleteUser").attr('href', link);
$("#action-delete").attr('data-id', $(this).data('id'));
});

//Display a modal pop-up so as to confirm if a user has to be deleted or not
Expand All @@ -166,6 +192,37 @@
$('#frmConfirmDelete').data('id', id).modal('show');
});

//Enable a user
$("#users tbody").on('click', '.action-enable', function(){
var id = $(this).data('id');
var ref = $(this);
$.post( "<?php echo base_url();?>users/account", { operation: "enable", id: id }).done(function() {
ref.attr('class', 'action-disable');
ref.attr('title', '<?php echo lang('users_index_thead_tip_active');?>');
ref.children(":first").attr('class', 'mdi mdi-account-off nolink');
});
});

//Disable a user
$("#users tbody").on('click', '.action-disable', function(){
var id = $(this).data('id');
var ref = $(this);
$.post( "<?php echo base_url();?>users/account", { operation: "disable", id: id }).done(function() {
ref.attr('class', 'action-enable');
ref.attr('title', '<?php echo lang('users_index_thead_tip_inactive');?>');
ref.children(":first").attr('class', 'mdi mdi-account mdi-dark mdi-inactive');
});
});

//Delete a user
$("#action-delete").on('click', function(){
var id = $(this).data('id');
$.post( "<?php echo base_url();?>users/account", { operation: "delete", id: id }).done(function() {
oTable.rows('tr[data-id="' + id + '"]').remove().draw();
$('#frmConfirmDelete').modal('hide');
});
});

//Prevent to load always the same content (refreshed each time)
$('#frmConfirmDelete').on('hidden', function() {
$(this).removeData('modal');
Expand Down

0 comments on commit 299b5a3

Please sign in to comment.