Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrejs Verza <andrejs.verza@zabbix.com>2022-03-07 15:53:35 +0300
committerAndrejs Verza <andrejs.verza@zabbix.com>2022-03-07 17:41:04 +0300
commit701e98671d8ec71fb60cf4f7a12630e469c809c2 (patch)
tree4792a702f9d9998333658f702fef935312c93f71
parente3b8d15622633521bed8056b38667be926ca43b4 (diff)
..F....... [ZBX-19583] unified date format across datepickers
Merge in ZBX/zabbix from feature/ZBX-19583-6.0 to release/6.0 * commit 'aee2b261169543db8c3562e54e5fb64e4269e6cf': .......... [ZBX-19583] updated unit tests ..F....... [ZBX-19583] added uint64 input validation rule ..F....... [ZBX-19583] fixed typos ..F....... [ZBX-19583] fixed undefined index errors in forged requests ..F....... [ZBX-19583] fixed absolute time parser .......... [ZBX-19583] added new test cases for CAbsoluteTimeParser class .......... [ZBX-19583] added new test cases for CValidationRule class ..F....... [ZBX-19583] unified date format across datepickers (cherry picked from commit 6519662e85d65e77fbd74360837610241c9d6630)
-rw-r--r--ChangeLog.d/bugfix/ZBX-195831
-rw-r--r--ui/app/controllers/CControllerTokenCreate.php51
-rw-r--r--ui/app/controllers/CControllerTokenEdit.php2
-rw-r--r--ui/app/controllers/CControllerTokenUpdate.php48
-rw-r--r--ui/app/controllers/CControllerUserTokenEdit.php2
-rw-r--r--ui/app/views/administration.token.edit.php2
-rw-r--r--ui/app/views/administration.user.token.edit.php2
-rw-r--r--ui/include/classes/parsers/CAbsoluteTimeParser.php15
-rw-r--r--ui/include/classes/parsers/CValidationRule.php91
-rw-r--r--ui/include/classes/validators/CNewValidator.php49
-rw-r--r--ui/tests/unit/include/classes/parsers/CAbsoluteTimeParserTest.php17
-rw-r--r--ui/tests/unit/include/classes/parsers/CValidationRuleTest.php15
12 files changed, 251 insertions, 44 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-19583 b/ChangeLog.d/bugfix/ZBX-19583
new file mode 100644
index 00000000000..cd097dd4572
--- /dev/null
+++ b/ChangeLog.d/bugfix/ZBX-19583
@@ -0,0 +1 @@
+..F....... [ZBX-19583] unified date format across datepickers (averza)
diff --git a/ui/app/controllers/CControllerTokenCreate.php b/ui/app/controllers/CControllerTokenCreate.php
index 58efb9cc7f0..06649cc245a 100644
--- a/ui/app/controllers/CControllerTokenCreate.php
+++ b/ui/app/controllers/CControllerTokenCreate.php
@@ -27,16 +27,46 @@ class CControllerTokenCreate extends CController {
'description' => 'db token.description',
'userid' => 'db users.userid|required',
'expires_state' => 'in 0,1|required',
- 'expires_at' => 'range_time',
+ 'expires_at' => 'abs_time',
'status' => 'db token.status|required|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED,
'action_src' => 'fatal|required|in token.edit,user.token.edit',
'action_dst' => 'fatal|required|in token.view,user.token.view'
];
+ $validation_result = self::VALIDATION_OK;
+
$ret = $this->validateInput($fields);
+ if ($ret) {
+ $fields = [];
+
+ if ($this->getInput('expires_state') == 1) {
+ $fields['expires_at'] = 'required';
+ }
+
+ if ($fields) {
+ $validator = new CNewValidator($this->getInputAll(), $fields);
+
+ foreach ($validator->getAllErrors() as $error) {
+ info($error);
+ }
+
+ if ($validator->isErrorFatal()) {
+ $validation_result = self::VALIDATION_FATAL_ERROR;
+ }
+ elseif ($validator->isError()) {
+ $validation_result = self::VALIDATION_ERROR;
+ }
+
+ $ret = $validation_result == self::VALIDATION_OK;
+ }
+ }
+ else {
+ $validation_result = $this->getValidationError();
+ }
+
if (!$ret) {
- switch ($this->getValidationError()) {
+ switch ($validation_result) {
case self::VALIDATION_ERROR:
$location = (new CUrl('zabbix.php'))->setArgument('action', $this->getInput('action_src'));
$response = new CControllerResponseRedirect($location);
@@ -61,12 +91,23 @@ class CControllerTokenCreate extends CController {
return $this->checkAccess(CRoleHelper::ACTIONS_MANAGE_API_TOKENS);
}
+ /**
+ * @throws Exception
+ */
protected function doAction() {
$this->getInputs($token, ['name', 'description', 'userid', 'expires_at', 'status']);
- $token['expires_at'] = $this->getInput('expires_state')
- ? (new DateTime($token['expires_at']))->getTimestamp()
- : 0;
+ if ($this->getInput('expires_state')) {
+ $parser = new CAbsoluteTimeParser();
+ $parser->parse($token['expires_at']);
+
+ $token['expires_at'] = $parser
+ ->getDateTime(true)
+ ->getTimestamp();
+ }
+ else {
+ $token['expires_at'] = 0;
+ }
$result = API::Token()->create($token);
diff --git a/ui/app/controllers/CControllerTokenEdit.php b/ui/app/controllers/CControllerTokenEdit.php
index 405a44d822a..608a96920b5 100644
--- a/ui/app/controllers/CControllerTokenEdit.php
+++ b/ui/app/controllers/CControllerTokenEdit.php
@@ -69,7 +69,7 @@ class CControllerTokenEdit extends CController {
$data = $tokens[0];
if ($data['expires_at'] != 0) {
- $data['expires_at'] = date(DATE_TIME_FORMAT_SECONDS, (int) $data['expires_at']);
+ $data['expires_at'] = date(ZBX_FULL_DATE_TIME, (int) $data['expires_at']);
$data['expires_state'] = '1';
}
else {
diff --git a/ui/app/controllers/CControllerTokenUpdate.php b/ui/app/controllers/CControllerTokenUpdate.php
index 052c0a59ef2..10f1de673cd 100644
--- a/ui/app/controllers/CControllerTokenUpdate.php
+++ b/ui/app/controllers/CControllerTokenUpdate.php
@@ -27,17 +27,47 @@ class CControllerTokenUpdate extends CController {
'name' => 'db token.name|required|not_empty',
'description' => 'db token.description',
'expires_state' => 'in 0,1|required',
- 'expires_at' => 'range_time',
+ 'expires_at' => 'abs_time',
'status' => 'db token.status|required|in '.ZBX_AUTH_TOKEN_ENABLED.','.ZBX_AUTH_TOKEN_DISABLED,
'action_src' => 'fatal|required|in token.edit,user.token.edit',
'action_dst' => 'fatal|required|in token.list,user.token.list,token.view,user.token.view',
'regenerate' => 'in 1'
];
+ $validation_result = self::VALIDATION_OK;
+
$ret = $this->validateInput($fields);
+ if ($ret) {
+ $fields = [];
+
+ if ($this->getInput('expires_state') == 1) {
+ $fields['expires_at'] = 'required';
+ }
+
+ if ($fields) {
+ $validator = new CNewValidator($this->getInputAll(), $fields);
+
+ foreach ($validator->getAllErrors() as $error) {
+ info($error);
+ }
+
+ if ($validator->isErrorFatal()) {
+ $validation_result = self::VALIDATION_FATAL_ERROR;
+ }
+ elseif ($validator->isError()) {
+ $validation_result = self::VALIDATION_ERROR;
+ }
+
+ $ret = $validation_result == self::VALIDATION_OK;
+ }
+ }
+ else {
+ $validation_result = $this->getValidationError();
+ }
+
if (!$ret) {
- switch ($this->getValidationError()) {
+ switch ($validation_result) {
case self::VALIDATION_ERROR:
$location = (new CUrl('zabbix.php'))
->setArgument('tokenid', $this->getInput('tokenid'))
@@ -67,9 +97,17 @@ class CControllerTokenUpdate extends CController {
protected function doAction() {
$this->getInputs($token, ['tokenid', 'name', 'description', 'expires_at', 'status']);
- $token['expires_at'] = $this->getInput('expires_state')
- ? (new DateTime($token['expires_at']))->getTimestamp()
- : 0;
+ if ($this->getInput('expires_state')) {
+ $parser = new CAbsoluteTimeParser();
+ $parser->parse($token['expires_at']);
+
+ $token['expires_at'] = $parser
+ ->getDateTime(true)
+ ->getTimestamp();
+ }
+ else {
+ $token['expires_at'] = 0;
+ }
$result = API::Token()->update($token);
diff --git a/ui/app/controllers/CControllerUserTokenEdit.php b/ui/app/controllers/CControllerUserTokenEdit.php
index 881689869bb..a84d7dd5f31 100644
--- a/ui/app/controllers/CControllerUserTokenEdit.php
+++ b/ui/app/controllers/CControllerUserTokenEdit.php
@@ -66,7 +66,7 @@ class CControllerUserTokenEdit extends CController {
$data = $tokens[0];
if ($data['expires_at'] != 0) {
- $data['expires_at'] = date(DATE_TIME_FORMAT_SECONDS, (int) $data['expires_at']);
+ $data['expires_at'] = date(ZBX_FULL_DATE_TIME, (int) $data['expires_at']);
$data['expires_state'] = '1';
}
else {
diff --git a/ui/app/views/administration.token.edit.php b/ui/app/views/administration.token.edit.php
index cf54131a865..52b7ed0c26a 100644
--- a/ui/app/views/administration.token.edit.php
+++ b/ui/app/views/administration.token.edit.php
@@ -81,7 +81,7 @@ $token_from_list = (new CFormList())
)
->addRow((new CLabel(_('Expires at')))->setAsteriskMark(),
(new CDateSelector('expires_at', $data['expires_at']))
- ->setDateFormat(DATE_TIME_FORMAT_SECONDS)
+ ->setDateFormat(ZBX_FULL_DATE_TIME)
->setPlaceholder(_('YYYY-MM-DD hh:mm:ss'))
->setAriaRequired(),
'expires-at-row'
diff --git a/ui/app/views/administration.user.token.edit.php b/ui/app/views/administration.user.token.edit.php
index 0cf6d3c2e28..9193b1185ab 100644
--- a/ui/app/views/administration.user.token.edit.php
+++ b/ui/app/views/administration.user.token.edit.php
@@ -62,7 +62,7 @@ $token_from_list = (new CFormList())
)
->addRow((new CLabel(_('Expires at')))->setAsteriskMark(),
(new CDateSelector('expires_at', $data['expires_at']))
- ->setDateFormat(DATE_TIME_FORMAT_SECONDS)
+ ->setDateFormat(ZBX_FULL_DATE_TIME)
->setPlaceholder(_('YYYY-MM-DD hh:mm:ss'))
->setAriaRequired(),
'expires-at-row'
diff --git a/ui/include/classes/parsers/CAbsoluteTimeParser.php b/ui/include/classes/parsers/CAbsoluteTimeParser.php
index ea7d847267b..b7c0ba271a4 100644
--- a/ui/include/classes/parsers/CAbsoluteTimeParser.php
+++ b/ui/include/classes/parsers/CAbsoluteTimeParser.php
@@ -106,19 +106,20 @@ class CAbsoluteTimeParser extends CParser {
}
/**
- * Returns date in "YYYY-MM-DD hh:mm:ss" format.
+ * Get DateTime object with its value set to either start or end of the period derived from the date/time specified.
*
- * @param bool $is_start If set to true date will be modified to lowest value, example "2018" will be returned
- * as "2018-01-01 00:00:00", otherwise "2018-12-31 23:59:59".
+ * @param $is_start
+ * @param DateTimeZone|null $timezone
*
+ * @throws Exception
* @return DateTime|null
*/
- public function getDateTime($is_start) {
+ public function getDateTime($is_start, DateTimeZone $timezone = null) {
if ($this->date === '') {
return null;
}
- $date = new DateTime($this->date);
+ $date = new DateTime($this->date, $timezone);
if ($is_start) {
return $date;
@@ -137,11 +138,11 @@ class CAbsoluteTimeParser extends CParser {
}
if (!array_key_exists('i', $this->tokens)) {
- return new DateTime($date->format('Y-m-d H:59:59'));
+ return new DateTime($date->format('Y-m-d H:59:59'), $timezone);
}
if (!array_key_exists('s', $this->tokens)) {
- return new DateTime($date->format('Y-m-d H:i:59'));
+ return new DateTime($date->format('Y-m-d H:i:59'), $timezone);
}
return $date;
diff --git a/ui/include/classes/parsers/CValidationRule.php b/ui/include/classes/parsers/CValidationRule.php
index 313d0287899..b0e9f9ad4d2 100644
--- a/ui/include/classes/parsers/CValidationRule.php
+++ b/ui/include/classes/parsers/CValidationRule.php
@@ -42,7 +42,6 @@ class CValidationRule {
$pos = 0;
$state = self::STATE_BEGIN;
$rules = [];
- $is_empty = true;
while (isset($buffer[$pos])) {
switch ($state) {
@@ -53,28 +52,30 @@ class CValidationRule {
break;
default:
- $is_empty = false;
$rule = [];
- if (!$this->parseString($buffer, $pos, $rule) // string
- && !$this->parseRangeTime($buffer, $pos, $rule) // range time
- && !$this->parseTimePeriods($buffer, $pos, $rule) // time periods
- && !$this->parseTimeUnit($buffer, $pos, $rule) // time unit
- && !$this->parseRgb($buffer, $pos, $rule) // rgb
- && !$this->parseRequired($buffer, $pos, $rule) // required
- && !$this->parseNotEmpty($buffer, $pos, $rule) // not_empty
- && !$this->parseLE($buffer, $pos, $rule) // le
- && !$this->parseJson($buffer, $pos, $rule) // json
- && !$this->parseInt32($buffer, $pos, $rule) // int32
- && !$this->parseIn($buffer, $pos, $rule) // in
- && !$this->parseId($buffer, $pos, $rule) // id
- && !$this->parseGE($buffer, $pos, $rule) // ge
- && !$this->parseFatal($buffer, $pos, $rule) // fatal
- && !$this->parseDB($buffer, $pos, $rule) // db
- && !$this->parseArrayId($buffer, $pos, $rule) // array_id
- && !$this->parseArrayDB($buffer, $pos, $rule) // array_db
- && !$this->parseArray($buffer, $pos, $rule) // array
- && !$this->parseFlags($buffer, $pos, $rule)) { // flags
+ if (!$this->parseString($buffer, $pos, $rule)
+ && !$this->parseRangeTime($buffer, $pos, $rule)
+ && !$this->parseAbsDate($buffer, $pos, $rule)
+ && !$this->parseAbsTime($buffer, $pos, $rule)
+ && !$this->parseTimePeriods($buffer, $pos, $rule)
+ && !$this->parseTimeUnit($buffer, $pos, $rule)
+ && !$this->parseRgb($buffer, $pos, $rule)
+ && !$this->parseRequired($buffer, $pos, $rule)
+ && !$this->parseNotEmpty($buffer, $pos, $rule)
+ && !$this->parseLE($buffer, $pos, $rule)
+ && !$this->parseJson($buffer, $pos, $rule)
+ && !$this->parseInt32($buffer, $pos, $rule)
+ && !$this->parseUInt64($buffer, $pos, $rule)
+ && !$this->parseIn($buffer, $pos, $rule)
+ && !$this->parseId($buffer, $pos, $rule)
+ && !$this->parseGE($buffer, $pos, $rule)
+ && !$this->parseFatal($buffer, $pos, $rule)
+ && !$this->parseDB($buffer, $pos, $rule)
+ && !$this->parseArrayId($buffer, $pos, $rule)
+ && !$this->parseArrayDB($buffer, $pos, $rule)
+ && !$this->parseArray($buffer, $pos, $rule)
+ && !$this->parseFlags($buffer, $pos, $rule)) {
// incorrect validation rule
break 3;
}
@@ -175,6 +176,38 @@ class CValidationRule {
}
/**
+ * abs_date
+ *
+ * 'abs_date' => true
+ */
+ private function parseAbsDate($buffer, &$pos, &$rules) {
+ if (strncmp(substr($buffer, $pos), 'abs_date', 8) != 0) {
+ return false;
+ }
+
+ $pos += 8;
+ $rules['abs_date'] = true;
+
+ return true;
+ }
+
+ /**
+ * abs_time
+ *
+ * 'abs_time' => true
+ */
+ private function parseAbsTime($buffer, &$pos, &$rules) {
+ if (strncmp(substr($buffer, $pos), 'abs_time', 8) != 0) {
+ return false;
+ }
+
+ $pos += 8;
+ $rules['abs_time'] = true;
+
+ return true;
+ }
+
+ /**
* range_time
*
* 'time_periods' => true
@@ -356,6 +389,22 @@ class CValidationRule {
}
/**
+ * uint64
+ *
+ * 'uint64' => true
+ */
+ private function parseUInt64($buffer, &$pos, &$rules) {
+ if (strncmp(substr($buffer, $pos), 'uint64', 6) != 0) {
+ return false;
+ }
+
+ $pos += 6;
+ $rules['uint64'] = true;
+
+ return true;
+ }
+
+ /**
* in <value1>[,...,<valueN>]
*
* 'in' => array('<value1>', ..., '<valueN>')
diff --git a/ui/include/classes/validators/CNewValidator.php b/ui/include/classes/validators/CNewValidator.php
index 7517951e04e..31324d0e9c2 100644
--- a/ui/include/classes/validators/CNewValidator.php
+++ b/ui/include/classes/validators/CNewValidator.php
@@ -140,6 +140,20 @@ class CNewValidator {
}
break;
+ case 'uint64':
+ if (array_key_exists($field, $this->input)) {
+ if (!is_string($this->input[$field]) || !self::is_uint64($this->input[$field])) {
+ $this->addError($fatal,
+ is_scalar($this->input[$field])
+ ? _s('Incorrect value "%1$s" for "%2$s" field.', $this->input[$field], $field)
+ : _s('Incorrect value for "%1$s" field.', $field)
+ );
+
+ return false;
+ }
+ }
+ break;
+
case 'id':
if (array_key_exists($field, $this->input)) {
if (!is_string($this->input[$field]) || !self::is_id($this->input[$field])) {
@@ -276,6 +290,41 @@ class CNewValidator {
}
break;
+ case 'abs_date':
+ if (array_key_exists($field, $this->input)) {
+ $absolute_time_parser = new CAbsoluteTimeParser();
+
+ $has_errors = !is_string($this->input[$field])
+ || $absolute_time_parser->parse($this->input[$field]) != CParser::PARSE_SUCCESS
+ || $absolute_time_parser->getDateTime(true)->format('H:i:s') !== '00:00:00';
+
+ if ($has_errors) {
+ $this->addError($fatal,
+ _s('Incorrect value for field "%1$s": %2$s.', $field, _('a date is expected'))
+ );
+
+ return false;
+ }
+ }
+ break;
+
+ case 'abs_time':
+ if (array_key_exists($field, $this->input)) {
+ $absolute_time_parser = new CAbsoluteTimeParser();
+
+ $has_errors = !is_string($this->input[$field])
+ || $absolute_time_parser->parse($this->input[$field]) != CParser::PARSE_SUCCESS;
+
+ if ($has_errors) {
+ $this->addError($fatal,
+ _s('Incorrect value for field "%1$s": %2$s.', $field, _('a time is expected'))
+ );
+
+ return false;
+ }
+ }
+ break;
+
/*
* 'time_periods' => true
*/
diff --git a/ui/tests/unit/include/classes/parsers/CAbsoluteTimeParserTest.php b/ui/tests/unit/include/classes/parsers/CAbsoluteTimeParserTest.php
index 25849a80eaa..82966eed277 100644
--- a/ui/tests/unit/include/classes/parsers/CAbsoluteTimeParserTest.php
+++ b/ui/tests/unit/include/classes/parsers/CAbsoluteTimeParserTest.php
@@ -157,6 +157,14 @@ class CAbsoluteTimeParserTest extends TestCase {
'datetime' => ['values' => ['2018-04-01 00:00:00', '2018-04-30 23:59:59']]
],
[
+ '2018-04-15 12:45', 0,
+ [
+ 'rc' => CParser::PARSE_SUCCESS,
+ 'match' => '2018-04-15 12:45'
+ ],
+ 'datetime' => ['values' => ['2018-04-15 12:45:00', '2018-04-15 12:45:59'], 'tz' => 'UTC']
+ ],
+ [
'text', 0,
[
'rc' => CParser::PARSE_FAIL,
@@ -256,9 +264,14 @@ class CAbsoluteTimeParserTest extends TestCase {
]);
$this->assertSame(strlen($expected['match']), $parser->getLength());
- $ts_from = $parser->getDateTime(true);
- $ts_to = $parser->getDateTime(false);
+ $tz = array_key_exists('tz', $datetime) ? new DateTimeZone($datetime['tz']) : null;
+ $ts_from = $parser->getDateTime(true, $tz);
+ $ts_to = $parser->getDateTime(false, $tz);
$this->assertSame($datetime['values'][0], $ts_from !== null ? $ts_from->format('Y-m-d H:i:s') : null);
$this->assertSame($datetime['values'][1], $ts_to !== null ? $ts_to->format('Y-m-d H:i:s') : null);
+ if ($tz !== null) {
+ $this->assertSame($datetime['tz'], $ts_from->getTimeZone()->getName());
+ $this->assertSame($datetime['tz'], $ts_to->getTimeZone()->getName());
+ }
}
}
diff --git a/ui/tests/unit/include/classes/parsers/CValidationRuleTest.php b/ui/tests/unit/include/classes/parsers/CValidationRuleTest.php
index 79ce9115604..350e5dfc82f 100644
--- a/ui/tests/unit/include/classes/parsers/CValidationRuleTest.php
+++ b/ui/tests/unit/include/classes/parsers/CValidationRuleTest.php
@@ -65,6 +65,11 @@ class CValidationRuleTest extends TestCase {
'int32' => true
]
],
+ ['uint64', '',
+ [
+ 'uint64' => true
+ ]
+ ],
['db hosts.name', '',
[
'db' => [
@@ -141,6 +146,16 @@ class CValidationRuleTest extends TestCase {
'range_time' => true
]
],
+ ['abs_date', '',
+ [
+ 'abs_date' => true
+ ]
+ ],
+ ['abs_time', '',
+ [
+ 'abs_time' => true
+ ]
+ ],
['time_unit', '',
[
'time_unit' => []