diff --git a/docs/en_US/images/rule_definition_enabled.png b/docs/en_US/images/rule_definition_enabled.png new file mode 100644 index 000000000..6764d8eda Binary files /dev/null and b/docs/en_US/images/rule_definition_enabled.png differ diff --git a/docs/en_US/release_notes_6_1.rst b/docs/en_US/release_notes_6_1.rst index 9acad051b..7ee272597 100644 --- a/docs/en_US/release_notes_6_1.rst +++ b/docs/en_US/release_notes_6_1.rst @@ -13,6 +13,7 @@ New features | `Issue #6081 `_ - Added support for advanced table fields like the foreign key, primary key in the ERD tool. | `Issue #6529 `_ - Added index creation when generating SQL in the ERD tool. | `Issue #6657 `_ - Added support for authentication via the webserver (REMOTE_USER). +| `Issue #6794 `_ - Added support to enable/disable rules. Housekeeping ************ diff --git a/docs/en_US/rule_dialog.rst b/docs/en_US/rule_dialog.rst index 2baebe662..152107cfe 100644 --- a/docs/en_US/rule_dialog.rst +++ b/docs/en_US/rule_dialog.rst @@ -37,6 +37,13 @@ Use the fields in the *Definition* tab to write parameters: executed instead of the original command; if Do Instead specifies *No*, the rule will be invoked in addition to the original command. +.. image:: images/rule_definition_enabled.png + :alt: Trigger enabled in dialog tab + :align: center + +* *Rule enabled* field is available in rule dialog once the rule is created. + You can select one of the four options available. + Click the *Condition* tab to continue. .. image:: images/rule_condition.png diff --git a/web/pgadmin/browser/server_groups/__init__.py b/web/pgadmin/browser/server_groups/__init__.py index 561772636..1cedc9c5d 100644 --- a/web/pgadmin/browser/server_groups/__init__.py +++ b/web/pgadmin/browser/server_groups/__init__.py @@ -177,7 +177,7 @@ class ServerGroupView(NodeView): # if server group id is 1 we won't delete it. sg = groups.first() - shared_servers = Server.query.filter_by(servergroup_id=sg.id, + shared_servers = Server.query.filter_by(servergroup_id=gid, shared=True).all() if shared_servers: return make_json_response( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py index 75a91c6b3..9a01eed4f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py @@ -249,7 +249,8 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): rset['rows'][0]['oid'], tid, rset['rows'][0]['name'], - icon="icon-rule" + icon="icon-rule" if + rset['rows'][0]['is_enable_rule'] == 'D' else "icon-rule-bad" ) return make_json_response( @@ -276,7 +277,9 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], tid, row['name'], - icon="icon-rule" + icon="icon-rule-bad" + if 'is_enable_rule' in row and + row['is_enable_rule'] == 'D' else "icon-rule" )) return make_json_response( @@ -385,7 +388,10 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): rid, tid, name, - icon="icon-%s" % self.node_type + icon="icon-%s-bad" % self.node_type + if 'is_enable_rule' in data and + data['is_enable_rule'] == 'D' + else "icon-%s" % self.node_type ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/img/rule-bad.svg b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/img/rule-bad.svg new file mode 100644 index 000000000..a1b4aef87 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/img/rule-bad.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js index 48f055b41..915189591 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js @@ -12,8 +12,8 @@ import RuleSchema from './rule.ui'; define('pgadmin.node.rule', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform', - 'pgadmin.node.schema.dir/schema_child_tree_node', -], function(gettext, url_for, $, _, pgAdmin, pgBrowser, Backform, SchemaChildTreeNode) { + 'pgadmin.node.schema.dir/schema_child_tree_node', 'pgadmin.alertifyjs', +], function(gettext, url_for, $, _, pgAdmin, pgBrowser, Backform, SchemaChildTreeNode, alertify) { /** Create and add a rule collection into nodes @@ -112,8 +112,93 @@ define('pgadmin.node.rule', [ icon: 'wcTabIcon icon-rule', data: {action: 'create', check: true}, enable: 'canCreate', }, + { + name: 'enable_rule', node: 'rule', module: this, + applies: ['object', 'context'], callback: 'enable_rule', + category: 'connect', priority: 3, label: gettext('Enable rule'), + icon: 'fa fa-check', enable: 'canCreate_with_rule_enable', + },{ + name: 'disable_rule', node: 'rule', module: this, + applies: ['object', 'context'], callback: 'disable_rule', + category: 'drop', priority: 3, label: gettext('Disable rule'), + icon: 'fa fa-times', enable: 'canCreate_with_rule_disable' + } ]); }, + callbacks: { + /* Enable rule */ + enable_rule: function(args) { + var input = args || {}, + obj = this, + t = pgBrowser.tree, + i = input.item || t.selected(), + d = i ? t.itemData(i) : undefined; + + if (!d) + return false; + + var data = d; + $.ajax({ + url: obj.generate_url(i, 'obj' , d, true), + type:'PUT', + data: {'is_enable_rule' : 'O'}, + dataType: 'json', + }) + .done(function() { + alertify.success('Rule updated.'); + t.removeIcon(i); + data.icon = 'icon-rule'; + t.addIcon(i, {icon: data.icon}); + t.unload(i); + t.setInode(false); + t.deselect(i); + // Fetch updated data from server + setTimeout(function() { + t.select(i); + }, 10); + }) + .fail(function(xhr, status, error) { + alertify.pgRespErrorNotify(xhr, error); + t.unload(i); + }); + }, + /* Disable rule */ + disable_rule: function(args) { + var input = args || {}, + obj = this, + t = pgBrowser.tree, + i = input.item || t.selected(), + d = i ? t.itemData(i) : undefined; + + if (!d) + return false; + + var data = d; + $.ajax({ + url: obj.generate_url(i, 'obj' , d, true), + type:'PUT', + data: {'is_enable_rule' : 'D'}, + dataType: 'json', + }) + .done(function() { + alertify.success('Rule updated'); + t.removeIcon(i); + data.icon = 'icon-rule-bad'; + t.addIcon(i, {icon: data.icon}); + t.unload(i); + t.setInode(false); + t.deselect(i); + // Fetch updated data from server + setTimeout(function() { + t.select(i); + }, 10); + }) + .fail(function(xhr, status, error) { + alertify.pgRespErrorNotify(xhr, error, gettext('Disable rule failed')); + t.unload(i); + }); + }, + }, getSchema: function(treeNodeInfo, itemNodeData) { return new RuleSchema( { @@ -216,6 +301,26 @@ define('pgadmin.node.rule', [ }, + canCreate_with_rule_enable: function(itemData, item, data) { + var treeData = pgBrowser.tree.getTreeNodeHierarchy(item); + if ('view' in treeData) { + return false; + } + + return itemData.icon === 'icon-rule-bad' && + this.canCreate.apply(this,[itemData, item, data]); + }, + // Check to whether rule is enable ? + canCreate_with_rule_disable: function(itemData, item, data) { + var treeData = pgBrowser.tree.getTreeNodeHierarchy(item); + if ('view' in treeData) { + return false; + } + + return itemData.icon === 'icon-rule' && + this.canCreate.apply(itemData, item, data); + }, + }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.ui.js index 777de8b17..c15e82ef1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.ui.js @@ -66,6 +66,24 @@ export default class RuleSchema extends BaseUISchema { state.view = obj.fieldOptions.nodeData.label; }, }, + { + id: 'is_enable_rule', label: gettext('Rule enabled?'), + mode: ['edit', 'properties'], group: gettext('Definition'), + type: 'select', + disabled: () => { + if('catalog' in obj.fieldOptions.nodeInfo || 'view' in obj.fieldOptions.nodeInfo) { + return true; + } + return false; + }, + options: [ + {label: gettext('Enable'), value: 'O'}, + {label: gettext('Enable Replica'), value: 'R'}, + {label: gettext('Enable Always'), value: 'A'}, + {label: gettext('Disable'), value: 'D'}, + ], + controlProps: { allowClear: false }, + }, { id: 'event', label: gettext('Event'), control: 'select2', group: gettext('Definition'), type: 'select', @@ -94,10 +112,6 @@ export default class RuleSchema extends BaseUISchema { id: 'system_rule', label: gettext('System rule?'), type: 'switch', mode: ['properties'], }, - { - id: 'enabled', label: gettext('Enabled?'), - type: 'switch', mode: ['properties'], - }, { id: 'comment', label: gettext('Comment'), cell: 'text', type: 'multiline', }, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/templates/rules/css/rule.css b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/templates/rules/css/rule.css index 0d7339cf8..63f4ecbce 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/templates/rules/css/rule.css +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/templates/rules/css/rule.css @@ -7,3 +7,14 @@ vertical-align: middle; height: 1.3em; } + + +.icon-rule-bad{ + background-image: url('{{ url_for('NODE-rule.static', filename='img/rule-bad.svg') }}') !important; + border-radius: 10px; + background-size: 20px !important; + background-repeat: no-repeat; + align-content: center; + vertical-align: middle; + height: 1.3em; +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql index 67ddae002..343b40bcf 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql @@ -1,6 +1,9 @@ SELECT rw.oid AS oid, - rw.rulename AS name + rw.rulename AS name, + CASE WHEN rw.ev_enabled != 'D' THEN True ELSE False END AS enabled, + rw.ev_enabled AS is_enable_rule + FROM pg_catalog.pg_rewrite rw WHERE diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/properties.sql index c983896b0..8f238bb8e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/properties.sql @@ -12,6 +12,7 @@ SELECT {# ===== Check whether it is system rule or not ===== #} CASE WHEN rw.rulename = '_RETURN' THEN True ELSE False END AS system_rule, CASE WHEN rw.ev_enabled != 'D' THEN True ELSE False END AS enabled, + rw.ev_enabled AS is_enable_rule, pg_catalog.pg_get_ruledef(rw.oid) AS definition FROM pg_catalog.pg_rewrite rw diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/update.sql index e033af7b8..90a94e2a8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/update.sql @@ -35,3 +35,13 @@ CREATE OR REPLACE RULE {{ conn|qtIdent(rule_name) }} AS {% set old_comment = o_data.comment|default('', true) %} {% if (data.comment is defined and (data.comment != old_comment)) %} COMMENT ON RULE {{ conn|qtIdent(rule_name) }} ON {{ conn|qtIdent(o_data.schema, o_data.view) }} IS {{ data.comment|qtLiteral }};{% endif %} + +{% if data.enabled is defined and o_data.enabled != data.enabled %} +ALTER TABLE {{ conn|qtIdent(o_data.schema, o_data.view) }} {% if (data.enabled in ['false', False]) %}DISABLE{% endif %}{% if (data.enabled in ['true', True]) %}ENABLE{% endif %} RULE {{ conn|qtIdent(o_data.name) }}; +{% endif %} + +{% if data.is_enable_rule is defined and o_data.is_enable_rule != data.is_enable_rule %} +{% set enable_map = {'R':'ENABLE REPLICA', 'A':'ENABLE ALWAYS', 'O':'ENABLE', 'D':'DISABLE'} %} +ALTER TABLE {{ conn|qtIdent(o_data.schema, o_data.view) }} + {{ enable_map[data.is_enable_rule] }} RULE {{ conn|qtIdent(o_data.name) }}; +{% endif %}