diff --git a/src/HttpBasicAuthentication/RequestPathMethodRule.php b/src/HttpBasicAuthentication/RequestPathMethodRule.php new file mode 100644 index 0000000..509bca9 --- /dev/null +++ b/src/HttpBasicAuthentication/RequestPathMethodRule.php @@ -0,0 +1,72 @@ + ["/"], + "passthrough" => [] + ]; + + /** + * Create a new rule instance + * + * @param string[] $options + * + */ + public function __construct($options = []) + { + $this->options = array_merge($this->options, $options); + } + + /** + * @param \Psr\Http\Message\RequestInterface $request + * @return boolean + */ + public function __invoke(RequestInterface $request) + { + $uri = "/" . $request->getUri()->getPath(); + $uri = preg_replace("#/+#", "/", $uri); + + /** If request path is matches passthrough should not authenticate. */ + foreach ((array)$this->options["passthrough"] as $passthrough => $method) { + $passthrough = rtrim($passthrough, "/"); + + /** If path defined as string, we use this little hack */ + if ($passthrough === '0') { + $passthrough = $method; + $method = null; + } + + if (preg_match("@^{$passthrough}(/.*)?$@", $uri)) { + if ((in_array(strtolower($request->getMethod()), (array)$method)) || empty((array)$method)) { + return false; + } + } + } + + /** Otherwise check if path matches and we should authenticate. */ + foreach ((array)$this->options["path"] as $path => $method) { + $path = rtrim($path, "/"); + + /** If path defined as string, we use this little hack */ + if ($path === '0') { + $path = $method; + $method = null; + } + if (preg_match("@^{$path}(/.*)?$@", $uri)) { + if ((in_array(strtolower($request->getMethod()), (array)$method)) || empty((array)$method)) { + return true; + } + } + } + + return false; + } +} diff --git a/tests/RequestPathMethodTest.php b/tests/RequestPathMethodTest.php new file mode 100644 index 0000000..3ec68c1 --- /dev/null +++ b/tests/RequestPathMethodTest.php @@ -0,0 +1,78 @@ +withUri(new Uri("https://example.com/api")) + ->withMethod("GET"); + + + $rule = new RequestPathMethodRule([ + 'path' => [ + '/api/*' => [ + 'post' + ] + ] + ]); + + $this->assertFalse($rule($request)); + } + + public function testShouldNotAuthenticatePost() + { + $request = (new Request()) + ->withUri(new Uri("https://example.com/api")) + ->withMethod("GET"); + + $rule = new RequestPathMethodRule([ + 'path' => [ + '/api/*' => [ + 'get' + ] + ] + ]); + + $this->assertTrue($rule($request)); + } + + public function testShouldNotAuthenticatePassthrough() + { + $requestOne = (new Request()) + ->withUri(new Uri("https://example.com/api")) + ->withMethod("GET"); + + $requestTwo = (new Request()) + ->withUri(new Uri("https://example.com/api/addlog")) + ->withMethod('POST'); + + $requestThree = (new Request()) + ->withUri(new Uri("https://example.com/api")) + ->withMethod("POST"); + + $rule = new RequestPathMethodRule([ + 'path' => [ + '/api/*' => [ + 'get', + 'post' + ] + ], + 'passthrough' => [ + '/api/addlog' => [ + 'post' + ] + ] + ]); + + $this->assertTrue($rule($requestOne)); + $this->assertFalse($rule($requestTwo)); + $this->assertTrue($rule($requestThree)); + } +} \ No newline at end of file