From 22d7f450fbf7ecf2ab97dd1a2ba2993913d8fa4f Mon Sep 17 00:00:00 2001 From: Sandstrom <1013635+tangix@users.noreply.github.com> Date: Wed, 15 Jul 2020 15:48:47 +0200 Subject: [PATCH 1/5] Pass filter arguments to after() and before() methods. Updated docs and added tests. --- system/Filters/CSRF.php | 9 ++-- system/Filters/DebugToolbar.php | 7 ++- system/Filters/FilterInterface.php | 6 ++- system/Filters/Filters.php | 2 +- system/Filters/Honeypot.php | 7 +-- tests/system/Filters/FiltersTest.php | 41 ++++++++++++++++- .../system/Filters/fixtures/GoogleCurious.php | 4 +- tests/system/Filters/fixtures/GoogleEmpty.php | 4 +- tests/system/Filters/fixtures/GoogleMe.php | 4 +- tests/system/Filters/fixtures/GoogleYou.php | 4 +- tests/system/Filters/fixtures/Multiple1.php | 4 +- tests/system/Filters/fixtures/Multiple2.php | 4 +- tests/system/Filters/fixtures/Role.php | 45 +++++++++++++++++++ user_guide_src/source/incoming/filters.rst | 15 +++++-- user_guide_src/source/incoming/routing.rst | 2 +- user_guide_src/source/libraries/throttler.rst | 6 ++- 16 files changed, 134 insertions(+), 30 deletions(-) create mode 100644 tests/system/Filters/fixtures/Role.php diff --git a/system/Filters/CSRF.php b/system/Filters/CSRF.php index 5209dc9fe15c..6805ea2a5d50 100644 --- a/system/Filters/CSRF.php +++ b/system/Filters/CSRF.php @@ -57,6 +57,7 @@ */ class CSRF implements FilterInterface { + /** * Do whatever processing this filter needs to do. * By default it should not return anything during @@ -68,11 +69,12 @@ class CSRF implements FilterInterface * redirects, etc. * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request + * @param array|null $arguments * * @return mixed - * @throws \CodeIgniter\Security\Exceptions\SecurityException + * @throws \Exception */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { if ($request->isCLI()) { @@ -103,10 +105,11 @@ public function before(RequestInterface $request) * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request * @param ResponseInterface|\CodeIgniter\HTTP\Response $response + * @param array|null $arguments * * @return mixed */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/system/Filters/DebugToolbar.php b/system/Filters/DebugToolbar.php index 465ca3eade6c..2c3a55c24ef2 100644 --- a/system/Filters/DebugToolbar.php +++ b/system/Filters/DebugToolbar.php @@ -48,14 +48,16 @@ */ class DebugToolbar implements FilterInterface { + /** * We don't need to do anything here. * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request + * @param array|null $arguments * * @return void */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { } @@ -67,10 +69,11 @@ public function before(RequestInterface $request) * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request * @param ResponseInterface|\CodeIgniter\HTTP\Response $response + * @param array|null $arguments * * @return void */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { Services::toolbar()->prepare($request, $response); } diff --git a/system/Filters/FilterInterface.php b/system/Filters/FilterInterface.php index d58be9e4af0a..48b682e41ba5 100644 --- a/system/Filters/FilterInterface.php +++ b/system/Filters/FilterInterface.php @@ -59,10 +59,11 @@ interface FilterInterface * redirects, etc. * * @param \CodeIgniter\HTTP\RequestInterface $request + * @param null $arguments * * @return mixed */ - public function before(RequestInterface $request); + public function before(RequestInterface $request, $arguments = null); //-------------------------------------------------------------------- @@ -74,10 +75,11 @@ public function before(RequestInterface $request); * * @param \CodeIgniter\HTTP\RequestInterface $request * @param \CodeIgniter\HTTP\ResponseInterface $response + * @param null $arguments * * @return mixed */ - public function after(RequestInterface $request, ResponseInterface $response); + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null); //-------------------------------------------------------------------- } diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index 101e42ed9747..37ba2df05141 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -196,7 +196,7 @@ public function run(string $uri, string $position = 'before') } elseif ($position === 'after') { - $result = $class->after($this->request, $this->response); + $result = $class->after($this->request, $this->response, $this->arguments[$alias] ?? null); if ($result instanceof ResponseInterface) { diff --git a/system/Filters/Honeypot.php b/system/Filters/Honeypot.php index 9c2bfb9f85b0..5f2d83c12ae7 100644 --- a/system/Filters/Honeypot.php +++ b/system/Filters/Honeypot.php @@ -55,11 +55,11 @@ class Honeypot implements FilterInterface * then the requester is a bot * * @param \CodeIgniter\HTTP\RequestInterface $request + * @param array|null $arguments * * @return void - * @throws \CodeIgniter\Honeypot\Exceptions\HoneypotException */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $honeypot = Services::honeypot(new \Config\Honeypot()); if ($honeypot->hasContent($request)) @@ -73,10 +73,11 @@ public function before(RequestInterface $request) * * @param \CodeIgniter\HTTP\RequestInterface $request * @param \CodeIgniter\HTTP\ResponseInterface $response + * @param array|null $arguments * * @return void */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { $honeypot = Services::honeypot(new \Config\Honeypot()); $honeypot->attachHoneypot($response); diff --git a/tests/system/Filters/FiltersTest.php b/tests/system/Filters/FiltersTest.php index 8118a4af6648..83e45d5a25eb 100644 --- a/tests/system/Filters/FiltersTest.php +++ b/tests/system/Filters/FiltersTest.php @@ -12,6 +12,7 @@ require_once __DIR__ . '/fixtures/InvalidClass.php'; require_once __DIR__ . '/fixtures/Multiple1.php'; require_once __DIR__ . '/fixtures/Multiple2.php'; +require_once __DIR__ . '/fixtures/Role.php'; /** * @backupGlobals enabled @@ -25,6 +26,7 @@ class FiltersTest extends \CodeIgniter\Test\CIUnitTestCase protected function setUp(): void { parent::setUp(); + Services::reset(); $this->request = Services::request(); $this->response = Services::response(); @@ -623,17 +625,54 @@ public function testEnableFilterWithArguments() ], ]; - $filters = new Filters((object) $config, $this->request, $this->response); + $filters = new Filters((object)$config, $this->request, $this->response); $filters = $filters->initialize('admin/foo/bar'); $filters->enableFilter('role:admin , super', 'before'); + $filters->enableFilter('role:admin , super', 'after'); $found = $filters->getFilters(); $this->assertTrue(in_array('role', $found['before'])); $this->assertEquals(['admin', 'super'], $filters->getArguments('role')); $this->assertEquals(['role' => ['admin', 'super']], $filters->getArguments()); + + $response = $filters->run('admin/foo/bar', 'before'); + $this->assertEquals('admin;super', $response); + + $response = $filters->run('admin/foo/bar', 'after'); + $this->assertEquals('admin;super', $response->getBody()); + } + + public function testEnableFilterWithNoArguments() + { + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $config = [ + 'aliases' => ['role' => 'CodeIgniter\Filters\fixtures\Role'], + 'globals' => [ + 'before' => [], + 'after' => [], + ], + ]; + + $filters = new Filters((object)$config, $this->request, $this->response); + + $filters = $filters->initialize('admin/foo/bar'); + + $filters->enableFilter('role', 'before'); + $filters->enableFilter('role', 'after'); + + $found = $filters->getFilters(); + + $this->assertTrue(in_array('role', $found['before'])); + + $response = $filters->run('admin/foo/bar', 'before'); + $this->assertEquals('Is null', $response); + + $response = $filters->run('admin/foo/bar', 'after'); + $this->assertEquals('Is null', $response->getBody()); } public function testEnableNonFilter() diff --git a/tests/system/Filters/fixtures/GoogleCurious.php b/tests/system/Filters/fixtures/GoogleCurious.php index c6251ab6039c..599b1cfaaaf3 100644 --- a/tests/system/Filters/fixtures/GoogleCurious.php +++ b/tests/system/Filters/fixtures/GoogleCurious.php @@ -7,12 +7,12 @@ class GoogleCurious implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { return 'This is curious'; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/GoogleEmpty.php b/tests/system/Filters/fixtures/GoogleEmpty.php index fa6286da6736..be685fea81e9 100644 --- a/tests/system/Filters/fixtures/GoogleEmpty.php +++ b/tests/system/Filters/fixtures/GoogleEmpty.php @@ -7,13 +7,13 @@ class GoogleEmpty implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request = ''; return $request; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/GoogleMe.php b/tests/system/Filters/fixtures/GoogleMe.php index 86859c8d8604..f9b8bb767a54 100644 --- a/tests/system/Filters/fixtures/GoogleMe.php +++ b/tests/system/Filters/fixtures/GoogleMe.php @@ -6,7 +6,7 @@ class GoogleMe implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request->url = 'http://google.com'; @@ -15,7 +15,7 @@ public function before(RequestInterface $request) //-------------------------------------------------------------------- - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { $response->csp = 'http://google.com'; diff --git a/tests/system/Filters/fixtures/GoogleYou.php b/tests/system/Filters/fixtures/GoogleYou.php index 2ebc8d85bd08..3cfbe16fd538 100644 --- a/tests/system/Filters/fixtures/GoogleYou.php +++ b/tests/system/Filters/fixtures/GoogleYou.php @@ -8,14 +8,14 @@ class GoogleYou implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $response = Services::response(); $response->csp = 'http://google.com'; return $response; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/Multiple1.php b/tests/system/Filters/fixtures/Multiple1.php index d6788554cc43..d253495493f8 100644 --- a/tests/system/Filters/fixtures/Multiple1.php +++ b/tests/system/Filters/fixtures/Multiple1.php @@ -7,13 +7,13 @@ class Multiple1 implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request->csp = 'http://exampleMultipleCSP.com'; return $request; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/Multiple2.php b/tests/system/Filters/fixtures/Multiple2.php index 61ca1a3e7150..4dbcb584c4ef 100644 --- a/tests/system/Filters/fixtures/Multiple2.php +++ b/tests/system/Filters/fixtures/Multiple2.php @@ -7,13 +7,13 @@ class Multiple2 implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request->url = 'http://exampleMultipleURL.com'; return $request; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/Role.php b/tests/system/Filters/fixtures/Role.php new file mode 100644 index 000000000000..280b163f03f7 --- /dev/null +++ b/tests/system/Filters/fixtures/Role.php @@ -0,0 +1,45 @@ +setBody(join(';', $arguments)); + } + elseif (is_null($arguments)) + { + $response->setBody('Is null'); + } + else + { + $response->setBody('Something else'); + } + return $response; + } + + public function before(RequestInterface $request, $arguments = null) + { + if (is_array($arguments)) + { + return join(';', $arguments); + } + elseif (is_null($arguments)) + { + return 'Is null'; + } + else + { + return 'Something else'; + } + } + +} diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 9000e8df5314..1e4bb974f126 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -35,14 +35,14 @@ but may leave the methods empty if they are not needed. A skeleton filter class class MyFilter implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { // Do something here } //-------------------------------------------------------------------- - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { // Do something here } @@ -58,7 +58,7 @@ Since before filters are executed prior to your controller being executed, you m actions in the controller from happening. You can do this by passing back anything that is not the request object. This is typically used to perform redirects, like in this example:: - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $auth = service('auth'); @@ -179,6 +179,15 @@ a list of URI patterns that filter should apply to:: 'bar' => ['before' => ['api/*', 'admin/*']] ]; +Filter arguments +================= + +When configuring filters, additional arguments may be passed to a filter when setting up the route:: + + $routes->add('users/delete/(:segment)', 'AdminController::index', ['filter' => 'admin-auth:dual,noreturn']); + +In this example, the array ``['dual', 'noreturn']`` will be passed in ``$arguments`` to the filter's ``before()`` and ``after()`` implementation methods. + **************** Provided Filters **************** diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 80d993f3eaeb..2fd55ae485ea 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -336,7 +336,7 @@ You can alter the behavior of specific routes by supplying a filter to run befor $routes->add('admin',' AdminController::index', ['filter' => 'admin-auth']); -The value for the filter must match one of the aliases defined within ``app/Config/Filters.php``. You may also supply parameters to be passed to the filter's ``before()`` and ``after()`` methods:: +The value for the filter must match one of the aliases defined within ``app/Config/Filters.php``. You may also supply arguments to be passed to the filter's ``before()`` and ``after()`` methods:: $routes->add('users/delete/(:segment)', 'AdminController::index', ['filter' => 'admin-auth:dual,noreturn']); diff --git a/user_guide_src/source/libraries/throttler.rst b/user_guide_src/source/libraries/throttler.rst index e551797cc483..1408900608b4 100644 --- a/user_guide_src/source/libraries/throttler.rst +++ b/user_guide_src/source/libraries/throttler.rst @@ -66,10 +66,11 @@ along the lines of:: * to implement rate limiting for your application. * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request + * @param array|null $arguments * * @return mixed */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $throttler = Services::throttler(); @@ -89,10 +90,11 @@ along the lines of:: * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request * @param ResponseInterface|\CodeIgniter\HTTP\Response $response + * @param array|null $arguments * * @return mixed */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } } From bbe0755e6cf78911712d06a996a7c16324b6e12f Mon Sep 17 00:00:00 2001 From: Sandstrom <1013635+tangix@users.noreply.github.com> Date: Wed, 15 Jul 2020 15:55:37 +0200 Subject: [PATCH 2/5] Pass filter arguments to after() and before() methods. Updated docs and added tests. Fixed phpstorm's unnecessary changes --- system/Filters/CSRF.php | 7 ++- system/Filters/DebugToolbar.php | 7 ++- system/Filters/FilterInterface.php | 6 ++- system/Filters/Filters.php | 2 +- system/Filters/Honeypot.php | 7 +-- tests/system/Filters/FiltersTest.php | 41 ++++++++++++++++- .../system/Filters/fixtures/GoogleCurious.php | 4 +- tests/system/Filters/fixtures/GoogleEmpty.php | 4 +- tests/system/Filters/fixtures/GoogleMe.php | 4 +- tests/system/Filters/fixtures/GoogleYou.php | 4 +- tests/system/Filters/fixtures/Multiple1.php | 4 +- tests/system/Filters/fixtures/Multiple2.php | 4 +- tests/system/Filters/fixtures/Role.php | 45 +++++++++++++++++++ user_guide_src/source/incoming/filters.rst | 15 +++++-- user_guide_src/source/incoming/routing.rst | 2 +- user_guide_src/source/libraries/throttler.rst | 6 ++- 16 files changed, 133 insertions(+), 29 deletions(-) create mode 100644 tests/system/Filters/fixtures/Role.php diff --git a/system/Filters/CSRF.php b/system/Filters/CSRF.php index 5209dc9fe15c..c79d1913ac85 100644 --- a/system/Filters/CSRF.php +++ b/system/Filters/CSRF.php @@ -57,6 +57,7 @@ */ class CSRF implements FilterInterface { + /** * Do whatever processing this filter needs to do. * By default it should not return anything during @@ -68,11 +69,12 @@ class CSRF implements FilterInterface * redirects, etc. * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request + * @param array|null $arguments * * @return mixed * @throws \CodeIgniter\Security\Exceptions\SecurityException */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { if ($request->isCLI()) { @@ -103,10 +105,11 @@ public function before(RequestInterface $request) * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request * @param ResponseInterface|\CodeIgniter\HTTP\Response $response + * @param array|null $arguments * * @return mixed */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/system/Filters/DebugToolbar.php b/system/Filters/DebugToolbar.php index 465ca3eade6c..2c3a55c24ef2 100644 --- a/system/Filters/DebugToolbar.php +++ b/system/Filters/DebugToolbar.php @@ -48,14 +48,16 @@ */ class DebugToolbar implements FilterInterface { + /** * We don't need to do anything here. * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request + * @param array|null $arguments * * @return void */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { } @@ -67,10 +69,11 @@ public function before(RequestInterface $request) * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request * @param ResponseInterface|\CodeIgniter\HTTP\Response $response + * @param array|null $arguments * * @return void */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { Services::toolbar()->prepare($request, $response); } diff --git a/system/Filters/FilterInterface.php b/system/Filters/FilterInterface.php index d58be9e4af0a..48b682e41ba5 100644 --- a/system/Filters/FilterInterface.php +++ b/system/Filters/FilterInterface.php @@ -59,10 +59,11 @@ interface FilterInterface * redirects, etc. * * @param \CodeIgniter\HTTP\RequestInterface $request + * @param null $arguments * * @return mixed */ - public function before(RequestInterface $request); + public function before(RequestInterface $request, $arguments = null); //-------------------------------------------------------------------- @@ -74,10 +75,11 @@ public function before(RequestInterface $request); * * @param \CodeIgniter\HTTP\RequestInterface $request * @param \CodeIgniter\HTTP\ResponseInterface $response + * @param null $arguments * * @return mixed */ - public function after(RequestInterface $request, ResponseInterface $response); + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null); //-------------------------------------------------------------------- } diff --git a/system/Filters/Filters.php b/system/Filters/Filters.php index 101e42ed9747..37ba2df05141 100644 --- a/system/Filters/Filters.php +++ b/system/Filters/Filters.php @@ -196,7 +196,7 @@ public function run(string $uri, string $position = 'before') } elseif ($position === 'after') { - $result = $class->after($this->request, $this->response); + $result = $class->after($this->request, $this->response, $this->arguments[$alias] ?? null); if ($result instanceof ResponseInterface) { diff --git a/system/Filters/Honeypot.php b/system/Filters/Honeypot.php index 9c2bfb9f85b0..5f2d83c12ae7 100644 --- a/system/Filters/Honeypot.php +++ b/system/Filters/Honeypot.php @@ -55,11 +55,11 @@ class Honeypot implements FilterInterface * then the requester is a bot * * @param \CodeIgniter\HTTP\RequestInterface $request + * @param array|null $arguments * * @return void - * @throws \CodeIgniter\Honeypot\Exceptions\HoneypotException */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $honeypot = Services::honeypot(new \Config\Honeypot()); if ($honeypot->hasContent($request)) @@ -73,10 +73,11 @@ public function before(RequestInterface $request) * * @param \CodeIgniter\HTTP\RequestInterface $request * @param \CodeIgniter\HTTP\ResponseInterface $response + * @param array|null $arguments * * @return void */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { $honeypot = Services::honeypot(new \Config\Honeypot()); $honeypot->attachHoneypot($response); diff --git a/tests/system/Filters/FiltersTest.php b/tests/system/Filters/FiltersTest.php index 8118a4af6648..83e45d5a25eb 100644 --- a/tests/system/Filters/FiltersTest.php +++ b/tests/system/Filters/FiltersTest.php @@ -12,6 +12,7 @@ require_once __DIR__ . '/fixtures/InvalidClass.php'; require_once __DIR__ . '/fixtures/Multiple1.php'; require_once __DIR__ . '/fixtures/Multiple2.php'; +require_once __DIR__ . '/fixtures/Role.php'; /** * @backupGlobals enabled @@ -25,6 +26,7 @@ class FiltersTest extends \CodeIgniter\Test\CIUnitTestCase protected function setUp(): void { parent::setUp(); + Services::reset(); $this->request = Services::request(); $this->response = Services::response(); @@ -623,17 +625,54 @@ public function testEnableFilterWithArguments() ], ]; - $filters = new Filters((object) $config, $this->request, $this->response); + $filters = new Filters((object)$config, $this->request, $this->response); $filters = $filters->initialize('admin/foo/bar'); $filters->enableFilter('role:admin , super', 'before'); + $filters->enableFilter('role:admin , super', 'after'); $found = $filters->getFilters(); $this->assertTrue(in_array('role', $found['before'])); $this->assertEquals(['admin', 'super'], $filters->getArguments('role')); $this->assertEquals(['role' => ['admin', 'super']], $filters->getArguments()); + + $response = $filters->run('admin/foo/bar', 'before'); + $this->assertEquals('admin;super', $response); + + $response = $filters->run('admin/foo/bar', 'after'); + $this->assertEquals('admin;super', $response->getBody()); + } + + public function testEnableFilterWithNoArguments() + { + $_SERVER['REQUEST_METHOD'] = 'GET'; + + $config = [ + 'aliases' => ['role' => 'CodeIgniter\Filters\fixtures\Role'], + 'globals' => [ + 'before' => [], + 'after' => [], + ], + ]; + + $filters = new Filters((object)$config, $this->request, $this->response); + + $filters = $filters->initialize('admin/foo/bar'); + + $filters->enableFilter('role', 'before'); + $filters->enableFilter('role', 'after'); + + $found = $filters->getFilters(); + + $this->assertTrue(in_array('role', $found['before'])); + + $response = $filters->run('admin/foo/bar', 'before'); + $this->assertEquals('Is null', $response); + + $response = $filters->run('admin/foo/bar', 'after'); + $this->assertEquals('Is null', $response->getBody()); } public function testEnableNonFilter() diff --git a/tests/system/Filters/fixtures/GoogleCurious.php b/tests/system/Filters/fixtures/GoogleCurious.php index c6251ab6039c..599b1cfaaaf3 100644 --- a/tests/system/Filters/fixtures/GoogleCurious.php +++ b/tests/system/Filters/fixtures/GoogleCurious.php @@ -7,12 +7,12 @@ class GoogleCurious implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { return 'This is curious'; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/GoogleEmpty.php b/tests/system/Filters/fixtures/GoogleEmpty.php index fa6286da6736..be685fea81e9 100644 --- a/tests/system/Filters/fixtures/GoogleEmpty.php +++ b/tests/system/Filters/fixtures/GoogleEmpty.php @@ -7,13 +7,13 @@ class GoogleEmpty implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request = ''; return $request; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/GoogleMe.php b/tests/system/Filters/fixtures/GoogleMe.php index 86859c8d8604..f9b8bb767a54 100644 --- a/tests/system/Filters/fixtures/GoogleMe.php +++ b/tests/system/Filters/fixtures/GoogleMe.php @@ -6,7 +6,7 @@ class GoogleMe implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request->url = 'http://google.com'; @@ -15,7 +15,7 @@ public function before(RequestInterface $request) //-------------------------------------------------------------------- - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { $response->csp = 'http://google.com'; diff --git a/tests/system/Filters/fixtures/GoogleYou.php b/tests/system/Filters/fixtures/GoogleYou.php index 2ebc8d85bd08..3cfbe16fd538 100644 --- a/tests/system/Filters/fixtures/GoogleYou.php +++ b/tests/system/Filters/fixtures/GoogleYou.php @@ -8,14 +8,14 @@ class GoogleYou implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $response = Services::response(); $response->csp = 'http://google.com'; return $response; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/Multiple1.php b/tests/system/Filters/fixtures/Multiple1.php index d6788554cc43..d253495493f8 100644 --- a/tests/system/Filters/fixtures/Multiple1.php +++ b/tests/system/Filters/fixtures/Multiple1.php @@ -7,13 +7,13 @@ class Multiple1 implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request->csp = 'http://exampleMultipleCSP.com'; return $request; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/Multiple2.php b/tests/system/Filters/fixtures/Multiple2.php index 61ca1a3e7150..4dbcb584c4ef 100644 --- a/tests/system/Filters/fixtures/Multiple2.php +++ b/tests/system/Filters/fixtures/Multiple2.php @@ -7,13 +7,13 @@ class Multiple2 implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $request->url = 'http://exampleMultipleURL.com'; return $request; } - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } diff --git a/tests/system/Filters/fixtures/Role.php b/tests/system/Filters/fixtures/Role.php new file mode 100644 index 000000000000..280b163f03f7 --- /dev/null +++ b/tests/system/Filters/fixtures/Role.php @@ -0,0 +1,45 @@ +setBody(join(';', $arguments)); + } + elseif (is_null($arguments)) + { + $response->setBody('Is null'); + } + else + { + $response->setBody('Something else'); + } + return $response; + } + + public function before(RequestInterface $request, $arguments = null) + { + if (is_array($arguments)) + { + return join(';', $arguments); + } + elseif (is_null($arguments)) + { + return 'Is null'; + } + else + { + return 'Something else'; + } + } + +} diff --git a/user_guide_src/source/incoming/filters.rst b/user_guide_src/source/incoming/filters.rst index 9000e8df5314..1e4bb974f126 100644 --- a/user_guide_src/source/incoming/filters.rst +++ b/user_guide_src/source/incoming/filters.rst @@ -35,14 +35,14 @@ but may leave the methods empty if they are not needed. A skeleton filter class class MyFilter implements FilterInterface { - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { // Do something here } //-------------------------------------------------------------------- - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { // Do something here } @@ -58,7 +58,7 @@ Since before filters are executed prior to your controller being executed, you m actions in the controller from happening. You can do this by passing back anything that is not the request object. This is typically used to perform redirects, like in this example:: - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $auth = service('auth'); @@ -179,6 +179,15 @@ a list of URI patterns that filter should apply to:: 'bar' => ['before' => ['api/*', 'admin/*']] ]; +Filter arguments +================= + +When configuring filters, additional arguments may be passed to a filter when setting up the route:: + + $routes->add('users/delete/(:segment)', 'AdminController::index', ['filter' => 'admin-auth:dual,noreturn']); + +In this example, the array ``['dual', 'noreturn']`` will be passed in ``$arguments`` to the filter's ``before()`` and ``after()`` implementation methods. + **************** Provided Filters **************** diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 80d993f3eaeb..2fd55ae485ea 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -336,7 +336,7 @@ You can alter the behavior of specific routes by supplying a filter to run befor $routes->add('admin',' AdminController::index', ['filter' => 'admin-auth']); -The value for the filter must match one of the aliases defined within ``app/Config/Filters.php``. You may also supply parameters to be passed to the filter's ``before()`` and ``after()`` methods:: +The value for the filter must match one of the aliases defined within ``app/Config/Filters.php``. You may also supply arguments to be passed to the filter's ``before()`` and ``after()`` methods:: $routes->add('users/delete/(:segment)', 'AdminController::index', ['filter' => 'admin-auth:dual,noreturn']); diff --git a/user_guide_src/source/libraries/throttler.rst b/user_guide_src/source/libraries/throttler.rst index e551797cc483..1408900608b4 100644 --- a/user_guide_src/source/libraries/throttler.rst +++ b/user_guide_src/source/libraries/throttler.rst @@ -66,10 +66,11 @@ along the lines of:: * to implement rate limiting for your application. * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request + * @param array|null $arguments * * @return mixed */ - public function before(RequestInterface $request) + public function before(RequestInterface $request, $arguments = null) { $throttler = Services::throttler(); @@ -89,10 +90,11 @@ along the lines of:: * * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request * @param ResponseInterface|\CodeIgniter\HTTP\Response $response + * @param array|null $arguments * * @return mixed */ - public function after(RequestInterface $request, ResponseInterface $response) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } } From efc2e477891015a295ddfea2990e02746bbd9a68 Mon Sep 17 00:00:00 2001 From: Sandstrom <1013635+tangix@users.noreply.github.com> Date: Wed, 15 Jul 2020 15:59:03 +0200 Subject: [PATCH 3/5] Phpstorm keeps change the @throws doc --- system/Filters/CSRF.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Filters/CSRF.php b/system/Filters/CSRF.php index 6805ea2a5d50..c79d1913ac85 100644 --- a/system/Filters/CSRF.php +++ b/system/Filters/CSRF.php @@ -72,7 +72,7 @@ class CSRF implements FilterInterface * @param array|null $arguments * * @return mixed - * @throws \Exception + * @throws \CodeIgniter\Security\Exceptions\SecurityException */ public function before(RequestInterface $request, $arguments = null) { From 1a14436d1cc0169df6aa8ce0f1f62eea3975d5bd Mon Sep 17 00:00:00 2001 From: Sandstrom <1013635+tangix@users.noreply.github.com> Date: Wed, 15 Jul 2020 16:15:19 +0200 Subject: [PATCH 4/5] Updated changelog --- user_guide_src/source/changelogs/v4.0.4.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/changelogs/v4.0.4.rst b/user_guide_src/source/changelogs/v4.0.4.rst index 42ce88aacbec..01be1a3faf7c 100644 --- a/user_guide_src/source/changelogs/v4.0.4.rst +++ b/user_guide_src/source/changelogs/v4.0.4.rst @@ -52,6 +52,8 @@ Bugs Fixed: - Fixed bug in Image GD handler that would try to compress images twice in certain cases - Ensure get translation output logic work on selected locale, dashed locale, and fallback "en" - Fix is_unique/is_not_unique validation called on POST/PUT via API in Postgresql +- Added ``$arguments`` parameter to after() and before() in FilterInterface +- Fixed a bug where filter arguments were not passed to after() From 374ddf3baccd85f3fa95d0093dcd1e82e2c28d29 Mon Sep 17 00:00:00 2001 From: Sandstrom <1013635+tangix@users.noreply.github.com> Date: Wed, 15 Jul 2020 16:17:18 +0200 Subject: [PATCH 5/5] Clarified the message by adding code needs to be updated. --- user_guide_src/source/changelogs/v4.0.4.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/changelogs/v4.0.4.rst b/user_guide_src/source/changelogs/v4.0.4.rst index 01be1a3faf7c..eb762861e31e 100644 --- a/user_guide_src/source/changelogs/v4.0.4.rst +++ b/user_guide_src/source/changelogs/v4.0.4.rst @@ -52,7 +52,7 @@ Bugs Fixed: - Fixed bug in Image GD handler that would try to compress images twice in certain cases - Ensure get translation output logic work on selected locale, dashed locale, and fallback "en" - Fix is_unique/is_not_unique validation called on POST/PUT via API in Postgresql -- Added ``$arguments`` parameter to after() and before() in FilterInterface +- Added ``$arguments`` parameter to after() and before() in FilterInterface. This is a breaking change, so all code implementing the FilterInterface must be updated - Fixed a bug where filter arguments were not passed to after()