From 512ef745da34539c4e02c194bc1d4e4bb4a2004a Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Mon, 16 Nov 2020 22:18:37 +0100 Subject: [PATCH] Don't expose uihelper views via the API / allow to get stock_log via generic entity interaction endpoints (no edit) --- changelog/60_UNRELEASED_2020-xx-xx.md | 4 +--- controllers/GenericEntityApiController.php | 24 ++++++++++++++-------- controllers/OpenApiController.php | 20 +++++++++++++----- grocy.openapi.json | 24 ++++++++++++++++------ 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/changelog/60_UNRELEASED_2020-xx-xx.md b/changelog/60_UNRELEASED_2020-xx-xx.md index 558701b1..1165fb47 100644 --- a/changelog/60_UNRELEASED_2020-xx-xx.md +++ b/changelog/60_UNRELEASED_2020-xx-xx.md @@ -170,8 +170,6 @@ - `/objects/{entity}` - `/stock/products/{productId}/entries` - `/stock/products/{productId}/locations` - - `/stock/journal` - - `/stock/journal/summary` - `/recipes/fulfillment` - `/users` - `/tasks` @@ -191,10 +189,10 @@ - `>=` greater or equal - `<=` less or equal - `` is the value to search for -- New endpoints `/stock/journal` and `/stock/journal/summary` to get the stock journal (thanks @fipwmaqzufheoxq92ebc) - New endpoint `/stock/shoppinglist/add-overdue-products` to add all currently in-stock but overdue products to a shopping list (thanks @m-byte) - New endpoint `/stock/shoppinglist/add-expired-products` to add all currently in-stock but expired products to a shopping list - New endpoints GET/POST/PUT `/users/{userId}/permissions` for the new user permissions feature mentioned above +- The stock journal (entity `stock_log`) is now also available via the endpoint `/objects/{entity}` (=> `/objects/stock_log`) - Performance improvements of the `/stock/products/*` endpoints (thanks @fipwmaqzufheoxq92ebc) - Fixed that the endpoint `/objects/{entity}/{objectId}` always returned successfully, even when the given object not exists (now returns `404` when the object is not found) (thanks @fipwmaqzufheoxq92ebc) - Fixed that the endpoint `/stock/volatile` didn't include products which expire today (thanks @fipwmaqzufheoxq92ebc) diff --git a/controllers/GenericEntityApiController.php b/controllers/GenericEntityApiController.php index 06546e59..ca28539c 100644 --- a/controllers/GenericEntityApiController.php +++ b/controllers/GenericEntityApiController.php @@ -11,7 +11,7 @@ class GenericEntityApiController extends BaseApiController { User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT); - if ($this->IsValidEntity($args['entity'])) + if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithNoEdit($args['entity'])) { if ($this->IsEntityWithEditRequiresAdmin($args['entity'])) { @@ -27,10 +27,10 @@ class GenericEntityApiController extends BaseApiController throw new \Exception('Request body could not be parsed (probably invalid JSON format or missing/wrong Content-Type header)'); } - $newRow = $this->getDatabase()->{$args['entity']} - ()->createRow($requestBody); + $newRow = $this->getDatabase()->{$args['entity']}()->createRow($requestBody); $newRow->save(); $success = $newRow->isClean(); + return $this->ApiResponse($response, [ 'created_object_id' => $this->getDatabase()->lastInsertId() ]); @@ -50,16 +50,17 @@ class GenericEntityApiController extends BaseApiController { User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT); - if ($this->IsValidEntity($args['entity'])) + if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithNoEdit($args['entity'])) { if ($this->IsEntityWithEditRequiresAdmin($args['entity'])) { User::checkPermission($request, User::PERMISSION_ADMIN); } - $row = $this->getDatabase()->{$args['entity']} - ($args['objectId']); + + $row = $this->getDatabase()->{$args['entity']}($args['objectId']); $row->delete(); $success = $row->isClean(); + return $this->EmptyApiResponse($response); } else @@ -72,7 +73,7 @@ class GenericEntityApiController extends BaseApiController { User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT); - if ($this->IsValidEntity($args['entity'])) + if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithNoEdit($args['entity'])) { if ($this->IsEntityWithEditRequiresAdmin($args['entity'])) { @@ -88,10 +89,10 @@ class GenericEntityApiController extends BaseApiController throw new \Exception('Request body could not be parsed (probably invalid JSON format or missing/wrong Content-Type header)'); } - $row = $this->getDatabase()->{$args['entity']} - ($args['objectId']); + $row = $this->getDatabase()->{$args['entity']}($args['objectId']); $row->update($requestBody); $success = $row->isClean(); + return $this->EmptyApiResponse($response); } catch (\Exception $ex) @@ -213,6 +214,11 @@ class GenericEntityApiController extends BaseApiController return !in_array($entity, $this->getOpenApiSpec()->components->internalSchemas->ExposedEntityButNoListing->enum); } + private function IsEntityWithNoEdit($entity) + { + return in_array($entity, $this->getOpenApiSpec()->components->internalSchemas->ExposedEntityNoEdit->enum); + } + private function IsValidEntity($entity) { return in_array($entity, $this->getOpenApiSpec()->components->internalSchemas->ExposedEntity->enum); diff --git a/controllers/OpenApiController.php b/controllers/OpenApiController.php index 71fba589..300bedc1 100644 --- a/controllers/OpenApiController.php +++ b/controllers/OpenApiController.php @@ -28,14 +28,24 @@ class OpenApiController extends BaseApiController public function DocumentationSpec(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) { + $spec = $this->getOpenApiSpec(); + $applicationService = $this->getApplicationService(); - $versionInfo = $applicationService->GetInstalledVersion(); - $this->getOpenApiSpec()->info->version = $versionInfo->Version; - $this->getOpenApiSpec()->info->description = str_replace('PlaceHolderManageApiKeysUrl', $this->AppContainer->get('UrlManager')->ConstructUrl('/manageapikeys'), $this->getOpenApiSpec()->info->description); - $this->getOpenApiSpec()->servers[0]->url = $this->AppContainer->get('UrlManager')->ConstructUrl('/api'); + $spec->info->version = $versionInfo->Version; + $spec->info->description = str_replace('PlaceHolderManageApiKeysUrl', $this->AppContainer->get('UrlManager')->ConstructUrl('/manageapikeys'), $spec->info->description); + $spec->servers[0]->url = $this->AppContainer->get('UrlManager')->ConstructUrl('/api'); - return $this->ApiResponse($response, $this->getOpenApiSpec()); + $spec->components->internalSchemas->ExposedEntity_NotIncludingNotEditable = clone $spec->components->internalSchemas->StringEnumTemplate; + foreach ($spec->components->internalSchemas->ExposedEntity->enum as $value) + { + if (!in_array($value, $spec->components->internalSchemas->ExposedEntityNoEdit->enum)) + { + array_push($spec->components->internalSchemas->ExposedEntity_NotIncludingNotEditable->enum, $value); + } + } + + return $this->ApiResponse($response, $spec); } public function DocumentationUi(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) diff --git a/grocy.openapi.json b/grocy.openapi.json index 680c4f24..fc447ca0 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -280,7 +280,7 @@ "required": true, "description": "A valid entity name", "schema": { - "$ref": "#/components/internalSchemas/ExposedEntity" + "$ref": "#/components/internalSchemas/ExposedEntity_NotIncludingNotEditable" } } ], @@ -442,7 +442,7 @@ "required": true, "description": "A valid entity name", "schema": { - "$ref": "#/components/internalSchemas/ExposedEntity" + "$ref": "#/components/internalSchemas/ExposedEntity_NotIncludingNotEditable" } }, { @@ -516,7 +516,7 @@ "required": true, "description": "A valid entity name", "schema": { - "$ref": "#/components/internalSchemas/ExposedEntity" + "$ref": "#/components/internalSchemas/ExposedEntity_NotIncludingNotEditable" } }, { @@ -608,7 +608,7 @@ "required": true, "description": "A valid entity name", "schema": { - "$ref": "#/components/internalSchemas/ExposedEntity" + "$ref": "#/components/internalSchemas/ExposedEntity_NotIncludingNotEditable" } }, { @@ -3851,7 +3851,8 @@ "userfields", "userentities", "userobjects", - "meal_plan" + "meal_plan", + "stock_log" ] }, "ExposedEntityButNoListing": { @@ -3877,7 +3878,8 @@ "userfields", "userentities", "userobjects", - "meal_plan" + "meal_plan", + "stock_log" ] }, "EntityEditRequiresAdmin": { @@ -3886,6 +3888,12 @@ "api_keys" ] }, + "ExposedEntityNoEdit": { + "type": "string", + "enum": [ + "stock_log" + ] + }, "StockTransactionType": { "type": "string", "enum": [ @@ -3894,6 +3902,10 @@ "inventory-correction", "product-opened" ] + }, + "StringEnumTemplate": { + "type": "string", + "enum": [] } }, "schemas": {