From 9dcb0d1024a3fffb4111aabd07dd4e70d2d5d72d Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Mon, 1 Jul 2024 18:21:32 +0530 Subject: [PATCH] Fixed the permission denied issue for functions of the pgstattuple extension when accessing statistics with a non-admin user. #7035 --- docs/en_US/release_notes_8_10.rst | 3 +++ .../exclusion_constraint/__init__.py | 10 +++------- .../constraints/index_constraint/__init__.py | 10 +++------- .../schemas/tables/indexes/__init__.py | 11 +++-------- .../servers/databases/schemas/tables/utils.py | 12 ++---------- .../servers/databases/schemas/utils.py | 17 +++++++++++++++++ .../servers/databases/schemas/views/__init__.py | 13 +++---------- 7 files changed, 34 insertions(+), 42 deletions(-) diff --git a/docs/en_US/release_notes_8_10.rst b/docs/en_US/release_notes_8_10.rst index 7eb5cfa0fd4..d525915d4b6 100644 --- a/docs/en_US/release_notes_8_10.rst +++ b/docs/en_US/release_notes_8_10.rst @@ -24,6 +24,8 @@ New features Housekeeping ************ + | `Issue #7494 `_ - Replace pgAdmin NW.js container with Electron container. + | `Issue #7501 `_ - Updated to the latest version of the Notistack library. | `Issue #7537 `_ - Ensure that pgAdmin 4 is compatible with PostgreSQL v17. | `Issue #7607 `_ - Automatically apply virtualization in the DataGridView of SchemaView if the schema contains only one collection. | `Issue #7623 `_ - Add the git commit hash details to the About dialog. @@ -31,5 +33,6 @@ Housekeeping Bug fixes ********* + | `Issue #7035 `_ - Fixed the permission denied issue for functions of the pgstattuple extension when accessing statistics with a non-admin user. | `Issue #7554 `_ - Fixed an issue where sorting the database activity table on the dashboard by any column caused the details to expand in the wrong position. | `Issue #7627 `_ - Fixed an issue where users could not autofill their saved passwords in the connect server dialog in the browser. \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py index 3ae4f2f72d3..34f6dced07a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py @@ -24,6 +24,8 @@ constraints.exclusion_constraint import utils as exclusion_utils from pgadmin.utils.driver import get_driver from config import PG_DEFAULT_DRIVER +from pgadmin.browser.server_groups.servers.databases.schemas.utils \ + import check_pgstattuple class ExclusionConstraintModule(ConstraintTypeModule): @@ -837,13 +839,7 @@ def statistics(self, gid, sid, did, scid, tid, exid): Returns the statistics for a particular object if cid is specified """ - # Check if pgstattuple extension is already created? - # if created then only add extended stats - status, is_pgstattuple = self.conn.execute_scalar(""" - SELECT (pg_catalog.count(extname) > 0) AS is_pgstattuple - FROM pg_catalog.pg_extension - WHERE extname='pgstattuple' - """) + status, is_pgstattuple = check_pgstattuple(self.conn, tid) if not status: return internal_server_error(errormsg=is_pgstattuple) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py index 15a8d180d7f..7ed2be7b223 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py @@ -24,6 +24,8 @@ constraints.index_constraint import utils as idxcons_utils from pgadmin.utils.driver import get_driver from config import PG_DEFAULT_DRIVER +from pgadmin.browser.server_groups.servers.databases.schemas.utils \ + import check_pgstattuple class IndexConstraintModule(ConstraintTypeModule): @@ -926,13 +928,7 @@ def statistics(self, gid, sid, did, scid, tid, cid): Returns the statistics for a particular object if cid is specified """ - # Check if pgstattuple extension is already created? - # if created then only add extended stats - status, is_pgstattuple = self.conn.execute_scalar(""" - SELECT (pg_catalog.count(extname) > 0) AS is_pgstattuple - FROM pg_catalog.pg_extension - WHERE extname='pgstattuple' - """) + status, is_pgstattuple = check_pgstattuple(self.conn, tid) if not status: return internal_server_error(errormsg=is_pgstattuple) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py index b650103091b..b4ef91c768b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py @@ -29,6 +29,8 @@ from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare from pgadmin.browser.server_groups.servers.databases.schemas. \ tables.indexes import utils as index_utils +from pgadmin.browser.server_groups.servers.databases.schemas.utils \ + import check_pgstattuple class IndexesModule(CollectionNodeModule): @@ -998,14 +1000,7 @@ def statistics(self, gid, sid, did, scid, tid, idx=None): if idx is not None: # Individual index - - # Check if pgstattuple extension is already created? - # if created then only add extended stats - status, is_pgstattuple = self.conn.execute_scalar(""" - SELECT (pg_catalog.count(extname) > 0) AS is_pgstattuple - FROM pg_catalog.pg_extension - WHERE extname='pgstattuple' - """) + status, is_pgstattuple = check_pgstattuple(self.conn, tid) if not status: return internal_server_error(errormsg=is_pgstattuple) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py index 718e6403a6e..c2d19b8f1f8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py @@ -21,7 +21,7 @@ from pgadmin.utils.ajax import make_json_response, internal_server_error, \ gone, make_response as ajax_response from pgadmin.browser.server_groups.servers.databases.schemas.utils \ - import DataTypeReader, parse_rule_definition + import DataTypeReader, parse_rule_definition, check_pgstattuple from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \ parse_priv_to_db from pgadmin.browser.utils import PGChildNodeView @@ -49,7 +49,6 @@ from pgadmin.browser.server_groups.servers.databases.schemas.utils \ import VacuumSettings from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry -from pgadmin.dashboard import locks class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings): @@ -446,14 +445,7 @@ def get_table_statistics(self, scid, tid): ) else: # For Individual table stats - - # Check if pgstattuple extension is already created? - # if created then only add extended stats - status, is_pgstattuple = self.conn.execute_scalar(""" - SELECT (count(extname) > 0) AS is_pgstattuple - FROM pg_catalog.pg_extension - WHERE extname='pgstattuple' - """) + status, is_pgstattuple = check_pgstattuple(self.conn, tid) if not status: return internal_server_error(errormsg=is_pgstattuple) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/utils.py index 068a7d47138..51707e15636 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/utils.py @@ -720,3 +720,20 @@ def get_schemas(conn, show_system_objects=False): status, rset = conn.execute_2darray(SQL) return status, rset + + +def check_pgstattuple(conn, oid): + """ + This function is used to check pgstattuple extension is already created, + and current_user have permission to access that object. + """ + status, is_pgstattuple = conn.execute_scalar(""" + SELECT CASE WHEN (SELECT(count(extname) > 0) AS is_pgstattuple + FROM pg_catalog.pg_extension WHERE extname = 'pgstattuple') + THEN (SELECT pg_catalog.has_table_privilege(current_user, {0}, + 'SELECT')) ELSE FALSE END""".format(oid)) + + if not status: + return status, internal_server_error(errormsg=is_pgstattuple) + + return status, is_pgstattuple diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py index 5c1efcc2c9b..2f8c3cc3b5d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py @@ -20,7 +20,7 @@ from pgadmin.browser.server_groups.servers import databases from config import PG_DEFAULT_DRIVER from pgadmin.browser.server_groups.servers.databases.schemas.utils import \ - SchemaChildModule, parse_rule_definition, VacuumSettings, get_schema + SchemaChildModule, parse_rule_definition, VacuumSettings, check_pgstattuple from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \ parse_priv_to_db from pgadmin.browser.utils import PGChildNodeView @@ -29,7 +29,7 @@ from pgadmin.utils.driver import get_driver from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry from .schema_diff_view_utils import SchemaDiffViewCompare -from pgadmin.utils import html, does_utility_exist, get_server +from pgadmin.utils import does_utility_exist, get_server from pgadmin.model import Server from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc from pgadmin.utils.constants import SERVER_NOT_FOUND @@ -2477,14 +2477,7 @@ def statistics(self, gid, sid, did, scid, vid=None): ) else: # For Individual mview stats - - # Check if pgstattuple extension is already created? - # if created then only add extended stats - status, is_pgstattuple = self.conn.execute_scalar(""" - SELECT (count(extname) > 0) AS is_pgstattuple - FROM pg_catalog.pg_extension - WHERE extname='pgstattuple' - """) + status, is_pgstattuple = check_pgstattuple(self.conn, vid) if not status: return internal_server_error(errormsg=is_pgstattuple)