diff --git a/src/Lunr/Corona/Parsers/BearerToken/BearerTokenCliParser.php b/src/Lunr/Corona/Parsers/BearerToken/BearerTokenCliParser.php new file mode 100644 index 00000000..fd7b5c76 --- /dev/null +++ b/src/Lunr/Corona/Parsers/BearerToken/BearerTokenCliParser.php @@ -0,0 +1,102 @@ +params = $params; + } + + /** + * Destructor. + */ + public function __destruct() + { + // no-op + } + + /** + * Return the request value type the parser handles. + * + * @return class-string The FQDN of the type enum the parser handles + */ + public function get_request_value_type(): string + { + return BearerTokenValue::class; + } + + /** + * Get a request value. + * + * @param BackedEnum&RequestValueInterface $key The identifier/name of the request value to get + * + * @return string|null The requested value + */ + public function get(BackedEnum&RequestValueInterface $key): ?string + { + return match ($key) { + BearerTokenValue::BearerToken => $this->bearerToken ?? $this->parse(), + default => throw new RuntimeException('Unsupported request value type "' . $key::class . '"'), + }; + } + + /** + * Parse the bearer token value from the HTTP authorization header. + * + * @return string|null The parsed bearer token + */ + protected function parse(): ?string + { + $token = NULL; + + if (array_key_exists('bearer-token', $this->params)) + { + $token = $this->params['bearer-token'][0]; + } + + $this->bearerToken = $token; + + return $token; + } + +} + +?> diff --git a/src/Lunr/Corona/Parsers/BearerToken/BearerTokenParser.php b/src/Lunr/Corona/Parsers/BearerToken/BearerTokenParser.php new file mode 100644 index 00000000..8d9b5d1d --- /dev/null +++ b/src/Lunr/Corona/Parsers/BearerToken/BearerTokenParser.php @@ -0,0 +1,95 @@ + $this->bearerToken ?? $this->parse(), + default => throw new RuntimeException('Unsupported request value type "' . $key::class . '"'), + }; + } + + /** + * Parse the bearer token value from the HTTP authorization header. + * + * @return string|null The parsed bearer token + */ + protected function parse(): ?string + { + $token = NULL; + + if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER)) + { + $matches = []; + if (preg_match('/^Bearer ([^ ]+)$/', $_SERVER['HTTP_AUTHORIZATION'], $matches) === 1) + { + $token = $matches[1]; + } + } + + $this->bearerToken = $token; + + return $token; + } + +} + +?> diff --git a/src/Lunr/Corona/Parsers/BearerToken/BearerTokenValue.php b/src/Lunr/Corona/Parsers/BearerToken/BearerTokenValue.php new file mode 100644 index 00000000..a908fda6 --- /dev/null +++ b/src/Lunr/Corona/Parsers/BearerToken/BearerTokenValue.php @@ -0,0 +1,27 @@ + diff --git a/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenCliParserGetTest.php b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenCliParserGetTest.php new file mode 100644 index 00000000..04863f4b --- /dev/null +++ b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenCliParserGetTest.php @@ -0,0 +1,99 @@ +assertEquals(BearerTokenValue::class, $this->class->get_request_value_type()); + } + + /** + * Test getting an unsupported value. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenCliParser::get + */ + public function testGetUnsupportedValue() + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Unsupported request value type "Lunr\Corona\Tests\Helpers\MockRequestValue"'); + + $this->class->get(MockRequestValue::Foo); + } + + /** + * Test getting a parsed bearer token. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenCliParser::get + */ + public function testGetParsedBearerToken() + { + $token = '123456789'; + + $this->set_reflection_property_value('bearerToken', $token); + + $value = $this->class->get(BearerTokenValue::BearerToken); + + $this->assertEquals($token, $value); + } + + /** + * Test getting a bearer token when it's not in the authorization header. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenCliParser::get + */ + public function testGetBearerTokenWithMissingCliArgument() + { + $class = new BearerTokenCliParser([]); + + $value = $class->get(BearerTokenValue::BearerToken); + + $this->assertNull($value); + + $property = $this->get_reflection_property('bearerToken'); + + $this->assertNull($property->getValue($class)); + } + + /** + * Test getting a parsed bearer token. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenCliParser::get + */ + public function testGetBearerToken() + { + $token = '123456789'; + + $value = $this->class->get(BearerTokenValue::BearerToken); + + $this->assertEquals($token, $value); + $this->assertPropertySame('bearerToken', $token); + } + +} + +?> diff --git a/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenCliParserTest.php b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenCliParserTest.php new file mode 100644 index 00000000..aa9315d2 --- /dev/null +++ b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenCliParserTest.php @@ -0,0 +1,59 @@ + [ + $token, + ] + ]; + + $this->class = new BearerTokenCliParser($ast); + + parent::baseSetUp($this->class); + } + + /** + * TestCase Destructor. + */ + public function tearDown(): void + { + unset($this->class); + + parent::tearDown(); + } + +} + +?> diff --git a/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenParserGetTest.php b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenParserGetTest.php new file mode 100644 index 00000000..f08f387f --- /dev/null +++ b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenParserGetTest.php @@ -0,0 +1,112 @@ +assertEquals(BearerTokenValue::class, $this->class->get_request_value_type()); + } + + /** + * Test getting an unsupported value. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenParser::get + */ + public function testGetUnsupportedValue() + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Unsupported request value type "Lunr\Corona\Tests\Helpers\MockRequestValue"'); + + $this->class->get(MockRequestValue::Foo); + } + + /** + * Test getting a parsed bearer token. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenParser::get + */ + public function testGetParsedBearerToken() + { + $token = '123456789'; + + $this->set_reflection_property_value('bearerToken', $token); + + $value = $this->class->get(BearerTokenValue::BearerToken); + + $this->assertEquals($token, $value); + } + + /** + * Test getting a bearer token when it's not in the authorization header. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenParser::get + */ + public function testGetBearerTokenWithOtherAuthorization() + { + $_SERVER['HTTP_AUTHORIZATION'] = 'Token 123456789'; + + $value = $this->class->get(BearerTokenValue::BearerToken); + + $this->assertNull($value); + $this->assertPropertySame('bearerToken', NULL); + } + + /** + * Test getting a bearer token when it's invalid in the authorization header. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenParser::get + */ + public function testGetBearerTokenWithInvalidAuthorization() + { + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer 123456789'; + + $value = $this->class->get(BearerTokenValue::BearerToken); + + $this->assertNull($value); + $this->assertPropertySame('bearerToken', NULL); + } + + /** + * Test getting a parsed bearer token. + * + * @covers Lunr\Corona\Parsers\BearerToken\BearerTokenParser::get + */ + public function testGetBearerToken() + { + $token = '123456789'; + + $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer 123456789'; + + $value = $this->class->get(BearerTokenValue::BearerToken); + + $this->assertEquals($token, $value); + $this->assertPropertySame('bearerToken', $token); + } + +} + +?> diff --git a/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenParserTest.php b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenParserTest.php new file mode 100644 index 00000000..512f8292 --- /dev/null +++ b/src/Lunr/Corona/Parsers/BearerToken/Tests/BearerTokenParserTest.php @@ -0,0 +1,51 @@ +class = new BearerTokenParser(); + + parent::baseSetUp($this->class); + } + + /** + * TestCase Destructor. + */ + public function tearDown(): void + { + unset($this->class); + + parent::tearDown(); + } + +} + +?> diff --git a/src/Lunr/Corona/Tests/WebRequestParserParseRequestTest.php b/src/Lunr/Corona/Tests/WebRequestParserParseRequestTest.php index d6da2ad1..a8e817b4 100644 --- a/src/Lunr/Corona/Tests/WebRequestParserParseRequestTest.php +++ b/src/Lunr/Corona/Tests/WebRequestParserParseRequestTest.php @@ -496,66 +496,6 @@ public function testParseRequestSetsRequestIdFromWebserver(): void $this->cleanup_request_test(); } - /** - * Test that the bearer_token is NULL with non bearer authentication. - * - * @covers Lunr\Corona\WebRequestParser::parse_request - */ - public function testRequestNonBearerAuthentication() - { - $this->prepare_request_test(); - - $_SERVER['HTTP_AUTHORIZATION'] = 'Token 123456789'; - - $request = $this->class->parse_request(); - - $this->assertIsArray($request); - $this->assertArrayHasKey('bearer_token', $request); - $this->assertNull($request['bearer_token']); - - $this->cleanup_request_test(); - } - - /** - * Test that the bearer_token is NULL with non bearer authentication. - * - * @covers Lunr\Corona\WebRequestParser::parse_request - */ - public function testRequestInvalidBearerAuthentication() - { - $this->prepare_request_test(); - - $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer 123456789'; - - $request = $this->class->parse_request(); - - $this->assertIsArray($request); - $this->assertArrayHasKey('bearer_token', $request); - $this->assertNull($request['bearer_token']); - - $this->cleanup_request_test(); - } - - /** - * Test that parse_request() sets the bearer_token. - * - * @covers Lunr\Corona\WebRequestParser::parse_request - */ - public function testRequestBearerAuthentication() - { - $this->prepare_request_test(); - - $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer 123456789'; - - $request = $this->class->parse_request(); - - $this->assertIsArray($request); - $this->assertArrayHasKey('bearer_token', $request); - $this->assertSame('123456789', $request['bearer_token']); - - $this->cleanup_request_test(); - } - } ?> diff --git a/src/Lunr/Corona/WebRequestParser.php b/src/Lunr/Corona/WebRequestParser.php index 21a76cbb..ec4ee207 100644 --- a/src/Lunr/Corona/WebRequestParser.php +++ b/src/Lunr/Corona/WebRequestParser.php @@ -143,17 +143,6 @@ public function parse_request() $request['useragent'] = $_SERVER['HTTP_USER_AGENT']; } - $request['bearer_token'] = NULL; - - if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER)) - { - $matches = []; - if (preg_match('/^Bearer ([^ ]+)$/', $_SERVER['HTTP_AUTHORIZATION'], $matches) === 1) - { - $request['bearer_token'] = $matches[1]; - } - } - // Preset with default values: $request['controller'] = $this->config['default_controller']; $request['method'] = $this->config['default_method']; diff --git a/src/Lunr/Shadow/CliRequestParser.php b/src/Lunr/Shadow/CliRequestParser.php index 9b1a0a52..d6fb8b66 100644 --- a/src/Lunr/Shadow/CliRequestParser.php +++ b/src/Lunr/Shadow/CliRequestParser.php @@ -94,7 +94,6 @@ public function parse_request() $request['device_useragent'] = NULL; $request['useragent'] = NULL; - $request['bearer_token'] = NULL; foreach ([ 'action', 'x' ] as $key) { @@ -117,11 +116,6 @@ public function parse_request() $request['useragent'] = $this->ast['useragent'][0]; } - if (array_key_exists('bearer-token', $this->ast)) - { - $request['bearer_token'] = $this->ast['bearer-token'][0]; - } - foreach ([ 'controller', 'method', 'c', 'm' ] as $key) { if (array_key_exists($key, $this->ast)) diff --git a/src/Lunr/Shadow/Tests/CliRequestParserParseRequestTest.php b/src/Lunr/Shadow/Tests/CliRequestParserParseRequestTest.php index 94d2bfc8..ec386f49 100644 --- a/src/Lunr/Shadow/Tests/CliRequestParserParseRequestTest.php +++ b/src/Lunr/Shadow/Tests/CliRequestParserParseRequestTest.php @@ -359,28 +359,6 @@ public function testParseRequestSetsVerbosityLevel($key, $amount, $level): void $this->cleanup_request_test(); } - /** - * Test that the authentication bearer token is stored correctly. - */ - public function testRequestWithPassedBearerToken(): void - { - $this->prepare_request_test(); - - $ast = $this->get_reflection_property_value('ast'); - - $ast['bearer-token'] = [ 'a1b2c3d4' ]; - - $this->set_reflection_property_value('ast', $ast); - - $request = $this->class->parse_request(); - - $this->assertIsArray($request); - $this->assertArrayHasKey('bearer_token', $request); - $this->assertSame('a1b2c3d4', $request['bearer_token']); - - $this->cleanup_request_test(); - } - } ?> diff --git a/tests/phpstan.neon.dist b/tests/phpstan.neon.dist index 0ead84d3..edc6066a 100644 --- a/tests/phpstan.neon.dist +++ b/tests/phpstan.neon.dist @@ -8,6 +8,10 @@ parameters: excludePaths: - ../src/*/Tests/* ignoreErrors: + - + identifier: property.uninitializedReadonly + - + identifier: property.readOnlyAssignNotInConstructor - message: '#Variable \$(response|result) might not be defined.#' paths: diff --git a/tests/phpunit.xml b/tests/phpunit.xml index bc1c1591..32bd1af0 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -22,6 +22,7 @@ ../src/Lunr/Corona/Tests/ ../src/Lunr/Corona/Exceptions/Tests/ + ../src/Lunr/Corona/Parsers/BearerToken/Tests/ ../src/Lunr/Ray/Tests/ @@ -42,6 +43,7 @@ ../src/Lunr/Core/Tests/ ../src/Lunr/Corona/Tests/ ../src/Lunr/Corona/Exceptions/Tests/ + ../src/Lunr/Corona/Parsers/BearerToken/Tests/ ../src/Lunr/Ray/Tests/ ../src/Lunr/Shadow/Tests/ ../src/Lunr/Spark/Tests/