Skip to content

Commit

Permalink
[10.x] Named static methods for middleware (#46362)
Browse files Browse the repository at this point in the history
* wip

* Standardise of `using` for Authorization middleware

* Update ValidateSignature.php

* Update ThrottleRequests.php

* Update ThrottleRequests.php

* Update RequirePassword.php

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
timacdonald and taylorotwell committed Apr 24, 2023
1 parent 2922575 commit 7136338
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/Illuminate/Auth/Middleware/Authenticate.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ public function __construct(Auth $auth)
$this->auth = $auth;
}

/**
* Specify the guards for the middleware.
*
* @param string $guard
* @param string $others
* @return string
*/
public static function using($guard, ...$others)
{
return static::class.':'.implode(',', [$guard, ...$others]);
}

/**
* Handle an incoming request.
*
Expand Down
14 changes: 14 additions & 0 deletions src/Illuminate/Auth/Middleware/AuthenticateWithBasicAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ public function __construct(AuthFactory $auth)
$this->auth = $auth;
}

/**
* Specify the guard and field for the middleware.
*
* @param string|null $guard
* @param string|null $field
* @return string
*
* @named-arguments-supported
*/
public static function using($guard = null, $field = null)
{
return static::class.':'.implode(',', func_get_args());
}

/**
* Handle an incoming request.
*
Expand Down
12 changes: 12 additions & 0 deletions src/Illuminate/Auth/Middleware/Authorize.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ public function __construct(Gate $gate)
$this->gate = $gate;
}

/**
* Specify the ability and models for the middleware.
*
* @param string $ability
* @param string ...$models
* @return string
*/
public static function using($ability, ...$models)
{
return static::class.':'.implode(',', [$ability, ...$models]);
}

/**
* Handle an incoming request.
*
Expand Down
11 changes: 11 additions & 0 deletions src/Illuminate/Auth/Middleware/EnsureEmailIsVerified.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@

class EnsureEmailIsVerified
{
/**
* Specify the redirect route for the middleware.
*
* @param string $route
* @return string
*/
public static function redirectTo($route)
{
return static::class.':'.$route;
}

/**
* Handle an incoming request.
*
Expand Down
18 changes: 16 additions & 2 deletions src/Illuminate/Auth/Middleware/RequirePassword.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,27 @@ public function __construct(ResponseFactory $responseFactory, UrlGenerator $urlG
$this->passwordTimeout = $passwordTimeout ?: 10800;
}

/**
* Specify the redirect route and timeout for the middleware.
*
* @param string|null $redirectToRoute
* @param string|null $passwordTimeoutSeconds
* @return string
*
* @named-arguments-supported
*/
public static function using($redirectToRoute = null, $passwordTimeoutSeconds = null)
{
return static::class.':'.implode(',', func_get_args());
}

/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $redirectToRoute
* @param int|null $passwordTimeoutSeconds
* @param string|int|null $passwordTimeoutSeconds
* @return mixed
*/
public function handle($request, Closure $next, $redirectToRoute = null, $passwordTimeoutSeconds = null)
Expand All @@ -63,7 +77,7 @@ public function handle($request, Closure $next, $redirectToRoute = null, $passwo
}

return $this->responseFactory->redirectGuest(
$this->urlGenerator->route($redirectToRoute ?? 'password.confirm')
$this->urlGenerator->route($redirectToRoute ?: 'password.confirm')
);
}

Expand Down
19 changes: 19 additions & 0 deletions src/Illuminate/Http/Middleware/SetCacheHeaders.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,29 @@

use Closure;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

class SetCacheHeaders
{
/**
* Specify the options for the middleware.
*
* @param array|string $options
* @return string
*/
public static function using($options)
{
if (is_string($options)) {
return static::class.':'.$options;
}

return collect($options)
->map(fn ($value, $key) => is_int($key) ? $value : "{$key}={$value}")
->map(fn ($value) => Str::finish($value, ';'))
->pipe(fn ($options) => rtrim(static::class.':'.$options->implode(''), ';'));
}

/**
* Add cache related HTTP headers.
*
Expand Down
26 changes: 26 additions & 0 deletions src/Illuminate/Routing/Middleware/ThrottleRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,32 @@ public function __construct(RateLimiter $limiter)
$this->limiter = $limiter;
}

/**
* Specify the named rate limiter to use for the middleware.
*
* @param string $name
* @return string
*/
public static function using($name)
{
return static::class.':'.$name;
}

/**
* Specify the rate limiter configuration for the middleware.
*
* @param int $maxAttempts
* @param int $decayMinutes
* @param string $prefix
* @return string
*
* @named-arguments-supported
*/
public static function with($maxAttempts = 60, $decayMinutes = 1, $prefix = '')
{
return static::class.':'.implode(',', func_get_args());
}

/**
* Handle an incoming request.
*
Expand Down
20 changes: 20 additions & 0 deletions src/Illuminate/Routing/Middleware/ValidateSignature.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@ class ValidateSignature
//
];

/**
* Specify that the URL signature is for a relative URL.
*
* @return string
*/
public static function relative()
{
return static::class.':relative';
}

/**
* Specify that the URL signature is for an absolute URL.
*
* @return class-string
*/
public static function absolute()
{
return static::class;
}

/**
* Handle an incoming request.
*
Expand Down
25 changes: 25 additions & 0 deletions tests/Auth/AuthenticateMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Auth\AuthManager;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Auth\Middleware\Authenticate;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Illuminate\Auth\RequestGuard;
use Illuminate\Config\Repository as Config;
use Illuminate\Container\Container;
Expand Down Expand Up @@ -36,6 +37,30 @@ protected function tearDown(): void
Container::setInstance(null);
}

public function testItCanGenerateDefinitionViaStaticMethod()
{
$signature = (string) Authenticate::using('foo');
$this->assertSame('Illuminate\Auth\Middleware\Authenticate:foo', $signature);

$signature = (string) Authenticate::using('foo', 'bar');
$this->assertSame('Illuminate\Auth\Middleware\Authenticate:foo,bar', $signature);

$signature = (string) Authenticate::using('foo', 'bar', 'baz');
$this->assertSame('Illuminate\Auth\Middleware\Authenticate:foo,bar,baz', $signature);
}

public function testItCanGenerateDefinitionViaStaticMethodForBasic()
{
$signature = (string) AuthenticateWithBasicAuth::using('guard');
$this->assertSame('Illuminate\Auth\Middleware\AuthenticateWithBasicAuth:guard', $signature);

$signature = (string) AuthenticateWithBasicAuth::using('guard', 'field');
$this->assertSame('Illuminate\Auth\Middleware\AuthenticateWithBasicAuth:guard,field', $signature);

$signature = (string) AuthenticateWithBasicAuth::using(field: 'field');
$this->assertSame('Illuminate\Auth\Middleware\AuthenticateWithBasicAuth:,field', $signature);
}

public function testDefaultUnauthenticatedThrows()
{
$this->expectException(AuthenticationException::class);
Expand Down
12 changes: 12 additions & 0 deletions tests/Auth/AuthorizeMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ protected function tearDown(): void
Container::setInstance(null);
}

public function testItCanGenerateDefinitionViaStaticMethod()
{
$signature = (string) Authorize::using('ability');
$this->assertSame('Illuminate\Auth\Middleware\Authorize:ability', $signature);

$signature = (string) Authorize::using('ability', 'model');
$this->assertSame('Illuminate\Auth\Middleware\Authorize:ability,model', $signature);

$signature = (string) Authorize::using('ability', 'model', \App\Models\Comment::class);
$this->assertSame('Illuminate\Auth\Middleware\Authorize:ability,model,App\Models\Comment', $signature);
}

public function testSimpleAbilityUnauthorized()
{
$this->expectException(AuthorizationException::class);
Expand Down
15 changes: 15 additions & 0 deletions tests/Auth/EnsureEmailIsVerifiedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Illuminate\Tests\Auth;

use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
use PHPUnit\Framework\TestCase;

class EnsureEmailIsVerifiedTest extends TestCase
{
public function testItCanGenerateDefinitionViaStaticMethod()
{
$signature = (string) EnsureEmailIsVerified::redirectTo('route.name');
$this->assertSame('Illuminate\Auth\Middleware\EnsureEmailIsVerified:route.name', $signature);
}
}
23 changes: 23 additions & 0 deletions tests/Http/Middleware/CacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@

class CacheTest extends TestCase
{
public function testItCanGenerateDefinitionViaStaticMethod()
{
$signature = (string) Cache::using('max_age=120;no-transform;s_maxage=60;');
$this->assertSame('Illuminate\Http\Middleware\SetCacheHeaders:max_age=120;no-transform;s_maxage=60;', $signature);

$signature = (string) Cache::using('max_age=120;no-transform;s_maxage=60');
$this->assertSame('Illuminate\Http\Middleware\SetCacheHeaders:max_age=120;no-transform;s_maxage=60', $signature);

$signature = (string) Cache::using([
'max_age=120',
'no-transform',
's_maxage=60',
]);
$this->assertSame('Illuminate\Http\Middleware\SetCacheHeaders:max_age=120;no-transform;s_maxage=60', $signature);

$signature = (string) Cache::using([
'max_age' => 120,
'no-transform',
's_maxage' => '60',
]);
$this->assertSame('Illuminate\Http\Middleware\SetCacheHeaders:max_age=120;no-transform;s_maxage=60', $signature);
}

public function testDoNotSetHeaderWhenMethodNotCacheable()
{
$request = new Request;
Expand Down
12 changes: 12 additions & 0 deletions tests/Integration/Auth/Middleware/RequirePasswordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@

class RequirePasswordTest extends TestCase
{
public function testItCanGenerateDefinitionViaStaticMethod()
{
$signature = (string) RequirePassword::using('route.name');
$this->assertSame('Illuminate\Auth\Middleware\RequirePassword:route.name', $signature);

$signature = (string) RequirePassword::using('route.name', 100);
$this->assertSame('Illuminate\Auth\Middleware\RequirePassword:route.name,100', $signature);

$signature = (string) RequirePassword::using(passwordTimeoutSeconds: 100);
$this->assertSame('Illuminate\Auth\Middleware\RequirePassword:,100', $signature);
}

public function testUserSeesTheWantedPageIfThePasswordWasRecentlyConfirmed()
{
$this->withoutExceptionHandling();
Expand Down
21 changes: 21 additions & 0 deletions tests/Integration/Http/ThrottleRequestsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,25 @@ public function testLimitingUsingNamedLimiter()
$this->assertEquals(Carbon::now()->addSeconds(2)->getTimestamp(), $e->getHeaders()['X-RateLimit-Reset']);
}
}

public function testItCanGenerateDefinitionViaStaticMethod()
{
$signature = (string) ThrottleRequests::using('gold-tier');
$this->assertSame('Illuminate\Routing\Middleware\ThrottleRequests:gold-tier', $signature);

$signature = (string) ThrottleRequests::with(25);
$this->assertSame('Illuminate\Routing\Middleware\ThrottleRequests:25', $signature);

$signature = (string) ThrottleRequests::with(25, 2);
$this->assertSame('Illuminate\Routing\Middleware\ThrottleRequests:25,2', $signature);

$signature = (string) ThrottleRequests::with(25, 2, 'foo');
$this->assertSame('Illuminate\Routing\Middleware\ThrottleRequests:25,2,foo', $signature);

$signature = (string) ThrottleRequests::with(maxAttempts: 25, decayMinutes: 2, prefix: 'foo');
$this->assertSame('Illuminate\Routing\Middleware\ThrottleRequests:25,2,foo', $signature);

$signature = (string) ThrottleRequests::with(prefix: 'foo');
$this->assertSame('Illuminate\Routing\Middleware\ThrottleRequests:60,1,foo', $signature);
}
}
9 changes: 9 additions & 0 deletions tests/Integration/Routing/UrlSigningTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,15 @@ public function testSignedMiddlewareIgnoringParameter()
}
}

public function testItCanGenerateMiddlewareDefinitionViaStaticMethod()
{
$signature = (string) ValidateSignature::relative();
$this->assertSame('Illuminate\Routing\Middleware\ValidateSignature:relative', $signature);

$signature = (string) ValidateSignature::absolute();
$this->assertSame('Illuminate\Routing\Middleware\ValidateSignature', $signature);
}

protected function createValidateSignatureMiddleware(array $ignore)
{
return new class($ignore) extends ValidateSignature
Expand Down

0 comments on commit 7136338

Please sign in to comment.