From 4078e106d2eff3182b6d04827cd55832eb9cb48a Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Tue, 27 Aug 2024 23:43:11 +0800 Subject: [PATCH 01/15] add property for self ownership to db priv response --- db/roles/operations/select.py | 4 ++-- db/sql/00_msar.sql | 7 ++++--- mathesar/rpc/database_privileges.py | 14 ++++++++------ mathesar/tests/rpc/test_endpoints.py | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/db/roles/operations/select.py b/db/roles/operations/select.py index a6c7119ca9..f35f2c1a70 100644 --- a/db/roles/operations/select.py +++ b/db/roles/operations/select.py @@ -17,5 +17,5 @@ def list_table_privileges(table_oid, conn): return exec_msar_func(conn, 'list_table_privileges', table_oid).fetchone()[0] -def get_curr_role_db_priv(db_name, conn): - return exec_msar_func(conn, 'get_owner_oid_and_curr_role_db_priv', db_name).fetchone()[0] +def get_curr_role_db_priv(conn): + return exec_msar_func(conn, 'get_self_database_privileges').fetchone()[0] diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index 6049b07a9d..1080f368ac 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -1063,7 +1063,7 @@ SELECT COALESCE(jsonb_agg(priv_cte.p), '[]'::jsonb) FROM priv_cte; $$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; -CREATE OR REPLACE FUNCTION msar.get_owner_oid_and_curr_role_db_priv(db_name text) RETURNS jsonb AS $$/* +CREATE OR REPLACE FUNCTION msar.get_self_database_privileges() RETURNS jsonb AS $$/* Given a database name, returns a json object with database owner oid and database privileges for the role executing the function. @@ -1081,9 +1081,10 @@ SELECT jsonb_build_object( CASE WHEN has_database_privilege(pgd.oid, 'TEMPORARY') THEN 'TEMPORARY' END, CASE WHEN has_database_privilege(pgd.oid, 'CONNECT') THEN 'CONNECT' END ], NULL - ) + ), + 'current_role_owner', pg_catalog.pg_has_role(pgd.datdba, 'USAGE') ) FROM pg_catalog.pg_database AS pgd -WHERE pgd.datname = db_name; +WHERE pgd.datname = current_database(); $$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; diff --git a/mathesar/rpc/database_privileges.py b/mathesar/rpc/database_privileges.py index f45908da3c..f5bd3b62c3 100644 --- a/mathesar/rpc/database_privileges.py +++ b/mathesar/rpc/database_privileges.py @@ -36,15 +36,18 @@ class CurrentDBPrivileges(TypedDict): Attributes: owner_oid: The `oid` of the owner of the database. current_role_db_priv: A list of database privileges for the current user. + current_role_owner: Whether the current role is an owner of the database. """ owner_oid: int - current_role_db_priv: list[str] + current_role_db_priv: list[Literal['CONNECT', 'CREATE', 'TEMPORARY']] + current_role_owner: bool @classmethod def from_dict(cls, d): return cls( owner_oid=d["owner_oid"], - current_role_db_priv=d["current_role_db_priv"] + current_role_db_priv=d["current_role_db_priv"], + current_role_owner=d["current_role_owner"] ) @@ -69,10 +72,10 @@ def list_direct(*, database_id: int, **kwargs) -> list[DBPrivileges]: # TODO: Think of something concise for the endpoint name. -@rpc_method(name="database_privileges.get_owner_oid_and_curr_role_db_priv") +@rpc_method(name="database_privileges.get_self") @http_basic_auth_login_required @handle_rpc_exceptions -def get_owner_oid_and_curr_role_db_priv(*, database_id: int, **kwargs) -> CurrentDBPrivileges: +def get_self(*, database_id: int, **kwargs) -> CurrentDBPrivileges: """ Get database privileges for the current user. @@ -84,8 +87,7 @@ def get_owner_oid_and_curr_role_db_priv(*, database_id: int, **kwargs) -> Curren """ user = kwargs.get(REQUEST_KEY).user with connect(database_id, user) as conn: - db_name = Database.objects.get(id=database_id).name - curr_role_db_priv = get_curr_role_db_priv(db_name, conn) + curr_role_db_priv = get_curr_role_db_priv(conn) return CurrentDBPrivileges.from_dict(curr_role_db_priv) diff --git a/mathesar/tests/rpc/test_endpoints.py b/mathesar/tests/rpc/test_endpoints.py index c26ea473f4..dd3ff756ea 100644 --- a/mathesar/tests/rpc/test_endpoints.py +++ b/mathesar/tests/rpc/test_endpoints.py @@ -154,8 +154,8 @@ [user_is_authenticated] ), ( - database_privileges.get_owner_oid_and_curr_role_db_priv, - "database_privileges.get_owner_oid_and_curr_role_db_priv", + database_privileges.get_self, + "database_privileges.get_self", [user_is_authenticated] ), ( From 7e1e6dbf9ecfe56a5cffb849cd1774402ba60b73 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 00:11:54 +0800 Subject: [PATCH 02/15] add privilege info to schemas getter return object --- db/sql/00_msar.sql | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index 1080f368ac..b0c685b874 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -893,6 +893,9 @@ Each returned JSON object in the array will have the form: "oid": "name": "description": + "owner_oid": , + "current_role_priv": [], + "current_role_owns": , "table_count": } */ @@ -902,6 +905,15 @@ FROM ( s.oid::bigint AS oid, s.nspname AS name, pg_catalog.obj_description(s.oid) AS description, + s.nspowner::bigint AS owner_oid, + array_remove( + ARRAY[ + CASE WHEN pg_catalog.has_schema_privilege(s.oid, 'USAGE') THEN 'USAGE' END, + CASE WHEN pg_catalog.has_schema_privilege(s.oid, 'CREATE') THEN 'CREATE' END + ], + NULL + ) AS current_role_priv, + pg_catalog.pg_has_role(s.nspowner, 'USAGE') AS current_role_owns, COALESCE(count(c.oid), 0) AS table_count FROM pg_catalog.pg_namespace s LEFT JOIN pg_catalog.pg_class c ON @@ -914,7 +926,8 @@ FROM ( s.nspname NOT LIKE 'pg_%' GROUP BY s.oid, - s.nspname + s.nspname, + s.nspowner ) AS schema_data; $$ LANGUAGE SQL; @@ -1063,26 +1076,27 @@ SELECT COALESCE(jsonb_agg(priv_cte.p), '[]'::jsonb) FROM priv_cte; $$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; -CREATE OR REPLACE FUNCTION msar.get_self_database_privileges() RETURNS jsonb AS $$/* +CREATE OR REPLACE FUNCTION msar.get_current_role_database_privileges() RETURNS jsonb AS $$/* Given a database name, returns a json object with database owner oid and database privileges for the role executing the function. The returned JSON object has the form: { "owner_oid": , - "current_role_db_priv" [] + "current_role_priv": [], + "current_role_owner": } */ SELECT jsonb_build_object( 'owner_oid', pgd.datdba::bigint, - 'current_role_db_priv', array_remove( + 'current_role_priv', array_remove( ARRAY[ CASE WHEN has_database_privilege(pgd.oid, 'CREATE') THEN 'CREATE' END, CASE WHEN has_database_privilege(pgd.oid, 'TEMPORARY') THEN 'TEMPORARY' END, CASE WHEN has_database_privilege(pgd.oid, 'CONNECT') THEN 'CONNECT' END ], NULL ), - 'current_role_owner', pg_catalog.pg_has_role(pgd.datdba, 'USAGE') + 'current_role_owns', pg_catalog.pg_has_role(pgd.datdba, 'USAGE') ) FROM pg_catalog.pg_database AS pgd WHERE pgd.datname = current_database(); $$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; From 8d133924465209044d35003bdd6bb9078539dff9 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 00:13:47 +0800 Subject: [PATCH 03/15] add new schema privilege info to RPC lister --- mathesar/rpc/schemas.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mathesar/rpc/schemas.py b/mathesar/rpc/schemas.py index a372f3b8e0..733f908ac3 100644 --- a/mathesar/rpc/schemas.py +++ b/mathesar/rpc/schemas.py @@ -1,7 +1,7 @@ """ Classes and functions exposed to the RPC endpoint for managing schemas. """ -from typing import Optional, TypedDict +from typing import Literal, Optional, TypedDict from modernrpc.core import rpc_method, REQUEST_KEY from modernrpc.auth.basic import http_basic_auth_login_required @@ -23,11 +23,19 @@ class SchemaInfo(TypedDict): oid: The OID of the schema name: The name of the schema description: A description of the schema + owner_oid: The OID of the owner of the schema + current_role_priv: All privileges available to the calling role + on the schema. + current_role_owns: Whether the current role is the owner of the + schema (even indirectly). table_count: The number of tables in the schema """ oid: int name: str description: Optional[str] + owner_oid: int + current_role_priv: list[Literal['USAGE', 'CREATE']] + current_role_owns: bool table_count: int From 9de56a18914163b1c70aa368c3b8385dba155671 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 00:32:29 +0800 Subject: [PATCH 04/15] Add table privilege info to SQL lister and getter --- db/sql/00_msar.sql | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index b0c685b874..60c74f20a5 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -844,6 +844,20 @@ SELECT jsonb_build_object( 'name', relname, 'schema', relnamespace::bigint, 'description', msar.obj_description(oid, 'pg_class') + 'owner_oid', relowner, + 'current_role_priv', array_remove( + ARRAY[ + CASE WHEN pg_catalog.has_table_privilege(oid, 'SELECT') THEN 'SELECT' END, + CASE WHEN pg_catalog.has_table_privilege(oid, 'INSERT') THEN 'INSERT' END, + CASE WHEN pg_catalog.has_table_privilege(oid, 'UPDATE') THEN 'UPDATE' END, + CASE WHEN pg_catalog.has_table_privilege(oid, 'DELETE') THEN 'DELETE' END, + CASE WHEN pg_catalog.has_table_privilege(oid, 'TRUNCATE') THEN 'TRUNCATE' END, + CASE WHEN pg_catalog.has_table_privilege(oid, 'REFERENCES') THEN 'REFERENCES' END, + CASE WHEN pg_catalog.has_table_privilege(oid, 'TRIGGER') THEN 'TRIGGER' END + ], + NULL + ), + 'current_role_owns', pg_catalog.pg_has_role(relowner, 'USAGE') ) FROM pg_catalog.pg_class WHERE oid = tab_id; $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; @@ -856,7 +870,10 @@ Each returned JSON object in the array will have the form: "oid": , "name": , "schema": , - "description": + "description": , + "owner_oid": , + "current_role_priv": [], + "current_role_owns": } Args: @@ -868,7 +885,21 @@ SELECT coalesce( 'oid', pgc.oid::bigint, 'name', pgc.relname, 'schema', pgc.relnamespace::bigint, - 'description', msar.obj_description(pgc.oid, 'pg_class') + 'description', msar.obj_description(pgc.oid, 'pg_class'), + 'owner_oid', pgc.relowner, + 'current_role_priv', array_remove( + ARRAY[ + CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'SELECT') THEN 'SELECT' END, + CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'INSERT') THEN 'INSERT' END, + CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'UPDATE') THEN 'UPDATE' END, + CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'DELETE') THEN 'DELETE' END, + CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'TRUNCATE') THEN 'TRUNCATE' END, + CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'REFERENCES') THEN 'REFERENCES' END, + CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'TRIGGER') THEN 'TRIGGER' END + ], + NULL + ), + 'current_role_owns', pg_catalog.pg_has_role(pgc.relowner, 'USAGE') ) ), '[]'::jsonb From 9d562d9d3ac59eb4cf6f79e92ef38a3af48391b2 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 00:34:05 +0800 Subject: [PATCH 05/15] remove extraneous and out-of-date docstring snippets --- db/tables/operations/select.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/db/tables/operations/select.py b/db/tables/operations/select.py index a25fca1d43..fea5b168b4 100644 --- a/db/tables/operations/select.py +++ b/db/tables/operations/select.py @@ -22,15 +22,6 @@ def get_table(table, conn): The `table` can be given as either a "qualified name", or an OID. The OID is the preferred identifier, since it's much more robust. - The returned dictionary is of the following form: - - { - "oid": , - "name": , - "schema": , - "description": - } - Args: table: The table for which we want table info. """ @@ -44,15 +35,6 @@ def get_table_info(schema, conn): The `schema` can be given as either a "qualified name", or an OID. The OID is the preferred identifier, since it's much more robust. - The returned list contains dictionaries of the following form: - - { - "oid": , - "name": , - "schema": , - "description": - } - Args: schema: The schema for which we want table info. """ From 12a6b63ac38b5b4ed159da5d224023b71ae56e27 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 00:39:42 +0800 Subject: [PATCH 06/15] wire up table privilege info to RPC function --- db/sql/00_msar.sql | 5 ++++- mathesar/rpc/tables/base.py | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index 60c74f20a5..55c12b80c8 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -833,7 +833,10 @@ Each returned JSON object will have the form: "oid": , "name": , "schema": , - "description": + "description": , + "owner_oid": , + "current_role_priv": [], + "current_role_owns": } Args: diff --git a/mathesar/rpc/tables/base.py b/mathesar/rpc/tables/base.py index 9ee9b4e73e..b0132e480f 100644 --- a/mathesar/rpc/tables/base.py +++ b/mathesar/rpc/tables/base.py @@ -1,7 +1,7 @@ """ Classes and functions exposed to the RPC endpoint for managing tables in a database. """ -from typing import Optional, TypedDict +from typing import Literal, Optional, TypedDict from modernrpc.core import rpc_method, REQUEST_KEY from modernrpc.auth.basic import http_basic_auth_login_required @@ -28,11 +28,27 @@ class TableInfo(TypedDict): name: The name of the table. schema: The `oid` of the schema where the table lives. description: The description of the table. + owner_oid: The OID of the direct owner of the table. + current_role_priv: The privileges held by the user on the table. + current_role_owns: Whether the current role owns the table. """ oid: int name: str schema: int description: Optional[str] + owner_oid: int + current_role_priv: list[ + Literal[ + 'SELECT', + 'INSERT', + 'UPDATE', + 'DELETE', + 'TRUNCATE', + 'REFERENCES', + 'TRIGGER' + ] + ] + current_role_owns: bool class SettableTableInfo(TypedDict): From 3ae677a4eb0937e53941735be26253b9bc82977b Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 00:50:26 +0800 Subject: [PATCH 07/15] add privilege info to column response object --- db/columns/operations/select.py | 1 + db/sql/00_msar.sql | 10 ++++++++++ mathesar/rpc/columns/base.py | 1 + 3 files changed, 12 insertions(+) diff --git a/db/columns/operations/select.py b/db/columns/operations/select.py index a79e63e1c8..5ef5f1f508 100644 --- a/db/columns/operations/select.py +++ b/db/columns/operations/select.py @@ -33,6 +33,7 @@ def get_column_info_for_table(table, conn): "valid_target_types": [, , ..., ] "default": {"value": , "is_dynamic": }, "has_dependents": , + "current_role_priv": [, , ...], "description": } diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index 55c12b80c8..f603cd0d5e 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -776,6 +776,7 @@ Each returned JSON object in the array will have the form: "default": {"value": , "is_dynamic": }, "has_dependents": , "description": , + "current_role_priv": [, , ...], "valid_target_types": [, , ...] } @@ -808,6 +809,15 @@ SELECT jsonb_agg( ), 'has_dependents', msar.has_dependents(tab_id, attnum), 'description', msar.col_description(tab_id, attnum), + 'current_role_priv', array_remove( + ARRAY[ + CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'SELECT') THEN 'SELECT' END, + CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'INSERT') THEN 'INSERT' END, + CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'UPDATE') THEN 'UPDATE' END, + CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'REFERENCES') THEN 'REFERENCES' END + ], + NULL + ), 'valid_target_types', msar.get_valid_target_type_strings(atttypid) ) ) diff --git a/mathesar/rpc/columns/base.py b/mathesar/rpc/columns/base.py index 1b0f5e954d..cb1ef972d2 100644 --- a/mathesar/rpc/columns/base.py +++ b/mathesar/rpc/columns/base.py @@ -186,6 +186,7 @@ def from_dict(cls, col_info): default=ColumnDefault.from_dict(col_info.get("default")), has_dependents=col_info["has_dependents"], description=col_info.get("description"), + current_role_priv=col_info["current_role_priv"], valid_target_types=col_info.get("valid_target_types") ) From 7723c4261a0d61b66cd570e3c9f99beff0f16a28 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 01:05:02 +0800 Subject: [PATCH 08/15] Modify test for new column lister response --- db/sql/00_msar.sql | 2 +- mathesar/rpc/columns/base.py | 4 +++- mathesar/tests/rpc/columns/test_c_base.py | 10 ++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index f603cd0d5e..df3d765222 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -856,7 +856,7 @@ SELECT jsonb_build_object( 'oid', oid::bigint, 'name', relname, 'schema', relnamespace::bigint, - 'description', msar.obj_description(oid, 'pg_class') + 'description', msar.obj_description(oid, 'pg_class'), 'owner_oid', relowner, 'current_role_priv', array_remove( ARRAY[ diff --git a/mathesar/rpc/columns/base.py b/mathesar/rpc/columns/base.py index cb1ef972d2..82251e1b9e 100644 --- a/mathesar/rpc/columns/base.py +++ b/mathesar/rpc/columns/base.py @@ -1,7 +1,7 @@ """ Classes and functions exposed to the RPC endpoint for managing table columns. """ -from typing import Optional, TypedDict +from typing import Literal, Optional, TypedDict from modernrpc.core import rpc_method, REQUEST_KEY from modernrpc.auth.basic import http_basic_auth_login_required @@ -160,6 +160,7 @@ class ColumnInfo(TypedDict): default: The default value and whether it's dynamic. has_dependents: Whether the column has dependent objects. description: The description of the column. + current_role_priv: The privileges of the user for the column. valid_target_types: A list of all types to which the column can be cast. """ @@ -172,6 +173,7 @@ class ColumnInfo(TypedDict): default: ColumnDefault has_dependents: bool description: str + current_role_priv: list[Literal['SELECT', 'INSERT', 'UPDATE', 'REFERENCES']] valid_target_types: list[str] @classmethod diff --git a/mathesar/tests/rpc/columns/test_c_base.py b/mathesar/tests/rpc/columns/test_c_base.py index 88f7db64f5..69d7bc767c 100644 --- a/mathesar/tests/rpc/columns/test_c_base.py +++ b/mathesar/tests/rpc/columns/test_c_base.py @@ -37,6 +37,7 @@ def mock_column_info(_table_oid, conn): 'nullable': False, 'description': None, 'primary_key': True, 'type_options': None, 'has_dependents': True, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 2, 'name': 'numcol', 'type': 'numeric', @@ -46,6 +47,7 @@ def mock_column_info(_table_oid, conn): 'primary_key': False, 'type_options': {'scale': None, 'precision': None}, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 4, 'name': 'numcolmod', 'type': 'numeric', @@ -53,6 +55,7 @@ def mock_column_info(_table_oid, conn): 'nullable': True, 'description': None, 'primary_key': False, 'type_options': {'scale': 3, 'precision': 5}, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 8, 'name': 'ivlcolmod', 'type': 'interval', @@ -60,6 +63,7 @@ def mock_column_info(_table_oid, conn): 'nullable': True, 'description': None, 'primary_key': False, 'type_options': {'fields': 'day to second'}, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 10, 'name': 'arrcol', 'type': '_array', @@ -67,6 +71,7 @@ def mock_column_info(_table_oid, conn): 'nullable': True, 'description': None, 'primary_key': False, 'type_options': {'item_type': 'character varying', 'length': 3}, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': None }, ] @@ -80,6 +85,7 @@ def mock_column_info(_table_oid, conn): 'nullable': False, 'description': None, 'primary_key': True, 'type_options': None, 'has_dependents': True, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 2, 'name': 'numcol', 'type': 'numeric', @@ -89,6 +95,7 @@ def mock_column_info(_table_oid, conn): 'primary_key': False, 'type_options': None, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 4, 'name': 'numcolmod', 'type': 'numeric', @@ -96,6 +103,7 @@ def mock_column_info(_table_oid, conn): 'nullable': True, 'description': None, 'primary_key': False, 'type_options': {'scale': 3, 'precision': 5}, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 8, 'name': 'ivlcolmod', 'type': 'interval', @@ -103,6 +111,7 @@ def mock_column_info(_table_oid, conn): 'nullable': True, 'description': None, 'primary_key': False, 'type_options': {'fields': 'day to second'}, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': ['text'] }, { 'id': 10, 'name': 'arrcol', 'type': '_array', @@ -110,6 +119,7 @@ def mock_column_info(_table_oid, conn): 'nullable': True, 'description': None, 'primary_key': False, 'type_options': {'item_type': 'character varying', 'length': 3}, 'has_dependents': False, + 'current_role_priv': ['SELECT', 'INSERT', 'UPDATE'], 'valid_target_types': None } ] From 22ff7fb12291fd06695b0f40d0d048d9c31443da Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 01:12:24 +0800 Subject: [PATCH 09/15] update test for new column info response type --- db/sql/test_00_msar.sql | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/db/sql/test_00_msar.sql b/db/sql/test_00_msar.sql index 7648e7ba1f..2b802e65d1 100644 --- a/db/sql/test_00_msar.sql +++ b/db/sql/test_00_msar.sql @@ -2597,6 +2597,7 @@ BEGIN "primary_key": true, "type_options": null, "has_dependents": true, + "current_role_priv": ["SELECT", "INSERT", "UPDATE", "REFERENCES"], "valid_target_types": null }, { @@ -2612,6 +2613,7 @@ BEGIN "precision": null }, "has_dependents": false, + "current_role_priv": ["SELECT", "INSERT", "UPDATE", "REFERENCES"], "valid_target_types": null }, { @@ -2626,6 +2628,7 @@ BEGIN "length": 128 }, "has_dependents": false, + "current_role_priv": ["SELECT", "INSERT", "UPDATE", "REFERENCES"], "valid_target_types": null }, { @@ -2641,6 +2644,7 @@ BEGIN "primary_key": false, "type_options": null, "has_dependents": false, + "current_role_priv": ["SELECT", "INSERT", "UPDATE", "REFERENCES"], "valid_target_types": ["numeric", "text"] }, { @@ -2658,6 +2662,7 @@ BEGIN "precision": null }, "has_dependents": false, + "current_role_priv": ["SELECT", "INSERT", "UPDATE", "REFERENCES"], "valid_target_types": null }, { @@ -2672,6 +2677,7 @@ BEGIN "item_type": "integer" }, "has_dependents": false, + "current_role_priv": ["SELECT", "INSERT", "UPDATE", "REFERENCES"], "valid_target_types": null }, { @@ -2688,6 +2694,7 @@ BEGIN "precision": 15 }, "has_dependents": false, + "current_role_priv": ["SELECT", "INSERT", "UPDATE", "REFERENCES"], "valid_target_types": null } ]$j$::jsonb From 402baeb13cc390e4aab3edc28c005ca2ca608b4f Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 13:32:51 +0800 Subject: [PATCH 10/15] tidy and extract privilege listing logic --- db/sql/00_msar.sql | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index df3d765222..5b06361222 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -835,6 +835,20 @@ SELECT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid=tab_id AND attname=col_ $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; +CREATE OR REPLACE FUNCTION +msar.list_table_privileges_for_current_role(tab_id regclass) RETURNS jsonb AS $$/* +Return a JSONB array of all privileges current_user holds on the passed table. +*/ +SELECT coalesce(jsonb_agg(privilege), '[]'::jsonb) +FROM + unnest( + ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'] + ) AS x(privilege), + has_table_privilege(tab_id, privilege) as has_privilege +WHERE has_privilege; +$$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; + + CREATE OR REPLACE FUNCTION msar.get_table(tab_id regclass) RETURNS jsonb AS $$/* Given a table identifier, return a JSON object describing the table. @@ -858,18 +872,7 @@ SELECT jsonb_build_object( 'schema', relnamespace::bigint, 'description', msar.obj_description(oid, 'pg_class'), 'owner_oid', relowner, - 'current_role_priv', array_remove( - ARRAY[ - CASE WHEN pg_catalog.has_table_privilege(oid, 'SELECT') THEN 'SELECT' END, - CASE WHEN pg_catalog.has_table_privilege(oid, 'INSERT') THEN 'INSERT' END, - CASE WHEN pg_catalog.has_table_privilege(oid, 'UPDATE') THEN 'UPDATE' END, - CASE WHEN pg_catalog.has_table_privilege(oid, 'DELETE') THEN 'DELETE' END, - CASE WHEN pg_catalog.has_table_privilege(oid, 'TRUNCATE') THEN 'TRUNCATE' END, - CASE WHEN pg_catalog.has_table_privilege(oid, 'REFERENCES') THEN 'REFERENCES' END, - CASE WHEN pg_catalog.has_table_privilege(oid, 'TRIGGER') THEN 'TRIGGER' END - ], - NULL - ), + 'current_role_priv', msar.list_table_privileges_for_current_role(tab_id), 'current_role_owns', pg_catalog.pg_has_role(relowner, 'USAGE') ) FROM pg_catalog.pg_class WHERE oid = tab_id; $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; @@ -900,18 +903,7 @@ SELECT coalesce( 'schema', pgc.relnamespace::bigint, 'description', msar.obj_description(pgc.oid, 'pg_class'), 'owner_oid', pgc.relowner, - 'current_role_priv', array_remove( - ARRAY[ - CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'SELECT') THEN 'SELECT' END, - CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'INSERT') THEN 'INSERT' END, - CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'UPDATE') THEN 'UPDATE' END, - CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'DELETE') THEN 'DELETE' END, - CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'TRUNCATE') THEN 'TRUNCATE' END, - CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'REFERENCES') THEN 'REFERENCES' END, - CASE WHEN pg_catalog.has_table_privilege(pgc.oid, 'TRIGGER') THEN 'TRIGGER' END - ], - NULL - ), + 'current_role_priv', msar.list_table_privileges_for_current_role(pgc.oid), 'current_role_owns', pg_catalog.pg_has_role(pgc.relowner, 'USAGE') ) ), From 8fb3975bbbe6afc67c0ab7843127e822b88b6899 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 14:53:26 +0800 Subject: [PATCH 11/15] extract privilege listing for databases, tidy up naming --- db/roles/operations/select.py | 7 +++- db/sql/00_msar.sql | 59 +++++++++++++++++++---------- mathesar/rpc/database_privileges.py | 4 +- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/db/roles/operations/select.py b/db/roles/operations/select.py index f35f2c1a70..4b182ad31f 100644 --- a/db/roles/operations/select.py +++ b/db/roles/operations/select.py @@ -18,4 +18,9 @@ def list_table_privileges(table_oid, conn): def get_curr_role_db_priv(conn): - return exec_msar_func(conn, 'get_self_database_privileges').fetchone()[0] + db_info = exec_msar_func(conn, 'get_current_database_info').fetchone()[0] + return { + "owner_oid": db_info["owner_oid"], + "current_role_priv": db_info["current_role_priv"], + "current_role_owns": db_info["current_role_owns"], + } diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index 5b06361222..0466af6767 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -844,7 +844,7 @@ FROM unnest( ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'] ) AS x(privilege), - has_table_privilege(tab_id, privilege) as has_privilege + pg_catalog.has_table_privilege(tab_id, privilege) as has_privilege WHERE has_privilege; $$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; @@ -915,6 +915,20 @@ WHERE pgc.relnamespace = sch_id AND pgc.relkind = 'r'; $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; +CREATE OR REPLACE FUNCTION +msar.list_schema_privileges_for_current_role(sch_id regnamespace) RETURNS jsonb AS $$/* +Return a JSONB array of all privileges current_user holds on the passed schema. +*/ +SELECT coalesce(jsonb_agg(privilege), '[]'::jsonb) +FROM + unnest( + ARRAY['USAGE', 'CREATE'] + ) AS x(privilege), + pg_catalog.has_schema_privilege(sch_id, privilege) as has_privilege +WHERE has_privilege; +$$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; + + CREATE OR REPLACE FUNCTION msar.get_schemas() RETURNS jsonb AS $$/* Return a json array of objects describing the user-defined schemas in the database. @@ -942,13 +956,7 @@ FROM ( s.nspname AS name, pg_catalog.obj_description(s.oid) AS description, s.nspowner::bigint AS owner_oid, - array_remove( - ARRAY[ - CASE WHEN pg_catalog.has_schema_privilege(s.oid, 'USAGE') THEN 'USAGE' END, - CASE WHEN pg_catalog.has_schema_privilege(s.oid, 'CREATE') THEN 'CREATE' END - ], - NULL - ) AS current_role_priv, + msar.list_schema_privileges_for_current_role(s.oid) AS current_role_priv, pg_catalog.pg_has_role(s.nspowner, 'USAGE') AS current_role_owns, COALESCE(count(c.oid), 0) AS table_count FROM pg_catalog.pg_namespace s @@ -968,7 +976,6 @@ FROM ( $$ LANGUAGE SQL; -DROP FUNCTION IF EXISTS msar.role_info_table(); CREATE OR REPLACE FUNCTION msar.list_schema_privileges(sch_id regnamespace) RETURNS jsonb AS $$/* Given a schema, returns a json array of objects with direct, non-default schema privileges @@ -995,6 +1002,7 @@ SELECT COALESCE(jsonb_agg(priv_cte.p), '[]'::jsonb) FROM priv_cte; $$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; +DROP FUNCTION IF EXISTS msar.role_info_table(); CREATE OR REPLACE FUNCTION msar.role_info_table() RETURNS TABLE ( oid bigint, -- The OID of the role. @@ -1112,26 +1120,37 @@ SELECT COALESCE(jsonb_agg(priv_cte.p), '[]'::jsonb) FROM priv_cte; $$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; -CREATE OR REPLACE FUNCTION msar.get_current_role_database_privileges() RETURNS jsonb AS $$/* -Given a database name, returns a json object with database owner oid and database privileges -for the role executing the function. +CREATE OR REPLACE FUNCTION +msar.list_database_privileges_for_current_role(dat_id oid) RETURNS jsonb AS $$/* +Return a JSONB array of all privileges current_user holds on the passed database. +*/ +SELECT coalesce(jsonb_agg(privilege), '[]'::jsonb) +FROM + unnest( + ARRAY['CONNECT', 'CREATE', 'TEMPORARY'] + ) AS x(privilege), + pg_catalog.has_database_privilege(dat_id, privilege) as has_privilege +WHERE has_privilege; +$$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; + + +CREATE OR REPLACE FUNCTION msar.get_current_database_info() RETURNS jsonb AS $$/* +Return information about the current database. The returned JSON object has the form: { - "owner_oid": , + "oid": , + "name": , + "owner_oid": , "current_role_priv": [], "current_role_owner": } */ SELECT jsonb_build_object( + 'oid', pgd.oid::bigint, + 'name', pgd.datname, 'owner_oid', pgd.datdba::bigint, - 'current_role_priv', array_remove( - ARRAY[ - CASE WHEN has_database_privilege(pgd.oid, 'CREATE') THEN 'CREATE' END, - CASE WHEN has_database_privilege(pgd.oid, 'TEMPORARY') THEN 'TEMPORARY' END, - CASE WHEN has_database_privilege(pgd.oid, 'CONNECT') THEN 'CONNECT' END - ], NULL - ), + 'current_role_priv', msar.list_database_privileges_for_current_role(pgd.oid), 'current_role_owns', pg_catalog.pg_has_role(pgd.datdba, 'USAGE') ) FROM pg_catalog.pg_database AS pgd WHERE pgd.datname = current_database(); diff --git a/mathesar/rpc/database_privileges.py b/mathesar/rpc/database_privileges.py index f5bd3b62c3..13d1d09076 100644 --- a/mathesar/rpc/database_privileges.py +++ b/mathesar/rpc/database_privileges.py @@ -46,8 +46,8 @@ class CurrentDBPrivileges(TypedDict): def from_dict(cls, d): return cls( owner_oid=d["owner_oid"], - current_role_db_priv=d["current_role_db_priv"], - current_role_owner=d["current_role_owner"] + current_role_priv=d["current_role_priv"], + current_role_owns=d["current_role_owns"] ) From ad91464a6c06ee10dd5aa909ec8a059cd25777a9 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 15:48:58 +0800 Subject: [PATCH 12/15] extract column privileges getter function --- db/sql/00_msar.sql | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/db/sql/00_msar.sql b/db/sql/00_msar.sql index 0466af6767..452662efd2 100644 --- a/db/sql/00_msar.sql +++ b/db/sql/00_msar.sql @@ -762,6 +762,18 @@ SELECT EXISTS ( $$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; +CREATE OR REPLACE FUNCTION +msar.list_column_privileges_for_current_role(tab_id regclass, attnum smallint) RETURNS jsonb AS $$/* +Return a JSONB array of all privileges current_user holds on the passed table. +*/ +SELECT coalesce(jsonb_agg(privilege), '[]'::jsonb) +FROM + unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES']) AS x(privilege), + pg_catalog.has_column_privilege(tab_id, attnum, privilege) as has_privilege +WHERE has_privilege; +$$ LANGUAGE SQL STABLE RETURNS NULL ON NULL INPUT; + + CREATE OR REPLACE FUNCTION msar.get_column_info(tab_id regclass) RETURNS jsonb AS $$/* Given a table identifier, return an array of objects describing the columns of the table. @@ -809,15 +821,7 @@ SELECT jsonb_agg( ), 'has_dependents', msar.has_dependents(tab_id, attnum), 'description', msar.col_description(tab_id, attnum), - 'current_role_priv', array_remove( - ARRAY[ - CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'SELECT') THEN 'SELECT' END, - CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'INSERT') THEN 'INSERT' END, - CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'UPDATE') THEN 'UPDATE' END, - CASE WHEN pg_catalog.has_column_privilege(tab_id, attnum, 'REFERENCES') THEN 'REFERENCES' END - ], - NULL - ), + 'current_role_priv', msar.list_column_privileges_for_current_role(tab_id, attnum), 'valid_target_types', msar.get_valid_target_type_strings(atttypid) ) ) From 332b27fbdf0ee7375bdca7f021c9ca4c4be0967d Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 15:59:38 +0800 Subject: [PATCH 13/15] fix naming in db privilege class --- mathesar/rpc/database_privileges.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mathesar/rpc/database_privileges.py b/mathesar/rpc/database_privileges.py index 13d1d09076..dfc661b3d4 100644 --- a/mathesar/rpc/database_privileges.py +++ b/mathesar/rpc/database_privileges.py @@ -39,8 +39,8 @@ class CurrentDBPrivileges(TypedDict): current_role_owner: Whether the current role is an owner of the database. """ owner_oid: int - current_role_db_priv: list[Literal['CONNECT', 'CREATE', 'TEMPORARY']] - current_role_owner: bool + current_role_priv: list[Literal['CONNECT', 'CREATE', 'TEMPORARY']] + current_role_owns: bool @classmethod def from_dict(cls, d): From b6852f3cf2b6353f3dffd036a5289e675feb5253 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 16:35:52 +0800 Subject: [PATCH 14/15] add tests for new SQL privilege lister functions --- db/sql/test_00_msar.sql | 134 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/db/sql/test_00_msar.sql b/db/sql/test_00_msar.sql index 2b802e65d1..c3d914ce76 100644 --- a/db/sql/test_00_msar.sql +++ b/db/sql/test_00_msar.sql @@ -4552,3 +4552,137 @@ BEGIN ); END; $$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_list_column_privileges_for_current_role() RETURNS SETOF TEXT AS $$ +DECLARE + tab_id oid; +BEGIN +CREATE TABLE mytab (col1 varchar, col2 varchar); +tab_id := 'mytab'::regclass::oid; +CREATE ROLE test_intern1; +CREATE ROLE test_intern2; +GRANT USAGE ON SCHEMA msar, __msar TO test_intern1, test_intern2; +GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA msar, __msar TO test_intern1, test_intern2; +GRANT SELECT, INSERT (col1) ON TABLE mytab TO test_intern1; +GRANT SELECT (col2) ON TABLE mytab TO test_intern1; +GRANT UPDATE (col1) ON TABLE mytab TO test_intern2; +GRANT UPDATE, REFERENCES (col2) ON TABLE mytab TO test_intern2; + +RETURN NEXT is( + msar.list_column_privileges_for_current_role(tab_id, 1::smallint), + '["SELECT", "INSERT", "UPDATE", "REFERENCES"]' +); +RETURN NEXT is( + msar.list_column_privileges_for_current_role(tab_id, 2::smallint), + '["SELECT", "INSERT", "UPDATE", "REFERENCES"]' +); + +SET ROLE test_intern1; +RETURN NEXT is( + msar.list_column_privileges_for_current_role(tab_id, 1::smallint), + '["SELECT", "INSERT"]' +); +RETURN NEXT is( + msar.list_column_privileges_for_current_role(tab_id, 2::smallint), + '["SELECT"]' +); + +SET ROLE test_intern2; +RETURN NEXT is( + msar.list_column_privileges_for_current_role(tab_id, 1::smallint), + '["UPDATE"]' +); +RETURN NEXT is( + msar.list_column_privileges_for_current_role(tab_id, 2::smallint), + '["UPDATE", "REFERENCES"]' +); + +END; +$$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_list_schema_privileges_for_current_role() RETURNS SETOF TEXT AS $$ +DECLARE + sch_id oid; +BEGIN +CREATE SCHEMA restricted; +sch_id := 'restricted'::regnamespace::oid; +CREATE ROLE test_intern1; +CREATE ROLE test_intern2; +GRANT USAGE ON SCHEMA msar, __msar TO test_intern1, test_intern2; +GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA msar, __msar TO test_intern1, test_intern2; +GRANT USAGE ON SCHEMA restricted TO test_intern1; +GRANT USAGE, CREATE ON SCHEMA restricted TO test_intern2; + +RETURN NEXT is(msar.list_schema_privileges_for_current_role(sch_id), '["USAGE", "CREATE"]'); + +SET ROLE test_intern1; +RETURN NEXT is(msar.list_schema_privileges_for_current_role(sch_id), '["USAGE"]'); + +SET ROLE test_intern2; +RETURN NEXT is(msar.list_schema_privileges_for_current_role(sch_id), '["USAGE", "CREATE"]'); + +END; +$$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_list_table_privileges_for_current_role() RETURNS SETOF TEXT AS $$ +DECLARE + tab_id oid; +BEGIN +CREATE TABLE mytab (col1 varchar); +tab_id := 'mytab'::regclass::oid; +CREATE ROLE test_intern1; +CREATE ROLE test_intern2; +GRANT USAGE ON SCHEMA msar, __msar TO test_intern1, test_intern2; +GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA msar, __msar TO test_intern1, test_intern2; + +GRANT SELECT, INSERT, UPDATE ON TABLE mytab TO test_intern1; +GRANT DELETE, TRUNCATE, REFERENCES, TRIGGER ON TABLE mytab TO test_intern2; + +RETURN NEXT is( + msar.list_table_privileges_for_current_role(tab_id), + '["SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER"]' +); + +SET ROLE test_intern1; +RETURN NEXT is( + msar.list_table_privileges_for_current_role(tab_id), + '["SELECT", "INSERT", "UPDATE"]' +); + +SET ROLE test_intern2; +RETURN NEXT is( + msar.list_table_privileges_for_current_role(tab_id), + '["DELETE", "TRUNCATE", "REFERENCES", "TRIGGER"]' +); +END; +$$ LANGUAGE plpgsql; + + +CREATE OR REPLACE FUNCTION test_list_database_privileges_for_current_role() RETURNS SETOF TEXT AS $$ +DECLARE + dat_id oid := oid FROM pg_database WHERE datname=current_database(); +BEGIN +CREATE ROLE test_intern1; +CREATE ROLE test_intern2; +GRANT USAGE ON SCHEMA msar, __msar TO test_intern1, test_intern2; +GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA msar, __msar TO test_intern1, test_intern2; + +REVOKE ALL ON DATABASE mathesar_testing FROM PUBLIC; +GRANT CONNECT, CREATE ON DATABASE mathesar_testing TO test_intern1; +GRANT CONNECT, TEMPORARY ON DATABASE mathesar_testing TO test_intern2; + +RETURN NEXT is( + msar.list_database_privileges_for_current_role(dat_id), + '["CONNECT", "CREATE", "TEMPORARY"]' +); + +SET ROLE test_intern1; +RETURN NEXT is(msar.list_database_privileges_for_current_role(dat_id), '["CONNECT", "CREATE"]'); + +SET ROLE test_intern2; +RETURN NEXT is(msar.list_database_privileges_for_current_role(dat_id), '["CONNECT", "TEMPORARY"]'); +END; +$$ LANGUAGE plpgsql; From dfc50145af9d25d3442e77f72ee34cd863d4ee12 Mon Sep 17 00:00:00 2001 From: Brent Moran Date: Wed, 28 Aug 2024 16:39:44 +0800 Subject: [PATCH 15/15] update documentation to be more precise w.r.t. privileges --- mathesar/rpc/columns/base.py | 2 +- mathesar/rpc/database_privileges.py | 4 ++-- mathesar/rpc/tables/base.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mathesar/rpc/columns/base.py b/mathesar/rpc/columns/base.py index 82251e1b9e..16a7641e39 100644 --- a/mathesar/rpc/columns/base.py +++ b/mathesar/rpc/columns/base.py @@ -160,7 +160,7 @@ class ColumnInfo(TypedDict): default: The default value and whether it's dynamic. has_dependents: Whether the column has dependent objects. description: The description of the column. - current_role_priv: The privileges of the user for the column. + current_role_priv: The privileges available to the user for the column. valid_target_types: A list of all types to which the column can be cast. """ diff --git a/mathesar/rpc/database_privileges.py b/mathesar/rpc/database_privileges.py index dfc661b3d4..eb41e04a0c 100644 --- a/mathesar/rpc/database_privileges.py +++ b/mathesar/rpc/database_privileges.py @@ -35,8 +35,8 @@ class CurrentDBPrivileges(TypedDict): Attributes: owner_oid: The `oid` of the owner of the database. - current_role_db_priv: A list of database privileges for the current user. - current_role_owner: Whether the current role is an owner of the database. + current_role_priv: A list of privileges available to the user. + current_role_owns: Whether the user is an owner of the database. """ owner_oid: int current_role_priv: list[Literal['CONNECT', 'CREATE', 'TEMPORARY']] diff --git a/mathesar/rpc/tables/base.py b/mathesar/rpc/tables/base.py index b0132e480f..8b971ca9a3 100644 --- a/mathesar/rpc/tables/base.py +++ b/mathesar/rpc/tables/base.py @@ -29,7 +29,7 @@ class TableInfo(TypedDict): schema: The `oid` of the schema where the table lives. description: The description of the table. owner_oid: The OID of the direct owner of the table. - current_role_priv: The privileges held by the user on the table. + current_role_priv: The privileges available to the user on the table. current_role_owns: Whether the current role owns the table. """ oid: int