diff --git a/docs/en_US/release_notes_5_4.rst b/docs/en_US/release_notes_5_4.rst index 31487baf4..e2c60d505 100644 --- a/docs/en_US/release_notes_5_4.rst +++ b/docs/en_US/release_notes_5_4.rst @@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o New features ************ +| `Issue #1591 `_ - Added Grant Wizard option under Package node. | `Issue #2341 `_ - Added support to launch PSQL for the connected database server. | `Issue #4064 `_ - Added window maximize/restore functionality for properties dialog. | `Issue #6231 `_ - Added OS, Browser, Configuration details in the About dialog. diff --git a/web/pgadmin/tools/grant_wizard/__init__.py b/web/pgadmin/tools/grant_wizard/__init__.py index f91002883..9df3715d9 100644 --- a/web/pgadmin/tools/grant_wizard/__init__.py +++ b/web/pgadmin/tools/grant_wizard/__init__.py @@ -251,6 +251,15 @@ def _get_rows_for_type(conn, ntype, server_prop, node_id): status, res = conn.execute_dict(sql) + # Logic for generating privileges sql only for ppas + # Fetch Packages. + if server_prop['server_type'] == 'ppas' and ntype in ['package']: + sql = render_template("/".join( + [server_prop['template_path'], '/sql/package.sql']), + node_id=node_id) + + status, res = conn.execute_dict(sql) + return status, res @@ -300,7 +309,8 @@ def properties(sid, did, node_id, node_type): current_app.logger.error(res) failed_objects.append(disp_type) else: - res_data.extend(res['rows']) + if len(res) > 0: + res_data.extend(res['rows']) for row in node_types: if 'oid' in row: @@ -338,6 +348,10 @@ def properties(sid, did, node_id, node_type): status, res = _get_rows_for_type( conn, 'foreign_table', server_prop, node_id) _append_rows(status, res, 'foreign table') + + status, res = _get_rows_for_type( + conn, 'package', server_prop, node_id) + _append_rows(status, res, 'package') else: status, res = _get_rows_for_type(conn, ntype, server_prop, node_id) _append_rows(status, res, 'function') @@ -401,6 +415,12 @@ def msql(sid, did): data['acl'], acls['foreign_table']['acl']) + # Logic for setting privileges only for ppas + if server_prop['server_type'] == 'ppas': + data['priv']['package'] = parse_priv_to_db( + data['acl'], + acls['package']['acl']) + # Pass database objects and get SQL for privileges sql_data = '' data_func = {'objects': data['objects'], @@ -438,6 +458,17 @@ def msql(sid, did): if sql and sql.strip('\n') != '': sql_data += sql + # Logic for generating privileges sql only for ppas + if server_prop['server_type'] == 'ppas': + data_package = {'objects': data['objects'], + 'priv': data['priv']['package']} + sql = render_template( + "/".join([server_prop['template_path'], + '/sql/grant_package.sql']), + data=data_package, conn=conn) + if sql and sql.strip('\n') != '': + sql_data += sql + res = {'data': sql_data} return ajax_response( @@ -501,6 +532,12 @@ def save(sid, did): data['acl'], acls['foreign_table']['acl']) + # Logic for setting privileges only for ppas + if server_prop['server_type'] == 'ppas': + data['priv']['package'] = parse_priv_to_db( + data['acl'], + acls['package']['acl']) + # Pass database objects and get SQL for privileges # Pass database objects and get SQL for privileges sql_data = '' @@ -539,6 +576,17 @@ def save(sid, did): if sql and sql.strip('\n') != '': sql_data += sql + # Logic for generating privileges sql only for ppas + if server_prop['server_type'] == 'ppas': + data_package = {'objects': data['objects'], + 'priv': data['priv']['package']} + sql = render_template( + "/".join([server_prop['template_path'], + '/sql/grant_package.sql']), + data=data_package, conn=conn) + if sql and sql.strip('\n') != '': + sql_data += sql + status, res = conn.execute_dict(sql_data) if not status: return internal_server_error(errormsg=res) diff --git a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js index 8e7a067f2..4d19ec4bd 100644 --- a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js +++ b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js @@ -545,6 +545,9 @@ define([ case 'Foreign Table': object_type = 'foreign_table'; break; + case 'Package': + object_type = 'package'; + break; default: break; } diff --git a/web/pgadmin/tools/grant_wizard/static/js/menu_utils.js b/web/pgadmin/tools/grant_wizard/static/js/menu_utils.js index 013ef85a2..07db3dcdf 100644 --- a/web/pgadmin/tools/grant_wizard/static/js/menu_utils.js +++ b/web/pgadmin/tools/grant_wizard/static/js/menu_utils.js @@ -11,6 +11,7 @@ export const supportedNodes = [ 'schema', 'coll-function', 'coll-sequence', 'coll-table', 'coll-view', 'coll-procedure', 'coll-mview', 'database', 'coll-trigger_function', + 'coll-package', ]; diff --git a/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/12_plus/sql/package.sql b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/12_plus/sql/package.sql new file mode 100644 index 000000000..55d72cf44 --- /dev/null +++ b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/12_plus/sql/package.sql @@ -0,0 +1,15 @@ +{# ===== Fetch list of Database object types(Package) ===== #} +{% if node_id %} +SELECT + nsp.nspname AS name, + snsp.nspname AS nspname, + 'Package' as object_type, + 'icon-package' as icon +FROM + pg_catalog.pg_namespace nsp +LEFT OUTER JOIN pg_catalog.pg_namespace snsp ON (nsp.nspparent = snsp.oid) +WHERE nsp.nspparent = {{ node_id }}::oid +AND nsp.nspobjecttype = 0 +AND nsp.nspcompoundtrigger = false +ORDER BY nsp.nspname; +{% endif %} diff --git a/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/acl.json b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/acl.json index 6c9a5fed8..bb42cdf92 100644 --- a/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/acl.json +++ b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/acl.json @@ -30,5 +30,9 @@ "procedure": { "type": "PROCEDURE", "acl": ["X"] + }, + "package": { + "type": "PACKAGE", + "acl": ["X"] } } diff --git a/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/sql/grant_package.sql b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/sql/grant_package.sql new file mode 100644 index 000000000..98d6b3040 --- /dev/null +++ b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/sql/grant_package.sql @@ -0,0 +1,9 @@ +{# ===== Grant Permissions on Database Objects Selected ==== #} +{% import 'macros/schemas/privilege.macros' as PRIVILEGE %} +{% for obj in data.objects -%} +{% for priv in data.priv -%} +{% if obj.object_type == 'Package' %} +{{ PRIVILEGE.SET(conn, 'PACKAGE', priv['grantee'], obj.name, priv['without_grant'], priv['with_grant'], obj.nspname ) }} +{% endif %} +{% endfor -%} +{% endfor -%} diff --git a/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/sql/package.sql b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/sql/package.sql new file mode 100644 index 000000000..f2d7c3b4e --- /dev/null +++ b/web/pgadmin/tools/grant_wizard/templates/grant_wizard/ppas/9.1_plus/sql/package.sql @@ -0,0 +1,14 @@ +{# ===== Fetch list of Database object types(Package) ===== #} +{% if node_id %} +SELECT + nsp.nspname AS name, + snsp.nspname AS nspname, + 'Package' as object_type, + 'icon-package' as icon +FROM + pg_catalog.pg_namespace nsp +LEFT OUTER JOIN pg_catalog.pg_namespace snsp ON (nsp.nspparent = snsp.oid) +WHERE nsp.nspparent = {{ node_id }}::oid +AND nsp.nspobjecttype = 0 +ORDER BY nsp.nspname; +{% endif %} diff --git a/web/pgadmin/tools/grant_wizard/tests/grant_wizard_test_data.json b/web/pgadmin/tools/grant_wizard/tests/grant_wizard_test_data.json index 33e7f4bfd..195c03f24 100644 --- a/web/pgadmin/tools/grant_wizard/tests/grant_wizard_test_data.json +++ b/web/pgadmin/tools/grant_wizard/tests/grant_wizard_test_data.json @@ -217,6 +217,38 @@ "expected_data": { "status_code": 200 } + }, + { + "name": "Grant wizard to packages SQL statement", + "url": "/grant_wizard/sql/", + "is_positive_test": true, + "mocking_required": false, + "test_data": { + "objects": [ + { + "selected": true, + "name": "auth_group", + "name_with_args": "auth_group", + "nspname": "public", + "object_type": "Package" + } + ], + "acl": [ + { + "privileges": [ + { + "privilege_type": "X", + "privilege": true, + "with_grant": true + } + ] + } + ] + }, + "mock_data": {}, + "expected_data": { + "status_code": 200 + } } ], "grant_wizard_get_acl_list": [ diff --git a/web/pgadmin/tools/grant_wizard/tests/test_grant_wizard_get_sql.py b/web/pgadmin/tools/grant_wizard/tests/test_grant_wizard_get_sql.py index d4043a8a4..1ba7e177d 100644 --- a/web/pgadmin/tools/grant_wizard/tests/test_grant_wizard_get_sql.py +++ b/web/pgadmin/tools/grant_wizard/tests/test_grant_wizard_get_sql.py @@ -22,6 +22,8 @@ from pgadmin.utils.route import BaseTestGenerator from regression import parent_node_dict from regression.python_test_utils import test_utils as utils from . import utils as grant_wizard_utils +from pgadmin.browser.server_groups.servers.databases.schemas.packages.tests \ + import utils as package_utils class GrantWizardSaveGetSQLTestCase(BaseTestGenerator): @@ -52,12 +54,35 @@ class GrantWizardSaveGetSQLTestCase(BaseTestGenerator): self.schema_name) if not schema_response: raise Exception("Could not find the schema to add a table.") - self.table_name = "table_for_wizard%s" % (str(uuid.uuid4())[1:8]) - self.table_id = tables_utils.create_table(self.server, self.db_name, - self.schema_name, - self.table_name) - self.test_data['objects'][-1]['name'] = self.table_name - self.test_data['objects'][-1]['name_with_args'] = self.table_name + + if self.test_data['objects'][-1]['object_type'] == 'Package': + + if self.server_information['type'] == 'pg': + message = "Packages are not supported by PG." + self.skipTest(message) + + self.pkg_name = "pkg_%s" % str(uuid.uuid4())[1:8] + self.proc_name = "proc_%s" % str(uuid.uuid4())[1:8] + + self.package_id = package_utils.create_package(self.server, + self.db_name, + self.schema_name, + self.pkg_name, + self.proc_name) + + self.test_data['objects'][-1]['name'] = self.pkg_name + self.test_data['objects'][-1]['name_with_args'] = self.pkg_name + + else: + self.table_name = "table_for_wizard%s" % (str(uuid.uuid4())[1:8]) + self.table_id = tables_utils.create_table(self.server, + self.db_name, + self.schema_name, + self.table_name) + + self.test_data['objects'][-1]['name'] = self.table_name + self.test_data['objects'][-1]['name_with_args'] = self.table_name + self.test_data['objects'][-1]['nspname'] = self.schema_name if self.server_information['type'] == 'ppas':