diff --git a/application/config/version.php b/application/config/version.php index ff894c054..9f3c363d5 100644 --- a/application/config/version.php +++ b/application/config/version.php @@ -29,14 +29,14 @@ * * @var string */ -$config['version'] = '9.3.1'; +$config['version'] = '9.3.2'; /** * Version release date. * * @var string */ -$config['release_date'] = '2024-08-28'; +$config['release_date'] = '2024-08-29'; /** * Link to the code repository downloads page. diff --git a/modules/rest_api/controllers/rest_api_client_connection.php b/modules/rest_api/controllers/rest_api_client_connection.php index 0ea5de026..a15e2d130 100644 --- a/modules/rest_api/controllers/rest_api_client_connection.php +++ b/modules/rest_api/controllers/rest_api_client_connection.php @@ -33,6 +33,7 @@ public function __construct() { $this->columns = [ 'id' => 'ID', 'title' => '', + 'username' => '', 'proj_id' => 'Project ID', 'description' => '', ]; @@ -45,10 +46,14 @@ public function __construct() { * Index action method. */ public function index() { + if ($this->uri->total_arguments() > 0) { + // Apply the filter to only show connections for this client. + $this->base_filter['rest_api_client_id'] = $this->uri->argument(1); + } parent::index(); - // Pass the client into the view, so the add button can pass through to the - // create form. if ($this->uri->total_arguments() > 0) { + // Pass the client into the view, so the add button can pass through to the + // create form. $this->view->rest_api_client_id = $this->uri->argument(1); } } diff --git a/modules/rest_api/controllers/services/rest.php b/modules/rest_api/controllers/services/rest.php index 5a5eb3686..8cd66179e 100644 --- a/modules/rest_api/controllers/services/rest.php +++ b/modules/rest_api/controllers/services/rest.php @@ -2968,7 +2968,13 @@ private function authenticateUsingDirectClientInDb($clientSystemId, $secret) { if (!password_verify($secret, $r->secret)) { RestObjects::$apiResponse->fail('Unauthorized', 401, 'Incorrect secret'); } - if (in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'DELETE'])) { + // This type of connection is read only as we don't have a user ID. + // @todo A default user ID could be an option in the connection metadata. + $blockedMethods = ['PUT', 'DELETE']; + if (!$this->elasticProxy) { + $blockedMethods[] = 'POST'; + } + if (in_array($_SERVER['REQUEST_METHOD'], $blockedMethods)) { RestObjects::$apiResponse->fail('Method Not Allowed', 405, 'Connection is read only.'); } $this->applyConnectionSettingsFromRestConnectionInDb($r); diff --git a/modules/rest_api/db/version_9_0_0/202312271711_rest_client_tables.sql b/modules/rest_api/db/version_9_0_0/202312271711_rest_client_tables.sql index 25d5a567e..c6bf7c1e6 100644 --- a/modules/rest_api/db/version_9_0_0/202312271711_rest_client_tables.sql +++ b/modules/rest_api/db/version_9_0_0/202312271711_rest_client_tables.sql @@ -73,9 +73,6 @@ CREATE TABLE IF NOT EXISTS rest_api_client_connections CONSTRAINT chk_rest_api_client_connection_sharing_options CHECK ((sharing = ANY (ARRAY['R'::bpchar, 'P'::bpchar, 'V'::bpchar, 'D'::bpchar, 'M'::bpchar]))) ); -COMMENT ON TABLE rest_api_client_connections - IS 'Configugration for a single connection method to the REST API by a client. A client may be allowed to use multiple connections for different purposes. - Includes privileges and filtering to define the capabilities when using this connection.'; COMMENT ON COLUMN rest_api_client_connections.id IS 'Primary key for the table.'; COMMENT ON COLUMN rest_api_client_connections.title IS 'Title of the REST API connection, for admin purposes only.'; COMMENT ON COLUMN rest_api_client_connections.proj_id IS 'Name of the connection as passed to the API with requests.'; diff --git a/modules/rest_api/db/version_9_3_2/202408281736_rest_client_tidy.sql b/modules/rest_api/db/version_9_3_2/202408281736_rest_client_tidy.sql new file mode 100644 index 000000000..c109ca7f8 --- /dev/null +++ b/modules/rest_api/db/version_9_3_2/202408281736_rest_client_tidy.sql @@ -0,0 +1,17 @@ +DROP VIEW gv_rest_api_clients; +CREATE OR REPLACE VIEW gv_rest_api_clients AS +SELECT c.id, c.title, c.username, c.description, w.title as website_title, c.website_id +FROM rest_api_clients c +JOIN websites w ON w.id=c.website_id AND w.deleted=false +WHERE c.deleted=false; + +DROP VIEW gv_rest_api_client_connections; +CREATE OR REPLACE VIEW gv_rest_api_client_connections AS +SELECT cc.id, cc.title, c.username, cc.proj_id, cc.description, c.website_id, cc.rest_api_client_id +FROM rest_api_client_connections cc +JOIN rest_api_clients c ON c.id=cc.rest_api_client_id AND c.deleted=false +WHERE cc.deleted=false; + +COMMENT ON TABLE rest_api_client_connections + IS 'Configuration for a single connection method to the REST API by a client. A client may be allowed to use multiple connections for different purposes. + Includes privileges and filtering to define the capabilities when using this connection.'; \ No newline at end of file diff --git a/modules/rest_api/libraries/RestApiElasticsearch.php b/modules/rest_api/libraries/RestApiElasticsearch.php index 3361fc883..aebede7b6 100644 --- a/modules/rest_api/libraries/RestApiElasticsearch.php +++ b/modules/rest_api/libraries/RestApiElasticsearch.php @@ -486,7 +486,7 @@ private function applyEsPermissionsQuery(&$postObj) { $postObj->query->bool->must = array_merge($postObj->query->bool->must, $filterDefBool['must']); } if (!empty($filterDefBool['must_not'])) { - $postObj->query->bool->must = $filterDefBool['must_not']; + $postObj->query->bool->must_not = $filterDefBool['must_not']; } } @@ -2298,6 +2298,7 @@ private function proxyToEs($url, $requestBody, $format, $ret, $requestIsRawStrin $response = curl_exec($session); $headers = curl_getinfo($session); $httpCode = curl_getinfo($session, CURLINFO_HTTP_CODE); + kohana::log('error', 'Query: ' . $postData); if ($httpCode !== 200) { $error = curl_error($session); kohana::log('error', 'ES proxy request failed: ' . $error . ': ' . json_encode($error));