diff options
author | Endi S. Dewata <edewata@redhat.com> | 2010-11-15 11:10:55 -0600 |
---|---|---|
committer | Endi Sukma Dewata <edewata@redhat.com> | 2010-11-15 12:48:45 -0500 |
commit | 9c502641b5f7bf613eb9dbd4be21fbaf92312267 (patch) | |
tree | 9421ac0faa0dd3bbd2dac71c6b0a4a94ec3fd6b1 | |
parent | 629e9520e0b5ce1ae6138d4e2c69ac52927c044a (diff) | |
download | freeipa-9c502641b5f7bf613eb9dbd4be21fbaf92312267.tar.gz freeipa-9c502641b5f7bf613eb9dbd4be21fbaf92312267.tar.xz freeipa-9c502641b5f7bf613eb9dbd4be21fbaf92312267.zip |
HBAC details page enhancement
The HBAC details page has been enhanced to support Undo and Reset operations.
The functionality is implemented in the base widget class so the behavior
will be more consistent across widgets. A <span> tag now used to define the
field boundary in the HTML doc. The tag contains the visual representation
of the field which include the input tag and optionally the undo link.
The Update method on HBAC details page has been modified so that it executes
several operations using a batch command. The operations being executed
depends on the changes made to the fields. These operations may include:
- removing access time if access time is changed to any time
- removing memberships if member category is changed to all
- modifying rule attributes if description or rule type is changed
- enabling/disabling the rule if rule status is changed
The behavior of the Add & Remove buttons also has been changed such that
it adjust the category attribute properly in addition to adding the
memberships using batch command. For example, if category is initially
set to all, adding a new member will also change the category to empty.
The ipa_command have been modified to store the on_success and on_error
handlers as properties. When the command is executed as a part of batch
operation, the result of each command will be passed to the appropriate
handler.
The unit tests and test data have been updated as well.
22 files changed, 1360 insertions, 710 deletions
diff --git a/install/static/associate.js b/install/static/associate.js index 641409a8f..7dd81caec 100644 --- a/install/static/associate.js +++ b/install/static/associate.js @@ -244,7 +244,6 @@ function ipa_association_widget(spec) { that.other_entity = spec.other_entity; that.superior_create = that.superior('create'); - that.superior_setup = that.superior('setup'); that.create = function(container) { @@ -258,25 +257,42 @@ function ipa_association_widget(spec) { that.superior_create(container); - var div = $('#'+that.id, container); - var buttons = $('<span />').appendTo($('.action-panel')); //TODO replace with ipa_button + var ul = $('.action-panel ul'); + var li = $('<li/>').appendTo(ul); + // creating generic buttons for layout $('<input/>', { 'type': 'button', 'name': 'remove', 'value': IPA.messages.button.remove - }).appendTo(buttons); + }).appendTo(li); $('<input/>', { 'type': 'button', 'name': 'add', 'value': IPA.messages.button.enroll - }).appendTo(buttons); + }).appendTo(li); }; that.setup = function(container) { - that.superior_setup(container); + that.table_setup(container); + + // replacing generic buttons with ipa_button and setting click handler + var action_panel = $('.action-panel'); + var button = $('input[name=remove]', action_panel); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-trash', + 'click': function() { that.remove(that.container); } + })); + + button = $('input[name=add]', action_panel); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-plus', + 'click': function() { that.add(that.container) } + })); var entity = IPA.get_entity(that.entity_name); var association = entity.get_association(that.other_entity); @@ -308,18 +324,18 @@ function ipa_association_widget(spec) { 'associator': that.associator, 'method': that.add_method, 'on_success': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); }, 'on_error': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); } }); dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.remove = function(container) { @@ -344,18 +360,18 @@ function ipa_association_widget(spec) { 'associator': that.associator, 'method': that.delete_method, 'on_success': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); }, 'on_error': function() { - that.refresh(container); + that.refresh(that.container); dialog.close(); } }); dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.refresh = function(container) { @@ -374,15 +390,15 @@ function ipa_association_widget(spec) { for (var i = 0; i<values.length; i++){ var record = that.get_record(data.result.result, i); - that.add_row(container, record); + that.add_row(that.container, record); } } function on_error(xhr, text_status, error_thrown) { - var div = $('#'+that.id, container).empty(); - div.append('<p>Error: '+error_thrown.name+'</p>'); - div.append('<p>'+error_thrown.title+'</p>'); - div.append('<p>'+error_thrown.message+'</p>'); + var summary = $('span[name=summary]', that.tfoot).empty(); + summary.append('<p>Error: '+error_thrown.name+'</p>'); + summary.append('<p>'+error_thrown.title+'</p>'); + summary.append('<p>'+error_thrown.message+'</p>'); } var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; @@ -407,10 +423,21 @@ function ipa_association_facet(spec) { }; that.create = function(container) { + that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; that.other_entity = $.bbq.getState(that.entity_name + '-enroll', true) || ''; + var label = IPA.metadata[that.other_entity] ? IPA.metadata[that.other_entity].label : that.other_entity; + + that.table = ipa_association_widget({ + 'id': that.entity_name+'-'+that.other_entity, + 'name': 'association', + 'label': label, + 'entity_name': that.entity_name, + 'other_entity': that.other_entity + }); + //TODO I18N var header_message = that.other_entity + '(s) enrolled in ' + that.entity_name + ' ' + that.pkey; @@ -427,13 +454,17 @@ function ipa_association_facet(spec) { 'other_entity': that.other_entity }); - that.table.create(container); + var span = $('<span/>', { 'name': 'association' }).appendTo(container); + that.table.create(span); }; - that.setup = function(container, unspecified) { - that.table.setup(container); - that.table.refresh(container); + that.setup = function(container) { + + var span = $('span[name=association]', container); + + that.table.setup(span); + that.table.refresh(); }; return that; diff --git a/install/static/details.js b/install/static/details.js index 612716c35..49957a56d 100644 --- a/install/static/details.js +++ b/install/static/details.js @@ -40,29 +40,26 @@ function ipa_details_field(spec) { var that = ipa_widget(spec); that.create = spec.create || create; - that.setup = spec.setup || setup; that.load = spec.load || load; that.save = spec.save || save; function create(container) { - var dl = $('dl', container); - var title = that.name; var label = ''; + var param_info = ipa_get_param_info(that.entity_name, that.name); if (param_info) label = param_info['label']; + if (!label) label = that.label; + $('<dt></dt>', { id: that.name, title: title, html: label + ':' - }).appendTo(dl); - } - - function setup(container) { + }).appendTo(container); } function load(container, result) { @@ -129,10 +126,9 @@ function ipa_details_field(spec) { } function save(container) { - var field = this; var values = []; - var dd = $('dd[title='+field.name+']', container); + var dd = $('dd[title='+that.name+']', container); dd.each(function () { var input = $('input', $(this)); if (!input.length) return; @@ -156,15 +152,12 @@ function ipa_details_section(spec){ spec = spec || {}; var that = {}; + that.name = spec.name || ''; that.label = spec.label || ''; that.template = spec.template; that._entity_name = spec.entity_name; - that.setup = spec.setup || ipa_details_section_setup; - that.create = spec.create || ipa_details_section_create; - that.load = spec.load || ipa_details_section_load; - that.fields = []; that.fields_by_name = {}; @@ -234,6 +227,126 @@ function ipa_details_section(spec){ } }; + that.create = function(container) { + + if (that.template) return; + + var fields = that.fields; + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + + var span = $('<span/>', { 'name': field.name }).appendTo(container); + field.create(span); + } + }; + + that.setup = function(container) { + + this.container = container; + + if (that.template) return; + + var fields = that.fields; + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + + var span = $('span[name='+field.name+']', this.container).first(); + field.setup(span); + } + }; + + that.load = function(result) { + + var fields = that.fields; + + if (that.template) { + var template = IPA.get_template(that.template); + this.container.load( + template, + function(data, text_status, xhr) { + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + var span = $('span[name='+field.name+']', this.container).first(); + field.setup(span); + field.load(span, result); + } + } + ); + return; + } + + for (var j=0; j<fields.length; j++) { + var field = fields[j]; + var span = $('span[name='+field.name+']', this.container).first(); + field.load(span, result); + } + }; + + that.reset = function() { + for (var i=0; i<that.fields.length; i++) { + var field = that.fields[i]; + var span = $('span[name='+field.name+']', this.container).first(); + field.reset(span); + } + }; + + // methods that should be invoked by subclasses + that.section_create = that.create; + that.section_setup = that.setup; + that.section_load = that.load; + + return that; +} + +function ipa_details_list_section(spec){ + + spec = spec || {}; + + var that = ipa_details_section(spec); + + that.create = function(container) { + + // do not call section_create() here + + if (that.template) return; + + var dl = $('<dl/>', { + 'id': that.name, + 'class': 'entryattrs' + }).appendTo(container); + + var fields = that.fields; + for (var i = 0; i < fields.length; ++i) { + var field = fields[i]; + + var span = $('<span/>', { 'name': field.name }).appendTo(dl); + field.create(span); + } + }; + + /* populate definition lists with the class 'entryattrs' with entry attributes + * + * The list has to be specially crafted for this function to work properly: + * <dt> tags should have the 'title' attribute set to an LDAP attribute name + * OR to a javascript function name prefixed with 'call_', which will be given + * the <dt> object and entry_attrs as arguments. + * Example: + * <dl class="entryattrs"> + * <dt title="givenname">First Name:</dt> + * <dt title="call_some_callback">Some Attribute:</dt> + * </dl> + * + * arguments: + * result - 'result' field as returned by ipa *-show commnads + * (basically an associative array with attr:value pairs) */ + that.load = function(result) { + /* remove all <dd> tags i.e. all attribute values */ + $('dd', that.container).remove(); + + /* go through all <dt> tags and pair them with newly created <dd>s */ + that.section_load(result); + }; + // Deprecated: Used for backward compatibility only. function input(spec){ that.create_field(spec); @@ -247,7 +360,7 @@ function ipa_details_section(spec){ // Deprecated: Used for backward compatibility only. function ipa_stanza(spec) { - return ipa_details_section(spec); + return ipa_details_list_section(spec); } function ipa_details_facet(spec) { @@ -392,7 +505,8 @@ function ipa_details_create(container) } } -function ipa_details_setup(container, unspecified) { +function ipa_details_setup(container) { + var that = this; for (var i = 0; i < that.sections.length; ++i) { @@ -403,16 +517,17 @@ function ipa_details_setup(container, unspecified) { container ); - section.setup(div, unspecified); + section.setup(div); } } -function ipa_details_load(container, unspecified) { +function ipa_details_load(container) { var that = this; + var entity = IPA.get_entity(that.entity_name); that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; - if (!that.pkey && !unspecified) return; + if (!that.pkey && !entity.default_facet) return; function on_success(data, text_status, xhr) { var result = data.result.result; @@ -420,13 +535,7 @@ function ipa_details_load(container, unspecified) { ipa_details_cache[that.entity_name] = $.extend(true, {}, result); for (var i = 0; i < that.sections.length; ++i) { var section = that.sections[i]; - - var div = $( - '#'+that.entity_name+'-'+that.name+'-'+section.name, - container - ); - - section.load(div, result); + section.load(result); } } @@ -445,59 +554,6 @@ function ipa_details_load(container, unspecified) { ); } -function ipa_details_section_create(container) { - - var that = this; - if (that.template) return; - - var dl = $('<dl/>', { - 'id': that.name, - 'class': 'entryattrs' - }).appendTo(container); - - var fields = that.fields; - for (var i = 0; i < fields.length; ++i) { - var field = fields[i]; - field.create(container); - } -} - -function ipa_details_section_setup(container, unspecified) { - var that = this; - if (that.template) return; - - var fields = that.fields; - for (var i = 0; i < fields.length; ++i) { - var field = fields[i]; - field.setup(container); - } -} - -function ipa_details_section_load(container, result) { - var that = this; - var fields = that.fields; - - if (that.template) { - var template = IPA.get_template(that.template); - container.load( - template, - function(data, text_status, xhr) { - for (var i = 0; i < fields.length; ++i) { - var field = fields[i]; - field.setup(container); - field.load(container, result); - } - } - ); - return; - } - - for (var j=0; j<fields.length; j++) { - var field = fields[j]; - field.load(container, result); - } -} - function ipa_details_update(container, pkey, on_win, on_fail) { var facet = this; @@ -511,7 +567,7 @@ function ipa_details_update(container, pkey, on_win, on_fail) var result = data.result.result; ipa_details_cache[entity_name] = $.extend(true, {}, result); - facet.display(container, result); + facet.display(result); } function update_on_fail(xhr, text_status, error_thrown) { @@ -534,7 +590,8 @@ function ipa_details_update(container, pkey, on_win, on_fail) for (var j=0; j<section.fields.length; j++) { var field = section.fields[j]; - values = field.save(div); + var span = $('span[name='+field.name+']', div).first(); + values = field.save(span); var param_info = ipa_get_param_info(entity_name, field.name); if (param_info) { @@ -559,7 +616,7 @@ function ipa_details_update(container, pkey, on_win, on_fail) modlist['addattr'].push(attr + '=' + values[i]); } - ipa_cmd('mod', [pkey], modlist, update_on_win, update_on_fail, entity_name); + ipa_cmd('mod', [pkey], modlist, update_on_win, null, entity_name); } @@ -571,35 +628,13 @@ var _ipa_span_hint_template = '<span class="attrhint">Hint: D</span>'; -/* populate definition lists with the class 'entryattrs' with entry attributes - * - * The list has to be specially crafted for this function to work properly: - * <dt> tags should have the 'title' attribute set to an LDAP attribute name - * OR to a javascript function name prefixed with 'call_', which will be given - * the <dt> object and entry_attrs as arguments. - * Example: - * <dl class="entryattrs"> - * <dt title="givenname">First Name:</dt> - * <dt title="call_some_callback">Some Attribute:</dt> - * </dl> - * - * arguments: - * result - 'result' field as returned by ipa *-show commnads - * (basically an associative array with attr:value pairs) */ -function ipa_details_display(container, result) +function ipa_details_display(result) { var facet = this; - /* remove all <dd> tags i.e. all attribute values */ - $('dd', container).remove(); - - /* go through all <dt> tags and pair them with newly created <dd>s */ for (var i=0; i<facet.sections.length; i++) { var section = facet.sections[i]; - - var div = $('#'+facet.entity_name+'-'+facet.name+'-'+section.name, container); - - section.load(div, result); + section.load(result); } } @@ -607,7 +642,6 @@ function ipa_details_display(container, result) function ipa_create_first_dd(field_name, content){ return $('<dd/>', { - 'class': 'first', 'title': field_name }).append(content); @@ -783,13 +817,17 @@ function _ipa_create_text_input(attr, value, param_info, rights) function ipa_details_reset(container) { - var facet = this; - var entity_name = facet.entity_name; + var that = this; + var entity_name = that.entity_name; if (ipa_details_cache[entity_name]){ - facet.display(container, ipa_details_cache[entity_name]); + that.display(ipa_details_cache[entity_name]); } + for (var i=0; i<that.sections.length; i++) { + var section = that.sections[i]; + section.reset(); + } } /* Event handlers */ diff --git a/install/static/entity.js b/install/static/entity.js index 3eafedc0a..74a07d009 100644 --- a/install/static/entity.js +++ b/install/static/entity.js @@ -206,7 +206,8 @@ function ipa_entity_set_add_definition(entity_name, data) { dialog.add_field(ipa_text_widget({ name: field[0], label: field[1], - setup: field[2] + setup: field[2], + undo: false })); } } @@ -289,11 +290,11 @@ function ipa_details_only_setup(container){ ipa_entity_setup.call(this, container, 'details'); } -function ipa_entity_setup(container, unspecified) { +function ipa_entity_setup(container) { var entity = this; - var facet_name = $.bbq.getState(entity.name + '-facet', true) || unspecified || 'search'; + var facet_name = $.bbq.getState(entity.name + '-facet', true) || entity.default_facet || 'search'; var facet = entity.get_facet(facet_name); if (!facet) return; @@ -314,15 +315,15 @@ function ipa_entity_setup(container, unspecified) { facet.setup_views(container); facet.create(container); container.children().last().addClass('client'); - facet.setup(container, unspecified); - facet.load(container, unspecified); + facet.setup(container); + facet.load(container); } function action_panel(entity_name){ var div = $('<div/>', { "class":"action-panel", - html: $('<h3>Actions</h3>'), + html: $('<h3>Actions</h3>') }); var ul = $('<ul/>', {'class': 'action'}).appendTo(div); diff --git a/install/static/group.js b/install/static/group.js index 2358cf1fb..f94a7deab 100644 --- a/install/static/group.js +++ b/install/static/group.js @@ -57,10 +57,10 @@ function ipa_group_add_dialog(spec) { this.superior_init(); - this.add_field(ipa_text_widget({name:'cn', label:'Name'})); - this.add_field(ipa_text_widget({name:'description', label:'Description'})); - this.add_field(ipa_checkbox_widget({name:'posix', label:'Is this a POSIX group?'})); - this.add_field(ipa_text_widget({name:'gidnumber', label:'GID'})); + this.add_field(ipa_text_widget({name:'cn', label:'Name', undo: false})); + this.add_field(ipa_text_widget({name:'description', label:'Description', undo: false})); + this.add_field(ipa_checkbox_widget({name:'posix', label:'Is this a POSIX group?', undo: false})); + this.add_field(ipa_text_widget({name:'gidnumber', label:'GID', undo: false})); }; return that; diff --git a/install/static/hbac.js b/install/static/hbac.js index 7a08db38d..eb02bf738 100755 --- a/install/static/hbac.js +++ b/install/static/hbac.js @@ -71,12 +71,14 @@ function ipa_hbac_add_dialog(spec) { that.add_field(ipa_text_widget({ 'name': 'cn', - 'label': 'Rule Name' + 'label': 'Rule Name', + 'undo': false })); that.add_field(ipa_text_widget({ 'name': 'accessruletype', - 'label': 'Rule type (allow/deny)' + 'label': 'Rule type (allow/deny)', + 'undo': false })); }; @@ -102,12 +104,6 @@ function ipa_hbac_search_facet(spec) { that.create_column({name:'servicecategory', label:'Via Service'}); that.create_column({name:'sourcehostcategory', label:'From'}); - that.create_column({ - name: 'quick_links', - label: 'Quick Links', - setup: ipa_hbac_quick_links - }); - that.superior_init(); }; @@ -133,31 +129,29 @@ function ipa_hbac_search_facet(spec) { 'label': 'Cull Disabled Rules' })); */ - var right_buttons = $('<li/>', { - 'style': 'float: right;' - }).appendTo($('.action-panel ul')); + var ul = $('.action-panel ul'); - right_buttons.append(ipa_button({ - 'label': 'HBAC Services', + $('<li/>', { + title: 'hbacsvc', + text: 'HBAC Services', 'click': function() { var state = {}; state['entity'] = 'hbacsvc'; nav_push_state(state); return false; } - })); + }).appendTo(ul); - right_buttons.append(ipa_button({ - 'label': 'HBAC Service Groups', + $('<li/>', { + title: 'hbacsvcgroup', + text: 'HBAC Service Groups', 'click': function() { var state = {}; state['entity'] = 'hbacsvcgroup'; nav_push_state(state); return false; } - })); - - container.append('<br/><br/>'); + }).appendTo(ul); that.superior_create(container); }; @@ -165,45 +159,6 @@ function ipa_hbac_search_facet(spec) { return that; } -function ipa_hbac_quick_links(container, name, value, record) { - - var column = this; - var facet = column.facet; - - var pkey = IPA.metadata[column.entity_name].primary_key; - var pkey_value = record[pkey]; - - var span = $('span[name='+name+']', container); - - $('<a/>', { - 'href': '#details', - 'title': 'Details', - 'text': 'Details', - 'click': function() { - var state = {}; - state[column.entity_name+'-facet'] = 'details'; - state[column.entity_name+'-pkey'] = pkey_value; - nav_push_state(state); - return false; - } - }).appendTo(span); - - span.append(' | '); - - $('<a/>', { - 'href': '#test-rule', - 'title': 'Test Rule', - 'text': 'Test Rule', - 'click': function() { - var state = {}; - state[column.entity_name+'-facet'] = 'test-rule'; - state[column.entity_name+'-pkey'] = pkey_value; - nav_push_state(state); - return false; - } - }).appendTo(span); -} - function ipa_hbac_details_facet(spec) { spec = spec || {}; @@ -233,7 +188,7 @@ function ipa_hbac_details_facet(spec) { that.add_section(section); } - section.create_text({ 'name': 'cn', 'label': 'Name' }); + section.create_text({ 'name': 'cn', 'label': 'Name', 'read_only': true }); section.create_radio({ 'name': 'accessruletype', 'label': 'Rule Type' }); section.create_textarea({ 'name': 'description', 'label': 'Description' }); section.create_radio({ 'name': 'ipaenabledflag', 'label': 'Enabled' }); @@ -263,15 +218,15 @@ function ipa_hbac_details_facet(spec) { that.add_section(section); } - section.create_radio({ name: 'usercategory', label: 'User category' }); + var category = section.create_radio({ name: 'usercategory', label: 'User category' }); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-memberuser_user', - 'name': 'memberuser_user', 'label': 'Users', + 'name': 'memberuser_user', 'label': 'Users', 'category': category, 'other_entity': 'user', 'add_method': 'add_user', 'delete_method': 'remove_user' })); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-memberuser_group', - 'name': 'memberuser_group', 'label': 'Groups', + 'name': 'memberuser_group', 'label': 'Groups', 'category': category, 'other_entity': 'group', 'add_method': 'add_user', 'delete_method': 'remove_user' })); @@ -300,15 +255,15 @@ function ipa_hbac_details_facet(spec) { that.add_section(section); } - section.create_radio({ 'name': 'hostcategory', 'label': 'Host category' }); + category = section.create_radio({ 'name': 'hostcategory', 'label': 'Host category' }); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-memberhost_host', - 'name': 'memberhost_host', 'label': 'Hosts', + 'name': 'memberhost_host', 'label': 'Hosts', 'category': category, 'other_entity': 'host', 'add_method': 'add_host', 'delete_method': 'remove_host' })); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-memberhost_hostgroup', - 'name': 'memberhost_hostgroup', 'label': 'Host Groups', + 'name': 'memberhost_hostgroup', 'label': 'Host Groups', 'category': category, 'other_entity': 'hostgroup', 'add_method': 'add_host', 'delete_method': 'remove_host' })); @@ -337,15 +292,15 @@ function ipa_hbac_details_facet(spec) { that.add_section(section); } - section.create_radio({ 'name': 'servicecategory', 'label': 'Service category' }); + category = section.create_radio({ 'name': 'servicecategory', 'label': 'Service category' }); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-memberservice_hbacsvc', - 'name': 'memberservice_hbacsvc', 'label': 'Services', + 'name': 'memberservice_hbacsvc', 'label': 'Services', 'category': category, 'other_entity': 'hbacsvc', 'add_method': 'add_service', 'delete_method': 'remove_service' })); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-memberservice_hbacsvcgroup', - 'name': 'memberservice_hbacsvcgroup', 'label': 'Service Groups', + 'name': 'memberservice_hbacsvcgroup', 'label': 'Service Groups', 'category': category, 'other_entity': 'hbacsvcgroup', 'add_method': 'add_service', 'delete_method': 'remove_service' })); @@ -374,15 +329,15 @@ function ipa_hbac_details_facet(spec) { that.add_section(section); } - section.create_radio({ 'name': 'sourcehostcategory', 'label': 'Source host category' }); + category = section.create_radio({ 'name': 'sourcehostcategory', 'label': 'Source host category' }); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-sourcehost_host', - 'name': 'sourcehost_host', 'label': 'Host', + 'name': 'sourcehost_host', 'label': 'Host', 'category': category, 'other_entity': 'host', 'add_method': 'add_sourcehost', 'delete_method': 'remove_sourcehost' })); section.add_field(ipa_hbac_association_widget({ 'id': that.entity_name+'-sourcehost_hostgroup', - 'name': 'sourcehost_hostgroup', 'label': 'Host Groups', + 'name': 'sourcehost_hostgroup', 'label': 'Host Groups', 'category': category, 'other_entity': 'hostgroup', 'add_method': 'add_sourcehost', 'delete_method': 'remove_sourcehost' })); @@ -394,30 +349,233 @@ function ipa_hbac_details_facet(spec) { }); } else { + section = that.create_section({ + 'name': 'accesstime', + 'label': 'When' + }); +/* section = ipa_hbac_details_tables_section({ 'name': 'accesstime', 'label': 'When', 'text': 'Rule applies when access is being requested at:', - 'field_name': 'accesstime', - 'options': [ - { 'value': 'all', 'label': 'Any Time' }, - { 'value': '', 'label': 'Specified Times' } - ], + 'field_name': 'accesstimecategory', 'tables': [ { 'field_name': 'accesstime' } ] }); that.add_section(section); +*/ } section.add_field(ipa_hbac_accesstime_widget({ - 'id': that.entity_name+'-accesstime', - 'name': 'accesstime', 'label': 'Access Time' + 'id': 'accesstime', + 'name': 'accesstime', 'label': 'Access Time', + 'text': 'Rule applies when access is being requested at:', + 'options': [ + { 'value': 'all', 'label': 'Any Time' }, + { 'value': '', 'label': 'Specified Times' } + ] })); that.superior_init(); }; + that.update = function(container) { + + var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; + + var modify_operation = { + 'execute': false, + 'command': ipa_command({ + 'method': that.entity_name+'_mod', + 'args': [pkey], + 'options': {'all': true, 'rights': true} + }) + }; + + var remove_accesstime = { + 'template': ipa_command({ + 'method': that.entity_name+'_remove_accesstime', + 'args': [pkey], + 'options': {'all': true, 'rights': true} + }), + 'commands': [] + }; + + var member_category = { + 'usercategory': 'memberuser', + 'hostcategory': 'memberhost', + 'servicecategory': 'memberservice', + 'sourcehostcategory': 'sourcehost' + }; + + var remove_members = { + 'memberuser': { + 'category_changed': false, + 'has_values': false, + 'command': ipa_command({ + 'method': that.entity_name+'_remove_user', + 'args': [pkey], + 'options': {'all': true, 'rights': true} + }) + }, + 'memberhost': { + 'category_changed': false, + 'has_values': false, + 'command': ipa_command({ + 'method': that.entity_name+'_remove_host', + 'args': [pkey], + 'options': {'all': true, 'rights': true} + }) + }, + 'memberservice': { + 'category_changed': false, + 'has_values': false, + 'command': ipa_command({ + 'method': that.entity_name+'_remove_service', + 'args': [pkey], + 'options': {'all': true, 'rights': true} + }) + }, + 'sourcehost': { + 'category_changed': false, + 'has_values': false, + 'command': ipa_command({ + 'method': that.entity_name+'_remove_sourcehost', + 'args': [pkey], + 'options': {'all': true, 'rights': true} + }) + } + }; + + var enable_operation = { + 'execute': false, + 'command': ipa_command({ + 'method': that.entity_name+'_enable', + 'args': [pkey], + 'options': {'all': true, 'rights': true} + }) + }; + + for (var i=0; i<that.sections.length; i++) { + var section = that.sections[i]; + + var div = $('#'+that.entity_name+'-'+that.name+'-'+section.name, container); + + for (var j=0; j<section.fields.length; j++) { + var field = section.fields[j]; + + var span = $('span[name='+field.name+']', div).first(); + var values = field.save(span); + + var param_info = ipa_get_param_info(that.entity_name, field.name); + + // skip primary key + if (param_info && param_info['primary_key']) continue; + + var p = field.name.indexOf('_'); + if (p >= 0) { + // prepare command to remove members if needed + var attribute = field.name.substring(0, p); + var other_entity = field.name.substring(p+1); + + if (values.length) { + remove_members[attribute].command.set_option(other_entity, values.join(',')); + remove_members[attribute].has_values = true; + } + continue; + } + + // skip unchanged field + if (!field.is_dirty(span)) continue; + + // check enable/disable + if (field.name == 'ipaenabledflag') { + if (values[0] == 'FALSE') enable_operation.command.method = that.entity_name+'_disable'; + enable_operation.execute = true; + continue; + } + + if (field.name == 'accesstime') { + // if accesstime is dirty, it means 'Any Time' is selected, + // so existing values have to be removed + for (var k=0; k<field.values.length; k++) { + var command = ipa_command(remove_accesstime.template); + command.set_option(field.name, field.values[k]); + remove_accesstime.commands.push(command); + } + continue; + } + + // use setattr/addattr if param_info not available + if (!param_info) { + for (var k=0; k<values.length; k++) { + modify_operation.set_option( + k == 0 ? 'setattr' : 'addattr', + field.name+'='+values[k] + ); + modify_operation.execute = true; + } + continue; + } + + var attribute = member_category[field.name]; + if (attribute) { + // if category is dirty, it means 'Any *' is selected, + // so existing values have to be removed + remove_members[attribute].category_changed = true; + + // fall through to trigger modify operation + } + + // set modify options + if (values.length == 1) { + modify_operation.command.set_option(field.name, values[0]); + } else { + modify_operation.command.set_option(field.name, values); + } + modify_operation.execute = true; + } + } + + var batch = ipa_batch_command({ + 'on_success': function success_handler(data, text_status, xhr) { + that.load(container); + }, + 'on_error': function(xhr, text_status, error_thrown) { + that.load(container); + } + }); + + for (var attribute in remove_members) { + if (remove_members[attribute].has_values && + remove_members[attribute].category_changed) { + batch.add_command(remove_members[attribute].command); + } + } + + batch.add_commands(remove_accesstime.commands); + + if (modify_operation.execute) batch.add_command(modify_operation.command); + if (enable_operation.execute) batch.add_command(enable_operation.command); + + if (!batch.args.length) { + that.load(container); + return; + } + + //alert(JSON.stringify(batch.to_json())); + + batch.execute(); + }; + + that.reset = function() { + for (var i=0; i<that.sections.length; i++) { + var section = that.sections[i]; + section.reset(); + } + }; + return that; } @@ -443,11 +601,22 @@ function ipa_hbac_details_general_section(spec){ td = $('<td/>').appendTo(tr); + var span = $('<span/>', { 'name': 'cn' }).appendTo(td); + $('<input/>', { 'type': 'text', 'name': 'cn', 'size': 30 - }).appendTo(td); + }).appendTo(span); + + span.append(' '); + + $('<span/>', { + 'name': 'undo', + 'class': 'ui-state-highlight ui-corner-all', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(span); td = $('<td/>', { 'style': 'text-align: right;' @@ -455,21 +624,32 @@ function ipa_hbac_details_general_section(spec){ td.append('Rule type:'); + span = $('<span/>', { 'name': 'accessruletype' }).appendTo(td); + $('<input/>', { 'type': 'radio', 'name': 'accessruletype', 'value': 'allow' - }).appendTo(td); + }).appendTo(span); - td.append('Allow'); + span.append('Allow'); $('<input/>', { 'type': 'radio', 'name': 'accessruletype', 'value': 'deny' - }).appendTo(td); + }).appendTo(span); + + span.append('Deny'); - td.append('Deny'); + span.append(' '); + + $('<span/>', { + 'name': 'undo', + 'class': 'ui-state-highlight ui-corner-all', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(span); tr = $('<tr/>', { }).appendTo(table); @@ -483,11 +663,22 @@ function ipa_hbac_details_general_section(spec){ 'colspan': 2 }).appendTo(tr); + span = $('<span/>', { 'name': 'description' }).appendTo(td); + $('<textarea/>', { 'name': 'description', 'rows': 5, 'style': 'width: 100%' - }).appendTo(td); + }).appendTo(span); + + span.append(' '); + + $('<span/>', { + 'name': 'undo', + 'class': 'ui-state-highlight ui-corner-all', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(span); tr = $('<tr/>', { }).appendTo(table); @@ -501,21 +692,32 @@ function ipa_hbac_details_general_section(spec){ 'colspan': 2 }).appendTo(tr); + span = $('<span/>', { 'name': 'ipaenabledflag' }).appendTo(td); + $('<input/>', { 'type': 'radio', 'name': 'ipaenabledflag', 'value': 'TRUE' - }).appendTo(td); + }).appendTo(span); - td.append('Active'); + span.append('Active'); $('<input/>', { 'type': 'radio', 'name': 'ipaenabledflag', 'value': 'FALSE' - }).appendTo(td); + }).appendTo(span); + + span.append('Inactive'); - td.append('Inactive'); + span.append(' '); + + $('<span/>', { + 'name': 'undo', + 'class': 'ui-state-highlight ui-corner-all', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(span); }; return that; @@ -529,8 +731,8 @@ function ipa_hbac_details_tables_section(spec){ that.text = spec.text; that.field_name = spec.field_name; - that.options = spec.options; - that.tables = spec.tables; + that.options = spec.options || []; + that.tables = spec.tables || []; that.columns = spec.columns; that.superior_setup = that.superior('setup'); @@ -541,6 +743,8 @@ function ipa_hbac_details_tables_section(spec){ container.append(that.text); + var span = $('<span/>', { 'name': that.field_name }).appendTo(container); + for (var i=0; i<that.options.length; i++) { var option = that.options[i]; @@ -548,25 +752,29 @@ function ipa_hbac_details_tables_section(spec){ 'type': 'radio', 'name': that.field_name, 'value': option.value - }).appendTo(container); + }).appendTo(span); - container.append(option.label); + span.append(option.label); } - container.append('<br/>'); + span.append(' '); + + $('<span/>', { + 'name': 'undo', + 'class': 'ui-state-highlight ui-corner-all', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(span); + + span.append('<br/>'); for (var i=0; i<that.tables.length; i++) { var table = that.tables[i]; - $('<div/>', { - 'id': that.entity_name+'-'+table.field_name - }).appendTo(container); - } + var table_span = $('<span/>', { 'name': table.field_name }).appendTo(span); - var fields = that.fields; - for (var i = 0; i < fields.length; ++i) { - var field = fields[i]; - field.create(container); + var field = that.get_field(table.field_name); + field.create(table_span); } }; @@ -580,13 +788,13 @@ function ipa_hbac_association_widget(spec) { var that = ipa_table_widget(spec); that.other_entity = spec.other_entity; + that.category = spec.category; that.add_method = spec.add_method; that.delete_method = spec.delete_method; that.superior_init = that.superior('init'); that.superior_create = that.superior('create'); - that.superior_setup = that.superior('setup'); that.init = function() { // create a column if none defined @@ -605,9 +813,7 @@ function ipa_hbac_association_widget(spec) { that.superior_create(container); - var div = $('#'+that.id, container); - - var buttons = $('span[name=buttons]', div); + var buttons = $('span[name=buttons]', container); $('<input/>', { 'type': 'button', @@ -624,7 +830,21 @@ function ipa_hbac_association_widget(spec) { that.setup = function(container) { - that.superior_setup(container); + that.table_setup(container); + + var button = $('input[name=remove]', that.table); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-trash', + 'click': function() { that.remove(that.container); } + })); + + button = $('input[name=add]', that.table); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-plus', + 'click': function() { that.add(that.container) } + })); var entity = IPA.get_entity(that.entity_name); var association = entity.get_association(that.other_entity); @@ -636,6 +856,23 @@ function ipa_hbac_association_widget(spec) { } }; + that.load = function(container, result) { + + that.values = result[that.name] || []; + that.hide_undo(that.container); + that.set_values(that.container, that.values); + }; + + that.set_values = function(container, values) { + + that.tbody.empty(); + for (var i=0; values && i<values.length; i++) { + var record = {}; + record[that.name] = values[i]; + that.add_row(that.container, record); + } + }; + that.add = function(container) { var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; @@ -646,29 +883,55 @@ function ipa_hbac_association_widget(spec) { 'title': title, 'entity_name': that.entity_name, 'pkey': pkey, - 'other_entity': that.other_entity, - 'associator': that.associator, - 'method': that.add_method, - 'on_success': function() { - that.refresh(container); - dialog.close(); - }, - 'on_error': function() { - that.refresh(container); - dialog.close(); - } + 'other_entity': that.other_entity }); + dialog.add = function() { + + var values = dialog.get_selected_values(); + + var batch = ipa_batch_command({ + 'on_success': function() { + that.refresh(that.container); + dialog.close(); + }, + 'on_error': function() { + that.refresh(that.container); + dialog.close(); + } + }); + + var command = ipa_command({ + 'method': that.entity_name+'_mod', + 'args': [pkey], + 'options': {'all': true, 'rights': true}, + 'on_success': function() { + that.category.load(container, ['']); + } + }); + command.set_option(that.category.name, ''); + batch.add_command(command); + + command = ipa_command({ + 'method': that.entity_name+'_'+that.add_method, + 'args': [pkey] + }); + command.set_option(that.other_entity, values.join(',')); + batch.add_command(command); + + batch.execute(); + }; + dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.remove = function(container) { - var values = that.get_selected_values(); + var selected_values = that.get_selected_values(); - if (!values.length) { + if (!selected_values.length) { alert('Select '+that.label+' to be removed.'); return; } @@ -682,59 +945,51 @@ function ipa_hbac_association_widget(spec) { 'entity_name': that.entity_name, 'pkey': pkey, 'other_entity': that.other_entity, - 'values': values, - 'associator': that.associator, - 'method': that.delete_method, - 'on_success': function() { - that.refresh(container); - dialog.close(); - }, - 'on_error': function() { - that.refresh(container); - dialog.close(); - } + 'values': selected_values }); + dialog.remove = function() { + + var command = ipa_command({ + 'method': that.entity_name+'_'+that.delete_method, + 'args': [pkey], + 'on_success': function() { + that.refresh(that.container); + dialog.close(); + }, + 'on_error': function() { + that.refresh(that.container); + dialog.close(); + } + }); + + command.set_option(that.other_entity, selected_values.join(',')); + + command.execute(); + }; + dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.refresh = function(container) { function on_success(data, text_status, xhr) { - - that.tbody.empty(); - - var column_name = that.columns[0].name; - var values = data.result.result[column_name]; - //TODO, this is masking an error where the wrong - //direction association is presented upon page reload. - //if the values is unset, it is because - //form.associationColumns[0] doesn't exist in the results - if (!values) return; - - for (var i = 0; i<values.length; i++){ - var record = that.get_record(data.result.result, i); - that.add_row(container, record); - } + that.load(that.container, data.result.result); } function on_error(xhr, text_status, error_thrown) { - var div = $('#'+that.id, container).empty(); - div.append('<p>Error: '+error_thrown.name+'</p>'); - div.append('<p>'+error_thrown.title+'</p>'); - div.append('<p>'+error_thrown.message+'</p>'); + var summary = $('span[name=summary]', that.tfoot).empty(); + summary.append('<p>Error: '+error_thrown.name+'</p>'); + summary.append('<p>'+error_thrown.title+'</p>'); + summary.append('<p>'+error_thrown.message+'</p>'); } var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; ipa_cmd('show', [pkey], {'rights': true}, on_success, on_error, that.entity_name); }; - that.save = function(container) { - return []; - }; - return that; } @@ -742,21 +997,27 @@ function ipa_hbac_accesstime_widget(spec) { spec = spec || {}; - var that = ipa_table_widget(spec); + var that = ipa_widget(spec); + + that.text = spec.text; + that.options = spec.options || []; that.superior_init = that.superior('init'); that.superior_create = that.superior('create'); that.superior_setup = that.superior('setup'); that.init = function() { - // create a column if none defined - if (!that.columns.length) { - that.create_column({ - 'name': that.name, - 'label': that.label, - 'primary_key': true - }); - } + + that.table = ipa_table_widget({ + 'id': 'accesstime-table', + 'name': 'table', 'label': that.label + }); + + that.table.create_column({ + 'name': that.name, + 'label': that.label, + 'primary_key': true + }); that.superior_init(); }; @@ -765,9 +1026,38 @@ function ipa_hbac_accesstime_widget(spec) { that.superior_create(container); - var div = $('#'+that.id); + var span = $('<span/>', { 'name': 'text' }).appendTo(container); + + span.append(that.text); + + for (var i=0; i<that.options.length; i++) { + var option = that.options[i]; + + $('<input/>', { + 'type': 'radio', + 'name': that.name, + 'value': option.value + }).appendTo(container); + + container.append(option.label); + } + + container.append(' '); - var buttons = $('span[name=buttons]', div); + $('<span/>', { + 'name': 'undo', + 'class': 'ui-state-highlight ui-corner-all', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(container); + + container.append('<br/>'); + + span = $('<span/>', { 'name': 'table' }).appendTo(container); + + that.table.create(span); + + var buttons = $('span[name=buttons]', span); $('<input/>', { 'type': 'button', @@ -782,23 +1072,70 @@ function ipa_hbac_accesstime_widget(spec) { }).appendTo(buttons); }; - that.load = function(container, result) { - var values = result[that.name] || ''; - if (values) { - $('input[name="'+that.name+'"][value=""]', container).attr('checked', 'checked'); + that.setup = function(container) { + + that.widget_setup(container); + + var span = $('span[name="table"]', that.container); + that.table.setup(span); + + var button = $('input[name=remove]', span); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-trash', + 'click': function() { that.remove(that.container); } + })); + + button = $('input[name=add]', span); + button.replaceWith(ipa_button({ + 'label': button.val(), + 'icon': 'ui-icon-plus', + 'click': function() { that.add(that.container) } + })); + + var input = $('input[name="'+that.name+'"]', that.container); + input.change(function() { + that.show_undo(that.container); + }); + + var undo = that.get_undo(that.container); + undo.click(function() { + that.reset(that.container); + }); + }; + + that.save = function(container) { + var value = $('input[name="'+that.name+'"]:checked', that.container).val(); + if (value == '') { + return that.table.save(that.container); } else { - $('input[name="'+that.name+'"][value="all"]', container).attr('checked', 'checked'); + return []; } + }; - that.tbody.empty(); - for (var i=0; i<values.length; i++) { - var tr = that.row.clone(); - $('input[name="select"]', tr).val(values[i]); - $('span[name="'+that.name+'"]', tr).html(values[i]); - tr.appendTo(that.tbody); + that.load = function(container, result) { + + that.values = result[that.name] || []; + that.set_values(that.container, that.values); + that.hide_undo(that.container); + }; + + that.set_values = function(container, values) { + + that.set_radio_value(that.container, values && values.length ? '' : 'all'); + + that.table.tbody.empty(); + for (var i=0; values && i<values.length; i++) { + var record = {}; + record[that.name] = values[i]; + that.table.add_row(that.container, record); } }; + that.set_radio_value = function(container, value) { + $('input[name="'+that.name+'"][value="'+value+'"]', that.container).get(0).checked = true; + }; + that.add = function(container) { var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; @@ -824,11 +1161,14 @@ function ipa_hbac_accesstime_widget(spec) { td.append(that.label+': '); td = $('<td/>').appendTo(tr); + + var span = $('<span/>', { 'name': that.name }).appendTo(td); + $('<input/>', { 'type': 'text', 'name': that.name, 'size': 40 - }).appendTo(td); + }).appendTo(span); tr = $('<tr/>').appendTo(table); @@ -852,26 +1192,26 @@ function ipa_hbac_accesstime_widget(spec) { var value = field.save(dialog.container)[0]; var command = ipa_command({ - 'method': that.entity_name+'_add_'+that.name - }); - command.add_arg(pkey); - command.set_option(that.name, value); - - command.execute( - function() { - that.refresh(container); + 'method': that.entity_name+'_add_'+that.name, + 'args': [pkey], + 'on_success': function() { + that.refresh(that.container); if (on_success) on_success(); }, - function() { - that.refresh(container); + 'on_error': function() { + that.refresh(that.container); if (on_error) on_error(); } - ); + }); + + command.set_option(that.name, value); + + command.execute(); } dialog.add_button('Add', function() { add( - function() { dialog.clear(container); } + function() { dialog.clear(dialog.container); } ); }); @@ -888,12 +1228,12 @@ function ipa_hbac_accesstime_widget(spec) { dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.remove = function(container) { - var values = that.get_selected_values(); + var values = that.table.get_selected_values(); if (!values.length) { alert('Select '+that.label+' to be removed.'); @@ -909,64 +1249,53 @@ function ipa_hbac_accesstime_widget(spec) { }); dialog.remove = function() { - var batch = ipa_batch_command(); + + var batch = ipa_batch_command({ + 'on_success': function() { + that.refresh(that.container); + dialog.close(); + }, + 'on_error': function() { + that.refresh(that.container); + dialog.close(); + } + }); for (var i=0; i<values.length; i++) { var command = ipa_command({ - 'method': that.entity_name+'_remove_'+that.name + 'method': that.entity_name+'_remove_'+that.name, + 'args': [pkey] }); - command.add_arg(pkey); + command.set_option(that.name, values[i]); + batch.add_command(command); } - batch.execute( - function() { - that.refresh(container); - dialog.close(); - }, - function() { - that.refresh(container); - dialog.close(); - } - ); + batch.execute(); }; dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.refresh = function(container) { function on_success(data, text_status, xhr) { - - that.tbody.empty(); - - var column_name = that.columns[0].name; - var values = data.result.result[column_name]; - if (!values) return; - - for (var i = 0; i<values.length; i++){ - var record = that.get_record(data.result.result, i); - that.add_row(container, record); - } + that.load(that.container, data.result.result); } function on_error(xhr, text_status, error_thrown) { - var div = $('#'+that.id, container).empty(); - div.append('<p>Error: '+error_thrown.name+'</p>'); - div.append('<p>'+error_thrown.title+'</p>'); - div.append('<p>'+error_thrown.message+'</p>'); + var summary = $('span[name=summary]', that.table.tfoot).empty(); + summary.append('<p>Error: '+error_thrown.name+'</p>'); + summary.append('<p>'+error_thrown.title+'</p>'); + summary.append('<p>'+error_thrown.message+'</p>'); } var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; ipa_cmd('show', [pkey], {'rights': true}, on_success, on_error, that.entity_name); }; - that.save = function(container) { - return []; - }; - return that; } diff --git a/install/static/hbacsvc.js b/install/static/hbacsvc.js index 1ff5f0a86..a37c5dde2 100755 --- a/install/static/hbacsvc.js +++ b/install/static/hbacsvc.js @@ -69,8 +69,8 @@ function ipa_hbacsvc_add_dialog(spec) { this.superior_init(); - this.add_field(ipa_text_widget({name:'cn', label:'Name'})); - this.add_field(ipa_text_widget({name:'description', label:'Description'})); + this.add_field(ipa_text_widget({name:'cn', label:'Name', undo: false})); + this.add_field(ipa_text_widget({name:'description', label:'Description', undo: false})); }; return that; @@ -91,12 +91,6 @@ function ipa_hbacsvc_search_facet(spec) { that.create_column({name:'cn', label:'Service', primary_key: true}); that.create_column({name:'description', label:'Description'}); - that.create_column({ - name: 'quick_links', - label: 'Quick Links', - setup: ipa_hbacsvc_quick_links - }); - that.superior_init(); }; @@ -107,31 +101,29 @@ function ipa_hbacsvc_search_facet(spec) { // TODO: replace with IPA.metadata[that.entity_name].label $('<h2/>', { 'html': 'HBAC Services' }).appendTo(container); - var right_buttons = $('<li/>', { - 'style': 'float: right;' - }).appendTo($('.action-panel ul')); + var ul = $('.action-panel ul'); - right_buttons.append(ipa_button({ - 'label': 'HBAC Rules', + $('<li/>', { + title: 'hbac', + text: 'HBAC Rules', 'click': function() { var state = {}; state['entity'] = 'hbac'; nav_push_state(state); return false; } - })); + }).appendTo(ul); - right_buttons.append(ipa_button({ - 'label': 'HBAC Service Groups', + $('<li/>', { + title: 'hbacsvcgroup', + text: 'HBAC Service Groups', 'click': function() { var state = {}; state['entity'] = 'hbacsvcgroup'; nav_push_state(state); return false; } - })); - - container.append('<br/><br/>'); + }).appendTo(ul); that.superior_create(container); }; @@ -140,30 +132,6 @@ function ipa_hbacsvc_search_facet(spec) { } -function ipa_hbacsvc_quick_links(container, name, value, record) { - - var that = this; - - var pkey = IPA.metadata[that.entity_name].primary_key; - var pkey_value = record[pkey]; - - var link = $('<a/>', { - 'href': '#details', - 'title': 'Details', - 'text': 'Details', - 'click': function() { - var state = {}; - state[that.entity_name+'-facet'] = 'details'; - state[that.entity_name+'-pkey'] = pkey_value; - nav_push_state(state); - return false; - } - }); - - var span = $('span[name="'+name+'"]', container); - span.html(link); -} - function ipa_hbacsvc_details_facet(spec) { spec = spec || {}; @@ -176,10 +144,11 @@ function ipa_hbacsvc_details_facet(spec) { that.init = function() { - var section = that.create_section({ + var section = ipa_details_list_section({ 'name': 'general', 'label': 'General' }); + that.add_section(section); section.create_field({ 'name': 'cn', 'label': 'Name' }); section.create_field({ 'name': 'description', 'label': 'Description' }); diff --git a/install/static/hbacsvcgroup.js b/install/static/hbacsvcgroup.js index 979decdb7..3a3365559 100755 --- a/install/static/hbacsvcgroup.js +++ b/install/static/hbacsvcgroup.js @@ -80,8 +80,8 @@ function ipa_hbacsvcgroup_add_dialog(spec) { this.superior_init(); - this.add_field(ipa_text_widget({name:'cn', label:'Name'})); - this.add_field(ipa_text_widget({name:'description', label:'Description'})); + this.add_field(ipa_text_widget({name:'cn', label:'Name', undo: false})); + this.add_field(ipa_text_widget({name:'description', label:'Description', undo: false})); }; return that; @@ -102,12 +102,6 @@ function ipa_hbacsvcgroup_search_facet(spec) { that.create_column({name:'cn', label:'Group', primary_key: true}); that.create_column({name:'description', label:'Description'}); - that.create_column({ - name: 'quick_links', - label: 'Quick Links', - setup: ipa_hbacsvcgroup_quick_links - }); - that.superior_init(); }; @@ -118,31 +112,29 @@ function ipa_hbacsvcgroup_search_facet(spec) { // TODO: replace with IPA.metadata[that.entity_name].label $('<h2/>', { 'html': 'HBAC Service Groups' }).appendTo(container); - var right_buttons = $('<li/>', { - 'style': 'float: right;' - }).appendTo($('.action-panel ul')); + var ul = $('.action-panel ul'); - right_buttons.append(ipa_button({ - 'label': 'HBAC Rules', + $('<li/>', { + title: 'hbac', + text: 'HBAC Rules', 'click': function() { var state = {}; state['entity'] = 'hbac'; nav_push_state(state); return false; } - })); + }).appendTo(ul); - right_buttons.append(ipa_button({ - 'label': 'HBAC Services', + $('<li/>', { + title: 'hbacsvc', + text: 'HBAC Services', 'click': function() { var state = {}; state['entity'] = 'hbacsvc'; nav_push_state(state); return false; } - })); - - container.append('<br/><br/>'); + }).appendTo(ul); that.superior_create(container); }; @@ -151,30 +143,6 @@ function ipa_hbacsvcgroup_search_facet(spec) { } -function ipa_hbacsvcgroup_quick_links(container, name, value, record) { - - var that = this; - - var pkey = IPA.metadata[that.entity_name].primary_key; - var pkey_value = record[pkey]; - - var link = $('<a/>', { - 'href': '#details', - 'title': 'Details', - 'text': 'Details', - 'click': function() { - var state = {}; - state[that.entity_name+'-facet'] = 'details'; - state[that.entity_name+'-pkey'] = pkey_value; - nav_push_state(state); - return false; - } - }); - - var span = $('span[name="'+name+'"]', container); - span.html(link); -} - function ipa_hbacsvcgroup_details_facet(spec) { spec = spec || {}; @@ -187,10 +155,11 @@ function ipa_hbacsvcgroup_details_facet(spec) { that.init = function() { - var section = that.create_section({ + var section = ipa_details_list_section({ 'name': 'general', 'label': 'General' }); + that.add_section(section); section.create_field({ 'name': 'cn', 'label': 'Name' }); section.create_field({ 'name': 'description', 'label': 'Description' }); diff --git a/install/static/ipa.js b/install/static/ipa.js index ca4e958d3..ab69d5aa9 100644 --- a/install/static/ipa.js +++ b/install/static/ipa.js @@ -112,53 +112,58 @@ function ipa_command(spec) { spec = spec || {}; var that = {}; + that.method = spec.method; - that.params = spec.params || []; - that.params[0] = spec.args || []; - that.params[1] = spec.options || {}; + that.args = $.merge([], spec.args || []); + that.options = $.extend({}, spec.options || {}); - that.add_arg = function(arg) { - that.params[0].push(arg); - }; + that.on_success = spec.on_success; + that.on_error = spec.on_error; - that.get_args = function() { - return that.params[0]; + that.add_arg = function(arg) { + that.args.push(arg); }; that.set_option = function(name, value) { - that.params[1][name] = value; + that.options[name] = value; }; that.get_option = function(name) { - return that.params[1][name]; - }; - - that.get_options = function() { - return that.params[1]; + return that.options[name]; }; - that.execute = function(on_success, on_error) { + that.execute = function() { ipa_cmd( that.method, - that.get_args(), - that.get_options(), - on_success, - on_error + that.args, + that.options, + that.on_success, + that.on_error ); }; + that.to_json = function() { + var json = {}; + + json.method = that.method; + + json.params = []; + json.params[0] = that.args || []; + json.params[1] = that.options || {}; + + return json; + }; + that.to_string = function() { var string = that.method.replace(/_/g, '-'); - var args = that.get_args(); - for (var i=0; i<args.length; i++) { - string += ' '+args[i]; + for (var i=0; i<that.args.length; i++) { + string += ' '+that.args[i]; } - var options = that.get_options(); - for (var name in options) { - string += ' --'+name+'=\''+options[name]+'\''; + for (var name in that.options) { + string += ' --'+name+'=\''+that.options[name]+'\''; } return string; @@ -175,8 +180,59 @@ function ipa_batch_command(spec) { var that = ipa_command(spec); + that.commands = []; + that.add_command = function(command) { - that.add_arg(command); + that.commands.push(command); + that.add_arg(command.to_json()); + }; + + that.add_commands = function(commands) { + for (var i=0; i<commands.length; i++) { + that.add_command(commands[i]); + } + }; + + that.execute = function() { + ipa_cmd( + that.method, + that.args, + that.options, + function(data, text_status, xhr) { + for (var i=0; i<that.commands.length; i++) { + var command = that.commands[i]; + var result = data.result.results[i]; + + if (!result) { + if (command.on_error) command.on_error( + xhr, text_status, + { + title: 'Internal Error '+xhr.status, + message: result ? xhr.statusText : "Internal error" + } + ); + + } else if (result.error) { + if (command.on_error) command.on_error( + xhr, + text_status, + { + title: 'IPA Error '+result.error.code, + message: result.error.message + } + ); + + } else { + if (command.on_success) command.on_success(result, text_status, xhr); + } + } + if (that.on_success) that.on_success(data, text_status, xhr); + }, + function(xhr, text_status, error_thrown) { + // TODO: undefined behavior + if (that.on_error) that.on_error(xhr, text_status, error_thrown) + } + ); }; return that; @@ -207,7 +263,7 @@ function ipa_cmd(name, args, options, win_callback, fail_callback, objname) }, 'Cancel': function () { IPA.error_dialog.dialog('close'); - fail_callback.call(that, xhr, text_status, error_thrown); + if (fail_callback) fail_callback.call(that, xhr, text_status, error_thrown); } } }); diff --git a/install/static/layouts/default/hbac-details-accesstime.html b/install/static/layouts/default/hbac-details-accesstime.html index 4122c76a6..8d5e258b3 100755 --- a/install/static/layouts/default/hbac-details-accesstime.html +++ b/install/static/layouts/default/hbac-details-accesstime.html @@ -8,39 +8,42 @@ </head> <body> <div id="contents"> - Rule applies when access is being requested at: - <input type="radio" name="accesstime" value="all"/>Any Time - <input type="radio" name="accesstime" value=""/>Specified Times - <br/> + <span name="accesstime"> + <span name="text">Rule applies when access is being requested at:</span> + <input type="radio" name="accesstime" value="all"/>Any Time + <input type="radio" name="accesstime" value=""/>Specified Times + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + <br/> - <div id="hbac-accesstime"> - <table class="search-table"> - <thead> - <tr> - <th style="width: 25px;"> - <input type="checkbox" name="select"/> - </th> - <th> - <span style="float: left;">Access Time</span> - <span name="buttons" style="float: right;"> - <input type="button" name="remove" value="Remove Access Times"/> - <input type="button" name="add" value="Add Access Times"/> - </span> - </th> - </tr> - </thead> - <tbody> - <tr> - <td> - <input type="checkbox" name="select" value="time"/> - </td> - <td> - <span name="accesstime">time</span> - </td> - </tr> - </tbody> - </table> - </div> + <span name="table"> + <table class="search-table"> + <thead> + <tr> + <th style="width: 25px;"> + <input type="checkbox" name="select"/> + </th> + <th> + <span style="float: left;">Access Time</span> + <span name="buttons" style="float: right;"> + <input type="button" name="remove" value="Remove Access Times"/> + <input type="button" name="add" value="Add Access Times"/> + </span> + </th> + </tr> + </thead> + <tbody> + <tr> + <td> + <input type="checkbox" name="select" value="time"/> + </td> + <td> + <span name="accesstime">time</span> + </td> + </tr> + </tbody> + </table> + </span> + </span> </div> </body> </html>
\ No newline at end of file diff --git a/install/static/layouts/default/hbac-details-general.html b/install/static/layouts/default/hbac-details-general.html index 81b2a4ae6..978369090 100755 --- a/install/static/layouts/default/hbac-details-general.html +++ b/install/static/layouts/default/hbac-details-general.html @@ -14,12 +14,18 @@ Name: </td> <td> - <input type="text" name="cn" size="30"/> + <span name="cn"> + <input type="text" name="cn" size="30"/> + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> </td> <td style="text-align: right;"> Rule type: - <input type="radio" name="accessruletype" value="allow"/>Allow - <input type="radio" name="accessruletype" value="deny"/>Deny + <span name="accessruletype"> + <input type="radio" name="accessruletype" value="allow"/>Allow + <input type="radio" name="accessruletype" value="deny"/>Deny + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> </td> </tr> <tr> @@ -27,7 +33,10 @@ Description: </td> <td colspan="2"> - <textarea name="description" rows="5" style="width: 100%;" cols="40"></textarea> + <span name="description"> + <textarea name="description" rows="5" style="width: 100%;" cols="40"></textarea> + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> </td> </tr> <tr> @@ -35,8 +44,11 @@ Rule status: </td> <td colspan="2"> - <input type="radio" name="ipaenabledflag" value="TRUE"/>Active - <input type="radio" name="ipaenabledflag" value="FALSE"/>Inactive + <span name="ipaenabledflag"> + <input type="radio" name="ipaenabledflag" value="TRUE"/>Active + <input type="radio" name="ipaenabledflag" value="FALSE"/>Inactive + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> </td> </tr> </table> diff --git a/install/static/layouts/default/hbac-details-host.html b/install/static/layouts/default/hbac-details-host.html index a20e8115a..1ba386dab 100755 --- a/install/static/layouts/default/hbac-details-host.html +++ b/install/static/layouts/default/hbac-details-host.html @@ -9,11 +9,14 @@ <body> <div id="contents"> Rule applies when access is requested to: - <input type="radio" name="hostcategory" value="all"/>Any Host - <input type="radio" name="hostcategory" value=""/>Specified Hosts and Groups + <span name="hostcategory"> + <input type="radio" name="hostcategory" value="all"/>Any Host + <input type="radio" name="hostcategory" value=""/>Specified Hosts and Groups + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> <br/> - <div id="hbac-memberhost_host"> + <span name="memberhost_host"> <table class="search-table"> <thead> <tr> @@ -40,9 +43,9 @@ </tr> </tbody> </table> - </div> + </span> - <div id="hbac-memberhost_hostgroup"> + <span name="memberhost_hostgroup"> <table class="search-table"> <thead> <tr> @@ -69,7 +72,7 @@ </tr> </tbody> </table> - </div> + </span> </div> </body> </html>
\ No newline at end of file diff --git a/install/static/layouts/default/hbac-details-service.html b/install/static/layouts/default/hbac-details-service.html index 380cb1bb4..77e8420d3 100755 --- a/install/static/layouts/default/hbac-details-service.html +++ b/install/static/layouts/default/hbac-details-service.html @@ -9,11 +9,14 @@ <body> <div id="contents"> Rule applies when access is requested via: - <input type="radio" name="servicecategory" value="all"/>Any Service - <input type="radio" name="servicecategory" value=""/>Specified Services and Groups + <span name="servicecategory"> + <input type="radio" name="servicecategory" value="all"/>Any Service + <input type="radio" name="servicecategory" value=""/>Specified Services and Groups + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> <br/> - <div id="hbac-memberservice_hbacsvc"> + <span name="memberservice_hbacsvc"> <table class="search-table"> <thead> <tr> @@ -40,9 +43,9 @@ </tr> </tbody> </table> - </div> + </span> - <div id="hbac-memberservice_hbacsvcgroup"> + <span name="memberservice_hbacsvcgroup"> <table class="search-table"> <thead> <tr> @@ -69,7 +72,7 @@ </tr> </tbody> </table> - </div> + </span> </div> </body> </html>
\ No newline at end of file diff --git a/install/static/layouts/default/hbac-details-sourcehost.html b/install/static/layouts/default/hbac-details-sourcehost.html index 12e934c0d..aae1ef380 100755 --- a/install/static/layouts/default/hbac-details-sourcehost.html +++ b/install/static/layouts/default/hbac-details-sourcehost.html @@ -9,11 +9,14 @@ <body> <div id="contents"> Rule applies when access is being initiated from: - <input type="radio" name="sourcehostcategory" value="all"/>Any Host - <input type="radio" name="sourcehostcategory" value=""/>Specified Hosts and Groups + <span name="sourcehostcategory"> + <input type="radio" name="sourcehostcategory" value="all"/>Any Host + <input type="radio" name="sourcehostcategory" value=""/>Specified Hosts and Groups + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> <br/> - <div id="hbac-sourcehost_host"> + <span name="sourcehost_host"> <table class="search-table"> <thead> <tr> @@ -40,9 +43,9 @@ </tr> </tbody> </table> - </div> + </span> - <div id="hbac-sourcehost_hostgroup"> + <span name="sourcehost_hostgroup"> <table class="search-table"> <thead> <tr> @@ -69,7 +72,7 @@ </tr> </tbody> </table> - </div> + </span> </div> </body> </html>
\ No newline at end of file diff --git a/install/static/layouts/default/hbac-details-user.html b/install/static/layouts/default/hbac-details-user.html index ef41b6f8d..1b58848fe 100755 --- a/install/static/layouts/default/hbac-details-user.html +++ b/install/static/layouts/default/hbac-details-user.html @@ -9,11 +9,14 @@ <body> <div id="contents"> Rule applies when access is requested by: - <input type="radio" name="usercategory" value="all"/>Anyone - <input type="radio" name="usercategory" value=""/>Specified Users and Groups + <span name="usercategory"> + <input type="radio" name="usercategory" value="all"/>Anyone + <input type="radio" name="usercategory" value=""/>Specified Users and Groups + <span name="undo" class="ui-state-highlight ui-corner-all" style="display: none;">undo</span> + </span> <br/> - <div id="hbac-memberuser_user"> + <span name="memberuser_user"> <table class="search-table"> <thead> <tr> @@ -40,9 +43,9 @@ </tr> </tbody> </table> - </div> + </span> - <div id="hbac-memberuser_group"> + <span name="memberuser_group"> <table class="search-table"> <thead> <tr> @@ -69,7 +72,7 @@ </tr> </tbody> </table> - </div> + </span> </div> </body> </html>
\ No newline at end of file diff --git a/install/static/policy.js b/install/static/policy.js index 26af6aa18..c56e4d512 100644 --- a/install/static/policy.js +++ b/install/static/policy.js @@ -252,7 +252,7 @@ function ipa_records_facet(spec){ // that.setup_views(container); } - function setup(container, unspecified){ + function setup(container){ that.pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; that.record = $.bbq.getState(that.entity_name + '-record', true) || ''; @@ -515,5 +515,7 @@ ipa_entity_set_details_definition('krbtpolicy', [ input({name:'krbmaxticketlife', label:'Max Ticket Life'}) ]); +IPA.get_entity('krbtpolicy').default_facet = 'details'; + ipa_entity_set_association_definition('krbtpolicy', { }); diff --git a/install/static/search.js b/install/static/search.js index d187d6027..214208a27 100644 --- a/install/static/search.js +++ b/install/static/search.js @@ -29,14 +29,12 @@ function ipa_search_widget(spec) { var that = ipa_table_widget(spec); that.superior_create = that.superior('create'); - that.superior_setup = that.superior('setup'); that.create = function(container) { - var div = $('#'+that.id); var search_controls = $('<div/>', { 'class': 'search-controls' - }).appendTo(div); + }).appendTo(container); var search_filter = $('<span/>', { 'class': 'search-filter' @@ -70,16 +68,16 @@ function ipa_search_widget(spec) { search_controls.append('<span class="search-buttons"></span>'); - var search_results = $('<div/>', { + $('<div/>', { 'class': 'search-results' - }).appendTo(div); + }).appendTo(container); that.superior_create(container); }; that.setup = function(container) { - that.superior_setup(container); + that.table_setup(container); var filter = $.bbq.getState(that.entity_name + '-filter', true) || ''; this.filter.val(filter); @@ -97,7 +95,7 @@ function ipa_search_widget(spec) { var entity = IPA.get_entity(that.entity_name); var dialog = entity.get_dialog('add'); - dialog.open(container); + dialog.open(that.container); return false; }; @@ -115,12 +113,22 @@ function ipa_search_widget(spec) { var dialog = ipa_deleter_dialog({ 'title': title, - 'parent': container, + 'parent': that.container, 'values': values }); dialog.remove = function() { - var batch = ipa_batch_command(); + + var batch = ipa_batch_command({ + 'on_success': function() { + that.refresh(that.container); + dialog.close(); + }, + 'on_error': function() { + that.refresh(that.container); + dialog.close(); + } + }); for (var i=0; i<values.length; i++) { var command = ipa_command({ @@ -130,21 +138,12 @@ function ipa_search_widget(spec) { batch.add_command(command); } - batch.execute( - function() { - that.refresh(container); - dialog.close(); - }, - function() { - that.refresh(container); - dialog.close(); - } - ); + batch.execute(); }; dialog.init(); - dialog.open(container); + dialog.open(that.container); }; that.refresh = function(container) { @@ -156,7 +155,7 @@ function ipa_search_widget(spec) { var result = data.result.result; for (var i = 0; i<result.length; i++) { var record = that.get_record(result[i], 0); - that.add_row(container, record); + that.add_row(that.container, record); } var summary = $('span[name=summary]', that.tfoot); @@ -172,10 +171,10 @@ function ipa_search_widget(spec) { } function on_error(xhr, text_status, error_thrown) { - var search_results = $('.search-results', container); - search_results.append('<p>Error: '+error_thrown.name+'</p>'); - search_results.append('<p>'+error_thrown.title+'</p>'); - search_results.append('<p>'+error_thrown.message+'</p>'); + var summary = $('span[name=summary]', that.tfoot).empty(); + summary.append('<p>Error: '+error_thrown.name+'</p>'); + summary.append('<p>'+error_thrown.title+'</p>'); + summary.append('<p>'+error_thrown.message+'</p>'); } var filter = $.bbq.getState(that.entity_name + '-filter', true) || ''; @@ -246,7 +245,7 @@ function ipa_search_facet(spec) { that.table = ipa_search_widget({ 'id': that.entity_name+'-search', - 'name': that.entity_name, 'label': IPA.metadata[that.entity_name].label, + 'name': 'search', 'label': IPA.metadata[that.entity_name].label, 'entity_name': that.entity_name }); @@ -272,20 +271,20 @@ function ipa_search_facet(spec) { container.attr('title', that.entity_name); - $('<div/>', { - 'id': that.entity_name+'-search' - }).appendTo(container); + var span = $('<span/>', { 'name': 'search' }).appendTo(container); - that.table.create(container); + that.table.create(span); } - function setup(container, unspecified) { - that.table.setup(container); + function setup(container) { + var span = $('span[name=search]', container); + that.table.setup(span); } - function load(container, unspecified) { + function load(container) { that.filter = $.bbq.getState(that.entity_name + '-filter', true) || ''; - that.table.refresh(container); + var span = $('span[name=search]', container); + that.table.refresh(span); } if (spec.columns) { diff --git a/install/static/serverconfig.js b/install/static/serverconfig.js index 63c77d068..e793af34a 100644 --- a/install/static/serverconfig.js +++ b/install/static/serverconfig.js @@ -115,3 +115,5 @@ ipa_entity_set_details_definition('config',[ input({name:'ipasearchtimelimit', label:'Search Time Limit'}). input({name:'ipausersearchfields', label:'User Search Fields'}) ]); + +IPA.get_entity('config').default_facet = 'details'; diff --git a/install/static/service.js b/install/static/service.js index 86545cc0f..0b0adb82f 100644 --- a/install/static/service.js +++ b/install/static/service.js @@ -85,8 +85,18 @@ function ipa_service_add_dialog(spec) { label: 'Principal' })); - this.add_field(ipa_text_widget({name:'service', label:'Service'})); - this.add_field(ipa_text_widget({name:'host', label:'Host Name'})); + this.add_field(ipa_text_widget({ + 'name': 'service', 'label': 'Service', + 'size': 20, + 'undo': false + })); + + this.add_field(ipa_text_widget({ + 'name': 'host', + 'label': 'Host Name', + 'size': 40, + 'undo': false + })); }; that.create = function() { @@ -106,11 +116,8 @@ function ipa_service_add_dialog(spec) { 'style': 'vertical-align: top;' }).appendTo(tr); - $('<input/>', { - 'type': 'text', - 'name': 'service', - 'size': 20 - }).appendTo(td); + var span = $('<span/>', { 'name': 'service' }).appendTo(td); + field.create(span); field = that.get_field('host'); @@ -125,11 +132,8 @@ function ipa_service_add_dialog(spec) { 'style': 'vertical-align: top;' }).appendTo(tr); - $('<input/>', { - 'type': 'text', - 'name': 'host', - 'size': 40 - }).appendTo(td); + span = $('<span/>', { 'name': 'host' }).appendTo(td); + field.create(span); }; that.get_record = function() { @@ -176,7 +180,11 @@ function ipa_service_details_facet(spec) { that.init = function() { - var section = this.create_section({name:'details', label:'Service Details'}); + var section = ipa_details_list_section({ + name:'details', + label:'Service Details' + }); + that.add_section(section); section.create_field({ name: 'krbprincipalname', @@ -195,7 +203,11 @@ function ipa_service_details_facet(spec) { load: service_host_load }); - section = this.create_section({name:'provisioning', label:'Provisioning'}); + section = ipa_details_list_section({ + name:'provisioning', + label:'Provisioning' + }); + that.add_section(section); section.create_field({ name: 'provisioning_status', @@ -203,7 +215,11 @@ function ipa_service_details_facet(spec) { load: service_provisioning_status_load }); - section = this.create_section({name:'certificate', label:'Service Certificate'}); + section = ipa_details_list_section({ + name:'certificate', + label:'Service Certificate' + }); + that.add_section(section); section.create_field({ name: 'certificate_status', diff --git a/install/static/test/data/hbac_mod.json b/install/static/test/data/hbac_mod.json index ea090040a..ea2b4d1e8 100644 --- a/install/static/test/data/hbac_mod.json +++ b/install/static/test/data/hbac_mod.json @@ -1,12 +1,60 @@ { - "error": { - "code": 4202, - "kw": {}, - "message": "no modifications to be performed", - "name": { - "__base64__": "RW1wdHlNb2RsaXN0" - } - }, + "error": null, "id": 0, - "result": null + "result": { + "result": { + "accessruletype": [ + "allow" + ], + "attributelevelrights": { + "accessruletype": "rscwo", + "accesstime": "rscwo", + "aci": "rscwo", + "cn": "rscwo", + "description": "rscwo", + "externalhost": "rscwo", + "hostcategory": "rscwo", + "ipaenabledflag": "rscwo", + "ipauniqueid": "rsc", + "memberhost": "rscwo", + "memberservice": "rscwo", + "memberuser": "rscwo", + "nsaccountlock": "rscwo", + "servicecategory": "rscwo", + "sourcehost": "rscwo", + "sourcehostcategory": "rscwo", + "usercategory": "rscwo" + }, + "cn": [ + "test" + ], + "description": [ + "Test HBAC rule." + ], + "hostcategory": [ + "all" + ], + "ipaenabledflag": [ + "TRUE" + ], + "ipauniqueid": [ + "4ed8b682-edf511df-b3f78f4b-11cc007b" + ], + "objectclass": [ + "ipaassociation", + "ipahbacrule" + ], + "servicecategory": [ + "all" + ], + "sourcehostcategory": [ + "all" + ], + "usercategory": [ + "all" + ] + }, + "summary": null, + "value": "test" + } } diff --git a/install/static/test/data/hbac_show.json b/install/static/test/data/hbac_show.json index 183a52182..2c0b64b39 100644 --- a/install/static/test/data/hbac_show.json +++ b/install/static/test/data/hbac_show.json @@ -4,19 +4,41 @@ "result": { "result": { "accessruletype": [ - "allow" + "deny" ], "accesstime": [ "periodic daily 0800-1400", "absolute 201012161032 ~ 201012161033" ], + "attributelevelrights": { + "accessruletype": "rscwo", + "accesstime": "rscwo", + "aci": "rscwo", + "cn": "rscwo", + "description": "rscwo", + "externalhost": "rscwo", + "hostcategory": "rscwo", + "ipaenabledflag": "rscwo", + "ipauniqueid": "rsc", + "memberhost": "rscwo", + "memberservice": "rscwo", + "memberuser": "rscwo", + "nsaccountlock": "rscwo", + "servicecategory": "rscwo", + "sourcehost": "rscwo", + "sourcehostcategory": "rscwo", + "usercategory": "rscwo" + }, "cn": [ "test" ], - "dn": "ipauniqueid=e8aca082-e64a11df-9864f2e0-e0578392,cn=hbac,dc=dev,dc=example,dc=com", + "dn": "ipauniqueid=4ed8b682-edf511df-b3f78f4b-11cc007b,cn=hbac,dc=dev,dc=example,dc=com", "ipaenabledflag": [ "TRUE" ], + "ipauniqueid": [ + "4ed8b682-edf511df-b3f78f4b-11cc007b" + ], "memberhost_host": [ "dev.example.com" ], @@ -31,13 +53,16 @@ "sudo" ], "memberuser_group": [ - "admins", "editors" ], "memberuser_user": [ "admin", "test" ], + "objectclass": [ + "ipaassociation", + "ipahbacrule" + ], "sourcehost_host": [ "dev.example.com" ], diff --git a/install/static/test/details_tests.js b/install/static/test/details_tests.js index 80dbc3986..2bb9b9c66 100644 --- a/install/static/test/details_tests.js +++ b/install/static/test/details_tests.js @@ -34,7 +34,7 @@ test("Testing ipa_details_section.create().", function() { } ); - var section = ipa_details_section({name:'IDIDID', label:'NAMENAMENAME'}). + var section = ipa_details_list_section({name:'IDIDID', label:'NAMENAMENAME'}). input({name:'cn', label:'Entity Name'}). input({name:'description', label:'Description'}). input({name:'number', label:'Entity ID'}); @@ -168,7 +168,7 @@ test("Testing details lifecycle: create, setup, load.", function(){ var facet = entity.get_facet('details'); facet.create(container); facet.setup(container); - facet.load(container, result); + facet.display(result); var contact = container.find('dl#contact.entryattrs'); @@ -256,7 +256,7 @@ test("Testing _ipa_create_text_input() read only .", function(){ test("Testing ipa_details_section_setup again()",function(){ - var section = ipa_details_section({name: 'IDIDID', label: 'NAMENAMENAME'}). + var section = ipa_details_list_section({name: 'IDIDID', label: 'NAMENAMENAME'}). input({name:'cn', label:'Entity Name'}). input({name:'description', label:'Description'}). input({name:'number', label:'Entity ID'}); @@ -269,7 +269,7 @@ test("Testing ipa_details_section_setup again()",function(){ section.create(container); section.setup(container); - section.load(container, result); + section.load(result); ok(container.find('hr'),'hr'); @@ -278,14 +278,33 @@ test("Testing ipa_details_section_setup again()",function(){ //ok(h2[0].innerHTML.indexOf(section.label) > 1,"find name in html"); var dl = container.find('dl'); - ok(dl,'dl'); - same(dl[0].children.length,6,'6 children'); - same(dl[0].id, section.name); - same(dl[0].children[0].title, fields[0].name,'title matches name'); - same(dl[0].children[0].innerHTML, fields[0].label+":", - 'inner HTML matches label'); - same(dl[0].children[5].title, fields[2].name, - 'title matches fields[2] name'); + ok( + dl.length, + 'dl is created' + ); + + same( + dl[0].children.length, 3, + '3 spans' + ); + + same( + dl[0].id, section.name, + 'checking section name' + ); + same( + dl[0].children[0].children[0].title, fields[0].name, + 'title matches name' + ); + + same( + dl[0].children[0].children[0].innerHTML, fields[0].label+":", + 'inner HTML matches label' + ); + same( + dl[0].children[2].children[0].title, fields[2].name, + 'title matches fields[2] name' + ); }); diff --git a/install/static/widget.js b/install/static/widget.js index 741195504..84b1d9aeb 100755 --- a/install/static/widget.js +++ b/install/static/widget.js @@ -32,6 +32,8 @@ function ipa_widget(spec) { that.read_only = spec.read_only; that._entity_name = spec.entity_name; + that.undo = typeof spec.undo == 'undefined' ? true : spec.undo; + that.init = spec.init || init; that.create = spec.create || create; that.setup = spec.setup || setup; @@ -61,6 +63,7 @@ function ipa_widget(spec) { } function setup(container) { + this.container = container; } function load(container, result) { @@ -73,6 +76,41 @@ function ipa_widget(spec) { function clear(container) { } + that.is_dirty = function(container) { + if (!that.values) return true; + var values = that.save(that.container); + if (values.length != that.values.length) return true; + for (var i=0; i<values.length; i++) { + if (values[i] != that.values[i]) return true; + } + return false; + }; + + that.set_values = function(container, values) { + }; + + that.reset = function(container) { + that.hide_undo(that.container); + that.set_values(that.container, that.values); + }; + + that.get_undo = function(container) { + return $('span[name="undo"]', that.container); + }; + + that.show_undo = function(container) { + var undo = that.get_undo(that.container); + undo.css('display', 'inline'); + }; + + that.hide_undo = function(container) { + var undo = that.get_undo(that.container); + undo.css('display', 'none'); + }; + + // methods that should be invoked by subclasses + that.widget_setup = that.setup; + return that; } @@ -85,43 +123,74 @@ function ipa_text_widget(spec) { that.size = spec.size || 30; that.create = function(container) { + $('<input/>', { 'type': 'text', 'name': that.name, 'size': that.size }).appendTo(container); + + if (that.undo) { + $('<span/>', { + 'name': 'undo', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(container); + } + }; + + that.setup = function(container) { + + this.widget_setup(container); + + var input = $('input[name="'+that.name+'"]', that.container); + input.keyup(function() { + that.show_undo(that.container); + }); + + var undo = that.get_undo(that.container); + undo.click(function() { + that.reset(that.container); + }); }; that.load = function(container, result) { - that.value = result[that.name] || ''; - var input = $('input[name="'+that.name+'"]', container); - var param_info = ipa_get_param_info(that.entity_name, that.name); - if (param_info.primary_key) { - input.replaceWith($('<label/>', { 'html': that.value.toString() })); + that.values = result[that.name] || ['']; + + if (that.read_only) { + var input = $('input[name="'+that.name+'"]', that.container); + var label = $('<label/>', { + 'name': that.name, + 'html': that.values[0] + }); + input.replaceWith(label); } else { - input.val(that.value); + that.set_values(that.container, that.values); + that.hide_undo(that.container); } }; that.save = function(container) { - var values = []; - - if (that.value) { - values.push(that.value); - + if (that.read_only) { + return that.values; } else { - var input = $('input[name="'+that.name+'"]', container); - values.push(input.val()); + var value = $('input[name="'+that.name+'"]', that.container).val(); + return [value]; } + }; - return values; + that.set_values = function(container, values) { + if (that.read_only) { + $('label[name="'+that.name+'"]', that.container).val(values[0]); + } else { + $('input[name="'+that.name+'"]', that.container).val(values[0]); + } }; that.clear = function(container) { - var input = $('input[name="'+that.name+'"]', container); - input.val(''); + that.set_values(that.container, ['']); }; return that; @@ -134,29 +203,54 @@ function ipa_checkbox_widget(spec) { var that = ipa_widget(spec); that.create = function(container) { + $('<input/>', { 'type': 'checkbox', 'name': that.name }).appendTo(container); + + if (that.undo) { + $('<span/>', { + 'name': 'undo', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(container); + } + }; + + that.setup = function(container) { + + that.widget_setup(container); + + var input = $('input[name="'+that.name+'"]', that.container); + input.change(function() { + that.show_undo(that.container); + }); + + var undo = that.get_undo(that.container); + undo.click(function() { + that.reset(that.container); + }); }; that.load = function(container, result) { - var value = result[that.name] || ''; - $('input[name="'+that.name+'"][value="'+value+'"]', container).attr('checked', 'checked'); + that.values = result[that.name] || [false]; + that.set_values(that.container, that.values); + that.hide_undo(that.container); }; that.save = function(container) { - var values = []; - - var value = $('input[name="'+that.name+'"]', container).is(':checked'); - values.push(value); + var value = $('input[name="'+that.name+'"]', that.container).is(':checked'); + return [value]; + }; - return values; + that.set_values = function(container, values) { + var value = values && values.length ? values[0] : false; + $('input[name="'+that.name+'"]', that.container).get(0).checked = value; }; that.clear = function(container) { - var input = $('input[name="'+that.name+'"]', container).get(0); - input.checked = false; + $('input[name="'+that.name+'"]', that.container).get(0).checked = false; }; return that; @@ -168,18 +262,38 @@ function ipa_radio_widget(spec) { var that = ipa_widget(spec); + that.setup = function(container) { + + that.widget_setup(container); + + var input = $('input[name="'+that.name+'"]', that.container); + input.change(function() { + that.show_undo(that.container); + }); + + var undo = that.get_undo(that.container); + undo.click(function() { + that.reset(that.container); + }); + }; + that.load = function(container, result) { - var value = result[that.name] || ''; - $('input[name="'+that.name+'"][value="'+value+'"]', container).attr('checked', 'checked'); + that.values = result[that.name] || ['']; + that.set_values(that.container, that.values); + that.hide_undo(that.container); }; that.save = function(container) { - var values = []; + var value = $('input[name="'+that.name+'"]:checked', that.container).val(); + return [value]; + }; - var value = $('input[name="'+that.name+'"]:checked', container).val(); - values.push(value); + that.set_values = function(container, values) { + $('input[name="'+that.name+'"][value="'+values[0]+'"]', that.container).get(0).checked = true; + }; - return values; + that.clear = function(container) { + $('input[name="'+that.name+'"]', that.container).get().checked = false; }; return that; @@ -195,30 +309,54 @@ function ipa_textarea_widget(spec) { that.cols = spec.cols || 40; that.create = function(container) { + $('<textarea/>', { 'rows': that.rows, 'cols': that.cols, 'name': that.name }).appendTo(container); + + if (that.undo) { + $('<span/>', { + 'name': 'undo', + 'style': 'display: none;', + 'html': 'undo' + }).appendTo(container); + } + }; + + that.setup = function(container) { + + that.widget_setup(container); + + var input = $('textarea[name="'+that.name+'"]', that.container); + input.keyup(function() { + undo.css('display', 'inline'); + }); + + var undo = that.get_undo(that.container); + undo.click(function() { + that.reset(that.container); + }); }; that.load = function(container, result) { - var value = result[that.name] || ''; - $('textarea[name="'+that.name+'"]', container).val(value); + that.values = result[that.name] || ['']; + that.set_values(that.container, that.values); + that.hide_undo(that.container); }; that.save = function(container) { - var values = []; - - var value = $('textarea[name="'+that.name+'"]', container).val(); - values.push(value); + var value = $('textarea[name="'+that.name+'"]', that.container).val(); + return [value]; + }; - return values; + that.set_values = function(container, values) { + $('textarea[name="'+that.name+'"]', that.container).val(values[0]); }; that.clear = function(container) { - var input = $('input[name="'+that.name+'"]', container); - input.val(''); + that.set_values(that.container, ['']); }; return that; @@ -237,7 +375,10 @@ function ipa_button_widget(spec) { that.click = spec.click; function setup(container) { - var input = $('[name="'+that.name+'"]', container); + + that.widget_setup(container); + + var input = $('[name="'+that.name+'"]', that.container); input.replaceWith(ipa_button({ 'label': that.label, 'click': that.click })); } @@ -256,6 +397,7 @@ function ipa_column_widget(spec) { spec = spec || {}; + // TODO: should not inherit from widget var that = ipa_widget(spec); that.primary_key = spec.primary_key; @@ -302,11 +444,6 @@ function ipa_table_widget(spec) { spec = spec || {}; - spec.create = spec.create || create; - spec.setup = spec.setup || setup; - spec.load = spec.load || load; - spec.save = spec.save || save; - var that = ipa_widget(spec); that.add = spec.add; @@ -335,13 +472,11 @@ function ipa_table_widget(spec) { return column; }; - function create(container) { - - var div = $('#'+that.id, container); + that.create = function(container) { var table = $('<table/>', { 'class': 'search-table' - }).appendTo(div); + }).appendTo(container); var thead = $('<thead/>').appendTo(table); @@ -407,11 +542,13 @@ function ipa_table_widget(spec) { $('<span/>', { 'name': 'summary' }).appendTo(td); - } + }; - function setup(container) { - var div = $('#'+that.id, container); - that.table = $('table', div); + that.setup = function(container) { + + that.widget_setup(container); + + that.table = $('table', that.container); that.thead = $('thead', that.table); that.tbody = $('tbody', that.table); that.tfoot = $('tfoot', that.table); @@ -428,25 +565,11 @@ function ipa_table_widget(spec) { } }); - var button = $('input[name=remove]', that.table); - button.replaceWith(ipa_button({ - 'label': button.val(), - 'icon': 'ui-icon-trash', - 'click': function() { that.remove(container); } - })); - - button = $('input[name=add]', that.table); - button.replaceWith(ipa_button({ - 'label': button.val(), - 'icon': 'ui-icon-plus', - 'click': function() { that.add(container) } - })); - that.row = that.tbody.children().first(); that.row.detach(); - } + }; - function load(container, result) { + that.load = function(container, result) { that.tbody.empty(); @@ -455,11 +578,11 @@ function ipa_table_widget(spec) { for (var i=0; i<values.length; i++) { var record = that.get_record(result, i); - that.add_row(container, record); + that.add_row(that.container, record); } - } + }; - function save(container) { + that.save = function(container) { var values = []; $('input[name="select"]', that.tbody).each(function() { @@ -467,7 +590,7 @@ function ipa_table_widget(spec) { }); return values; - } + }; that.get_selected_values = function(container) { var values = []; @@ -513,28 +636,14 @@ function ipa_table_widget(spec) { that.refresh = function(container) { function on_success(data, text_status, xhr) { - - that.tbody.empty(); - - var column_name = that.columns[0].name; - var values = data.result.result[column_name]; - //TODO, this is masking an error where the wrong - //direction association is presented upon page reload. - //if the values is unset, it is because - //form.associationColumns[0] doesn't exist in the results - if (!values) return; - - for (var i = 0; i<values.length; i++){ - var record = that.get_record(data.result.result, i); - that.add_row(container, record); - } + that.load(that.container, data.result.result); } function on_error(xhr, text_status, error_thrown) { - var div = $('#'+that.id, container).empty(); - div.append('<p>Error: '+error_thrown.name+'</p>'); - div.append('<p>'+error_thrown.title+'</p>'); - div.append('<p>'+error_thrown.message+'</p>'); + that.container.empty(); + that.container.append('<p>Error: '+error_thrown.name+'</p>'); + that.container.append('<p>'+error_thrown.title+'</p>'); + that.container.append('<p>'+error_thrown.message+'</p>'); } var pkey = $.bbq.getState(that.entity_name + '-pkey', true) || ''; @@ -547,6 +656,9 @@ function ipa_table_widget(spec) { } } + // methods that should be invoked by subclasses + that.table_setup = that.setup; + return that; } @@ -627,7 +739,8 @@ function ipa_dialog(spec) { 'style': 'vertical-align: top;' }).appendTo(tr); - field.create(td); + var span = $('<span/>', { 'name': field.name }).appendTo(td); + field.create(span); } }; @@ -635,6 +748,12 @@ function ipa_dialog(spec) { * Setup behavior */ that.setup = function() { + for (var i=0; i<that.fields.length; i++) { + var field = that.fields[i]; + + var span = $('span[name="'+field.name+'"]', that.container); + field.setup(span); + } }; /** |