Skip to content
This repository has been archived by the owner on Dec 13, 2022. It is now read-only.

fix(conf): prevent timeperiod to call itself via templates #7024

Merged
merged 4 commits into from
Dec 14, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/Centreon/Domain/Repository/TimePeriodRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,36 @@ public function getChainByParant($id, &$result)

return $result;
}

/**
* Get chain of included templates
*
* @param int $id
jdelpierre marked this conversation as resolved.
Show resolved Hide resolved
* @param array $result
* @return array
*/
public function getIncludeChainByParant($id, &$result)
vhr marked this conversation as resolved.
Show resolved Hide resolved
{
$sql = <<<SQL
SELECT
vhr marked this conversation as resolved.
Show resolved Hide resolved
t.timeperiod_include_id AS `id`
FROM timeperiod_include_relations AS t
WHERE t.timeperiod_include_id IS NOT NULL AND t.timeperiod_id = :id
GROUP BY t.timeperiod_include_id
SQL;
$stmt = $this->db->prepare($sql);
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();

while ($row = $stmt->fetch()) {
$isExisting = array_key_exists($row['id'], $result);
$result[$row['id']] = $row['id'];

if (!$isExisting) {
$this->getChainByParant($row['id'], $result);
jdelpierre marked this conversation as resolved.
Show resolved Hide resolved
}
}

return $result;
}
}
61 changes: 44 additions & 17 deletions www/api/class/centreon_configuration_timeperiod.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

class CentreonConfigurationTimeperiod extends CentreonConfigurationObjects
{

/**
* CentreonConfigurationTimeperiod constructor.
*/
Expand All @@ -53,42 +54,68 @@ public function __construct()
*/
public function getList()
jdelpierre marked this conversation as resolved.
Show resolved Hide resolved
{
$queryValues = array();
$queryWhere = $queryValues = [];

// Check for select2 'q' argument
if (isset($this->arguments['q'])) {
$queryValues['name'] = '%' . (string)$this->arguments['q'] . '%';
} else {
$queryValues['name'] = '%%';
$queryWhere[] = 'tp_name LIKE :name';
$queryValues['name'] = [
PDO::PARAM_STR => "%{$this->arguments['q']}%",
];
}

// exclude some values from the result
if (isset($this->arguments['exclude'])) {
$queryWhere[] = 'tp_id <> :exclude';
$queryValues['exclude'] = [
PDO::PARAM_INT => (int) $this->arguments['exclude'],
];
}

$queryTimePeriod = 'SELECT SQL_CALC_FOUND_ROWS DISTINCT tp_id, tp_name FROM timeperiod ' .
'WHERE tp_name LIKE :name ' .
($queryWhere ? "WHERE " . join(' AND ', $queryWhere) : '') .
' ' .
jdelpierre marked this conversation as resolved.
Show resolved Hide resolved
'ORDER BY tp_name ';

if (isset($this->arguments['page_limit']) && isset($this->arguments['page'])) {
if (!is_numeric($this->arguments['page']) || !is_numeric($this->arguments['page_limit'])) {
throw new \RestBadRequestException('Error, limit must be numerical');
}

$offset = ($this->arguments['page'] - 1) * $this->arguments['page_limit'];

$queryTimePeriod .= 'LIMIT :offset, :limit';
$queryValues['offset'] = (int)$offset;
$queryValues['limit'] = (int)$this->arguments['page_limit'];

$queryValues['offset'] = [
PDO::PARAM_INT => (int) $offset,
];
$queryValues['limit'] = [
PDO::PARAM_INT => (int) $this->arguments['page_limit'],
];
}

$stmt = $this->pearDB->prepare($queryTimePeriod);
$stmt->bindParam(':name', $queryValues['name'], PDO::PARAM_STR);
if (isset($queryValues['offset'])) {
$stmt->bindParam(':offset', $queryValues["offset"], PDO::PARAM_INT);
$stmt->bindParam(':limit', $queryValues["limit"], PDO::PARAM_INT);

foreach ($queryValues as $bindId => $bindData) {
foreach ($bindData as $bindType => $bindValue) {
$stmt->bindValue($bindId, $bindValue, $bindType);
break;
}
}

$stmt->execute();
$timePeriodList = array();
$timePeriodList = [];

while ($data = $stmt->fetch()) {
$timePeriodList[] = array(
$timePeriodList[] = [
'id' => $data['tp_id'],
'text' => html_entity_decode($data['tp_name']),
);
];
}
return array(

return [
'items' => $timePeriodList,
'total' => $stmt->rowCount()
);
'total' => $stmt->rowCount(),
];
}
}
60 changes: 60 additions & 0 deletions www/include/configuration/configObject/timeperiod/DB-Func.php
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,63 @@ function getTimeperiodIdByName($name)
}
return $id;
}

/**
* Get chain of time periods via template relation
*
* @global \Pimple\Container $dependencyInjector
* @param array $tpIds
* @param array $result
* @return array
*/
jdelpierre marked this conversation as resolved.
Show resolved Hide resolved
function getTimeperiodsFromTemplate(array $tpIds, array $result = null)
{
global $dependencyInjector;

$db = $dependencyInjector['centreon.db-manager'];

$result = [];

foreach ($tpIds as $tpId) {
$db
->getRepository(Centreon\Domain\Repository\TimePeriodRepository::class)
->getIncludeChainByParant($tpId, $result)
;
jdelpierre marked this conversation as resolved.
Show resolved Hide resolved
}

return $result;
}

/**
* Validator prevent loops via template
*
* @global \HTML_QuickFormCustom $form
* @param array $value
* @return boolean
*/
jdelpierre marked this conversation as resolved.
Show resolved Hide resolved
function testTemplateLoop($value)
{
// skip check if template field is empty
if (!$value) {
return true;
}

global $form;

$data = $form->getSubmitValues();

// skip check if timeperiod is new
if (!$data['tp_id']) {
return true;
} elseif (in_array($data['tp_id'], $value)) {
// try to skip heavy check of templates

return false;
} elseif (in_array($data['tp_id'], getTimeperiodsFromTemplate($value))) {
// get list of all timeperiods related via templates

return false;
}

return true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@
$eTemplate = '<table><tr><td><div class="ams">{label_2}</div>{unselected}</td><td align="center">{add}<br /><br />'
. '<br />{remove}</td><td><div class="ams">{label_3}</div>{selected}</td></tr></table>';

$timeAvRoute = './include/common/webServices/rest/internal.php?object=centreon_configuration_timeperiod&action=list';
$timeAvRoute = './include/common/webServices/rest/internal.php?object=centreon_configuration_timeperiod&action=list' .
($tp_id ? "&exclude={$tp_id}" : '') // exclude this timeperiod from list
;
$attrTimeperiods = array(
'datasourceOrigin' => 'ajax',
'availableDatasetRoute' => $timeAvRoute,
Expand Down Expand Up @@ -200,6 +202,12 @@ function myReplace()
$form->addRule('tp_friday', _('Error in hour definition'), 'format');
$form->addRule('tp_saturday', _('Error in hour definition'), 'format');

/*
* Check for template loops
*/
$form->registerRule('templateLoop', 'callback', 'testTemplateLoop');
$form->addRule('tp_include', _('The selected template has the same time period as a template'), 'templateLoop');

$form->setRequiredNote("<font style='color: red;'>*</font>&nbsp;" . _("Required fields"));

/*
Expand Down