Skip to content

Commit

Permalink
An ability to have wildcards in yii\log\Target::$maskVars array yii…
Browse files Browse the repository at this point in the history
  • Loading branch information
xcopy committed Dec 10, 2024
1 parent 4ea0575 commit 6cb2c8b
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 3 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Yii Framework 2 Change Log
- Bug #20140: Fix compatibility with PHP 8.4: calling `session_set_save_handler()` (Izumi-kun)
- New #20185: Add `BackedEnum` support to `AttributeTypecastBehavior` (briedis)
- Bug #17365: Fix "Trying to access array offset on null" warning (xcopy)
- Enh #20295: An ability to have wildcards in `yii\log\Target::$maskVars` array (xcopy)

2.0.51 July 18, 2024
--------------------
Expand Down
58 changes: 55 additions & 3 deletions framework/log/Target.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\helpers\StringHelper;
use yii\helpers\VarDumper;
use yii\web\Request;

Expand Down Expand Up @@ -161,6 +162,54 @@ public function collect($messages, $final)
}
}

/**
* Flattens a multidimensional array into a one-dimensional array.
*
* This method recursively traverses the input array and concatenates the keys
* to form a new key in the resulting array.
*
* Example:
*
* ```php
* $array = [
* 'A' => [1, 2],
* 'B' => [
* 'C' => 1,
* 'D' => 2,
* ],
* 'E' => 1,
* ];
* $result = \yii\log\Target::flatten($array);
* // result will be:
* // [
* // 'A.0' => 1
* // 'A.1' => 2
* // 'B.C' => 1
* // 'B.D' => 2
* // 'E' => 1
* // ]
* ```
*
* @param array $array the input array to be flattened.
* @param string $prefix the prefix to be added to each key in the resulting array.
*
* @return array the flattened array.
*/
private static function flatten($array, $prefix = ''): array
{
$result = [];

foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, self::flatten($value, $prefix . $key . '.'));
} else {
$result[$prefix . $key] = $value;
}
}

return $result;
}

/**
* Generates the context information to be logged.
* The default implementation will dump user information, system variables, etc.
Expand All @@ -169,9 +218,12 @@ public function collect($messages, $final)
protected function getContextMessage()
{
$context = ArrayHelper::filter($GLOBALS, $this->logVars);
$items = self::flatten($context);
foreach ($this->maskVars as $var) {
if (ArrayHelper::getValue($context, $var) !== null) {
ArrayHelper::setValue($context, $var, '***');
foreach ($items as $key => $value) {
if (StringHelper::matchWildcard($var, $key, ['caseSensitive' => false])) {
ArrayHelper::setValue($context, $key, '***');
}
}
}
$result = [];
Expand Down Expand Up @@ -292,7 +344,7 @@ public static function filterMessages($messages, $levels = 0, $categories = [],
*/
public function formatMessage($message)
{
list($text, $level, $category, $timestamp) = $message;
[$text, $level, $category, $timestamp] = $message;
$level = Logger::getLevelName($level);
if (!is_string($text)) {
// exceptions may not be serializable if in the call stack somewhere is a Closure
Expand Down
39 changes: 39 additions & 0 deletions tests/framework/log/TargetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,45 @@ public function testFlushingWithProfilingEnabledAndOverflow()
$logger->log('token.b', Logger::LEVEL_PROFILE_END, 'category');
$logger->log('token.a', Logger::LEVEL_PROFILE_END, 'category');
}

public function testWildcardsInMaskVars()
{
$keys = [
'PASSWORD',
'password',
'password_repeat',
'repeat_password',
'repeat_password_again',
'1password',
'password1',
];

$password = '!P@$$w0rd#';

$items = array_fill_keys($keys, $password);

$GLOBALS['_TEST'] = array_merge(
$items,
['a' => $items],
['b' => ['c' => $items]],
['d' => ['e' => ['f' => $items]]],
);

$target = new TestTarget([
'logVars' => ['_SERVER', '_TEST'],
'maskVars' => [
// option 1: exact value(s)
'_SERVER.DOCUMENT_ROOT',
// option 2: pattern(s)
'_TEST.*password*',
]
]);

$message = $target->getContextMessage();

$this->assertStringContainsString("'DOCUMENT_ROOT' => '***'", $message);
$this->assertStringNotContainsString($password, $message);
}
}

class TestTarget extends Target
Expand Down

0 comments on commit 6cb2c8b

Please sign in to comment.