From 779c2d6cf097c9aa754ddc8cb51e88824ca10436 Mon Sep 17 00:00:00 2001 From: Syndesi Date: Sat, 7 Oct 2023 15:07:18 +0200 Subject: [PATCH] wip --- config/services.yaml | 1 + docs/_sidebar.md | 2 +- docs/api-endpoints/element/post-index.md | 187 +++++++++++++++++- .../post-index/204-response-header.txt | 8 + .../element/post-index/400-response-body.json | 6 + .../post-index/400-response-header.txt | 10 + .../element/post-index/401-response-body.json | 6 + .../post-index/401-response-header.txt | 10 + .../element/post-index/403-response-body.json | 6 + .../post-index/403-response-header.txt | 10 + .../element/post-index/429-response-body.json | 6 + .../post-index/429-response-header.txt | 9 + .../Element/DeleteElementController.php | 6 - .../Element/GetChildrenController.php | 6 - .../Element/GetElementController.php | 6 - src/Controller/Element/GetIndexController.php | 5 - .../Element/GetParentsController.php | 6 - .../Element/GetRelatedController.php | 6 - .../Element/PatchElementController.php | 6 - .../Element/PostElementController.php | 71 ++++--- .../Element/PostIndexController.php | 150 ++++---------- .../Element/PutElementController.php | 53 ++--- .../Search/PostSearchController.php | 5 - src/Controller/User/DeleteTokenController.php | 6 - src/Controller/User/GetMeController.php | 6 - src/Controller/User/GetTokenController.php | 8 - .../Event/ElementPropertyChangeEvent.php | 6 +- ...okenElementPropertyChangeEventListener.php | 2 +- ...UserElementPropertyChangeEventListener.php | 2 +- .../Event/ElementPropertyResetEvent.php | 43 ++++ ...eatedElementPropertyResetEventListener.php | 13 ++ .../IdElementPropertyResetEventListener.php | 13 ++ ...TokenElementPropertyResetEventListener.php | 22 +++ ...datedElementPropertyResetEventListener.php | 13 ++ .../UserElementPropertyResetEventListener.php | 21 ++ .../ElementPropertyReset/config.yaml | 35 ++++ src/Security/AuthProvider.php | 6 +- .../CreateElementFromRawDataService.php | 74 +++++++ src/Service/ResetElementPropertiesService.php | 33 ++++ .../UpdateElementFromRawDataService.php | 57 ++++++ .../Event/ElementPropertyChangeEventTest.php | 4 +- tests/UnitTests/Security/AuthProviderTest.php | 9 +- 42 files changed, 696 insertions(+), 258 deletions(-) create mode 100644 docs/api-endpoints/element/post-index/204-response-header.txt create mode 100644 docs/api-endpoints/element/post-index/400-response-body.json create mode 100644 docs/api-endpoints/element/post-index/400-response-header.txt create mode 100644 docs/api-endpoints/element/post-index/401-response-body.json create mode 100644 docs/api-endpoints/element/post-index/401-response-header.txt create mode 100644 docs/api-endpoints/element/post-index/403-response-body.json create mode 100644 docs/api-endpoints/element/post-index/403-response-header.txt create mode 100644 docs/api-endpoints/element/post-index/429-response-body.json create mode 100644 docs/api-endpoints/element/post-index/429-response-header.txt create mode 100644 src/EventSystem/ElementPropertyReset/Event/ElementPropertyResetEvent.php create mode 100644 src/EventSystem/ElementPropertyReset/EventListener/CreatedElementPropertyResetEventListener.php create mode 100644 src/EventSystem/ElementPropertyReset/EventListener/IdElementPropertyResetEventListener.php create mode 100644 src/EventSystem/ElementPropertyReset/EventListener/TokenElementPropertyResetEventListener.php create mode 100644 src/EventSystem/ElementPropertyReset/EventListener/UpdatedElementPropertyResetEventListener.php create mode 100644 src/EventSystem/ElementPropertyReset/EventListener/UserElementPropertyResetEventListener.php create mode 100644 src/EventSystem/ElementPropertyReset/config.yaml create mode 100644 src/Service/CreateElementFromRawDataService.php create mode 100644 src/Service/ResetElementPropertiesService.php create mode 100644 src/Service/UpdateElementFromRawDataService.php diff --git a/config/services.yaml b/config/services.yaml index 3c75052a..f0d095ee 100755 --- a/config/services.yaml +++ b/config/services.yaml @@ -12,6 +12,7 @@ imports: - {resource: ../src/EventSystem/NormalizedValueToRawValue/config.yaml} - {resource: ../src/EventSystem/RawValueToNormalizedValue/config.yaml} - {resource: ../src/EventSystem/ElementPropertyChange/config.yaml} + - {resource: ../src/EventSystem/ElementPropertyReset/config.yaml} - {resource: ../src/EventSystem/ElementPropertyReturn/config.yaml} services: diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 84b2455c..13984e68 100755 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -28,7 +28,7 @@ - [GET` //parents -` Get Parents](/api-endpoints/element/get-parents) - [GET` //children -` Get Children](/api-endpoints/element/get-children) - [GET` //related -` Get Related](/api-endpoints/element/get-related) - - [POST` / -` Create Root Element](/api-endpoints/element/post-index) + - [POST` / -` Create Root Level Element](/api-endpoints/element/post-index) - [POST` / -` Create Element](/api-endpoints/element/post-element) - [PUT` / -` Replace Element](/api-endpoints/element/put-element) - [PATCH` / -` Update Element](/api-endpoints/element/patch-element) diff --git a/docs/api-endpoints/element/post-index.md b/docs/api-endpoints/element/post-index.md index 591f8a58..83c4dab5 100644 --- a/docs/api-endpoints/element/post-index.md +++ b/docs/api-endpoints/element/post-index.md @@ -1,3 +1,188 @@ -# POST` / -` Create Root Element +# POST` / -` Create Root Level Element + + + + Creates a new data element. If the data element is a node, it is directly owned by the current user. + +## Request Body + +The posted request must be a valid JSON document. + +The request must contain the following attributes: + +- `type`: The type of element to be created. Internally used types might have restrictions. +- `id`: The elements UUID, optional. If not set, the API will generate one for you. +- `start`: The start node's UUID, only required for relations. +- `end`: The end node's UUID, only required for relations. +- `data`: Data related to the element in the form of an JSON object. Restrictions might apply to internally used + properties. If no properties should be used, send an empty object, e.g. `"data": {}`; + +```json +{ + "type": "Demo", + "data": { + "hello": "world :D" + } +} +``` + +## Request Example + +```bash +curl \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{"type": "Demo", "data": {"hello": "world :D"}}' \ + https://api.localhost/ +``` + + + +### **🟢 Success 204** + +
Response Headers
+ +[Response Body](./post-index/204-response-header.txt ':include :type=code') + +Success response does not have a response body. The UUID of the created element is written in the `Location`-header. + +### **🔴 Error 400** + +
Response Headers
+ +[Response Body](./post-index/400-response-header.txt ':include :type=code') + +
Response Body
+ +[Response Body](./post-index/400-response-body.json ':include :type=code problem+json') + +### **🔴 Error 401** + +
Response Headers
+ +[Response Body](./post-index/401-response-header.txt ':include :type=code') + +
Response Body
+ +[Response Body](./post-index/401-response-body.json ':include :type=code problem+json') + +### **🔴 Error 403** + +
Response Headers
+ +[Response Body](./post-index/403-response-header.txt ':include :type=code') + +
Response Body
+ +[Response Body](./post-index/403-response-body.json ':include :type=code problem+json') + +### **🔴 Error 429** + +
Response Headers
+ +[Response Body](./post-index/429-response-header.txt ':include :type=code') + +
Response Body
+ +[Response Body](./post-index/429-response-body.json ':include :type=code problem+json') + + + + + +## Internal Workflow + +Once the server receives such a request, it checks several things internally: + +
+ + + + diff --git a/docs/api-endpoints/element/post-index/204-response-header.txt b/docs/api-endpoints/element/post-index/204-response-header.txt new file mode 100644 index 00000000..75ed1a08 --- /dev/null +++ b/docs/api-endpoints/element/post-index/204-response-header.txt @@ -0,0 +1,8 @@ +Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method +Access-Control-Allow-Methods: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Access-Control-Allow-Origin: * +Allow: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Cache-Control: no-cache, private +Date: Fri, 29 Sep 2023 10:05:24 GMT +Server: Unit +X-Powered-By: Ember-Nexus-API \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/400-response-body.json b/docs/api-endpoints/element/post-index/400-response-body.json new file mode 100644 index 00000000..f9716d0a --- /dev/null +++ b/docs/api-endpoints/element/post-index/400-response-body.json @@ -0,0 +1,6 @@ +{ + "type": "http://ember-nexus-api/error/400/bad-content", + "title": "Bad content", + "status": 400, + "detail": "Endpoint expects property 'type' to be ActionChangePassword, got 'NotActionChangePassword'." +} \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/400-response-header.txt b/docs/api-endpoints/element/post-index/400-response-header.txt new file mode 100644 index 00000000..10cf4a3b --- /dev/null +++ b/docs/api-endpoints/element/post-index/400-response-header.txt @@ -0,0 +1,10 @@ +Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method +Access-Control-Allow-Methods: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Access-Control-Allow-Origin: * +Allow: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Cache-Control: no-cache, private +Content-Type: application/problem+json; charset=utf-8 +Date: Fri, 29 Sep 2023 10:11:29 GMT +Server: Unit +Transfer-Encoding: chunked +X-Powered-By: Ember-Nexus-API \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/401-response-body.json b/docs/api-endpoints/element/post-index/401-response-body.json new file mode 100644 index 00000000..6f9e2f20 --- /dev/null +++ b/docs/api-endpoints/element/post-index/401-response-body.json @@ -0,0 +1,6 @@ +{ + "type": "http://ember-nexus-api/error/401/unauthorized", + "title": "Unauthorized", + "status": 401, + "detail": "Authorization for the request failed due to possible problems with the token (incorrect or expired), password (incorrect or changed), the user's unique identifier, or the user's status (e.g., missing, blocked, or deleted)." +} \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/401-response-header.txt b/docs/api-endpoints/element/post-index/401-response-header.txt new file mode 100644 index 00000000..9a7fd330 --- /dev/null +++ b/docs/api-endpoints/element/post-index/401-response-header.txt @@ -0,0 +1,10 @@ +Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method +Access-Control-Allow-Methods: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Access-Control-Allow-Origin: * +Allow: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Cache-Control: no-cache, private +Content-Type: application/problem+json; charset=utf-8 +Date: Fri, 29 Sep 2023 10:14:53 GMT +Server: Unit +Transfer-Encoding: chunked +X-Powered-By: Ember-Nexus-API \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/403-response-body.json b/docs/api-endpoints/element/post-index/403-response-body.json new file mode 100644 index 00000000..7e8a60e1 --- /dev/null +++ b/docs/api-endpoints/element/post-index/403-response-body.json @@ -0,0 +1,6 @@ +{ + "type": "http://ember-nexus-api/error/403/forbidden", + "title": "Forbidden", + "status": 403, + "detail": "Requested endpoint, element or action is forbidden." +} \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/403-response-header.txt b/docs/api-endpoints/element/post-index/403-response-header.txt new file mode 100644 index 00000000..67a03dc4 --- /dev/null +++ b/docs/api-endpoints/element/post-index/403-response-header.txt @@ -0,0 +1,10 @@ +Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method +Access-Control-Allow-Methods: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Access-Control-Allow-Origin: * +Allow: GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK +Cache-Control: no-cache, private +Content-Type: application/problem+json; charset=utf-8 +Date: Fri, 29 Sep 2023 17:33:00 GMT +Server: Unit +Transfer-Encoding: chunked +X-Powered-By: Ember-Nexus-API \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/429-response-body.json b/docs/api-endpoints/element/post-index/429-response-body.json new file mode 100644 index 00000000..4555b0be --- /dev/null +++ b/docs/api-endpoints/element/post-index/429-response-body.json @@ -0,0 +1,6 @@ +{ + "type": "401-unauthorized", + "title": "Request does not contain valid token, or anonymous user is disabled.", + "status": 401, + "detail": "" +} \ No newline at end of file diff --git a/docs/api-endpoints/element/post-index/429-response-header.txt b/docs/api-endpoints/element/post-index/429-response-header.txt new file mode 100644 index 00000000..1392311c --- /dev/null +++ b/docs/api-endpoints/element/post-index/429-response-header.txt @@ -0,0 +1,9 @@ +Access-Control-Allow-Origin: * +Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method +Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE +Allow: GET, POST, OPTIONS, PUT, PATCH, DELETE +Content-Type: application/json; charset=utf-8 +Cache-Control: no-cache, private +Date: Fri, 15 Sep 2023 08:03:41 GMT +Server: Unit +Transfer-Encoding: chunked \ No newline at end of file diff --git a/src/Controller/Element/DeleteElementController.php b/src/Controller/Element/DeleteElementController.php index e5e30ff6..ef83d6f3 100644 --- a/src/Controller/Element/DeleteElementController.php +++ b/src/Controller/Element/DeleteElementController.php @@ -2,7 +2,6 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Response\NoContentResponse; @@ -21,7 +20,6 @@ public function __construct( private ElementManager $elementManager, private AuthProvider $authProvider, private AccessChecker $accessChecker, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory ) { } @@ -39,10 +37,6 @@ public function deleteElement(string $uuid): Response $elementUuid = UuidV4::fromString($uuid); $userUuid = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - if (!$this->accessChecker->hasAccessToElement($userUuid, $elementUuid, AccessType::DELETE)) { throw $this->client404NotFoundExceptionFactory->createFromTemplate(); } diff --git a/src/Controller/Element/GetChildrenController.php b/src/Controller/Element/GetChildrenController.php index 8c236f72..e2089b66 100644 --- a/src/Controller/Element/GetChildrenController.php +++ b/src/Controller/Element/GetChildrenController.php @@ -2,7 +2,6 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Security\AccessChecker; @@ -24,7 +23,6 @@ public function __construct( private CollectionService $collectionService, private AuthProvider $authProvider, private AccessChecker $accessChecker, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory ) { } @@ -42,10 +40,6 @@ public function getChildren(string $uuid): Response $parentUuid = UuidV4::fromString($uuid); $userUuid = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - $type = $this->accessChecker->getElementType($parentUuid); if (ElementType::RELATION === $type) { // relations can not be parent nodes diff --git a/src/Controller/Element/GetElementController.php b/src/Controller/Element/GetElementController.php index 02026f55..bddbc9cc 100644 --- a/src/Controller/Element/GetElementController.php +++ b/src/Controller/Element/GetElementController.php @@ -2,7 +2,6 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Security\AccessChecker; @@ -20,7 +19,6 @@ public function __construct( private ElementResponseService $elementResponseService, private AuthProvider $authProvider, private AccessChecker $accessChecker, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory ) { } @@ -38,10 +36,6 @@ public function getElement(string $uuid): Response $elementUuid = UuidV4::fromString($uuid); $userUuid = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - if (!$this->accessChecker->hasAccessToElement($userUuid, $elementUuid, AccessType::READ)) { throw $this->client404NotFoundExceptionFactory->createFromTemplate(); } diff --git a/src/Controller/Element/GetIndexController.php b/src/Controller/Element/GetIndexController.php index 3c25e812..2e7b9b08 100644 --- a/src/Controller/Element/GetIndexController.php +++ b/src/Controller/Element/GetIndexController.php @@ -2,7 +2,6 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Security\AuthProvider; use App\Service\CollectionService; use Laudis\Neo4j\Databags\Statement; @@ -18,7 +17,6 @@ public function __construct( private CypherEntityManager $cypherEntityManager, private AuthProvider $authProvider, private CollectionService $collectionService, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory ) { } @@ -30,9 +28,6 @@ public function __construct( public function getIndex(): Response { $userUuid = $this->authProvider->getUserUuid(); - if (null === $userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } $cypherClient = $this->cypherEntityManager->getClient(); $res = $cypherClient->runStatement(Statement::create( "MATCH (user:User {id: \$userId})\n". diff --git a/src/Controller/Element/GetParentsController.php b/src/Controller/Element/GetParentsController.php index 040f0a87..e887b20f 100644 --- a/src/Controller/Element/GetParentsController.php +++ b/src/Controller/Element/GetParentsController.php @@ -2,7 +2,6 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Security\AccessChecker; @@ -24,7 +23,6 @@ public function __construct( private CollectionService $collectionService, private AuthProvider $authProvider, private AccessChecker $accessChecker, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory ) { } @@ -42,10 +40,6 @@ public function getParents(string $uuid): Response $childUuid = UuidV4::fromString($uuid); $userUuid = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - $type = $this->accessChecker->getElementType($childUuid); if (ElementType::RELATION === $type) { // relations can not be child nodes diff --git a/src/Controller/Element/GetRelatedController.php b/src/Controller/Element/GetRelatedController.php index b56bebcc..09761ffc 100644 --- a/src/Controller/Element/GetRelatedController.php +++ b/src/Controller/Element/GetRelatedController.php @@ -2,7 +2,6 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Security\AccessChecker; @@ -24,7 +23,6 @@ public function __construct( private CollectionService $collectionService, private AuthProvider $authProvider, private AccessChecker $accessChecker, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory ) { } @@ -42,10 +40,6 @@ public function getRelated(string $uuid): Response $centerUuid = UuidV4::fromString($uuid); $userUuid = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - $type = $this->accessChecker->getElementType($centerUuid); if (ElementType::RELATION === $type) { // relations can not be center nodes diff --git a/src/Controller/Element/PatchElementController.php b/src/Controller/Element/PatchElementController.php index e3268daf..bff5639c 100644 --- a/src/Controller/Element/PatchElementController.php +++ b/src/Controller/Element/PatchElementController.php @@ -2,7 +2,6 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Response\NoContentResponse; @@ -22,7 +21,6 @@ public function __construct( private ElementManager $elementManager, private AuthProvider $authProvider, private AccessChecker $accessChecker, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory ) { } @@ -40,10 +38,6 @@ public function patchElement(string $uuid, Request $request): Response $elementUuid = UuidV4::fromString($uuid); $userUuid = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - if (!$this->accessChecker->hasAccessToElement($userUuid, $elementUuid, AccessType::UPDATE)) { throw $this->client404NotFoundExceptionFactory->createFromTemplate(); } diff --git a/src/Controller/Element/PostElementController.php b/src/Controller/Element/PostElementController.php index f4a556bd..80af1bfc 100644 --- a/src/Controller/Element/PostElementController.php +++ b/src/Controller/Element/PostElementController.php @@ -3,17 +3,15 @@ namespace App\Controller\Element; use App\Factory\Exception\Client400MissingPropertyExceptionFactory; -use App\Factory\Exception\Client400ReservedIdentifierExceptionFactory; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Response\CreatedResponse; use App\Security\AccessChecker; use App\Security\AuthProvider; +use App\Service\CreateElementFromRawDataService; use App\Service\ElementManager; use App\Type\AccessType; use App\Type\ElementType; -use App\Type\NodeElement; use App\Type\RelationElement; use Ramsey\Uuid\Rfc4122\UuidV4; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -29,10 +27,9 @@ public function __construct( private AccessChecker $accessChecker, private ElementManager $elementManager, private UrlGeneratorInterface $router, - private Client400ReservedIdentifierExceptionFactory $client400ReservedIdentifierExceptionFactory, private Client400MissingPropertyExceptionFactory $client400MissingPropertyExceptionFactory, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, - private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory + private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory, + private CreateElementFromRawDataService $createElementFromRawDataService ) { } @@ -46,32 +43,34 @@ public function __construct( )] public function postElement(string $uuid, Request $request): Response { - $elementUuid = UuidV4::fromString($uuid); - $userUuid = $this->authProvider->getUserUuid(); + $parentElementId = UuidV4::fromString($uuid); + $userId = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - - $type = $this->accessChecker->getElementType($elementUuid); - if (ElementType::RELATION === $type) { + $parentType = $this->accessChecker->getElementType($parentElementId); + if (ElementType::RELATION === $parentType) { // relations can not own nodes throw $this->client404NotFoundExceptionFactory->createFromTemplate(); } - if (!$this->accessChecker->hasAccessToElement($userUuid, $elementUuid, AccessType::CREATE)) { + if (!$this->accessChecker->hasAccessToElement($userId, $parentElementId, AccessType::CREATE)) { throw $this->client404NotFoundExceptionFactory->createFromTemplate(); } $body = \Safe\json_decode($request->getContent(), true); - $newNodeUuid = UuidV4::uuid4(); + if (array_key_exists('start', $body)) { + // owns-relation can only target nodes + throw $this->client404NotFoundExceptionFactory->createFromTemplate(); + } + if (array_key_exists('end', $body)) { + // owns-relation can only target nodes + throw $this->client404NotFoundExceptionFactory->createFromTemplate(); + } + if (array_key_exists('id', $body)) { - $newNodeUuid = UuidV4::fromString($body['id']); - $uuidConflict = null !== $this->accessChecker->getElementType($newNodeUuid); - if ($uuidConflict) { - throw $this->client400ReservedIdentifierExceptionFactory->createFromTemplate($newNodeUuid->toString()); - } + $elementId = UuidV4::fromString($body['id']); + } else { + $elementId = UuidV4::uuid4(); } if (!array_key_exists('type', $body)) { @@ -82,36 +81,36 @@ public function postElement(string $uuid, Request $request): Response if (!array_key_exists('data', $body)) { throw $this->client400MissingPropertyExceptionFactory->createFromTemplate('data', 'an object'); } - $data = $body['data']; + $rawData = $body['data']; - $newNode = (new NodeElement()) - ->setIdentifier($newNodeUuid) - ->setLabel($type) - ->addProperties($data); + $element = $this->createElementFromRawDataService->createElementFromRawData( + $elementId, + $type, + rawData: $rawData + ); + $this->elementManager->create($element); $newNodeOwnsRelation = (new RelationElement()) ->setIdentifier(UuidV4::uuid4()) ->setType('OWNS') - ->setStart($elementUuid) - ->setEnd($newNodeUuid); + ->setStart($parentElementId) + ->setEnd($element->getIdentifier()); + $this->elementManager->create($newNodeOwnsRelation); $newNodeCreatedRelation = (new RelationElement()) ->setIdentifier(UuidV4::uuid4()) ->setType('CREATED') - ->setStart($this->authProvider->getUserUuid()) - ->setEnd($newNodeUuid); + ->setStart($userId) + ->setEnd($element->getIdentifier()); + $this->elementManager->create($newNodeCreatedRelation); - $this->elementManager - ->create($newNode) - ->create($newNodeOwnsRelation) - ->create($newNodeCreatedRelation) - ->flush(); + $this->elementManager->flush(); return new CreatedResponse( $this->router->generate( 'get-element', [ - 'uuid' => $newNodeUuid, + 'uuid' => $element->getIdentifier(), ] ) ); diff --git a/src/Controller/Element/PostIndexController.php b/src/Controller/Element/PostIndexController.php index 3b7da2d9..8fb27a8e 100644 --- a/src/Controller/Element/PostIndexController.php +++ b/src/Controller/Element/PostIndexController.php @@ -2,20 +2,17 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client400IncompleteMutualDependencyExceptionFactory; +use App\Contract\NodeElementInterface; use App\Factory\Exception\Client400MissingPropertyExceptionFactory; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Response\CreatedResponse; use App\Security\AccessChecker; use App\Security\AuthProvider; +use App\Service\CreateElementFromRawDataService; use App\Service\ElementManager; use App\Type\AccessType; -use App\Type\NodeElement; use App\Type\RelationElement; -use DateTime; use Ramsey\Uuid\Rfc4122\UuidV4; -use Ramsey\Uuid\UuidInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -34,9 +31,8 @@ public function __construct( private ElementManager $elementManager, private UrlGeneratorInterface $router, private Client400MissingPropertyExceptionFactory $client400MissingPropertyExceptionFactory, - private Client400IncompleteMutualDependencyExceptionFactory $client400IncompleteMutualDependencyExceptionFactory, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, - private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory + private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory, + private CreateElementFromRawDataService $createElementFromRawDataService ) { } @@ -48,9 +44,6 @@ public function __construct( public function postIndex(Request $request): Response { $userId = $this->authProvider->getUserUuid(); - if (!$userId) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } $body = \Safe\json_decode($request->getContent(), true); @@ -65,130 +58,59 @@ public function postIndex(Request $request): Response } $type = $body['type']; - $data = []; + $rawData = []; if (array_key_exists('data', $body)) { - $data = $body['data']; - foreach ($data as $key => $value) { - if (is_string($value)) { - if (strlen($value) >= 22 && strlen($value) <= 26) { - $possibleDate = DateTime::createFromFormat(DateTime::ATOM, $value); - if (false !== $possibleDate) { - $data[$key] = $possibleDate; - } - } - } - } + $rawData = $body['data']; } $startId = null; if (array_key_exists('start', $body)) { $startId = UuidV4::fromString($body['start']); + if (!$this->accessChecker->hasAccessToElement($userId, $startId, AccessType::CREATE)) { + throw $this->client404NotFoundExceptionFactory->createFromTemplate(); + } } $endId = null; if (array_key_exists('end', $body)) { $endId = UuidV4::fromString($body['end']); + if (!$this->accessChecker->hasAccessToElement($userId, $endId, AccessType::READ)) { + throw $this->client404NotFoundExceptionFactory->createFromTemplate(); + } } - if (null === $startId && null === $endId) { - return $this->createNode($type, $elementId, $data); - } - - if (null !== $startId && null !== $endId) { - return $this->createRelation($type, $elementId, $startId, $endId, $data); - } - - $setProperties = []; - $missingProperties = []; - if (null !== $startId) { - $setProperties[] = 'start'; - } else { - $missingProperties[] = 'start'; - } - if (null !== $endId) { - $setProperties[] = 'end'; - } else { - $missingProperties[] = 'end'; - } - throw $this->client400IncompleteMutualDependencyExceptionFactory->createFromTemplate(['start', 'end'], $setProperties, $missingProperties); - } - - /** - * @param array $data - */ - private function createNode(string $type, UuidInterface $nodeId, array $data): Response - { - $userId = $this->authProvider->getUserUuid(); - if (!$userId) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - - $newNode = (new NodeElement()) - ->setIdentifier($nodeId) - ->setLabel($type) - ->addProperties($data); - - $newNodeOwnsRelation = (new RelationElement()) - ->setIdentifier(UuidV4::uuid4()) - ->setType('OWNS') - ->setStart($userId) - ->setEnd($nodeId); - - $newNodeCreatedRelation = (new RelationElement()) - ->setIdentifier(UuidV4::uuid4()) - ->setType('CREATED') - ->setStart($userId) - ->setEnd($nodeId); - - $this->elementManager - ->create($newNode) - ->create($newNodeOwnsRelation) - ->create($newNodeCreatedRelation) - ->flush(); - - return new CreatedResponse( - $this->router->generate( - 'get-element', - [ - 'uuid' => $nodeId, - ] - ) + $element = $this->createElementFromRawDataService->createElementFromRawData( + $elementId, + $type, + $startId, + $endId, + $rawData ); - } - - /** - * @param array $data - */ - private function createRelation(string $type, UuidInterface $relationId, UuidInterface $startId, UuidInterface $endId, array $data): Response - { - $userId = $this->authProvider->getUserUuid(); - if (!$userId) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); + $this->elementManager->create($element); + + if ($element instanceof NodeElementInterface) { + $newNodeOwnsRelation = (new RelationElement()) + ->setIdentifier(UuidV4::uuid4()) + ->setType('OWNS') + ->setStart($userId) + ->setEnd($element->getIdentifier()); + $this->elementManager->create($newNodeOwnsRelation); + + $newNodeCreatedRelation = (new RelationElement()) + ->setIdentifier(UuidV4::uuid4()) + ->setType('CREATED') + ->setStart($userId) + ->setEnd($element->getIdentifier()); + $this->elementManager->create($newNodeCreatedRelation); } - if (!$this->accessChecker->hasAccessToElement($userId, $startId, AccessType::CREATE)) { - throw $this->client404NotFoundExceptionFactory->createFromTemplate(); - } - if (!$this->accessChecker->hasAccessToElement($userId, $endId, AccessType::READ)) { - throw $this->client404NotFoundExceptionFactory->createFromTemplate(); - } - - $newRelation = (new RelationElement()) - ->setIdentifier($relationId) - ->setType($type) - ->setStart($startId) - ->setEnd($endId) - ->addProperties($data); - - $this->elementManager - ->create($newRelation) - ->flush(); + $this->elementManager->flush(); return new CreatedResponse( $this->router->generate( 'get-element', [ - 'uuid' => $relationId, + 'uuid' => $element->getIdentifier(), ] ) ); diff --git a/src/Controller/Element/PutElementController.php b/src/Controller/Element/PutElementController.php index 9e49d963..14b5bc9b 100644 --- a/src/Controller/Element/PutElementController.php +++ b/src/Controller/Element/PutElementController.php @@ -2,13 +2,14 @@ namespace App\Controller\Element; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client404NotFoundExceptionFactory; use App\Helper\Regex; use App\Response\NoContentResponse; use App\Security\AccessChecker; use App\Security\AuthProvider; use App\Service\ElementManager; +use App\Service\ResetElementPropertiesService; +use App\Service\UpdateElementFromRawDataService; use App\Type\AccessType; use Ramsey\Uuid\Rfc4122\UuidV4; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -22,8 +23,9 @@ public function __construct( private ElementManager $elementManager, private AuthProvider $authProvider, private AccessChecker $accessChecker, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, - private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory + private Client404NotFoundExceptionFactory $client404NotFoundExceptionFactory, + private UpdateElementFromRawDataService $updateElementFromRawDataService, + private ResetElementPropertiesService $resetElementPropertiesService ) { } @@ -37,41 +39,40 @@ public function __construct( )] public function putElement(string $uuid, Request $request): Response { - $elementUuid = UuidV4::fromString($uuid); - $userUuid = $this->authProvider->getUserUuid(); + $elementId = UuidV4::fromString($uuid); + $userId = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - - if (!$this->accessChecker->hasAccessToElement($userUuid, $elementUuid, AccessType::UPDATE)) { + if (!$this->accessChecker->hasAccessToElement($userId, $elementId, AccessType::UPDATE)) { throw $this->client404NotFoundExceptionFactory->createFromTemplate(); } - $element = $this->elementManager->getElement($elementUuid); + $element = $this->elementManager->getElement($elementId); if (null === $element) { throw $this->client404NotFoundExceptionFactory->createFromTemplate(); } /** - * @var array $data + * @var array $rawData */ - $data = \Safe\json_decode($request->getContent(), true); + $rawData = \Safe\json_decode($request->getContent(), true); - foreach (array_keys($element->getProperties()) as $name) { - if ('id' === $name) { - continue; - } - if ('created' === $name) { - continue; - } - if ('updated' === $name) { - continue; - } - $element->addProperty($name, null); - } + $element = $this->resetElementPropertiesService->resetElementProperties($element); + $element = $this->updateElementFromRawDataService->updateElementFromRawData($element, $rawData); - $element->addProperties($data); + // foreach (array_keys($element->getProperties()) as $name) { + // if ('id' === $name) { + // continue; + // } + // if ('created' === $name) { + // continue; + // } + // if ('updated' === $name) { + // continue; + // } + // $element->addProperty($name, null); + // } + // + // $element->addProperties($data); $this->elementManager->merge($element); $this->elementManager->flush(); diff --git a/src/Controller/Search/PostSearchController.php b/src/Controller/Search/PostSearchController.php index 64358b11..a7b3cead 100644 --- a/src/Controller/Search/PostSearchController.php +++ b/src/Controller/Search/PostSearchController.php @@ -4,7 +4,6 @@ use App\Factory\Exception\Client400BadContentExceptionFactory; use App\Factory\Exception\Client400MissingPropertyExceptionFactory; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Server500InternalServerErrorExceptionFactory; use App\Security\AccessChecker; use App\Security\AuthProvider; @@ -30,7 +29,6 @@ public function __construct( private CollectionService $collectionService, private Client400BadContentExceptionFactory $client400BadContentExceptionFactory, private Client400MissingPropertyExceptionFactory $client400MissingPropertyExceptionFactory, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Server500InternalServerErrorExceptionFactory $server500InternalServerErrorExceptionFactory ) { } @@ -45,9 +43,6 @@ public function postSearch(Request $request): Response $body = \Safe\json_decode($request->getContent(), true); $currentUserUuid = $this->authProvider->getUserUuid(); - if (!$currentUserUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } $userGroups = $this->accessChecker->getUsersGroups($currentUserUuid); $stringUserGroups = []; diff --git a/src/Controller/User/DeleteTokenController.php b/src/Controller/User/DeleteTokenController.php index c65f05b4..dc5dd090 100644 --- a/src/Controller/User/DeleteTokenController.php +++ b/src/Controller/User/DeleteTokenController.php @@ -31,12 +31,6 @@ public function __construct( )] public function deleteToken(): Response { - $userUuid = $this->authProvider->getUserUuid(); - - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - if ($this->authProvider->isAnonymous()) { throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); } diff --git a/src/Controller/User/GetMeController.php b/src/Controller/User/GetMeController.php index d55ee6f0..2d2f1508 100644 --- a/src/Controller/User/GetMeController.php +++ b/src/Controller/User/GetMeController.php @@ -2,7 +2,6 @@ namespace App\Controller\User; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Security\AuthProvider; use App\Service\ElementResponseService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -14,7 +13,6 @@ class GetMeController extends AbstractController public function __construct( private ElementResponseService $elementResponseService, private AuthProvider $authProvider, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, ) { } @@ -27,10 +25,6 @@ public function getMe(): Response { $userUuid = $this->authProvider->getUserUuid(); - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - return $this->elementResponseService->buildElementResponseFromUuid($userUuid); } } diff --git a/src/Controller/User/GetTokenController.php b/src/Controller/User/GetTokenController.php index 8fc89177..96f7c3aa 100644 --- a/src/Controller/User/GetTokenController.php +++ b/src/Controller/User/GetTokenController.php @@ -2,7 +2,6 @@ namespace App\Controller\User; -use App\Factory\Exception\Client401UnauthorizedExceptionFactory; use App\Factory\Exception\Client403ForbiddenExceptionFactory; use App\Factory\Exception\Server500LogicExceptionFactory; use App\Security\AuthProvider; @@ -16,7 +15,6 @@ class GetTokenController extends AbstractController public function __construct( private ElementResponseService $elementResponseService, private AuthProvider $authProvider, - private Client401UnauthorizedExceptionFactory $client401UnauthorizedExceptionFactory, private Client403ForbiddenExceptionFactory $client403ForbiddenExceptionFactory, private Server500LogicExceptionFactory $server500LogicExceptionFactory ) { @@ -33,12 +31,6 @@ public function getToken(): Response throw $this->client403ForbiddenExceptionFactory->createFromTemplate(); } - $userUuid = $this->authProvider->getUserUuid(); - - if (!$userUuid) { - throw $this->client401UnauthorizedExceptionFactory->createFromTemplate(); - } - $tokenUuid = $this->authProvider->getTokenUuid(); if (!$tokenUuid) { diff --git a/src/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEvent.php b/src/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEvent.php index 90afc814..07b9f767 100644 --- a/src/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEvent.php +++ b/src/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEvent.php @@ -14,15 +14,15 @@ class ElementPropertyChangeEvent implements EventInterface * @param array $changedProperties */ public function __construct( - private string $type, + private string $labelOrType, private ?ElementInterface $element, private array $changedProperties ) { } - public function getType(): string + public function getLabelOrType(): string { - return $this->type; + return $this->labelOrType; } public function getElement(): ?ElementInterface diff --git a/src/EventSystem/ElementPropertyChange/EventListener/TokenElementPropertyChangeEventListener.php b/src/EventSystem/ElementPropertyChange/EventListener/TokenElementPropertyChangeEventListener.php index 1bcd5431..2c64ca2d 100644 --- a/src/EventSystem/ElementPropertyChange/EventListener/TokenElementPropertyChangeEventListener.php +++ b/src/EventSystem/ElementPropertyChange/EventListener/TokenElementPropertyChangeEventListener.php @@ -14,7 +14,7 @@ public function __construct( public function onElementPropertyChangeEvent(ElementPropertyChangeEvent $event): void { - if ('Token' !== $event->getType()) { + if ('Token' !== $event->getLabelOrType()) { return; } if (array_key_exists('token', $event->getChangedProperties())) { diff --git a/src/EventSystem/ElementPropertyChange/EventListener/UserElementPropertyChangeEventListener.php b/src/EventSystem/ElementPropertyChange/EventListener/UserElementPropertyChangeEventListener.php index f4a803ce..824047bf 100644 --- a/src/EventSystem/ElementPropertyChange/EventListener/UserElementPropertyChangeEventListener.php +++ b/src/EventSystem/ElementPropertyChange/EventListener/UserElementPropertyChangeEventListener.php @@ -16,7 +16,7 @@ public function __construct( public function onElementPropertyChangeEvent(ElementPropertyChangeEvent $event): void { - if ('User' !== $event->getType()) { + if ('User' !== $event->getLabelOrType()) { return; } if (array_key_exists('_passwordHash', $event->getChangedProperties())) { diff --git a/src/EventSystem/ElementPropertyReset/Event/ElementPropertyResetEvent.php b/src/EventSystem/ElementPropertyReset/Event/ElementPropertyResetEvent.php new file mode 100644 index 00000000..fc53274a --- /dev/null +++ b/src/EventSystem/ElementPropertyReset/Event/ElementPropertyResetEvent.php @@ -0,0 +1,43 @@ +element; + } + + public function addPropertyNameToBeKept(string $propertyName): self + { + $this->propertyNamesWhichAreKept[] = $propertyName; + + return $this; + } + + /** + * @return string[] + */ + public function getPropertyNamesWhichAreKept(): array + { + return $this->propertyNamesWhichAreKept; + } +} diff --git a/src/EventSystem/ElementPropertyReset/EventListener/CreatedElementPropertyResetEventListener.php b/src/EventSystem/ElementPropertyReset/EventListener/CreatedElementPropertyResetEventListener.php new file mode 100644 index 00000000..b90b6e5e --- /dev/null +++ b/src/EventSystem/ElementPropertyReset/EventListener/CreatedElementPropertyResetEventListener.php @@ -0,0 +1,13 @@ +addPropertyNameToBeKept('created'); + } +} diff --git a/src/EventSystem/ElementPropertyReset/EventListener/IdElementPropertyResetEventListener.php b/src/EventSystem/ElementPropertyReset/EventListener/IdElementPropertyResetEventListener.php new file mode 100644 index 00000000..0e9db688 --- /dev/null +++ b/src/EventSystem/ElementPropertyReset/EventListener/IdElementPropertyResetEventListener.php @@ -0,0 +1,13 @@ +addPropertyNameToBeKept('id'); + } +} diff --git a/src/EventSystem/ElementPropertyReset/EventListener/TokenElementPropertyResetEventListener.php b/src/EventSystem/ElementPropertyReset/EventListener/TokenElementPropertyResetEventListener.php new file mode 100644 index 00000000..2fcbf7a4 --- /dev/null +++ b/src/EventSystem/ElementPropertyReset/EventListener/TokenElementPropertyResetEventListener.php @@ -0,0 +1,22 @@ +getElement(); + if (!($element instanceof NodeElementInterface)) { + return; + } + if ('Token' !== $element->getLabel()) { + return; + } + $event->addPropertyNameToBeKept('token'); + $event->addPropertyNameToBeKept('_tokenHash'); + } +} diff --git a/src/EventSystem/ElementPropertyReset/EventListener/UpdatedElementPropertyResetEventListener.php b/src/EventSystem/ElementPropertyReset/EventListener/UpdatedElementPropertyResetEventListener.php new file mode 100644 index 00000000..082e14fc --- /dev/null +++ b/src/EventSystem/ElementPropertyReset/EventListener/UpdatedElementPropertyResetEventListener.php @@ -0,0 +1,13 @@ +addPropertyNameToBeKept('updated'); + } +} diff --git a/src/EventSystem/ElementPropertyReset/EventListener/UserElementPropertyResetEventListener.php b/src/EventSystem/ElementPropertyReset/EventListener/UserElementPropertyResetEventListener.php new file mode 100644 index 00000000..823b798b --- /dev/null +++ b/src/EventSystem/ElementPropertyReset/EventListener/UserElementPropertyResetEventListener.php @@ -0,0 +1,21 @@ +getElement(); + if (!($element instanceof NodeElementInterface)) { + return; + } + if ('User' !== $element->getLabel()) { + return; + } + $event->addPropertyNameToBeKept('_passwordHash'); + } +} diff --git a/src/EventSystem/ElementPropertyReset/config.yaml b/src/EventSystem/ElementPropertyReset/config.yaml new file mode 100644 index 00000000..3b8e1e8b --- /dev/null +++ b/src/EventSystem/ElementPropertyReset/config.yaml @@ -0,0 +1,35 @@ +services: + + _defaults: + autowire: true + autoconfigure: true + + App\EventSystem\ElementPropertyReset\EventListener\CreatedElementPropertyResetEventListener: + tags: + - name: kernel.event_listener + event: 'App\EventSystem\ElementPropertyReset\Event' + method: 'onElementPropertyResetEvent' + + App\EventSystem\ElementPropertyReset\EventListener\IdElementPropertyResetEventListener: + tags: + - name: kernel.event_listener + event: 'App\EventSystem\ElementPropertyReset\Event' + method: 'onElementPropertyResetEvent' + + App\EventSystem\ElementPropertyReset\EventListener\TokenElementPropertyResetEventListener: + tags: + - name: kernel.event_listener + event: 'App\EventSystem\ElementPropertyReset\Event' + method: 'onElementPropertyResetEvent' + + App\EventSystem\ElementPropertyReset\EventListener\UpdatedElementPropertyResetEventListener: + tags: + - name: kernel.event_listener + event: 'App\EventSystem\ElementPropertyReset\Event' + method: 'onElementPropertyResetEvent' + + App\EventSystem\ElementPropertyReset\EventListener\UserElementPropertyResetEventListener: + tags: + - name: kernel.event_listener + event: 'App\EventSystem\ElementPropertyReset\Event' + method: 'onElementPropertyResetEvent' diff --git a/src/Security/AuthProvider.php b/src/Security/AuthProvider.php index 3078bded..b6e6a13e 100755 --- a/src/Security/AuthProvider.php +++ b/src/Security/AuthProvider.php @@ -10,7 +10,7 @@ class AuthProvider { private bool $isAnonymous; - private ?UuidInterface $userUuid; + private UuidInterface $userUuid; private ?UuidInterface $tokenUuid = null; private ?string $hashedToken = null; @@ -41,7 +41,7 @@ public function getRedisTokenKeyFromRawToken(string $rawToken): string } public function setUserAndToken( - UuidInterface $userUuid = null, + UuidInterface $userUuid, UuidInterface $tokenUuid = null, string $hashedToken = null, bool $isAnonymous = false @@ -59,7 +59,7 @@ public function isAnonymous(): bool return $this->isAnonymous; } - public function getUserUuid(): ?UuidInterface + public function getUserUuid(): UuidInterface { return $this->userUuid; } diff --git a/src/Service/CreateElementFromRawDataService.php b/src/Service/CreateElementFromRawDataService.php new file mode 100644 index 00000000..80dfcfcf --- /dev/null +++ b/src/Service/CreateElementFromRawDataService.php @@ -0,0 +1,74 @@ + $rawData + */ + public function createElementFromRawData( + UuidInterface $elementId, + string $type, + UuidInterface $startNodeId = null, + UuidInterface $endNodeId = null, + array $rawData = [] + ): NodeElementInterface|RelationElementInterface { + if (null !== $startNodeId && null === $endNodeId) { + throw $this->client400IncompleteMutualDependencyExceptionFactory->createFromTemplate(['start', 'end'], ['start'], ['end']); + } + if (null === $startNodeId && null !== $endNodeId) { + throw $this->client400IncompleteMutualDependencyExceptionFactory->createFromTemplate(['start', 'end'], ['end'], ['start']); + } + if (null !== $this->elementManager->getElement($elementId)) { + throw $this->client400ReservedIdentifierExceptionFactory->createFromTemplate($elementId->toString()); + } + + /** + * @var array $normalizedData + */ + $normalizedData = []; + foreach ($rawData as $rawPropertyName => $rawPropertyValue) { + $rawValueToNormalizedValueEvent = new RawValueToNormalizedValueEvent($rawPropertyValue); + $this->eventDispatcher->dispatch($rawValueToNormalizedValueEvent); + $normalizedData[$rawPropertyName] = $rawValueToNormalizedValueEvent->getNormalizedValue(); + } + + $elementPropertyChangeEvent = new ElementPropertyChangeEvent($type, null, $normalizedData); + $this->eventDispatcher->dispatch($elementPropertyChangeEvent); + $verifiedData = $elementPropertyChangeEvent->getChangedProperties(); + + if ($startNodeId && $endNodeId) { + $element = new RelationElement(); + $element->setStart($startNodeId); + $element->setEnd($endNodeId); + $element->setType($type); + } else { + $element = new NodeElement(); + $element->setLabel($type); + } + $element->addProperties($verifiedData); + $element->setIdentifier($elementId); + + return $element; + } +} diff --git a/src/Service/ResetElementPropertiesService.php b/src/Service/ResetElementPropertiesService.php new file mode 100644 index 00000000..fb5f7c7d --- /dev/null +++ b/src/Service/ResetElementPropertiesService.php @@ -0,0 +1,33 @@ +eventDispatcher->dispatch($elementPropertyResetEvent); + + $propertyNames = array_keys($element->getProperties()); + foreach ($propertyNames as $propertyName) { + if (in_array($propertyName, $elementPropertyResetEvent->getPropertyNamesWhichAreKept())) { + continue; + } + $element->addProperty($propertyName, null); + } + + return $element; + } +} diff --git a/src/Service/UpdateElementFromRawDataService.php b/src/Service/UpdateElementFromRawDataService.php new file mode 100644 index 00000000..9681ecc1 --- /dev/null +++ b/src/Service/UpdateElementFromRawDataService.php @@ -0,0 +1,57 @@ + $rawData + */ + public function updateElementFromRawData( + NodeElementInterface|RelationElementInterface $element, + array $rawData = [] + ): NodeElementInterface|RelationElementInterface { + /** + * @var array $normalizedData + */ + $normalizedData = []; + foreach ($rawData as $rawPropertyName => $rawPropertyValue) { + $rawValueToNormalizedValueEvent = new RawValueToNormalizedValueEvent($rawPropertyValue); + $this->eventDispatcher->dispatch($rawValueToNormalizedValueEvent); + $normalizedData[$rawPropertyName] = $rawValueToNormalizedValueEvent->getNormalizedValue(); + } + + if ($element instanceof NodeElementInterface) { + $typeOrLabel = $element->getLabel(); + } else { + /** + * @var RelationElementInterface $element + */ + $typeOrLabel = $element->getType(); + } + if (null === $typeOrLabel) { + throw $this->server500LogicExceptionFactory->createFromTemplate('Type or label should not be null here.'); + } + + $elementPropertyChangeEvent = new ElementPropertyChangeEvent($typeOrLabel, $element, $normalizedData); + $this->eventDispatcher->dispatch($elementPropertyChangeEvent); + $verifiedData = $elementPropertyChangeEvent->getChangedProperties(); + + $element->addProperties($verifiedData); + + return $element; + } +} diff --git a/tests/UnitTests/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEventTest.php b/tests/UnitTests/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEventTest.php index e215fe08..2dd64fdd 100644 --- a/tests/UnitTests/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEventTest.php +++ b/tests/UnitTests/EventSystem/ElementPropertyChange/Event/ElementPropertyChangeEventTest.php @@ -11,7 +11,7 @@ class ElementPropertyChangeEventTest extends TestCase public function testEventReturnsCorrectWithoutElementData(): void { $event = new ElementPropertyChangeEvent('type', null, ['a' => 'A']); - $this->assertSame('type', $event->getType()); + $this->assertSame('type', $event->getLabelOrType()); $this->assertNull($event->getElement()); $changedProperties = $event->getChangedProperties(); $this->assertIsArray($changedProperties); @@ -26,7 +26,7 @@ public function testEventReturnsCorrectWithElementData(): void $element = new NodeElement(); $element->setLabel('Element'); $event = new ElementPropertyChangeEvent('type', $element, ['b' => 'B']); - $this->assertSame('type', $event->getType()); + $this->assertSame('type', $event->getLabelOrType()); $this->assertSame($element, $event->getElement()); $changedProperties = $event->getChangedProperties(); $this->assertIsArray($changedProperties); diff --git a/tests/UnitTests/Security/AuthProviderTest.php b/tests/UnitTests/Security/AuthProviderTest.php index 2e4305fc..5100fd5f 100644 --- a/tests/UnitTests/Security/AuthProviderTest.php +++ b/tests/UnitTests/Security/AuthProviderTest.php @@ -10,6 +10,7 @@ use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Ramsey\Uuid\Rfc4122\UuidV4; +use Ramsey\Uuid\Uuid; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; class AuthProviderTest extends TestCase @@ -68,10 +69,10 @@ public function testSetUserAndToken(): void $this->prophesize(Server500LogicExceptionFactory::class)->reveal() ); - $authProvider->setUserAndToken(); + $authProvider->setUserAndToken(Uuid::fromString('d3e0ce1e-cdf1-4c80-beae-266008d5e520')); $this->assertFalse($authProvider->isAnonymous()); - $this->assertNull($authProvider->getUserUuid()); + $this->assertSame($authProvider->getUserUuid()->toString(), 'd3e0ce1e-cdf1-4c80-beae-266008d5e520'); $this->assertNull($authProvider->getHashedToken()); $this->assertNull($authProvider->getTokenUuid()); @@ -86,10 +87,10 @@ public function testSetUserAndToken(): void $this->assertSame('some hashed token', $authProvider->getHashedToken()); $this->assertSame('8a961321-fd60-475a-95b4-7f976ce44213', $authProvider->getTokenUuid()->toString()); - $authProvider->setUserAndToken(null, null, null, true); + $authProvider->setUserAndToken(Uuid::fromString('c48aaf8e-4ab5-4e60-8f03-154b13e35724'), null, null, true); $this->assertTrue($authProvider->isAnonymous()); - $this->assertNull($authProvider->getUserUuid()); + $this->assertSame($authProvider->getUserUuid()->toString(), 'c48aaf8e-4ab5-4e60-8f03-154b13e35724'); $this->assertNull($authProvider->getHashedToken()); $this->assertNull($authProvider->getTokenUuid()); }