|
|
|
|
@ -22,9 +22,11 @@ use OCP\AppFramework\Http\Response;
|
|
|
|
|
use OCP\AppFramework\Http\TemplateResponse;
|
|
|
|
|
use OCP\AppFramework\Middleware;
|
|
|
|
|
use OCP\IAppConfig;
|
|
|
|
|
use OCP\IConfig;
|
|
|
|
|
use OCP\IRequest;
|
|
|
|
|
use OCP\ISession;
|
|
|
|
|
use OCP\IUserSession;
|
|
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
|
use ReflectionMethod;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -56,7 +58,9 @@ class RateLimitingMiddleware extends Middleware {
|
|
|
|
|
protected Limiter $limiter,
|
|
|
|
|
protected ISession $session,
|
|
|
|
|
protected IAppConfig $appConfig,
|
|
|
|
|
protected IConfig $serverConfig,
|
|
|
|
|
protected BruteforceAllowList $bruteForceAllowList,
|
|
|
|
|
protected LoggerInterface $logger,
|
|
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -74,7 +78,13 @@ class RateLimitingMiddleware extends Middleware {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($this->userSession->isLoggedIn()) {
|
|
|
|
|
$rateLimit = $this->readLimitFromAnnotationOrAttribute($controller, $methodName, 'UserRateThrottle', UserRateLimit::class);
|
|
|
|
|
$rateLimit = $this->readLimitFromAnnotationOrAttribute(
|
|
|
|
|
$controller,
|
|
|
|
|
$methodName,
|
|
|
|
|
'UserRateThrottle',
|
|
|
|
|
UserRateLimit::class,
|
|
|
|
|
'user',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($rateLimit !== null) {
|
|
|
|
|
if ($this->appConfig->getValueBool('bruteforcesettings', 'apply_allowlist_to_ratelimit')
|
|
|
|
|
@ -94,7 +104,13 @@ class RateLimitingMiddleware extends Middleware {
|
|
|
|
|
// If not user specific rate limit is found the Anon rate limit applies!
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$rateLimit = $this->readLimitFromAnnotationOrAttribute($controller, $methodName, 'AnonRateThrottle', AnonRateLimit::class);
|
|
|
|
|
$rateLimit = $this->readLimitFromAnnotationOrAttribute(
|
|
|
|
|
$controller,
|
|
|
|
|
$methodName,
|
|
|
|
|
'AnonRateThrottle',
|
|
|
|
|
AnonRateLimit::class,
|
|
|
|
|
'anon',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($rateLimit !== null) {
|
|
|
|
|
$this->limiter->registerAnonRequest(
|
|
|
|
|
@ -115,7 +131,35 @@ class RateLimitingMiddleware extends Middleware {
|
|
|
|
|
* @param class-string<T> $attributeClass
|
|
|
|
|
* @return ?ARateLimit
|
|
|
|
|
*/
|
|
|
|
|
protected function readLimitFromAnnotationOrAttribute(Controller $controller, string $methodName, string $annotationName, string $attributeClass): ?ARateLimit {
|
|
|
|
|
protected function readLimitFromAnnotationOrAttribute(Controller $controller, string $methodName, string $annotationName, string $attributeClass, string $overwriteKey): ?ARateLimit {
|
|
|
|
|
$rateLimitOverwrite = $this->serverConfig->getSystemValue('ratelimit_overwrite', []);
|
|
|
|
|
if (!empty($rateLimitOverwrite)) {
|
|
|
|
|
$controllerRef = new \ReflectionClass($controller);
|
|
|
|
|
$appName = $controllerRef->getProperty('appName')->getValue($controller);
|
|
|
|
|
$controllerName = substr($controller::class, strrpos($controller::class, '\\') + 1);
|
|
|
|
|
$controllerName = substr($controllerName, 0, 0 - strlen('Controller'));
|
|
|
|
|
|
|
|
|
|
$overwriteConfig = strtolower($appName . '.' . $controllerName . '.' . $methodName);
|
|
|
|
|
$rateLimitOverwriteForActionAndType = $rateLimitOverwrite[$overwriteConfig][$overwriteKey] ?? null;
|
|
|
|
|
if ($rateLimitOverwriteForActionAndType !== null) {
|
|
|
|
|
$isValid = isset($rateLimitOverwriteForActionAndType['limit'], $rateLimitOverwriteForActionAndType['period'])
|
|
|
|
|
&& $rateLimitOverwriteForActionAndType['limit'] > 0
|
|
|
|
|
&& $rateLimitOverwriteForActionAndType['period'] > 0;
|
|
|
|
|
|
|
|
|
|
if ($isValid) {
|
|
|
|
|
return new $attributeClass(
|
|
|
|
|
(int)$rateLimitOverwriteForActionAndType['limit'],
|
|
|
|
|
(int)$rateLimitOverwriteForActionAndType['period'],
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->logger->warning('Rate limit overwrite on controller "{overwriteConfig}" for "{overwriteKey}" is invalid', [
|
|
|
|
|
'overwriteConfig' => $overwriteConfig,
|
|
|
|
|
'overwriteKey' => $overwriteKey,
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$annotationLimit = $this->reflector->getAnnotationParameter($annotationName, 'limit');
|
|
|
|
|
$annotationPeriod = $this->reflector->getAnnotationParameter($annotationName, 'period');
|
|
|
|
|
|
|
|
|
|
|