From 5f4f732dbc36caa5ab66ef329906972cac40ad87 Mon Sep 17 00:00:00 2001 From: Endi S. Dewata <edewata@redhat.com> Date: Sat, 13 Nov 2010 21:18:18 -0600 Subject: [PATCH] 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. --- install/static/associate.js | 65 ++- install/static/details.js | 256 ++++--- install/static/entity.js | 13 +- install/static/group.js | 8 +- install/static/hbac.js | 779 ++++++++++++++------ install/static/hbacsvc.js | 57 +-- install/static/hbacsvcgroup.js | 57 +-- install/static/ipa.js | 110 +++- .../layouts/default/hbac-details-accesstime.html | 67 +- .../layouts/default/hbac-details-general.html | 24 +- .../static/layouts/default/hbac-details-host.html | 15 +- .../layouts/default/hbac-details-service.html | 15 +- .../layouts/default/hbac-details-sourcehost.html | 15 +- .../static/layouts/default/hbac-details-user.html | 15 +- install/static/policy.js | 4 +- install/static/search.js | 67 +- install/static/serverconfig.js | 2 + install/static/service.js | 46 +- install/static/test/data/hbac_mod.json | 66 ++- install/static/test/data/hbac_show.json | 31 +- install/static/test/details_tests.js | 43 +- install/static/widget.js | 307 ++++++--- 22 files changed, 1354 insertions(+), 708 deletions(-) diff --git a/install/static/associate.js b/install/static/associate.js index eda85dc8cd961a495b15d30f9e504c656ad0e635..49325d703735fb9a37be5978567009b97c1adb4f 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,8 +257,7 @@ function ipa_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', @@ -276,7 +274,21 @@ function ipa_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); @@ -308,18 +320,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 +356,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 +386,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 +419,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 +450,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 612716c35f0ced14cd4eca3e4dba88aae4745150..49957a56d91646b18a9c1fe19229de7dc9f7b75e 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 3eafedc0adefe099aef0f0593493633c76475c30..74a07d009530ddf4edad12bf1c244dc15e52a060 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 2358cf1fb113cdfd34b6f6806d2e7eb41f509c60..f94a7deaba935796cc6f2aee7b6661da17299291 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 7a08db38d659a22890540f773c7be9381ccf759b..eb02bf738370e375f858eb72fbb9375974278036 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); - td.append('Deny'); + span.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); - td.append('Inactive'); + span.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); - var buttons = $('span[name=buttons]', div); + 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(' '); + + $('<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 1ff5f0a867100de0d8014a6bad92fe230cd8b919..a37c5dde22f3c24f4b7d03c38e57e40e2410bcb1 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 979decdb714db7c6dee77dabc73bd265697fde72..3a336555946c9ab70d63830988663b44e8eb9f59 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 ca4e958d35a35050627dd8ba3b55bb1822909562..ab69d5aa919288fd9abd016350cc262821b27cad 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.on_success = spec.on_success; + that.on_error = spec.on_error; that.add_arg = function(arg) { - that.params[0].push(arg); - }; - - that.get_args = function() { - return that.params[0]; + 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]; + return that.options[name]; }; - that.get_options = function() { - return that.params[1]; - }; - - 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 4122c76a6a8fd5f3ad216b604502dccc6c3f4e2d..8d5e258b3587b4c0336ef9c2fd4c5f593ce4e133 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 81b2a4ae6f35a069feef55cc29e03114de592cd8..978369090e6779c93cda93de003181d4cf271a23 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 a20e8115aa6d1c2abac2bc26013d5ee7778915bc..1ba386dab8954538b169bd87c9183d21368618c6 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 380cb1bb4a463f39ac5d43a75dae827f03218181..77e8420d334b326f70d167d52bf245806e8c6e4a 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 12e934c0d35644fc9f683a005806b78fa05cbf7b..aae1ef380c89c037b5dfe58ab757548b032260e1 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 ef41b6f8dc04a6c59170a4c10376b14b88743b9a..1b58848fe236c4c37054c05bcaf4807da0c12dff 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 26af6aa18c8176251ff95ed56fcf64a5d5df1ed0..c56e4d51282ebd7ae8840b86b223cfea1e9b7934 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 d187d6027f7accb3d6729efc6e60def0c1dc0b78..214208a27f607b9358fad36a5f5fa1c9970c0bf1 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 63c77d068a8f6bd1f3c25065d37b08b6204bd6b8..e793af34aa3fdf5435a55c7b2a547bd12f2c1b18 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 86545cc0f35b928c18734bc41c71150364448044..0b0adb82f4f0b35aea06346a693001169fbd44c2 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 ea090040a7397378c4e2fb2f96556225ef7f3e82..ea2b4d1e85670082481b59acc2cd27ba6f1c25a5 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 183a52182eff4434895e6e2a81e8aee1e97a988e..2c0b64b39cb213eae6587ee6191f91bb84883b72 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 80dbc3986b8d825b34b693f9b7f4da9a9a2e947a..2bb9b9c66d0330f1e06342b265db43955aa32b02 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 741195504d85619a51aba9bb537dc7744e29e3a0..84b1d9aeb342f7281cdadf0d9238b83b1b51bdf6 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+'"]', that.container).is(':checked'); + return [value]; + }; - var value = $('input[name="'+that.name+'"]', container).is(':checked'); - values.push(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+'"]', that.container).val(); + return [value]; + }; - var value = $('textarea[name="'+that.name+'"]', container).val(); - values.push(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); + } }; /** -- 1.6.6.1