mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 06:15:19 +08:00
Fix #18236: Allow yii\filters\RateLimiter
to accept a closure function for the $user
property in order to assign values on runtime
This commit is contained in:
@ -4,6 +4,7 @@ Yii Framework 2 Change Log
|
||||
2.0.38 under development
|
||||
------------------------
|
||||
|
||||
- Enh #18236: Allow `yii\filters\RateLimiter` to accept a closure function for the `$user` property in order to assign values on runtime (nadar)
|
||||
- Bug #18233: Add PHP 8 support (samdark)
|
||||
- Bug #18229: Add flag for recognize SyBase databases on uses pdo_dblib (darkdef)
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
namespace yii\filters;
|
||||
|
||||
use Closure;
|
||||
use Yii;
|
||||
use yii\base\ActionFilter;
|
||||
use yii\web\Request;
|
||||
@ -48,8 +49,14 @@ class RateLimiter extends ActionFilter
|
||||
*/
|
||||
public $errorMessage = 'Rate limit exceeded.';
|
||||
/**
|
||||
* @var RateLimitInterface the user object that implements the RateLimitInterface.
|
||||
* If not set, it will take the value of `Yii::$app->user->getIdentity(false)`.
|
||||
* @var RateLimitInterface|Closure the user object that implements the RateLimitInterface. If not set, it will take the value of `Yii::$app->user->getIdentity(false)`.
|
||||
* {@since 2.0.38} It's possible to provide a closure function in order to assign the user identity on runtime. Using a closure to assign the user identity is recommend
|
||||
* when you are **not** using the standard `Yii::$app->user` component. See the example below:
|
||||
* ```php
|
||||
* 'user' => function() {
|
||||
* return Yii::$app->apiUser->identity;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public $user;
|
||||
/**
|
||||
@ -84,6 +91,10 @@ class RateLimiter extends ActionFilter
|
||||
$this->user = Yii::$app->getUser()->getIdentity(false);
|
||||
}
|
||||
|
||||
if ($this->user instanceof Closure) {
|
||||
$this->user = call_user_func($this->user, $action);
|
||||
}
|
||||
|
||||
if ($this->user instanceof RateLimitInterface) {
|
||||
Yii::debug('Check rate limit', __METHOD__);
|
||||
$this->checkRateLimit($this->user, $this->request, $this->response, $action);
|
||||
|
@ -158,4 +158,21 @@ class RateLimiterTest extends TestCase
|
||||
$rateLimiter->addRateLimitHeaders($response, 1, 0, 0);
|
||||
$this->assertCount(3, $response->getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2/issues/18236
|
||||
*/
|
||||
public function testUserWithClosureFunction()
|
||||
{
|
||||
$rateLimiter = new RateLimiter();
|
||||
$rateLimiter->user = function($action) {
|
||||
return new User(['identityClass' => RateLimit::className()]);
|
||||
};
|
||||
$rateLimiter->beforeAction('test');
|
||||
|
||||
// testing the evaluation of user closure, which in this case returns not the expect object and therefore
|
||||
// the log message "does not implement RateLimitInterface" is expected.
|
||||
$this->assertInstanceOf(User::className(), $rateLimiter->user);
|
||||
$this->assertContains('Rate limit skipped: "user" does not implement RateLimitInterface.', Yii::getLogger()->messages);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user