Patch functionality depends on not yet posted pviktori's patch which adds error_code (in case of command error) to batch response.

Patch description:

This patch adds support for new per-domain permissions to Web UI.

User with assigned permission (through role,priviledge) can edit DNS zone. These permissions can be added/remove by ipa dnszone-{add/remove}permission $dnszone command.

For adding/removing of this permission in Web UI new actions in DNS zone action list were created. DNS zone object doesn't contain information about existance of related permission. Such information is required for enabling/disabling of new actions. Web UI has to search for the permission to get it. DNS zone facet was modified to use batch command, in a same way as user facet, for loading dnszone and the permission at the same time - on load.

Batch command has a feature to report all errors. Such behavior is unwanted because we expect that permission-show command will fail when the permission doesn't exist. Batch command was therefore modified to not report commands which has retry attribute set to false. This attr was chosen because it has similar purpose in single command execution.

New actions should be enabled only for users with appropriate rights. It is not possible to obtain rights for certain action in advance so an approximation is used: write right for dns zones' managedby attribute.

https://fedorahosted.org/freeipa/ticket/2851
--
Petr Vobornik

From 1ac3638148528365b2b68d03191b0911692b6fa4 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Tue, 3 Jul 2012 14:18:03 +0200
Subject: [PATCH] Add and remove dns per-domain permission in Web UI

This patch adds support for new per-domain permissions to Web UI.

User with assigned permission (through role,priviledge) can edit DNS zone. These permissions can be added/remove by ipa dnszone-{add/remove}permission $dnszone command.

For adding/removing of this permission in Web UI new actions in DNS zone action list were created. DNS zone object doesn't contain information about existance of related permission. Such information is required for enabling/disabling of new actions. Web UI has to search for the permission to get it. DNS zone facet was modified to use batch command, in a same way as user facet, for loading dnszone and the permission at the same time - on load.

Batch command has a feature to report all errors. Such behavior is unwanted because we expect that permission-show command will fail when the permission doesn't exist. Batch command was therefore modified to not report commands which has retry attribute set to false. This attr was chosen because it has similar purpose in single command execution.

New actions should be enabled only for users with appropriate rights. It is not possible to obtain rights for certain action in advance so an approximation is used: write right for dns zones' managedby attribute.

https://fedorahosted.org/freeipa/ticket/2851
---
 install/ui/details.js                             |    4 +-
 install/ui/dns.js                                 |  160 ++++++++++++++++++++-
 install/ui/ipa.js                                 |    7 +-
 install/ui/test/data/dnszone_details_refresh.json |  119 +++++++++++++++
 install/ui/test/data/ipa_init.json                |    4 +-
 ipalib/plugins/internal.py                        |    2 +
 6 files changed, 285 insertions(+), 11 deletions(-)
 create mode 100644 install/ui/test/data/dnszone_details_refresh.json

diff --git a/install/ui/details.js b/install/ui/details.js
index 618d02f573e38f2573b532440265ff934e91f8c3..176e7883ebfa0593276d9397d47e5383a894ab12 100644
--- a/install/ui/details.js
+++ b/install/ui/details.js
@@ -996,7 +996,9 @@ IPA.acl_state_evaluator = function(spec) {
             rights = record.attributelevelrights[that.attribute];
         }
 
-        rights = rights || '';
+        // Full rights if we don't know the rights.  Better to allow action and
+        // then to show error dialog than not be able to do something.
+        rights = rights || 'rscwo';
 
         for (i=0; i<rights.length; i++) {
             state = that.attribute + '_' + rights.charAt(i);
diff --git a/install/ui/dns.js b/install/ui/dns.js
index 492d8c4f7ded27191f60d7fa154882db231e6f1d..1f4ba8ccdb98cda3e67d9d006139d42f99a3399e 100644
--- a/install/ui/dns.js
+++ b/install/ui/dns.js
@@ -26,7 +26,9 @@
 /* REQUIRES: ipa.js, details.js, search.js, add.js, facet.js, entity.js,
  *           net.js, widget.js */
 
-IPA.dns = {};
+IPA.dns = {
+    zone_permission_name: 'Manage DNS zone ${dnszone}'
+};
 
 IPA.dns.config_entity = function(spec) {
 
@@ -230,15 +232,23 @@ IPA.dns.zone_entity = function(spec) {
                 IPA.select_action,
                 IPA.enable_action,
                 IPA.disable_action,
-                IPA.delete_action
+                IPA.delete_action,
+                IPA.dns.add_permission_action,
+                IPA.dns.remove_permission_action
             ],
-            header_actions: ['select_action', 'enable', 'disable', 'delete'],
+            header_actions: ['select_action', 'enable', 'disable', 'delete',
+                'add_permission', 'remove_permission'],
             state: {
                 evaluators: [
                     {
                         factory: IPA.enable_state_evaluator,
                         field: 'idnszoneactive'
-                    }
+                    },
+                    {
+                        factory: IPA.acl_state_evaluator,
+                        attribute: 'managedby'
+                    },
+                    IPA.dns.zone_has_permission_evaluator
                 ],
                 summary_conditions: [
                     IPA.enabled_summary_cond(),
@@ -319,11 +329,69 @@ IPA.dns.zone_entity = function(spec) {
     return that;
 };
 
-IPA.dnszone_details_facet = function(spec) {
+IPA.dnszone_details_facet = function(spec, no_init) {
 
     spec = spec || {};
 
-    var that = IPA.details_facet(spec);
+    var that = IPA.details_facet(spec, true);
+    that.permission_load = IPA.observer();
+    that.permission_status = 'unknown'; // [unknown, set, none]
+
+    that.refresh_on_success = function(data, text_status, xhr) {
+        // do not load data from batch
+
+        that.show_content();
+    };
+
+    that.create_refresh_command = function() {
+
+        var pkey = IPA.nav.get_state(that.entity.name+'-pkey');
+
+        var batch = IPA.batch_command({
+            name: 'dnszone_details_refresh'
+        });
+
+        var dnszone_command = that.details_facet_create_refresh_command();
+
+        dnszone_command.on_success = function(data, text_status, xhr) {
+            // create data that mimics dnszone-show output
+            var dnszone_data = {};
+            dnszone_data.result = data;
+            that.load(dnszone_data);
+        };
+
+        batch.add_command(dnszone_command);
+
+        var permission_name = IPA.dns.zone_permission_name.replace('${dnszone}', pkey);
+
+        var permission_command = IPA.command({
+            entity: 'permission',
+            method: 'show',
+            args: [permission_name],
+            options: {},
+            retry: false
+        });
+
+        permission_command.on_success = function(data, text_status, xhr) {
+            that.permission_status = 'set';
+            that.permission_load.notify([that.permission_status], that);
+        };
+
+        permission_command.on_error = function(xhr, text_status, error_thrown) {
+            if (error_thrown && error_thrown.code === 4001) {
+                //NotFound error
+                that.permission_status = 'none';
+            } else {
+                that.permission_status = 'unknown';
+            }
+
+            that.permission_load.notify([that.permission_status], that);
+        };
+
+        batch.add_command(permission_command);
+
+        return batch;
+    };
 
     that.update_on_success = function(data, text_status, xhr) {
         that.refresh();
@@ -334,6 +402,8 @@ IPA.dnszone_details_facet = function(spec) {
         that.refresh();
     };
 
+    if (!no_init) that.init_details_facet();
+
     return that;
 };
 
@@ -528,6 +598,84 @@ IPA.dnszone_adder_dialog = function(spec) {
     return that;
 };
 
+IPA.dns.add_permission_action = function(spec) {
+
+    spec = spec || {};
+    spec.name = spec.name || 'add_permission';
+    spec.label = spec.label || IPA.messages.objects.dnszone.add_permission;
+    spec.enable_cond = spec.enable_cond || ['permission-none', 'managedby_w'];
+
+    var that = IPA.action(spec);
+
+    that.execute_action = function(facet) {
+
+        var pkey = IPA.nav.get_state('dnszone-pkey');
+
+         var command = IPA.command({
+            entity: 'dnszone',
+            method: 'add_permission',
+            args: [pkey],
+            options: {},
+            on_success: function() {
+                facet.refresh();
+            }
+        });
+
+        command.execute();
+    };
+
+    return that;
+};
+
+IPA.dns.remove_permission_action = function(spec) {
+
+    spec = spec || {};
+    spec.name = spec.name || 'remove_permission';
+    spec.label = spec.label || IPA.messages.objects.dnszone.remove_permission;
+    spec.enable_cond = spec.enable_cond || ['permission-set', 'managedby_w'];
+
+    var that = IPA.action(spec);
+
+    that.execute_action = function(facet) {
+
+        var pkey = IPA.nav.get_state('dnszone-pkey');
+
+         var command = IPA.command({
+            entity: 'dnszone',
+            method: 'remove_permission',
+            args: [pkey],
+            options: {},
+            on_success: function() {
+                facet.refresh();
+            }
+        });
+
+        command.execute();
+    };
+
+    return that;
+};
+
+IPA.dns.zone_has_permission_evaluator = function(spec) {
+    spec = spec || {};
+
+    spec.event = spec.event || 'permission_load';
+
+    var that = IPA.state_evaluator(spec);
+
+    that.on_event = function(permission_status) {
+
+        var old_state = that.state;
+        that.state = [
+            'permission-'+permission_status
+        ];
+
+        that.notify_on_change(old_state);
+    };
+
+    return that;
+};
+
 IPA.dns.record_search_facet = function(spec) {
 
     var that = IPA.nested_search_facet(spec);
diff --git a/install/ui/ipa.js b/install/ui/ipa.js
index aadea8d2af07c1d0c7f5ae1b8168a36966c546c5..383cd86f8b222d3a2cc2718ddf1f54d5d5db80d2 100644
--- a/install/ui/ipa.js
+++ b/install/ui/ipa.js
@@ -925,10 +925,11 @@ IPA.batch_command = function (spec) {
                 );
 
             } else if (result.error) {
-                name = IPA.get_message('errors.ipa_error', 'IPA Error')+(result.error.code ? ' '+result.error.code : '');
+                var code = result.error.code || result.error_code;
+                name = IPA.get_message('errors.ipa_error', 'IPA Error')+(code ? ' '+code : '');
                 message = result.error.message || result.error;
 
-                that.errors.add(command, name, message, text_status);
+                if (command.retry) that.errors.add(command, name, message, text_status);
 
                 if (command.on_error) command.on_error.call(
                     this,
@@ -936,7 +937,7 @@ IPA.batch_command = function (spec) {
                     text_status,
                     {
                         name: name,
-                        code: result.error.code,
+                        code: code,
                         message: message,
                         data: result
                     }
diff --git a/install/ui/test/data/dnszone_details_refresh.json b/install/ui/test/data/dnszone_details_refresh.json
new file mode 100644
index 0000000000000000000000000000000000000000..dcc2f8c2507f1758114b5f2cdb96e344c9c51a3f
--- /dev/null
+++ b/install/ui/test/data/dnszone_details_refresh.json
@@ -0,0 +1,119 @@
+{
+    "error": null,
+    "id": null,
+    "result": {
+        "count": 2,
+        "results": [
+            {
+                "error": null,
+                "result": {
+                    "attributelevelrights": {
+                        "a6record": "rscwo",
+                        "aaaarecord": "rscwo",
+                        "aci": "rscwo",
+                        "afsdbrecord": "rscwo",
+                        "arecord": "rscwo",
+                        "certrecord": "rscwo",
+                        "cn": "rscwo",
+                        "cnamerecord": "rscwo",
+                        "dnamerecord": "rscwo",
+                        "dnsclass": "rscwo",
+                        "dnsttl": "rscwo",
+                        "dsrecord": "rscwo",
+                        "hinforecord": "rscwo",
+                        "idnsallowdynupdate": "rscwo",
+                        "idnsallowquery": "rscwo",
+                        "idnsallowsyncptr": "rscwo",
+                        "idnsallowtransfer": "rscwo",
+                        "idnsforwarders": "rscwo",
+                        "idnsforwardpolicy": "rscwo",
+                        "idnsname": "rscwo",
+                        "idnssoaexpire": "rscwo",
+                        "idnssoaminimum": "rscwo",
+                        "idnssoamname": "rscwo",
+                        "idnssoarefresh": "rscwo",
+                        "idnssoaretry": "rscwo",
+                        "idnssoarname": "rscwo",
+                        "idnssoaserial": "rscwo",
+                        "idnsupdatepolicy": "rscwo",
+                        "idnszoneactive": "rscwo",
+                        "keyrecord": "rscwo",
+                        "kxrecord": "rscwo",
+                        "locrecord": "rscwo",
+                        "managedby": "rscwo",
+                        "mdrecord": "rscwo",
+                        "minforecord": "rscwo",
+                        "mxrecord": "rscwo",
+                        "naptrrecord": "rscwo",
+                        "nsaccountlock": "rscwo",
+                        "nsecrecord": "rscwo",
+                        "nsrecord": "rscwo",
+                        "nxtrecord": "rscwo",
+                        "objectclass": "rscwo",
+                        "ptrrecord": "rscwo",
+                        "rrsigrecord": "rscwo",
+                        "sigrecord": "rscwo",
+                        "srvrecord": "rscwo",
+                        "sshfprecord": "rscwo",
+                        "txtrecord": "rscwo"
+                    },
+                    "dn": "idnsname=example.com,cn=dns,dc=example,dc=com",
+                    "idnsallowdynupdate": [
+                        "FALSE"
+                    ],
+                    "idnsallowquery": [
+                        "any;"
+                    ],
+                    "idnsallowtransfer": [
+                        "none;"
+                    ],
+                    "idnsname": [
+                        "example.com"
+                    ],
+                    "idnssoaexpire": [
+                        "1209600"
+                    ],
+                    "idnssoaminimum": [
+                        "3600"
+                    ],
+                    "idnssoamname": [
+                        "test.example.com."
+                    ],
+                    "idnssoarefresh": [
+                        "3600"
+                    ],
+                    "idnssoaretry": [
+                        "900"
+                    ],
+                    "idnssoarname": [
+                        "hostmaster.example.com."
+                    ],
+                    "idnssoaserial": [
+                        "2012070401"
+                    ],
+                    "idnsupdatepolicy": [
+                        "grant EXAMPLE.COM krb5-self * A; grant EXAMPLE.COM krb5-self * AAAA; grant EXAMPLE.COM krb5-self * SSHFP;"
+                    ],
+                    "idnszoneactive": [
+                        "TRUE"
+                    ],
+                    "nsrecord": [
+                        "test.example.com."
+                    ],
+                    "objectclass": [
+                        "top",
+                        "idnsrecord",
+                        "idnszone"
+                    ]
+                },
+                "summary": null,
+                "value": "example.com"
+            },
+            {
+                "error": "Manage DNS zone example.com: permission not found",
+                "error_code": 4001,
+                "error_name": "NotFound"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 85ff9366ce4ad293b95829d864653561a55d6429..890b27a494bdc2986a923c4427fb65e3add2c9fd 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -236,7 +236,9 @@
                             "type": "Record Type"
                         },
                         "dnszone": {
-                            "identity": "DNS Zone Settings"
+                            "identity": "DNS Zone Settings",
+                            "add_permission": "Add Permission",
+                            "remove_permission": "Remove Permission"
                         },
                         "entitle": {
                             "account": "Account",
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index a4d87b1d744afe38b5e4ca1b6789724b33d6aa57..5ef4386939de5d8dd9df1b27b4d6cd4fb7335a8e 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -374,6 +374,8 @@ class i18n_messages(Command):
             },
             "dnszone": {
                 "identity": _("DNS Zone Settings"),
+                "add_permission":_("Add Permission"),
+                "remove_permission": _("Remove Permission"),
             },
             "entitle": {
                 "account": _("Account"),
-- 
1.7.7.6

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to