4242use OC \Log \ExceptionSerializer ;
4343use OCP \EventDispatcher \IEventDispatcher ;
4444use OCP \ILogger ;
45+ use OCP \IRequest ;
4546use OCP \IUserSession ;
4647use OCP \Log \BeforeMessageLoggedEvent ;
4748use OCP \Log \IDataLogger ;
@@ -181,7 +182,7 @@ public function debug(string $message, array $context = []): void {
181182 * @param array $context
182183 */
183184 public function log (int $ level , string $ message , array $ context = []): void {
184- $ minLevel = $ this ->getLogLevel ($ context );
185+ $ minLevel = $ this ->getLogLevel ($ context, $ message );
185186 if ($ level < $ minLevel
186187 && (($ this ->crashReporters ?->hasReporters() ?? false ) === false )
187188 && (($ this ->eventDispatcher ?->hasListeners(BeforeMessageLoggedEvent::class) ?? false ) === false )) {
@@ -222,9 +223,25 @@ public function log(int $level, string $message, array $context = []): void {
222223 }
223224 }
224225
225- public function getLogLevel ($ context ): int {
226+ public function getLogLevel (array $ context , string $ message ): int {
227+ /**
228+ * @psalm-var array{
229+ * shared_secret?: string,
230+ * users?: string[],
231+ * apps?: string[],
232+ * matches?: array<array-key, array{
233+ * shared_secret?: string,
234+ * users?: string[],
235+ * apps?: string[],
236+ * message?: string,
237+ * loglevel: 0|1|2|3|4,
238+ * }>
239+ * } $logCondition
240+ */
226241 $ logCondition = $ this ->config ->getValue ('log.condition ' , []);
227242
243+ $ userId = false ;
244+
228245 /**
229246 * check for a special log condition - this enables an increased log on
230247 * a per request/user base
@@ -234,21 +251,8 @@ public function getLogLevel($context): int {
234251 $ this ->logConditionSatisfied = false ;
235252 if (!empty ($ logCondition )) {
236253 // check for secret token in the request
237- if (isset ($ logCondition ['shared_secret ' ])) {
238- $ request = \OC ::$ server ->getRequest ();
239-
240- if ($ request ->getMethod () === 'PUT ' &&
241- !str_contains ($ request ->getHeader ('Content-Type ' ), 'application/x-www-form-urlencoded ' ) &&
242- !str_contains ($ request ->getHeader ('Content-Type ' ), 'application/json ' )) {
243- $ logSecretRequest = '' ;
244- } else {
245- $ logSecretRequest = $ request ->getParam ('log_secret ' , '' );
246- }
247-
248- // if token is found in the request change set the log condition to satisfied
249- if ($ request && hash_equals ($ logCondition ['shared_secret ' ], $ logSecretRequest )) {
250- $ this ->logConditionSatisfied = true ;
251- }
254+ if (isset ($ logCondition ['shared_secret ' ]) && $ this ->checkLogSecret ($ logCondition ['shared_secret ' ])) {
255+ $ this ->logConditionSatisfied = true ;
252256 }
253257
254258 // check for user
@@ -261,6 +265,8 @@ public function getLogLevel($context): int {
261265 } elseif (in_array ($ user ->getUID (), $ logCondition ['users ' ], true )) {
262266 // if the user matches set the log condition to satisfied
263267 $ this ->logConditionSatisfied = true ;
268+ } else {
269+ $ userId = $ user ->getUID ();
264270 }
265271 }
266272 }
@@ -271,6 +277,11 @@ public function getLogLevel($context): int {
271277 return ILogger::DEBUG ;
272278 }
273279
280+ if ($ userId === false && isset ($ logCondition ['matches ' ])) {
281+ $ user = \OCP \Server::get (IUserSession::class)->getUser ();
282+ $ userId = $ user === null ? false : $ user ->getUID ();
283+ }
284+
274285 if (isset ($ context ['app ' ])) {
275286 /**
276287 * check log condition based on the context of each log message
@@ -281,16 +292,49 @@ public function getLogLevel($context): int {
281292 }
282293 }
283294
284- $ configLogLevel = $ this ->config ->getValue ('loglevel ' , ILogger::WARN );
285- if (is_numeric ($ configLogLevel )) {
286- return min ((int )$ configLogLevel , ILogger::FATAL );
295+ if (isset ($ logCondition ['matches ' ])) {
296+ $ configLogLevel = $ this ->config ->getValue ('loglevel ' , ILogger::WARN );
297+ if (is_numeric ($ configLogLevel )) {
298+ return min ((int )$ configLogLevel , ILogger::FATAL );
299+ }
300+
301+ // Invalid configuration, warn the user and fall back to default level of WARN
302+ error_log ('Nextcloud configuration: "loglevel" is not a valid integer ' );
303+ return ILogger::WARN ;
304+ }
305+
306+ foreach ($ logCondition ['matches ' ] as $ option ) {
307+ if (
308+ (!isset ($ option ['shared_secret ' ]) || $ this ->checkLogSecret ($ option ['shared_secret ' ]))
309+ && (!isset ($ option ['users ' ]) || in_array ($ userId , $ option ['users ' ], true ))
310+ && (!isset ($ option ['apps ' ]) || (isset ($ context ['app ' ]) && in_array ($ context ['app ' ], $ option ['apps ' ], true )))
311+ && (!isset ($ option ['message ' ]) || str_contains ($ message , $ option ['message ' ]))
312+ ) {
313+ if (!isset ($ option ['apps ' ]) && !isset ($ option ['loglevel ' ]) && !isset ($ option ['message ' ])) {
314+ /* Only user and/or secret are listed as conditions, we can cache the result for the rest of the request */
315+ $ this ->logConditionSatisfied = true ;
316+ return ILogger::DEBUG ;
317+ }
318+ return $ option ['loglevel ' ] ?? ILogger::DEBUG ;
319+ }
287320 }
288321
289- // Invalid configuration, warn the user and fall back to default level of WARN
290- error_log ('Nextcloud configuration: "loglevel" is not a valid integer ' );
291322 return ILogger::WARN ;
292323 }
293324
325+ protected function checkLogSecret (string $ conditionSecret ): bool {
326+ $ request = \OCP \Server::get (IRequest::class);
327+
328+ if ($ request ->getMethod () === 'PUT ' &&
329+ !str_contains ($ request ->getHeader ('Content-Type ' ), 'application/x-www-form-urlencoded ' ) &&
330+ !str_contains ($ request ->getHeader ('Content-Type ' ), 'application/json ' )) {
331+ return hash_equals ($ conditionSecret , '' );
332+ }
333+
334+ // if token is found in the request change set the log condition to satisfied
335+ return hash_equals ($ conditionSecret , $ request ->getParam ('log_secret ' , '' ));
336+ }
337+
294338 /**
295339 * Logs an exception very detailed
296340 *
@@ -303,7 +347,7 @@ public function logException(Throwable $exception, array $context = []): void {
303347 $ app = $ context ['app ' ] ?? 'no app in context ' ;
304348 $ level = $ context ['level ' ] ?? ILogger::ERROR ;
305349
306- $ minLevel = $ this ->getLogLevel ($ context );
350+ $ minLevel = $ this ->getLogLevel ($ context, $ context [ ' message ' ] ?? $ exception -> getMessage () );
307351 if ($ level < $ minLevel
308352 && (($ this ->crashReporters ?->hasReporters() ?? false ) === false )
309353 && (($ this ->eventDispatcher ?->hasListeners(BeforeMessageLoggedEvent::class) ?? false ) === false )) {
@@ -348,7 +392,7 @@ public function logData(string $message, array $data, array $context = []): void
348392 $ app = $ context ['app ' ] ?? 'no app in context ' ;
349393 $ level = $ context ['level ' ] ?? ILogger::ERROR ;
350394
351- $ minLevel = $ this ->getLogLevel ($ context );
395+ $ minLevel = $ this ->getLogLevel ($ context, $ message );
352396
353397 array_walk ($ context , [$ this ->normalizer , 'format ' ]);
354398
0 commit comments