This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||
2 | /** |
||
3 | * Logger files. |
||
4 | * |
||
5 | * @package App |
||
6 | * |
||
7 | * @copyright YetiForce S.A. |
||
8 | * @license YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com) |
||
9 | * @author Mariusz Krzaczkowski <[email protected]> |
||
10 | */ |
||
11 | |||
12 | namespace App; |
||
13 | |||
14 | use yii\log\Logger; |
||
15 | |||
16 | /** |
||
17 | * Logger class. |
||
18 | */ |
||
19 | class Log extends Logger |
||
20 | { |
||
21 | public static $logToConsole; |
||
22 | public static $logToFile; |
||
23 | public static $logToProfile; |
||
24 | public $logToLevels = 0; |
||
25 | /** |
||
26 | * Column mapping by table for logs owasp. |
||
27 | * |
||
28 | * @var array |
||
29 | */ |
||
30 | public static $owaspColumnMapping = [ |
||
31 | 'access_for_admin' => ['date', 'username', 'ip', 'module', 'url', 'agent', 'request', 'referer'], |
||
32 | 'access_for_api' => ['date', 'username', 'ip', 'url', 'agent', 'request'], |
||
33 | 'access_for_user' => ['date', 'username', 'ip', 'module', 'url', 'agent', 'request', 'referer'], |
||
34 | 'access_to_record' => ['date', 'username', 'ip', 'module', 'record', 'url', 'agent', 'request', 'referer'], |
||
35 | 'csrf' => ['date', 'username', 'ip', 'referer', 'url', 'agent'], |
||
36 | ]; |
||
37 | /** |
||
38 | * Column mapping by table for logs viewer. |
||
39 | * |
||
40 | * @var array |
||
41 | */ |
||
42 | public static $logsViewerColumnMapping = [ |
||
43 | 'magento' => [ |
||
44 | 'label' => 'LBL_MAGENTO', |
||
45 | 6388 | 'labelModule' => 'Settings:Magento', |
|
46 | 'table' => 'l_#__magento', |
||
47 | 6388 | 'icon' => 'yfi-magento', |
|
48 | 6388 | 'columns' => [ |
|
49 | 6388 | 'time' => ['type' => 'DateTime', 'label' => 'LBL_TIME'], |
|
50 | 'category' => ['type' => 'Text', 'label' => 'LBL_CATEGORY'], |
||
51 | 6388 | 'message' => ['type' => 'Text', 'label' => 'LBL_MESSAGE'], |
|
52 | 'code' => ['type' => 'Text', 'label' => 'LBL_CODE'], |
||
53 | 'trace' => ['type' => 'Text', 'label' => 'LBL_BACKTRACE'], |
||
54 | 6388 | ], |
|
55 | 6388 | 'filter' => [ |
|
56 | 116 | 'time' => 'DateTimeRange', |
|
57 | 'category' => 'Text', |
||
58 | 6388 | 'message' => 'Text', |
|
59 | 'code' => 'Text', |
||
60 | 'trace' => 'Text', |
||
61 | ], |
||
62 | ], |
||
63 | 'wapro' => [ |
||
64 | 'label' => 'LBL_WAPRO_ERP', |
||
65 | 'labelModule' => 'Settings:Wapro', |
||
66 | 'table' => 'l_#__wapro', |
||
67 | 'icon' => 'fab fa-connectdevelop', |
||
68 | 5890 | 'columns' => [ |
|
69 | 'time' => ['type' => 'DateTime', 'label' => 'LBL_TIME'], |
||
70 | 5890 | 'category' => ['type' => 'Text', 'label' => 'LBL_CATEGORY'], |
|
71 | 5890 | 'message' => ['type' => 'Text', 'label' => 'LBL_MESSAGE'], |
|
72 | 'error' => ['type' => 'Text', 'label' => 'LBL_CODE'], |
||
73 | 5890 | 'trace' => ['type' => 'Text', 'label' => 'LBL_BACKTRACE'], |
|
74 | ], |
||
75 | 'filter' => [ |
||
76 | 'time' => 'DateTimeRange', |
||
77 | 'category' => 'Text', |
||
78 | 'message' => 'Text', |
||
79 | 'code' => 'Text', |
||
80 | 'trace' => 'Text', |
||
81 | ], |
||
82 | ], |
||
83 | 7 | 'switchUsers' => [ |
|
84 | 'label' => 'LBL_SWITCH_USERS', |
||
85 | 7 | 'labelModule' => 'Settings:Users', |
|
86 | 7 | 'table' => 'l_#__switch_users', |
|
87 | 'icon' => 'yfi-users', |
||
88 | 7 | 'columns' => [ |
|
89 | 'date' => ['type' => 'DateTime', 'label' => 'LBL_TIME'], |
||
90 | 'status' => ['type' => 'Text', 'label' => 'LBL_STATUS'], |
||
91 | 'busername' => ['type' => 'Text', 'label' => 'LBL_BASE_USER'], |
||
92 | 'dusername' => ['type' => 'Text', 'label' => 'LBL_DEST_USER'], |
||
93 | 'ip' => ['type' => 'Text', 'label' => 'LBL_IP_ADDRESS'], |
||
94 | 'agent' => ['type' => 'Text', 'label' => 'LBL_USER_AGENT'], |
||
95 | ], |
||
96 | 'filter' => [ |
||
97 | 'date' => 'DateTimeRange', |
||
98 | 7 | 'busername' => 'Text', |
|
99 | 'dusername' => 'Text', |
||
100 | 7 | 'ip' => 'Text', |
|
101 | 7 | 'agent' => 'Text', |
|
102 | ], |
||
103 | 7 | ], |
|
104 | 'batchMethod' => [ |
||
105 | 'label' => 'LBL_BATCH_METHODS', |
||
106 | 'labelModule' => 'Settings:CronTasks', |
||
107 | 'table' => 'l_#__batchmethod', |
||
108 | 'icon' => 'fas fa-swatchbook', |
||
109 | 'columns' => [ |
||
110 | 'date' => ['type' => 'DateTime', 'label' => 'LBL_TIME'], |
||
111 | 'method' => ['type' => 'Text', 'label' => 'LBL_BATCH_NAME'], |
||
112 | 'message' => ['type' => 'Text', 'label' => 'LBL_ERROR_MASAGE'], |
||
113 | 22 | 'userid' => ['type' => 'Owner', 'label' => 'LBL_OWNER'], |
|
114 | 'params' => ['type' => 'Text', 'label' => 'LBL_PARAMS'], |
||
115 | 22 | ], |
|
116 | 22 | 'filter' => [ |
|
117 | 'date' => 'DateTimeRange', |
||
118 | 'method' => 'Text', |
||
119 | 'message' => 'Text', |
||
120 | 'params' => 'Text', |
||
121 | ], |
||
122 | ], |
||
123 | 'mail' => [ |
||
124 | 'label' => 'LBL_MAILS_NOT_SENT', |
||
125 | 'labelModule' => 'Settings:Log', |
||
126 | 'table' => 'l_#__mail', |
||
127 | 'icon' => 'adminIcon-mail-queue', |
||
128 | 'columns' => [ |
||
129 | 'date' => ['type' => 'DateTime', 'label' => 'LBL_TIME'], |
||
130 | 'subject' => ['type' => 'Text', 'label' => 'LBL_SUBJECT'], |
||
131 | 'from' => ['type' => 'Text', 'label' => 'LBL_FROM'], |
||
132 | 'to' => ['type' => 'Text', 'label' => 'LBL_TO'], |
||
133 | 'owner' => ['type' => 'Owner', 'label' => 'LBL_OWNER'], |
||
134 | ], |
||
135 | 'filter' => [ |
||
136 | 'date' => 'DateTimeRange', |
||
137 | 'subject' => 'Text', |
||
138 | 'from' => 'Text', |
||
139 | 'to' => 'Text', |
||
140 | ], |
||
141 | ], |
||
142 | 'profile' => [ |
||
143 | 'label' => 'LBL_PROFILING', |
||
144 | 'labelModule' => 'Settings:Log', |
||
145 | 'table' => 'l_#__profile', |
||
146 | 'icon' => 'fas fa-stopwatch', |
||
147 | 'columns' => [ |
||
148 | 'category' => ['type' => 'Text', 'label' => 'Category'], |
||
149 | 'info' => ['type' => 'Text', 'label' => 'LBL_PARAMS'], |
||
150 | 'log_time' => ['type' => 'Text', 'label' => 'LBL_TIME'], |
||
151 | 'trace' => ['type' => 'Text', 'label' => 'LBL_BACKTRACE'], |
||
152 | 'duration' => ['type' => 'Text', 'label' => 'LBL_DURATION'], |
||
153 | ], |
||
154 | 'filter' => [ |
||
155 | 'category' => 'Text', |
||
156 | 'subinfoject' => 'Text', |
||
157 | 'log_time' => 'Text', |
||
158 | 'trace' => 'Text', |
||
159 | 'duration' => 'Text', |
||
160 | ], |
||
161 | ], |
||
162 | ]; |
||
163 | public static $levelMap = [ |
||
164 | 'error' => Logger::LEVEL_ERROR, |
||
165 | 'warning' => Logger::LEVEL_WARNING, |
||
166 | 'info' => Logger::LEVEL_INFO, |
||
167 | 'trace' => Logger::LEVEL_TRACE, |
||
168 | 'profile' => Logger::LEVEL_PROFILE, |
||
169 | ]; |
||
170 | |||
171 | /** |
||
172 | * Initializes the logger by registering [[flush()]] as a shutdown function. |
||
173 | */ |
||
174 | public function init() |
||
175 | { |
||
176 | parent::init(); |
||
177 | if (\Config\Debug::$LOG_LEVELS) { |
||
178 | $this->setLevels(\Config\Debug::$LOG_LEVELS); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
179 | } |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Sets the message levels that this target is interested in. |
||
184 | * |
||
185 | * @param array|int $levels message levels that this target is interested in. |
||
186 | */ |
||
187 | public function setLevels($levels) |
||
188 | { |
||
189 | if (\is_array($levels)) { |
||
190 | foreach ($levels as $level) { |
||
191 | if (isset(self::$levelMap[$level])) { |
||
192 | $this->logToLevels |= self::$levelMap[$level]; |
||
193 | } else { |
||
194 | throw new Exceptions\AppException("Unrecognized level: $level"); |
||
195 | } |
||
196 | } |
||
197 | } else { |
||
198 | $bitmapValues = array_reduce(self::$levelMap, fn ($carry, $item) => $carry | $item); |
||
199 | if (!($bitmapValues & $levels) && 0 !== $levels) { |
||
200 | throw new Exceptions\AppException("Incorrect $levels value"); |
||
201 | } |
||
202 | $this->logToLevels = $levels; |
||
203 | } |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * Logs a message with the given type and category. |
||
208 | * If [[traceLevel]] is greater than 0, additional call stack information about |
||
209 | * the application code will be logged as well. |
||
210 | * |
||
211 | * @param array|string $message the message to be logged. This can be a simple string or a more |
||
212 | * complex data structure that will be handled by a [[Target|log target]] |
||
213 | * @param int $level the level of the message. This must be one of the following: |
||
214 | * `Logger::LEVEL_ERROR`, `Logger::LEVEL_WARNING`, `Logger::LEVEL_INFO`, `Logger::LEVEL_TRACE`, |
||
215 | * `Logger::LEVEL_PROFILE_BEGIN`, `Logger::LEVEL_PROFILE_END` |
||
216 | * @param string $category the category of the message |
||
217 | */ |
||
218 | public function log($message, $level, $category = '') |
||
219 | { |
||
220 | if (0 !== $this->logToLevels && !($this->logToLevels & $level)) { |
||
221 | return; |
||
222 | } |
||
223 | $traces = ''; |
||
224 | if ($this->traceLevel) { |
||
225 | $traces = Debuger::getBacktrace(2, $this->traceLevel, ' - '); |
||
226 | } |
||
227 | if (static::$logToConsole) { |
||
228 | Debuger::addLogs($message, self::getLevelName($level), $traces); |
||
229 | } |
||
230 | $this->messages[] = [$message, $level, $category, microtime(true), $traces]; |
||
231 | if ($this->flushInterval > 0 && \count($this->messages) >= $this->flushInterval) { |
||
232 | $this->flush(); |
||
233 | } |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * Logs a trace message. |
||
238 | * Trace messages are logged mainly for development purpose to see |
||
239 | * the execution work flow of some code. |
||
240 | * |
||
241 | * @param string $message the message to be logged |
||
242 | * @param string $category the category of the message |
||
243 | */ |
||
244 | public static function trace($message, $category = '') |
||
245 | { |
||
246 | if (static::$logToFile) { |
||
247 | \Yii::getLogger()->log($message, Logger::LEVEL_TRACE, $category); |
||
248 | } |
||
249 | } |
||
250 | |||
251 | /** |
||
252 | * Logs an informative message. |
||
253 | * An informative message is typically logged by an application to keep record of |
||
254 | * something important (e.g. an administrator logs in). |
||
255 | * |
||
256 | * @param string $message the message to be logged |
||
257 | * @param string $category the category of the message |
||
258 | */ |
||
259 | public static function info($message, $category = '') |
||
260 | { |
||
261 | if (static::$logToFile) { |
||
262 | \Yii::getLogger()->log($message, Logger::LEVEL_INFO, $category); |
||
263 | } |
||
264 | } |
||
265 | |||
266 | /** |
||
267 | * Logs a warning message. |
||
268 | * A warning message is typically logged when an error occurs while the execution |
||
269 | * can still continue. |
||
270 | * |
||
271 | * @param string $message the message to be logged |
||
272 | * @param string $category the category of the message |
||
273 | */ |
||
274 | public static function warning($message, $category = '') |
||
275 | { |
||
276 | if (static::$logToFile) { |
||
277 | \Yii::getLogger()->log($message, Logger::LEVEL_WARNING, $category); |
||
278 | } |
||
279 | } |
||
280 | |||
281 | /** |
||
282 | * Logs an error message. |
||
283 | * An error message is typically logged when an unrecoverable error occurs |
||
284 | * during the execution of an application. |
||
285 | * |
||
286 | * @param string $message the message to be logged |
||
287 | * @param string $category the category of the message |
||
288 | */ |
||
289 | public static function error($message, $category = '') |
||
290 | { |
||
291 | if (static::$logToFile) { |
||
292 | \Yii::getLogger()->log($message, Logger::LEVEL_ERROR, $category); |
||
293 | } |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * Marks the beginning of a code block for profiling. |
||
298 | * This has to be matched with a call to [[endProfile]] with the same category name. |
||
299 | * The begin- and end- calls must also be properly nested. For example,. |
||
300 | * |
||
301 | * ```php |
||
302 | * \Yii::beginProfile('block1'); |
||
303 | * // some code to be profiled |
||
304 | * \Yii::beginProfile('block2'); |
||
305 | * // some other code to be profiled |
||
306 | * \Yii::endProfile('block2'); |
||
307 | * \Yii::endProfile('block1'); |
||
308 | * ``` |
||
309 | * |
||
310 | * @param string $token token for the code block |
||
311 | * @param string $category the category of this log message |
||
312 | * |
||
313 | * @see endProfile() |
||
314 | */ |
||
315 | public static function beginProfile($token, $category = '') |
||
316 | { |
||
317 | if (static::$logToProfile) { |
||
318 | $categories = \Config\Debug::$LOG_PROFILE_CATEGORIES ?? []; |
||
319 | if ($categories && !\in_array($category, $categories)) { |
||
320 | return; |
||
321 | } |
||
322 | \Yii::getLogger()->log($token, Logger::LEVEL_PROFILE_BEGIN, $category); |
||
323 | } |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Marks the end of a code block for profiling. |
||
328 | * This has to be matched with a previous call to [[beginProfile]] with the same category name. |
||
329 | * |
||
330 | * @param string $token token for the code block |
||
331 | * @param string $category the category of this log message |
||
332 | * |
||
333 | * @see beginProfile() |
||
334 | */ |
||
335 | public static function endProfile($token, $category = '') |
||
336 | { |
||
337 | if (static::$logToProfile) { |
||
338 | $categories = \Config\Debug::$LOG_PROFILE_CATEGORIES ?? []; |
||
339 | if ($categories && !\in_array($category, $categories)) { |
||
340 | return; |
||
341 | } |
||
342 | \Yii::getLogger()->log($token, Logger::LEVEL_PROFILE_END, $category); |
||
343 | } |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Get user action logs. |
||
348 | * |
||
349 | * @param string $type |
||
350 | * @param string $mode |
||
351 | * @param bool $countMode |
||
352 | * |
||
353 | * @return array |
||
354 | */ |
||
355 | public static function getLogs($type, $mode, $countMode = false) |
||
356 | { |
||
357 | $db = \App\Db::getInstance('log'); |
||
358 | $query = (new \App\Db\Query())->from('o_#__' . $type); |
||
359 | if ('oneDay' === $mode) { |
||
360 | $query->where(['>=', 'date', date('Y-m-d H:i:s', strtotime('-1 day'))]); |
||
361 | } else { |
||
362 | $query->limit(100); |
||
363 | } |
||
364 | if ($countMode) { |
||
365 | return $query->count('*', $db); |
||
0 ignored issues
–
show
|
|||
366 | } |
||
367 | $query->orderBy(['id' => SORT_DESC]); |
||
368 | return $query->all($db); |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * Get last logs. |
||
373 | * |
||
374 | * @param bool|string[] $types |
||
375 | * |
||
376 | * @return string |
||
377 | */ |
||
378 | public static function getlastLogs($types = false) |
||
379 | { |
||
380 | $content = ''; |
||
381 | $i = 0; |
||
382 | foreach (\Yii::getLogger()->messages as $message) { |
||
383 | $level = \yii\log\Logger::getLevelName($message[1]); |
||
384 | if (false !== $types && !\in_array($level, $types)) { |
||
385 | continue; |
||
386 | } |
||
387 | $content .= "#$i [$level]"; |
||
388 | $category = $message[2] ?: ''; |
||
389 | if ($category) { |
||
390 | $content .= "[$category]"; |
||
391 | } |
||
392 | $content .= " {$message[0]}" . PHP_EOL; |
||
393 | ++$i; |
||
394 | } |
||
395 | return $content; |
||
396 | } |
||
397 | } |
||
398 |