Skip to content

Commit

Permalink
Fix right access check on dashboards
Browse files Browse the repository at this point in the history
- Prevent anonymous access to dashboard cards
- Enhance rights checks on dashboard front files
- Add rights checks on dashboard AJAX endpoints
- Ensure new dashboard is private by default
  • Loading branch information
cedric-anne authored and trasher committed Jul 5, 2023
1 parent 84f2028 commit 6fcdcba
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 48 deletions.
107 changes: 98 additions & 9 deletions ajax/dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,43 +45,71 @@
$request_data = array_merge($_REQUEST, json_decode($_UREQUEST['data'] ?? '{}', true));
unset($request_data['data']);

if (!isset($request_data['embed']) || !$request_data['embed']) {
Session::checkLoginUser();
} else if (
!in_array($_REQUEST['action'], [
'get_dashboard_items',
'get_card',
'get_cards'
])
$embed = false;
if (
in_array($_REQUEST['action'], ['get_dashboard_items', 'get_card', 'get_cards'])
&& array_key_exists('embed', $request_data)
&& (bool)$request_data['embed']
) {
Html::displayRightError();
if (Grid::checkToken($request_data) === false) {
http_response_code(403);
exit;
}
$embed = true;
} else {
Session::checkLoginUser();
}

$dashboard = new Glpi\Dashboard\Dashboard($_REQUEST['dashboard'] ?? "");

switch ($_POST['action'] ?? null) {
case 'save_new_dashboard':
if (!Session::haveRight('dashboard', CREATE)) {
http_response_code(403);
exit();
}

echo $dashboard->saveNew(
$_POST['title'] ?? "",
$_POST['context'] ?? ""
);
exit;

case 'save_items':
if (!$dashboard->canUpdateCurrent()) {
http_response_code(403);
exit();
}

$dashboard->saveitems($_POST['items'] ?? []);
$dashboard->saveTitle($_POST['title'] ?? "");
exit;

case 'save_rights':
if (!$dashboard->canUpdateCurrent()) {
http_response_code(403);
exit();
}

$dashboard->setPrivate($_POST['is_private'] != '0');
$dashboard->saveRights($_POST['rights'] ?? []);
exit;

case 'save_filter_data':
if (!$dashboard->canViewCurrent()) {
http_response_code(403);
exit();
}

$dashboard->saveFilter($_POST['filters'] ?? []);
exit;

case 'delete_dashboard':
if (!$dashboard->canDeleteCurrent()) {
http_response_code(403);
exit();
}

echo $dashboard->delete(['key' => $_POST['dashboard']]);
exit;

Expand All @@ -91,13 +119,23 @@
exit;

case 'clone_dashboard':
if (!Session::haveRight('dashboard', CREATE) || !$dashboard->canViewCurrent()) {
http_response_code(403);
exit();
}

$new_dashboard = $dashboard->cloneCurrent();
echo json_encode($new_dashboard);
exit;
}

switch ($_GET['action'] ?? null) {
case 'get_filter_data':
if (!$dashboard->canViewCurrent()) {
http_response_code(403);
exit();
}

echo $dashboard->getFilter();
exit;
}
Expand All @@ -107,28 +145,59 @@
header("Content-Type: text/html; charset=UTF-8");
switch ($_REQUEST['action']) {
case 'add_new':
if (!Session::haveRight('dashboard', CREATE)) {
http_response_code(403);
exit();
}

$grid->displayAddDashboardForm();
break;

case 'edit_rights':
// FIXME This endpoint does not seems to be used.
if (!Session::haveRight('dashboard', UPDATE)) {
http_response_code(403);
exit();
}

$grid->displayEditRightsForm();
break;

case 'display_edit_widget':
case 'display_add_widget':
if (!$dashboard->canUpdateCurrent()) {
http_response_code(403);
exit();
}

$grid->displayWidgetForm($_REQUEST);
break;

case 'display_embed_form':
if (!Session::haveRight('dashboard', UPDATE)) {
http_response_code(403);
exit();
}

$grid->displayEmbedForm();
break;

case 'get_card':
if (!$dashboard->canViewCurrent() && !$embed) {
http_response_code(403);
exit();
}

Session::writeClose();
echo $grid->getCardHtml($_REQUEST['card_id'], $_REQUEST);
break;

case 'get_cards':
if (!$dashboard->canViewCurrent() && !$embed) {
http_response_code(403);
exit();
}

Session::writeClose();
header("Content-Type: application/json; charset=UTF-8");
$cards = $request_data['cards'];
Expand All @@ -148,16 +217,36 @@
break;

case 'display_add_filter':
if (!$dashboard->canUpdateCurrent()) {
http_response_code(403);
exit();
}

$grid->displayFilterForm($_REQUEST);
break;
case 'get_dashboard_filters':
if (!Session::haveRight('dashboard', READ)) {
http_response_code(403);
exit();
}

echo $grid->getFiltersSetHtml($_REQUEST['filters'] ?? []);
break;
case 'get_filter':
if (!Session::haveRight('dashboard', READ)) {
http_response_code(403);
exit();
}

echo $grid->getFilterHtml($_REQUEST['filter_id']);
break;

case 'get_dashboard_items':
if (!$dashboard->canViewCurrent() && !$embed) {
http_response_code(403);
exit();
}

echo $grid->getGridItemsHtml(true, $_REQUEST['embed'] ?? false);
break;
}
16 changes: 9 additions & 7 deletions front/dashboard_assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,10 @@
* ---------------------------------------------------------------------
*/

/**
* Filename was previously states.php
* @since 0.84
*/
use Glpi\Dashboard\Dashboard;

include('../inc/includes.php');


Session::checkCentralAccess();
$default = Glpi\Dashboard\Grid::getDefaultDashboardForMenu('assets');

Expand All @@ -49,9 +45,15 @@
Html::redirect($CFG_GLPI["root_doc"] . "/front/computer.php");
}

$dashboard = new Dashboard($default);
if (!$dashboard->canViewCurrent()) {
Html::displayRightError();
exit();
}

Html::header(__('Assets Dashboard'), $_SERVER['PHP_SELF'], "assets", "dashboard");

$dashboard = new Glpi\Dashboard\Grid($default);
$dashboard->showDefault();
$grid = new Glpi\Dashboard\Grid($default);
$grid->showDefault();

Html::footer();
15 changes: 9 additions & 6 deletions front/dashboard_helpdesk.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@
* ---------------------------------------------------------------------
*/

/**
* Filename was previously states.php
* @since 0.84
*/
use Glpi\Dashboard\Dashboard;

include('../inc/includes.php');

Expand All @@ -49,9 +46,15 @@
Html::redirect($CFG_GLPI["root_doc"] . "/front/ticket.php");
}

$dashboard = new Dashboard($default);
if (!$dashboard->canViewCurrent()) {
Html::displayRightError();
exit();
}

Html::header(__('Helpdesk Dashboard'), $_SERVER['PHP_SELF'], "helpdesk", "dashboard");

$dashboard = new Glpi\Dashboard\Grid($default);
$dashboard->showDefault();
$grid = new Glpi\Dashboard\Grid($default);
$grid->showDefault();

Html::footer();
61 changes: 46 additions & 15 deletions js/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class GLPIDashboard {
cell_margin: 5,
rand: '',
embed: false,
token: null,
entities_id: null,
is_recursive:null,
ajax_cards: true,
all_cards: [],
context: "core"
Expand All @@ -98,6 +101,9 @@ class GLPIDashboard {
this.elem_dom = this.element[0];
this.current_name = $(this.elem_id+' .dashboard_select').val() || options.current;
this.embed = options.embed;
this.token = options.token;
this.entities_id = options.entities_id;
this.is_recursive = options.is_recursive;
this.ajax_cards = options.ajax_cards;
this.all_cards = options.all_cards;
this.all_widgets = options.all_widgets;
Expand Down Expand Up @@ -336,6 +342,7 @@ class GLPIDashboard {
url: CFG_GLPI.root_doc+"/ajax/dashboard.php",
params: {
action: 'display_edit_widget',
dashboard: that.current_name,
gridstack_id: item.attr('gs-id'),
card_id: card_opt.card_id,
x: item.attr('gs-x'),
Expand All @@ -356,6 +363,7 @@ class GLPIDashboard {
url: CFG_GLPI.root_doc+"/ajax/dashboard.php",
params: {
action: 'display_add_widget',
dashboard: that.current_name,
x: add_ctrl.data('x'),
y: add_ctrl.data('y')
},
Expand All @@ -381,6 +389,7 @@ class GLPIDashboard {
url: CFG_GLPI.root_doc+"/ajax/dashboard.php",
params: {
action: 'display_add_filter',
dashboard: that.current_name,
used: filter_names
},
});
Expand Down Expand Up @@ -637,13 +646,20 @@ class GLPIDashboard {
var gridstack = $(this.elem_id+" .grid-stack");
this.grid.removeAll();

let data = {
dashboard: this.current_name,
action: 'get_dashboard_items',
};
if (this.embed) {
data.embed = 1;
data.token = this.token;
data.entities_id = this.entities_id;
data.is_recursive = this.is_recursive;
}

$.get({
url: CFG_GLPI.root_doc+"/ajax/dashboard.php",
data: {
dashboard: this.current_name,
action: 'get_dashboard_items',
embed: (this.embed ? 1 : 0),
}
data: data
}).done(function(html) {
gridstack.prepend(html);
gridstack.find('.grid-stack-item').each(function() {
Expand Down Expand Up @@ -1024,16 +1040,24 @@ class GLPIDashboard {
const promises = [];
requested_cards.forEach(function(requested_card) {
const card = requested_card.card_el;
promises.push($.get(CFG_GLPI.root_doc+"/ajax/dashboard.php", {

let data = {
'action': 'get_card',
'dashboard': that.current_name,
'card_id': requested_card.card_id,
'force': force,
'embed': (that.embed ? 1 : 0),
'args': requested_card.args,
'd_cache_key': that.cache_key,
'c_cache_key': requested_card.args.cache_key || ""
}).then(function(html) {
};
if (that.embed) {
data.embed = 1;
data.token = that.token;
data.entities_id = that.entities_id;
data.is_recursive = that.is_recursive;
}

promises.push($.get(CFG_GLPI.root_doc+"/ajax/dashboard.php", data).then(function(html) {
card.children('.grid-stack-item-content').html(html);

that.fitNumbers(card);
Expand All @@ -1046,18 +1070,25 @@ class GLPIDashboard {
return promises;
} else {
// Single ajax mode, spawn a single request
let data = {
'dashboard': this.current_name,
'force': (specific_one.length > 0 ? 1 : 0),
'd_cache_key': this.cache_key,
'cards': card_ajax_data
};
if (this.embed) {
data.embed = 1;
data.token = this.token;
data.entities_id = this.entities_id;
data.is_recursive = this.is_recursive;
}

return $.ajax({
url:CFG_GLPI.root_doc+"/ajax/dashboard.php",
method: 'POST',
data: {
'action': 'get_cards',
data: JSON.stringify({ //Preserve integers
'dashboard': this.current_name,
'force': (specific_one.length > 0 ? 1 : 0),
'embed': (this.embed ? 1 : 0),
'd_cache_key': this.cache_key,
'cards': card_ajax_data
})
data: JSON.stringify(data)
}
}).then(function(results) {
$.each(requested_cards, (i2, crd) => {
Expand Down
Loading

0 comments on commit 6fcdcba

Please sign in to comment.