On 06/06/2016 07:03 PM, Petr Vobornik wrote:
On 06/06/2016 12:27 PM, Pavel Vomacka wrote:

On 06/02/2016 06:22 PM, Petr Vobornik wrote:
On 06/01/2016 10:41 AM, Pavel Vomacka wrote:
On 05/27/2016 05:58 PM, Pavel Vomacka wrote:
On 05/27/2016 05:44 PM, Nathaniel McCallum wrote:
On Fri, 2016-05-27 at 17:43 +0200, Pavel Vomacka wrote:
On 05/12/2016 11:13 PM, Nathaniel McCallum wrote:
On Wed, 2016-05-11 at 13:08 +0200, Pavel Vomacka wrote:
Hi,

the patch adds webui part for authentication indicators.

Ticket: https://fedorahosted.org/freeipa/ticket/5872
The otp option displays as: OTP.
The radius option displays as: Radius.

However, both are acronyms. The capitalization should be
consistent.
I'm sorry for late answer. They are displayed this way: 'OTP' and
'Radius'. So it should not require any change.
That is incorrect. It should be: OTP and RADIUS.
I'm sorry, I didn't understand correctly. Fixed patch attached.



The last patch changes the 'Radius' to 'RADIUS' in whole WebUI.

After some though, we should really support the arbitrary values also in
Web UI.

I'd reuse aci.attributes_widget - move the widget elsewhere, make it a
general widget and a base class for the original aci.attributes_widget.

The only difference should be populate method and some strings.

The base widget can populate from options - same as normal checkboxes
widget so that service page doesn't need to inherit from the base class.

Ok, thank you for advice. The edited patch is attached.

1. The new base class should have different name, e.g.
custom_checkboxes_widget . It is not related to (aci) attributes.

Then it can be registered as such widget and the attributes widget can
be registered in ACI plugin. It would then also remove the ugly usage of
both $type and $factory.
Fixed.

2. Why not implement empty placeholder populate function in the base
class? Then
   if (that.populate && typeof that.populate === 'function') that.populate();

could be changed into:
   that.populate();

Child class should simply override.
I just did not like a empty method there. But it's true that it is more readable with empty method and the method is documented.

3. If I add a custom indicator to one server and then switch to another.
It will offer the custom option as well, but unchecked. The added
options are not cleared on page reset. I'm not sure if it should be
called a feature or a bug. It is remnant of the original implementation.
From my point of view it is a feature. I.e. When I add custom authentication indicator to one service there is a big chance that I would like to add it to another one. And in this case the custom auth. ind. is already present.

Fixed patch attached.

--
Pavel^3 Vomacka
From e15dd899ce14e6df6ad1be6bd1c00488908e3c06 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Mon, 6 Jun 2016 12:11:06 +0200
Subject: [PATCH] Auth Indicators webUI part

Add custom_checkbox_widget on service page. The old  aci.attribute_widget
now inherits from the new base class custom_checkobox_widget and overrides
the populate method.

https://fedorahosted.org/freeipa/ticket/5872
---
 install/ui/src/freeipa/aci.js      | 173 ++--------------------------------
 install/ui/src/freeipa/service.js  |  20 ++++
 install/ui/src/freeipa/widget.js   | 187 +++++++++++++++++++++++++++++++++++++
 install/ui/test/data/ipa_init.json |  11 ++-
 ipaserver/plugins/internal.py      |  11 ++-
 5 files changed, 233 insertions(+), 169 deletions(-)

diff --git a/install/ui/src/freeipa/aci.js b/install/ui/src/freeipa/aci.js
index 9a19dd7b45a362640ab1a93d2fe148dc15103248..6ac7f4c71b4632418805bd77682e2d3d5ac92bc0 100644
--- a/install/ui/src/freeipa/aci.js
+++ b/install/ui/src/freeipa/aci.js
@@ -537,146 +537,24 @@ return {
     }
 };};
 
-/**
- * @class aci.attributes_widget
- * @extends IPA.checkboxes_widget
- */
 aci.attributes_widget = function(spec) {
 
     spec = spec || {};
     spec.layout = spec.layout || 'columns attribute_widget';
-    spec.sort = spec.sort === undefined ? true : spec.sort;
+    spec.add_dialog_title = spec.add_dialog_title ||
+                            "@i18n:objects.permission.add_custom_attr";
+    spec.add_field_label = spec.add_field_label ||
+                            '@i18n:objects.permission.attribute';
 
-    var that = IPA.checkboxes_widget(spec);
-
-    /**
-     * Additional options which are not defined in metadata
-     * @property {string[]}
-     */
-    that.custom_options = spec.custom_options || [];
+    var that = IPA.custom_checkboxes_widget(spec);
 
     that.object_type = spec.object_type;
-    that.skip_unmatched = spec.skip_unmatched === undefined ? false : spec.skip_unmatched;
 
-    var id = spec.name;
+    that.populate = function() {
 
-    that.create = function(container) {
-        that.container = container;
-        that.widget_create(container);
+        if (!that.object_type || that.object_type === '') return;
 
-        that.controls = $('<div/>', {
-            'class': 'form-inline controls'
-        });
-        that.controls.appendTo(container);
-        that.create_search_filter(that.controls);
-        that.create_add_control(that.controls);
-        if (that.undo) {
-            that.create_undo(that.controls);
-        }
-
-        that.owb_create(container);
-
-        that.create_error_link(container);
-    };
-
-    that.create_search_filter = function(container) {
-        var filter_container = $('<div/>', {
-            'class': 'search-filter'
-        });
-
-        that.filter = $('<input/>', {
-            type: 'text',
-            name: 'filter',
-            'class': 'form-control',
-            placeholder: text.get('@i18n:objects.permission.filter')
-        }).appendTo(filter_container);
-
-        that.filter.keyup(function(e) {
-            that.filter_options();
-        });
-
-        var find_button = IPA.action_button({
-            name: 'find',
-            icon: 'fa-search',
-            click: function() {
-                that.filter_options();
-                return false;
-            }
-        }).appendTo(filter_container);
-
-        filter_container.appendTo(container);
-    };
-
-    that.create_add_control = function(container) {
-
-        that.add_button = IPA.button({
-            label: '@i18n:buttons.add',
-            click: that.show_add_dialog
-        });
-        container.append(' ');
-        that.add_button.appendTo(container);
-    };
-
-    that.show_add_dialog = function() {
-
-        var dialog = IPA.form_dialog({
-            name: "add_option",
-            title: "@i18n:objects.permission.add_custom_attr",
-            fields: [
-                {
-                    name: 'attr',
-                    label: '@i18n:objects.permission.attribute',
-                    required: true
-                }
-            ]
-        });
-        dialog.on_confirm = function() {
-            if (!dialog.validate()) return;
-            var attr = dialog.get_field('attr');
-            var value = attr.get_value()[0];
-            that.add_custom_option(value, false, true, true);
-            dialog.close();
-        };
-        dialog.open();
-    };
-
-    that.filter_options = function() {
-        $("li", that.$node).each(function() {
-            var item = $(this);
-            if(item.find('input').val().indexOf(that.filter.val()) === -1) {
-                item.css('display','none');
-            } else {
-                item.css('display','inline');
-            }
-        });
-    };
-
-    that.update = function(values) {
-
-        that.values = [];
-
-        values = values || [];
-        for (var i=0; i<values.length; i++) {
-
-            var value = values[i];
-
-            if (!value || value === '') continue;
-
-            value = value.toLowerCase();
-            that.values.push(value);
-        }
-
-        that.populate(that.object_type);
-        that.append();
-        that.owb_create(that.container);
-        that.owb_update(values);
-    };
-
-    that.populate = function(object_type) {
-
-        if (!object_type || object_type === '') return;
-
-        var metadata = metadata_provider.get('@mo:'+object_type);
+        var metadata = metadata_provider.get('@mo:'+that.object_type);
         if (!metadata) return;
 
         var aciattrs = metadata.aciattrs;
@@ -684,41 +562,6 @@ aci.attributes_widget = function(spec) {
         that.options = that.prepare_options(aciattrs);
     };
 
-    that.append = function() {
-
-        var unmatched = [];
-
-        function add_unmatched(source) {
-            for (var i=0, l=source.length; i<l; i++) {
-                if (!that.has_option(source[i])) {
-                    that.add_option(source[i], true /* suppress update */);
-                }
-            }
-        }
-
-        add_unmatched(that.custom_options);
-
-        if (that.values && !that.skip_unmatched) {
-            add_unmatched(that.values);
-        }
-    };
-
-    that.add_custom_option = function(name, to_custom, check, update) {
-
-        var value = (name || '').toLowerCase();
-        if (to_custom) that.custom_options.push(value);
-        if (check) that.values.push(value);
-        if (update) that.update(that.values);
-    };
-
-    that.has_option = function(value) {
-        var o = that.options;
-        for (var i=0, l=o.length; i<l; i++) {
-            if (o[i].value === value) return true;
-        }
-        return false;
-    };
-
     return that;
 };
 
diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js
index f1f8d951e415e9768aab433e28da852a732bc8ba..73732dd48e833668cdcb66e9057b5ae8e4f8a330 100644
--- a/install/ui/src/freeipa/service.js
+++ b/install/ui/src/freeipa/service.js
@@ -109,6 +109,26 @@ return {
                             ]
                         },
                         {
+                            $type: 'custom_checkboxes',
+                            label: '@i18n:objects.service.auth_indicators',
+                            name: 'krbprincipalauthind',
+                            add_dialog_title: '@i18n:objects.service.custom_auth_ind_title',
+                            add_field_label: '@i18n:objects.service.auth_indicator',
+                            options: [
+                                {
+                                    label: '@i18n:authtype.otp',
+                                    value: 'otp'
+                                },
+                                {
+                                    label: '@i18n:authtype.type_radius',
+                                    value: 'radius'
+                                }
+                            ],
+                            tooltip: {
+                                title: '@mc-opt:service_add:krbprincipalauthind:doc'
+                            }
+                        },
+                        {
                             name: 'ipakrbokasdelegate',
                             $type: 'checkbox',
                             acl_param: 'krbticketflags'
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
index fc2d6ef0bf9fd9361a88c9bf7523077739dc615f..f1679351bdd48ef123aefc18f8a35fdc09f66da1 100644
--- a/install/ui/src/freeipa/widget.js
+++ b/install/ui/src/freeipa/widget.js
@@ -1980,6 +1980,192 @@ IPA.checkboxes_widget = function (spec) {
     return that;
 };
 
+
+/**
+ * @class IPA.custom_checkboxes_widget
+ * @extends IPA.checkboxes_widget
+ */
+IPA.custom_checkboxes_widget = function(spec) {
+
+    spec = spec || {};
+    spec.layout = spec.layout || 'columns attribute_widget';
+    spec.sort = spec.sort === undefined ? true : spec.sort;
+
+    var that = IPA.checkboxes_widget(spec);
+
+    that.add_dialog_title = spec.add_dialog_title ||
+                            "@i18n:dialogs.add_custom_value";
+    that.add_field_label = spec.add_field_label ||
+                            '@i18n:dialogs.custom_value';
+
+    /**
+     * Additional options 
+     * @property {string[]}
+     */
+    that.custom_options = spec.custom_options || [];
+
+    that.skip_unmatched = spec.skip_unmatched === undefined ? false : spec.skip_unmatched;
+
+    var id = spec.name;
+
+    that.create = function(container) {
+        that.container = container;
+        that.widget_create(container);
+
+        that.controls = $('<div/>', {
+            'class': 'form-inline controls'
+        });
+        that.controls.appendTo(container);
+        that.create_search_filter(that.controls);
+        that.create_add_control(that.controls);
+        if (that.undo) {
+            that.create_undo(that.controls);
+        }
+
+        that.owb_create(container);
+
+        that.create_error_link(container);
+    };
+
+    that.create_search_filter = function(container) {
+        var filter_container = $('<div/>', {
+            'class': 'search-filter'
+        });
+
+        that.filter = $('<input/>', {
+            type: 'text',
+            name: 'filter',
+            'class': 'form-control',
+            placeholder: text.get('@i18n:search.placeholder_filter')
+        }).appendTo(filter_container);
+
+        that.filter.keyup(function(e) {
+            that.filter_options();
+        });
+
+        var find_button = IPA.action_button({
+            name: 'find',
+            icon: 'fa-search',
+            click: function() {
+                that.filter_options();
+                return false;
+            }
+        }).appendTo(filter_container);
+
+        filter_container.appendTo(container);
+    };
+
+    that.create_add_control = function(container) {
+
+        that.add_button = IPA.button({
+            label: '@i18n:buttons.add',
+            click: that.show_add_dialog
+        });
+        container.append(' ');
+        that.add_button.appendTo(container);
+    };
+
+    that.show_add_dialog = function() {
+
+        var dialog = IPA.form_dialog({
+            name: "add_option",
+            title: that.add_dialog_title,
+            fields: [
+                {
+                    name: 'custom_value',
+                    label: that.add_field_label,
+                    required: true
+                }
+            ]
+        });
+        dialog.on_confirm = function() {
+            if (!dialog.validate()) return;
+            var attr = dialog.get_field('custom_value');
+            var value = attr.get_value()[0];
+            that.add_custom_option(value, false, true, true);
+            dialog.close();
+        };
+        dialog.open();
+    };
+
+    that.filter_options = function() {
+        $("li", that.$node).each(function() {
+            var item = $(this);
+            if(item.find('input').val().indexOf(that.filter.val()) === -1) {
+                item.css('display','none');
+            } else {
+                item.css('display','inline');
+            }
+        });
+    };
+
+    that.update = function(values) {
+
+        that.values = [];
+
+        values = values || [];
+        for (var i=0; i<values.length; i++) {
+
+            var value = values[i];
+
+            if (!value || value === '') continue;
+
+            value = value.toLowerCase();
+            that.values.push(value);
+        }
+
+        that.populate();
+        that.append();
+        that.owb_create(that.container);
+        that.owb_update(values);
+    };
+
+    /**
+     * Method which can be overridden by child class for adding own
+     * autogenerated values. These values should be prepared using
+     * that.prepare_option() method and stored in that.options.
+     */
+    that.populate = function() {};
+
+    that.append = function() {
+
+        var unmatched = [];
+
+        function add_unmatched(source) {
+            for (var i=0, l=source.length; i<l; i++) {
+                if (!that.has_option(source[i])) {
+                    that.add_option(source[i], true /* suppress update */);
+                }
+            }
+        }
+
+        add_unmatched(that.custom_options);
+
+        if (that.values && !that.skip_unmatched) {
+            add_unmatched(that.values);
+        }
+    };
+
+    that.add_custom_option = function(name, to_custom, check, update) {
+
+        var value = (name || '').toLowerCase();
+        if (to_custom) that.custom_options.push(value);
+        if (check) that.values.push(value);
+        if (update) that.update(that.values);
+    };
+
+    that.has_option = function(value) {
+        var o = that.options;
+        for (var i=0, l=o.length; i<l; i++) {
+            if (o[i].value === value) return true;
+        }
+        return false;
+    };
+
+    return that;
+};
+
+
 /**
  * Creates input with properties defined by `spec` and an empty label which
  * targets the input.
@@ -6436,6 +6622,7 @@ exp.register = function() {
     w.register('action_panel', IPA.action_panel);
     w.register('activity', IPA.activity_widget);
     w.register('attribute_table', IPA.attribute_table_widget);
+    w.register('custom_checkboxes', IPA.custom_checkboxes_widget);
     w.register('button', IPA.button_widget);
     w.register('checkbox', IPA.checkbox_widget);
     w.register('checkboxes', IPA.checkboxes_widget);
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 6fbf4c06de99f7b5e2b96eb0a1dbf59583d1e75f..85a6388d0fbad2cb4bd67c18214f150eadbdca8d 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -50,9 +50,10 @@
                     },
                     "authtype": {
                         "config_tooltip": "<p>Implicit method (password) will be used if no method is chosen.</p><p><strong>Password + Two-factor:</strong> LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.</p><p><strong>RADIUS with another type:</strong> Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.</p>",
+                        "otp": "OTP",
                         "type_otp": "Two factor authentication (password + OTP)",
                         "type_password": "Password",
-                        "type_radius": "Radius",
+                        "type_radius": "RADIUS",
                         "type_disabled": "Disable per-user override",
                         "user_tooltip": "<p>Per-user setting, overwrites the global setting if any option is checked.</p><p><strong>Password + Two-factor:</strong> LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.</p><p><strong>RADIUS with another type:</strong> Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.</p>",
                     },
@@ -106,11 +107,13 @@
                     },
                     "dialogs": {
                         "add_confirmation": "${entity} successfully added",
+                        "add_custom_value": "Add custom value",
                         "add_title": "Add ${entity}",
                         "available": "Available",
                         "batch_error_message": "Some operations failed.",
                         "batch_error_title": "Operations Error",
                         "confirmation": "Confirmation",
+                        "custom_value": "Custom value",
                         "dirty_message": "This page has unsaved changes. Please save or revert.",
                         "dirty_title": "Unsaved Changes",
                         "edit_title": "Edit ${entity}",
@@ -468,7 +471,7 @@
                             "type_totp": "Time-based (TOTP)"
                         },
                         "permission": {
-                            "add_custom_attr": "Add custom attribute",
+                            "add_custom_attr": "Add Custom Attribute",
                             "attribute": "Attribute",
                             "filter": "Filter",
                             "identity": "Permission settings",
@@ -518,7 +521,10 @@
                             "user": "User"
                         },
                         "service": {
+                            "auth_indicators": "Authentication indicators",
+                            "auth_indicator": "Authentication indicator",
                             "certificate": "Service Certificate",
+                            "custom_auth_ind_title": "Add Custom Authentication Indicator",
                             "delete_key_unprovision": "Delete Key, Unprovision",
                             "details": "Service Settings",
                             "host": "Host Name",
@@ -659,6 +665,7 @@
                         "enabled": "${count} item(s) enabled",
                         "partial_delete": "Some entries were not deleted",
                         "placeholder": "Search",
+                        "placeholder_filter": "Filter",
                         "quick_links": "Quick Links",
                         "select_all": "Select All",
                         "truncated": "Query returned more results than the configured size limit. Displaying the first ${counter} results.",
diff --git a/ipaserver/plugins/internal.py b/ipaserver/plugins/internal.py
index 850156c34c47fa3d1fec5facbe06e1889b014552..0052e1f1b9a4e809961fe6f45d37dd9ef0b39478 100644
--- a/ipaserver/plugins/internal.py
+++ b/ipaserver/plugins/internal.py
@@ -185,9 +185,10 @@ class i18n_messages(Command):
         },
         "authtype": {
             "config_tooltip": _("<p>Implicit method (password) will be used if no method is chosen.</p><p><strong>Password + Two-factor:</strong> LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.</p><p><strong>RADIUS with another type:</strong> Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.</p>"),
+            "otp": _("OTP"),
             "type_otp": _("Two factor authentication (password + OTP)"),
             "type_password": _("Password"),
-            "type_radius": _("Radius"),
+            "type_radius": _("RADIUS"),
             "type_disabled": _("Disable per-user override"),
             "user_tooltip": _("<p>Per-user setting, overwrites the global setting if any option is checked.</p><p><strong>Password + Two-factor:</strong> LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.</p><p><strong>RADIUS with another type:</strong> Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.</p>"),
         },
@@ -242,11 +243,13 @@ class i18n_messages(Command):
         },
         "dialogs": {
             "add_confirmation": _("${entity} successfully added"),
+            "add_custom_value": _("Add custom value"),
             "add_title": _("Add ${entity}"),
             "available": _("Available"),
             "batch_error_message": _("Some operations failed."),
             "batch_error_title": _("Operations Error"),
             "confirmation": _("Confirmation"),
+            "custom_value": _("Custom value"),
             "dirty_message": _("This page has unsaved changes. Please save or revert."),
             "dirty_title": _("Unsaved Changes"),
             "edit_title": _("Edit ${entity}"),
@@ -606,7 +609,7 @@ class i18n_messages(Command):
                 "type_totp": _("Time-based (TOTP)"),
             },
             "permission": {
-                "add_custom_attr": _("Add custom attribute"),
+                "add_custom_attr": _("Add Custom Attribute"),
                 "attribute": _("Attribute"),
                 "filter": _("Filter"),
                 "identity": _("Permission settings"),
@@ -657,7 +660,10 @@ class i18n_messages(Command):
                 "user": _("User"),
             },
             "service": {
+                "auth_indicators": _("Authentication indicators"),
+                "auth_indicator": _("Authentication indicator"),
                 "certificate": _("Service Certificate"),
+                "custom_auth_ind_title": _("Add Custom Authentication Indicator"),
                 "delete_key_unprovision": _("Delete Key, Unprovision"),
                 "details": _("Service Settings"),
                 "host": _("Host Name"),
@@ -798,6 +804,7 @@ class i18n_messages(Command):
             "enabled": _("${count} item(s) enabled"),
             "partial_delete": _("Some entries were not deleted"),
             "placeholder": _("Search"),
+            "placeholder_filter": _("Filter"),
             "quick_links": _("Quick Links"),
             "select_all": _("Select All"),
             "truncated": _("Query returned more results than the configured size limit. Displaying the first ${counter} results."),
-- 
2.5.5

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to