From 7ec35d2e22a105040ac653d1caf9fe2e8089d124 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Sun, 10 Dec 2023 13:05:38 -0600 Subject: [PATCH] Removing ServiceAbstractBase.php --- docs/getting_started_03_create_rest_method.md | 6 +- docs/rest.md | 4 +- src/Model/User.php | 2 +- src/Repository/BaseRepository.php | 5 +- src/Rest/DummyHexRest.php | 16 +++-- src/Rest/DummyRest.php | 16 +++-- src/Rest/Login.php | 20 +++--- src/Rest/Sample.php | 2 +- src/Rest/SampleProtected.php | 7 +- .../JwtContext.php} | 69 +++---------------- src/Util/OpenApiContext.php | 40 +++++++++++ templates/codegen/rest.php.jinja | 16 +++-- 12 files changed, 102 insertions(+), 101 deletions(-) rename src/{Rest/ServiceAbstractBase.php => Util/JwtContext.php} (52%) create mode 100644 src/Util/OpenApiContext.php diff --git a/docs/getting_started_03_create_rest_method.md b/docs/getting_started_03_create_rest_method.md index 7629c39..2791116 100644 --- a/docs/getting_started_03_create_rest_method.md +++ b/docs/getting_started_03_create_rest_method.md @@ -102,10 +102,10 @@ public function putExampleCrudStatus(HttpResponse $response, HttpRequest $reques // Use one of the following methods: // a. Require a user with role admin - $data = $this->requireRole("admin"); + $data = JwtContext::requireRole("admin"); // b. OR require any logged user - $data = $this->requireAuthenticated(); + $data = JwtContext::requireAuthenticated(); // c. OR do nothing to make the endpoint public } @@ -137,7 +137,7 @@ public function putExampleCrudStatus(HttpResponse $response, HttpRequest $reques // The line below will validate again the OpenAPI attributes // If the request doesn't match, an exception `Error400Exception` will be thrown // If the request matches, the payload will be returned - $payload = $this->validateRequest($request); + $payload = OpenApiContext::validateRequest($request); } ``` diff --git a/docs/rest.md b/docs/rest.md index 50e1480..dd611a1 100644 --- a/docs/rest.md +++ b/docs/rest.md @@ -38,7 +38,7 @@ namespace RestReferenceArchitecture\Rest; use ByJG\RestServer\HttpRequest; use ByJG\RestServer\HttpResponse; -class Login extends ServiceAbstractBase +class Login public function mymethod(HttpRequest $request, HttpResponse $response) { // ... @@ -59,7 +59,7 @@ use ByJG\RestServer\HttpRequest; use ByJG\RestServer\HttpResponse; use OpenApi\Attributes as OA; -class Login extends ServiceAbstractBase +class Login /** * Do login diff --git a/src/Model/User.php b/src/Model/User.php index b5c0b62..f3c6930 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -8,7 +8,7 @@ use OpenApi\Attributes as OA; use RestReferenceArchitecture\Psr11; -#[OA\Schema(required: ["email"], type: "object", xml: new \OpenApi\Attributes\Xml(name: "User"))] +#[OA\Schema(required: ["email"], type: "object", xml: new OA\Xml(name: "User"))] class User extends UserModel { // Property Fields diff --git a/src/Repository/BaseRepository.php b/src/Repository/BaseRepository.php index 49bfd01..95f9cad 100644 --- a/src/Repository/BaseRepository.php +++ b/src/Repository/BaseRepository.php @@ -10,6 +10,7 @@ use ByJG\MicroOrm\Mapper; use ByJG\MicroOrm\Query; use ByJG\MicroOrm\Repository; +use ByJG\MicroOrm\UpdateConstraint; use ByJG\Serializer\Exception\InvalidArgumentException; use RestReferenceArchitecture\Psr11; use RestReferenceArchitecture\Util\HexUuidLiteral; @@ -186,9 +187,9 @@ protected function setClosureFixBinaryUUID(?Mapper $mapper, $binPropertyName = ' * @throws OrmInvalidFieldsException * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException */ - public function save($model) + public function save($model, ?UpdateConstraint $updateConstraint = null) { - $model = $this->repository->save($model); + $model = $this->repository->save($model, $updateConstraint); $primaryKey = $this->repository->getMapper()->getPrimaryKey()[0]; diff --git a/src/Rest/DummyHexRest.php b/src/Rest/DummyHexRest.php index 0990b72..a41b206 100644 --- a/src/Rest/DummyHexRest.php +++ b/src/Rest/DummyHexRest.php @@ -23,8 +23,10 @@ use RestReferenceArchitecture\Model\User; use RestReferenceArchitecture\Psr11; use RestReferenceArchitecture\Repository\DummyHexRepository; +use RestReferenceArchitecture\Util\JwtContext; +use RestReferenceArchitecture\Util\OpenApiContext; -class DummyHexRest extends ServiceAbstractBase +class DummyHexRest { /** * Get the DummyHex by id @@ -66,7 +68,7 @@ class DummyHexRest extends ServiceAbstractBase )] public function getDummyHex(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireAuthenticated(); + $data = JwtContext::requireAuthenticated(); $dummyHexRepo = Psr11::container()->get(DummyHexRepository::class); $id = $request->param('id'); @@ -152,7 +154,7 @@ public function getDummyHex(HttpResponse $response, HttpRequest $request): void )] public function listDummyHex(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireAuthenticated(); + $data = JwtContext::requireAuthenticated(); $repo = Psr11::container()->get(DummyHexRepository::class); @@ -225,9 +227,9 @@ public function listDummyHex(HttpResponse $response, HttpRequest $request): void )] public function postDummyHex(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireRole(User::ROLE_ADMIN); + $data = JwtContext::requireRole(User::ROLE_ADMIN); - $payload = $this->validateRequest($request); + $payload = OpenApiContext::validateRequest($request); $model = new DummyHex(); BinderObject::bind($payload, $model); @@ -284,9 +286,9 @@ public function postDummyHex(HttpResponse $response, HttpRequest $request): void )] public function putDummyHex(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireRole(User::ROLE_ADMIN); + $data = JwtContext::requireRole(User::ROLE_ADMIN); - $payload = $this->validateRequest($request); + $payload = OpenApiContext::validateRequest($request); $dummyHexRepo = Psr11::container()->get(DummyHexRepository::class); $model = $dummyHexRepo->get($payload['id']); diff --git a/src/Rest/DummyRest.php b/src/Rest/DummyRest.php index da16265..e4e892f 100644 --- a/src/Rest/DummyRest.php +++ b/src/Rest/DummyRest.php @@ -23,8 +23,10 @@ use RestReferenceArchitecture\Model\User; use RestReferenceArchitecture\Psr11; use RestReferenceArchitecture\Repository\DummyRepository; +use RestReferenceArchitecture\Util\JwtContext; +use RestReferenceArchitecture\Util\OpenApiContext; -class DummyRest extends ServiceAbstractBase +class DummyRest { /** * Get the Dummy by id @@ -66,7 +68,7 @@ class DummyRest extends ServiceAbstractBase )] public function getDummy(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireAuthenticated(); + $data = JwtContext::requireAuthenticated(); $dummyRepo = Psr11::container()->get(DummyRepository::class); $id = $request->param('id'); @@ -152,7 +154,7 @@ public function getDummy(HttpResponse $response, HttpRequest $request): void )] public function listDummy(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireAuthenticated(); + $data = JwtContext::requireAuthenticated(); $repo = Psr11::container()->get(DummyRepository::class); @@ -225,9 +227,9 @@ public function listDummy(HttpResponse $response, HttpRequest $request): void )] public function postDummy(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireRole(User::ROLE_ADMIN); + $data = JwtContext::requireRole(User::ROLE_ADMIN); - $payload = $this->validateRequest($request); + $payload = OpenApiContext::validateRequest($request); $model = new Dummy(); BinderObject::bind($payload, $model); @@ -284,9 +286,9 @@ public function postDummy(HttpResponse $response, HttpRequest $request): void )] public function putDummy(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireRole(User::ROLE_ADMIN); + $data = JwtContext::requireRole(User::ROLE_ADMIN); - $payload = $this->validateRequest($request); + $payload = OpenApiContext::validateRequest($request); $dummyRepo = Psr11::container()->get(DummyRepository::class); $model = $dummyRepo->get($payload['id']); diff --git a/src/Rest/Login.php b/src/Rest/Login.php index 0ad0157..9d6392c 100644 --- a/src/Rest/Login.php +++ b/src/Rest/Login.php @@ -14,8 +14,10 @@ use RestReferenceArchitecture\Psr11; use RestReferenceArchitecture\Repository\BaseRepository; use RestReferenceArchitecture\Util\HexUuidLiteral; +use RestReferenceArchitecture\Util\JwtContext; +use RestReferenceArchitecture\Util\OpenApiContext; -class Login extends ServiceAbstractBase +class Login { /** * Do login @@ -53,16 +55,16 @@ class Login extends ServiceAbstractBase )] public function post(HttpResponse $response, HttpRequest $request) { - $this->validateRequest($request); + OpenApiContext::validateRequest($request); $json = json_decode($request->payload()); $users = Psr11::container()->get(UsersDBDataset::class); $user = $users->isValidUser($json->username, $json->password); - $metadata = $this->createUserMetadata($user); + $metadata = JwtContext::createUserMetadata($user); $response->getResponseBag()->setSerializationRule(ResponseBag::SINGLE_OBJECT); - $response->write(['token' => $this->createToken($metadata)]); + $response->write(['token' => JwtContext::createToken($metadata)]); $response->write(['data' => $metadata]); } @@ -99,7 +101,7 @@ public function post(HttpResponse $response, HttpRequest $request) )] public function refreshToken(HttpResponse $response, HttpRequest $request) { - $result = $this->requireAuthenticated(null, true); + $result = JwtContext::requireAuthenticated(null, true); $diff = ($result["exp"] - time()) / 60; @@ -110,10 +112,10 @@ public function refreshToken(HttpResponse $response, HttpRequest $request) $users = Psr11::container()->get(UsersDBDataset::class); $user = $users->getById(new HexUuidLiteral($result["data"]["userid"])); - $metadata = $this->createUserMetadata($user); + $metadata = JwtContext::createUserMetadata($user); $response->getResponseBag()->setSerializationRule(ResponseBag::SINGLE_OBJECT); - $response->write(['token' => $this->createToken($metadata)]); + $response->write(['token' => JwtContext::createToken($metadata)]); $response->write(['data' => $metadata]); } @@ -147,7 +149,7 @@ public function refreshToken(HttpResponse $response, HttpRequest $request) )] public function postResetRequest(HttpResponse $response, HttpRequest $request) { - $this->validateRequest($request); + OpenApiContext::validateRequest($request); $json = json_decode($request->payload()); @@ -179,7 +181,7 @@ public function postResetRequest(HttpResponse $response, HttpRequest $request) protected function validateResetToken($response, $request): array { - $this->validateRequest($request); + OpenApiContext::validateRequest($request); $json = json_decode($request->payload()); diff --git a/src/Rest/Sample.php b/src/Rest/Sample.php index c085beb..ba10039 100644 --- a/src/Rest/Sample.php +++ b/src/Rest/Sample.php @@ -6,7 +6,7 @@ use ByJG\RestServer\HttpResponse; use OpenApi\Attributes as OA; -class Sample extends ServiceAbstractBase +class Sample { /** * Simple ping diff --git a/src/Rest/SampleProtected.php b/src/Rest/SampleProtected.php index e54f219..151a425 100644 --- a/src/Rest/SampleProtected.php +++ b/src/Rest/SampleProtected.php @@ -8,8 +8,9 @@ use ByJG\RestServer\HttpResponse; use OpenApi\Attributes as OA; use Psr\SimpleCache\InvalidArgumentException; +use RestReferenceArchitecture\Util\JwtContext; -class SampleProtected extends ServiceAbstractBase +class SampleProtected { /** * Sample Ping Only Authenticated @@ -43,7 +44,7 @@ class SampleProtected extends ServiceAbstractBase )] public function getPing(HttpResponse $response, HttpRequest $request) { - $this->requireAuthenticated(); + JwtContext::requireAuthenticated(); $response->write([ 'result' => 'pong' @@ -83,7 +84,7 @@ public function getPing(HttpResponse $response, HttpRequest $request) )] public function getPingAdm(HttpResponse $response, HttpRequest $request) { - $this->requireRole('admin'); + JwtContext::requireRole('admin'); $response->write([ 'result' => 'pongadm' diff --git a/src/Rest/ServiceAbstractBase.php b/src/Util/JwtContext.php similarity index 52% rename from src/Rest/ServiceAbstractBase.php rename to src/Util/JwtContext.php index 0c46143..92c45c4 100644 --- a/src/Rest/ServiceAbstractBase.php +++ b/src/Util/JwtContext.php @@ -1,38 +1,30 @@ get(JwtWrapper::class); - $jwtData = $jwt->createJwtData($properties, 60 * 60 * 10); // 10 hours + $jwtData = $jwt->createJwtData($properties, 60 * 60 * 24 * 7); // 7 Dias return $jwt->generateToken($jwtData); } - public function extractToken($token = null, $fullToken = false, $throwException = false) + public static function extractToken($token = null, $fullToken = false, $throwException = false) { try { $jwt = Psr11::container()->get(JwtWrapper::class); @@ -89,9 +80,9 @@ public function extractToken($token = null, $fullToken = false, $throwException * @throws Error401Exception * @throws InvalidArgumentException */ - public function requireAuthenticated($token = null, $fullToken = false) + public static function requireAuthenticated($token = null, $fullToken = false) { - return $this->extractToken($token, $fullToken, true); + return self::extractToken($token, $fullToken, true); } /** @@ -102,52 +93,12 @@ public function requireAuthenticated($token = null, $fullToken = false) * @throws Error403Exception * @throws InvalidArgumentException */ - public function requireRole($role, $token = null) + public static function requireRole($role, $token = null) { - $data = $this->requireAuthenticated($token); + $data = self::requireAuthenticated($token); if ($data['role'] !== $role) { throw new Error403Exception('Insufficient privileges'); } return $data; } - - /** - * @throws DependencyInjectionException - * @throws InvalidDateException - * @throws ConfigNotFoundException - * @throws KeyNotFoundException - * @throws Error400Exception - * @throws InvalidArgumentException - * @throws ConfigException - * @throws PathNotFoundException - * @throws ReflectionException - * @throws HttpMethodNotFoundException - */ - public function validateRequest(HttpRequest $request) - { - $schema = Psr11::container()->get(Schema::class); - - $path = $request->getRequestPath(); - $method = $request->server('REQUEST_METHOD'); - - // Returns a SwaggerRequestBody instance - $bodyRequestDef = $schema->getRequestParameters($path, $method); - - // Validate the request body (payload) - if (str_contains($request->getHeader('Content-Type'), 'multipart/')) { - $requestBody = $request->post(); - $files = $request->uploadedFiles()->getKeys(); - $requestBody = array_merge($requestBody, array_combine($files, $files)); - } else { - $requestBody = json_decode($request->payload(), true); - } - - try { - $bodyRequestDef->match($requestBody); - } catch (Exception $ex) { - throw new Error400Exception(explode("\n", $ex->getMessage())[0]); - } - - return $requestBody; - } } diff --git a/src/Util/OpenApiContext.php b/src/Util/OpenApiContext.php new file mode 100644 index 0000000..4766791 --- /dev/null +++ b/src/Util/OpenApiContext.php @@ -0,0 +1,40 @@ +get(Schema::class); + + $path = $request->getRequestPath(); + $method = $request->server('REQUEST_METHOD'); + + // Returns a SwaggerRequestBody instance + $bodyRequestDef = $schema->getRequestParameters($path, $method); + + // Validate the request body (payload) + if (str_contains($request->getHeader('Content-Type'), 'multipart/')) { + $requestBody = $request->post(); + $files = $request->uploadedFiles()->getKeys(); + $requestBody = array_merge($requestBody, array_combine($files, $files)); + } else { + $requestBody = json_decode($request->payload(), true); + } + + try { + $bodyRequestDef->match($requestBody); + } catch (Exception $ex) { + throw new Error400Exception(explode("\n", $ex->getMessage())[0]); + } + + return $requestBody; + } +} \ No newline at end of file diff --git a/templates/codegen/rest.php.jinja b/templates/codegen/rest.php.jinja index 7549c6e..c78138d 100644 --- a/templates/codegen/rest.php.jinja +++ b/templates/codegen/rest.php.jinja @@ -23,8 +23,10 @@ use {{ namespace }}\Model\{{ className }}; use {{ namespace }}\Psr11; use {{ namespace }}\Repository\{{ className }}Repository; use {{ namespace }}\Model\User; +use {{ namespace }}\Util\Jwt; +use {{ namespace }}\Util\OpenApiContext; -class {{ className }}Rest extends ServiceAbstractBase +class {{ className }}Rest { /** * Get the {{ className }} by id @@ -66,7 +68,7 @@ class {{ className }}Rest extends ServiceAbstractBase )] public function get{{ className }}(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireAuthenticated(); + $data = JwtContext::requireAuthenticated(); ${{ varTableName }}Repo = Psr11::container()->get({{ className }}Repository::class); $id = $request->param('id'); @@ -152,7 +154,7 @@ class {{ className }}Rest extends ServiceAbstractBase )] public function list{{ className }}(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireAuthenticated(); + $data = JwtContext::requireAuthenticated(); $repo = Psr11::container()->get({{ className }}Repository::class); @@ -227,9 +229,9 @@ class {{ className }}Rest extends ServiceAbstractBase )] public function post{{ className }}(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireRole(User::ROLE_ADMIN); + $data = JwtContext::requireRole(User::ROLE_ADMIN); - $payload = $this->validateRequest($request); + $payload = OpenApiContext::validateRequest($request); $model = new {{ className }}(); BinderObject::bind($payload, $model); @@ -286,9 +288,9 @@ class {{ className }}Rest extends ServiceAbstractBase )] public function put{{ className }}(HttpResponse $response, HttpRequest $request): void { - $data = $this->requireRole(User::ROLE_ADMIN); + $data = JwtContext::requireRole(User::ROLE_ADMIN); - $payload = $this->validateRequest($request); + $payload = OpenApiContext::validateRequest($request); ${{ varTableName }}Repo = Psr11::container()->get({{ className }}Repository::class); $model = ${{ varTableName }}Repo->get($payload['{{ fields.0.field }}']);