Service and Host Provisioning

The service and host details pages have been modified to display Kerberos
key provisioning status and to provide a way to unprovision. The host
enrollment via OTP has not been implemented yet.

The ipa_details_field has been modified to remove any old <dd> tags it
created in the previous load operation. This is to support other widgets
that need to perform load operation without removing <dd> tags.

The certificate_status_panel has been converted into a widget. The host
entity has been rewritten using the new framework.

The unit tests has been updated.
This commit is contained in:
Endi S. Dewata
2010-11-16 18:10:40 -06:00
committed by Adam Young
parent b42271c47d
commit 5da8313b66
11 changed files with 787 additions and 351 deletions

View File

@@ -95,6 +95,7 @@ function ipa_add_dialog(spec) {
}; };
that.superior_init = that.superior('init'); that.superior_init = that.superior('init');
that.add_dialog_init = that.init;
return that; return that;
} }

View File

@@ -389,12 +389,13 @@ function certificate_request_dialog(spec) {
return that; return that;
} }
function certificate_status_panel(spec) { function certificate_status_widget(spec) {
var that = $('<div/>');
spec = spec || {}; spec = spec || {};
that.entity_type = spec.entity_type; var that = ipa_widget(spec);
that.entity_label = spec.entity_label || that.entity_type;
that.entity_label = spec.entity_label || that.entity_name;
that.result = spec.result; that.result = spec.result;
@@ -403,17 +404,16 @@ function certificate_status_panel(spec) {
that.get_entity_principal = spec.get_entity_principal; that.get_entity_principal = spec.get_entity_principal;
that.get_entity_certificate = spec.get_entity_certificate; that.get_entity_certificate = spec.get_entity_certificate;
var li1, li2, li3; that.create = function(container) {
function init() { that.widget_create(container);
var pkey = that.get_entity_pkey(that.result);
var table = $('<table/>').appendTo(that); var table = $('<table/>').appendTo(container);
var tr = $('<tr/>').appendTo(table); var tr = $('<tr/>').appendTo(table);
var td = $('<td/>').appendTo(tr); var td = $('<td/>').appendTo(tr);
li1 = $('<li/>', { $('<li/>', {
'class': 'certificate-status-valid' 'class': 'certificate-status-valid'
}).appendTo(td); }).appendTo(td);
@@ -421,46 +421,29 @@ function certificate_status_panel(spec) {
td.append('Valid Certificate Present:'); td.append('Valid Certificate Present:');
td = $('<td/>').appendTo(tr); td = $('<td/>').appendTo(tr);
ipa_button({
'id': 'get_button', $('<input/>', {
'label': 'Get', 'type': 'button',
'click': function() { 'name': 'get',
ipa_cmd(that.entity_type+'_show', [pkey], {}, 'value': 'Get'
function(data, text_status, xhr) {
get_certificate(data.result.result);
}
);
}
}).appendTo(td); }).appendTo(td);
ipa_button({ $('<input/>', {
'id': 'revoke_button', 'type': 'button',
'label': 'Revoke', 'name': 'revoke',
'click': function() { 'value': 'Revoke'
ipa_cmd(that.entity_type+'_show', [pkey], {},
function(data, text_status, xhr) {
revoke_certificate(data.result.result);
}
);
}
}).appendTo(td); }).appendTo(td);
ipa_button({ $('<input/>', {
'id': 'view_button', 'type': 'button',
'label': 'View', 'name': 'view',
'click': function() { 'value': 'View'
ipa_cmd(that.entity_type+'_show', [pkey], {},
function(data, text_status, xhr) {
view_certificate(data.result.result);
}
);
}
}).appendTo(td); }).appendTo(td);
tr = $('<tr/>').appendTo(table); tr = $('<tr/>').appendTo(table);
td = $('<td/>').appendTo(tr); td = $('<td/>').appendTo(tr);
li2 = $('<li/>', { $('<li/>', {
'class': 'certificate-status-revoked' 'class': 'certificate-status-revoked'
}).appendTo(td); }).appendTo(td);
@@ -469,26 +452,20 @@ function certificate_status_panel(spec) {
td = $('<td/>').appendTo(tr); td = $('<td/>').appendTo(tr);
td.append($('<span/>', { td.append($('<span/>', {
'id': 'revocation_reason' 'name': 'revocation_reason'
})); }));
td.append(' '); td.append(' ');
ipa_button({ $('<input/>', {
'id': 'restore_button', 'type': 'button',
'label': 'Restore', 'name': 'restore',
'click': function() { 'value': 'Restore'
ipa_cmd(that.entity_type+'_show', [pkey], {},
function(data, text_status, xhr) {
restore_certificate(data.result.result);
}
);
}
}).appendTo(td); }).appendTo(td);
tr = $('<tr/>').appendTo(table); tr = $('<tr/>').appendTo(table);
td = $('<td/>').appendTo(tr); td = $('<td/>').appendTo(tr);
li3 = $('<li/>', { $('<li/>', {
'class': 'certificate-status-missing' 'class': 'certificate-status-missing'
}).appendTo(td); }).appendTo(td);
@@ -496,13 +473,89 @@ function certificate_status_panel(spec) {
td.append('No Valid Certificate:'); td.append('No Valid Certificate:');
td = $('<td/>').appendTo(tr); td = $('<td/>').appendTo(tr);
ipa_button({ $('<input/>', {
'id': 'create_button', 'type': 'button',
'name': 'create',
'value': 'New Certificate'
}).appendTo(td);
};
that.setup = function(container) {
that.container = container;
that.valid = $('li.certificate-status-valid', that.container);
that.revoked = $('li.certificate-status-revoked', that.container);
that.missing = $('li.certificate-status-missing', that.container);
var button = $('input[name=get]', that.container);
that.get_button = ipa_button({
'label': 'Get',
'click': function() {
ipa_cmd(that.entity_name+'_show', [that.pkey], {},
function(data, text_status, xhr) {
get_certificate(data.result.result);
}
);
}
});
button.replaceWith(that.get_button);
button = $('input[name=revoke]', that.container);
that.revoke_button = ipa_button({
'label': 'Revoke',
'click': function() {
ipa_cmd(that.entity_name+'_show', [that.pkey], {},
function(data, text_status, xhr) {
revoke_certificate(data.result.result);
}
);
}
});
button.replaceWith(that.revoke_button);
button = $('input[name=view]', that.container);
that.view_button = ipa_button({
'label': 'View',
'click': function() {
ipa_cmd(that.entity_name+'_show', [that.pkey], {},
function(data, text_status, xhr) {
view_certificate(data.result.result);
}
);
}
});
button.replaceWith(that.view_button);
that.revocation_reason = $('span[name=revocation_reason]', that.container);
button = $('input[name=restore]', that.container);
that.restore_button = ipa_button({
'label': 'Restore',
'click': function() {
ipa_cmd(that.entity_name+'_show', [that.pkey], {},
function(data, text_status, xhr) {
restore_certificate(data.result.result);
}
);
}
});
button.replaceWith(that.restore_button);
button = $('input[name=create]', that.container);
that.create_button = ipa_button({
'label': 'New Certificate', 'label': 'New Certificate',
'click': function() { 'click': function() {
request_certificate(that.result); request_certificate(that.result);
} }
}).appendTo(td); });
button.replaceWith(that.create_button);
};
that.load = function(container, result) {
that.result = result;
that.pkey = that.get_entity_pkey(that.result);
var entity_certificate = that.get_entity_certificate(that.result); var entity_certificate = that.get_entity_certificate(that.result);
if (entity_certificate) { if (entity_certificate) {
@@ -510,18 +563,18 @@ function certificate_status_panel(spec) {
} else { } else {
set_status(CERTIFICATE_STATUS_MISSING); set_status(CERTIFICATE_STATUS_MISSING);
} }
} };
function set_status(status, revocation_reason) { function set_status(status, revocation_reason) {
li1.toggleClass('certificate-status-active', status == CERTIFICATE_STATUS_VALID); that.valid.toggleClass('certificate-status-active', status == CERTIFICATE_STATUS_VALID);
li2.toggleClass('certificate-status-active', status == CERTIFICATE_STATUS_REVOKED); that.revoked.toggleClass('certificate-status-active', status == CERTIFICATE_STATUS_REVOKED);
li3.toggleClass('certificate-status-active', status == CERTIFICATE_STATUS_MISSING); that.missing.toggleClass('certificate-status-active', status == CERTIFICATE_STATUS_MISSING);
$('#get_button', that).css('visibility', status == CERTIFICATE_STATUS_VALID ? 'visible' : 'hidden'); that.get_button.css('visibility', status == CERTIFICATE_STATUS_VALID ? 'visible' : 'hidden');
$('#revoke_button', that).css('visibility', status == CERTIFICATE_STATUS_VALID ? 'visible' : 'hidden'); that.revoke_button.css('visibility', status == CERTIFICATE_STATUS_VALID ? 'visible' : 'hidden');
$('#view_button', that).css('visibility', status == CERTIFICATE_STATUS_VALID ? 'visible' : 'hidden'); that.view_button.css('visibility', status == CERTIFICATE_STATUS_VALID ? 'visible' : 'hidden');
$('#revocation_reason', that).html(revocation_reason == undefined ? '' : CRL_REASON[revocation_reason]); that.revocation_reason.html(revocation_reason == undefined ? '' : CRL_REASON[revocation_reason]);
$('#restore_button', that).css('visibility', revocation_reason == 6 ? 'visible' : 'hidden'); that.restore_button.css('visibility', revocation_reason == 6 ? 'visible' : 'hidden');
} }
function check_status(serial_number) { function check_status(serial_number) {
@@ -668,7 +721,5 @@ function certificate_status_panel(spec) {
dialog.open(); dialog.open();
} }
init();
return that; return that;
} }

View File

@@ -39,38 +39,20 @@ function ipa_details_field(spec) {
var that = ipa_widget(spec); var that = ipa_widget(spec);
that.create = spec.create || create;
that.load = spec.load || load; that.load = spec.load || load;
that.save = spec.save || save; that.save = spec.save || save;
function create(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(container);
}
function load(container, result) { function load(container, result) {
that.values = result[that.name];
/* remove all <dd> tags i.e. all attribute values */
$('dd', that.container).remove();
var multivalue = false; var multivalue = false;
var hint_span = null; var hint_span = null;
var dd; var dd;
var dt = $('dt[title='+that.name+']', container);
if (!dt.length) return;
var param_info = ipa_get_param_info(that.entity_name, that.name); var param_info = ipa_get_param_info(that.entity_name, that.name);
if (param_info) { if (param_info) {
if (param_info['multivalue'] || param_info['class'] == 'List') if (param_info['multivalue'] || param_info['class'] == 'List')
@@ -83,44 +65,39 @@ function ipa_details_field(spec) {
} }
} }
var value = result[that.name];
var rights = 'rsc'; var rights = 'rsc';
if (result.attributelevelrights){ if (result.attributelevelrights){
rights = result.attributelevelrights[this.name] || rights ; rights = result.attributelevelrights[this.name] || rights ;
} }
if (value) {
dd = ipa_create_first_dd( if (that.values) {
that.name,ipa_create_input( dd = ipa_create_first_dd(that.name);
that.entity_name, that.name, value[0],hint_span,rights) dd.append(ipa_details_field_create_input.call(that, that.values[0], hint_span, rights, 0));
); dd.appendTo(that.container);
dt.after(dd);
var last_dd = dd; for (var i = 1; i < that.values.length; ++i) {
for (var i = 1; i < value.length; ++i) { dd = ipa_create_other_dd(that.name);
dd = ipa_create_other_dd( dd.append(ipa_details_field_create_input.call(that, that.values[i], hint_span, rights, i));
that.name, ipa_create_input(that.entity_name, that.name, dd.appendTo(that.container);
value[i],hint_span,rights)
);
last_dd.after(dd);
last_dd = dd;
} }
if (multivalue && IPA.is_field_writable(rights) ) { if (multivalue && IPA.is_field_writable(rights) ) {
dd = ipa_create_other_dd( dd = ipa_create_other_dd(that.name);
that.name, _ipa_a_add_template.replace('A', that.name) dd.append(ipa_details_field_create_add_link.call(that, that.name, rights, that.values.length));
); dd.appendTo(that.container);
last_dd.after(dd);
} }
} else { } else {
if (multivalue && IPA.is_field_writable(rights)) { if (multivalue && IPA.is_field_writable(rights)) {
dd = ipa_create_first_dd( dd = ipa_create_first_dd(that.name);
that.name, _ipa_a_add_template.replace('A', that.name) dd.append(ipa_details_field_create_add_link.call(that, that.name, rights, 0));
); dd.appendTo(that.container);
dt.after(dd);
} else { } else {
dd = ipa_create_first_dd( dd = ipa_create_first_dd(that.name);
that.name, ipa_create_input( dd.append(ipa_details_field_create_input.call(that, '', hint_span, rights, 0));
that.entity_name, that.name,'',hint_span,rights) dd.appendTo(that.container);
);
dt.after(dd);
} }
} }
} }
@@ -128,8 +105,8 @@ function ipa_details_field(spec) {
function save(container) { function save(container) {
var values = []; var values = [];
var dd = $('dd[title='+that.name+']', container); $('dd', that.container).each(function () {
dd.each(function () {
var input = $('input', $(this)); var input = $('input', $(this));
if (!input.length) return; if (!input.length) return;
@@ -298,6 +275,30 @@ function ipa_details_section(spec){
return that; return that;
} }
/**
* This class creates a details section formatted as a list of
* attributes names and values. The list is defined using <dl> tag.
* The attribute name is defined inside a <dt> tag. The attribute
* value is defined using a <dd> tag inside a <span> tag. If the
* attribute has multiple values the content inside <span> will
* be duplicated to display each value.
*
* Example:
* <dl class="entryattrs">
*
* <dt title="givenname">First Name:</dt>
* <span name="givenname">
* <dd><input type="text" size="20"/></dd>
* </span>
*
* <dt title="telephonenumber">Telephone Number:</dt>
* <span name="telephonenumber">
* <dd><input type="text" size="20"/></dd>
* <dd><input type="text" size="20"/></dd>
* </span>
*
* </dl>
*/
function ipa_details_list_section(spec){ function ipa_details_list_section(spec){
spec = spec || {}; spec = spec || {};
@@ -319,34 +320,20 @@ function ipa_details_list_section(spec){
for (var i = 0; i < fields.length; ++i) { for (var i = 0; i < fields.length; ++i) {
var field = fields[i]; var field = fields[i];
var label = field.label;
var param_info = ipa_get_param_info(that.entity_name, field.name);
if (param_info && param_info['label']) label = param_info['label'];
$('<dt/>', {
html: label + ':'
}).appendTo(dl);
var span = $('<span/>', { 'name': field.name }).appendTo(dl); var span = $('<span/>', { 'name': field.name }).appendTo(dl);
field.create(span); 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. // Deprecated: Used for backward compatibility only.
function input(spec){ function input(spec){
that.create_field(spec); that.create_field(spec);
@@ -415,6 +402,8 @@ function ipa_details_facet(spec) {
} }
}; };
that.details_facet_init = that.init;
return that; return that;
} }
@@ -621,8 +610,6 @@ function ipa_details_update(container, pkey, on_win, on_fail)
/* HTML templates for ipa_details_display() */ /* HTML templates for ipa_details_display() */
var _ipa_a_add_template =
'<a href="jslink" onclick="return (_ipa_add_on_click(this))" title="A">Add</a>';
var _ipa_span_doc_template = '<span class="attrhint">Hint: D</span>'; var _ipa_span_doc_template = '<span class="attrhint">Hint: D</span>';
var _ipa_span_hint_template = '<span class="attrhint">Hint: D</span>'; var _ipa_span_hint_template = '<span class="attrhint">Hint: D</span>';
@@ -641,10 +628,12 @@ function ipa_details_display(result)
function ipa_create_first_dd(field_name, content){ function ipa_create_first_dd(field_name, content){
return $('<dd/>', { var dd = $('<dd/>', {
'class': 'first', 'class': 'first',
'title': field_name 'title': field_name
}).append(content); });
if (content) dd.append(content);
return dd;
} }
function ipa_create_other_dd(field_name, content){ function ipa_create_other_dd(field_name, content){
@@ -678,13 +667,15 @@ var _ipa_param_type_2_handler_map = {
* arguments: * arguments:
* attr - LDAP attribute name * attr - LDAP attribute name
* value - the attributes value */ * value - the attributes value */
function ipa_create_input(entity_name, attr, value,hint,rights) function ipa_details_field_create_input(value,hint,rights, index)
{ {
var that = this;
var input = $("<label>",{html:value.toString()}); var input = $("<label>",{html:value.toString()});
var param_info = ipa_get_param_info(entity_name, attr); var param_info = ipa_get_param_info(that.entity_name, that.name);
if (!param_info) { if (!param_info) {
/* no information about the param is available, default to text input */ /* no information about the param is available, default to text input */
input = _ipa_create_text_input(attr, value, null,rights); input = _ipa_create_text_input.call(that, value, null, rights, index);
if (hint){ if (hint){
input.after(hint); input.after(hint);
} }
@@ -697,11 +688,11 @@ function ipa_create_input(entity_name, attr, value,hint,rights)
/* call handler by param class */ /* call handler by param class */
var handler = _ipa_param_type_2_handler_map[param_info['class']]; var handler = _ipa_param_type_2_handler_map[param_info['class']];
if (handler) { if (handler) {
input = handler(attr, value, param_info,rights); input = handler.call(that, value, param_info, rights, index);
if ((param_info['multivalue'] || if ((param_info['multivalue'] ||
param_info['class'] == 'List') && param_info['class'] == 'List') &&
IPA.is_field_writable(rights)){ IPA.is_field_writable(rights)){
input.append( _ipa_create_remove_link(attr, param_info)); input.append( _ipa_create_remove_link(that.name, param_info));
} }
if (hint){ if (hint){
input.after(hint); input.after(hint);
@@ -733,22 +724,10 @@ function _ipa_create_remove_link(attr, param_info)
/* creates a input box for editing a string attribute */ /* creates a input box for editing a string attribute */
function _ipa_create_text_input(attr, value, param_info, rights) function _ipa_create_text_input(value, param_info, rights, index)
{ {
var that = this;
function calculate_dd_index(jobj){ index = index || 0;
var index = 0;
var dd = jobj.parents('dd').slice(0, 1)[0];
dd = dd.previousElementSibling;
while(dd.nodeName.toUpperCase() === 'DD'){
dd = dd.previousElementSibling;
index += 1;
if (index > 100 )
break;
}
return index;
}
function validate_input(text, param_info,error_link){ function validate_input(text, param_info,error_link){
if(param_info && param_info.pattern){ if(param_info && param_info.pattern){
@@ -766,9 +745,9 @@ function _ipa_create_text_input(attr, value, param_info, rights)
var span = $("<Span />"); var span = $("<Span />");
var input = $("<input/>",{ var input = $("<input/>",{
type:"text", type: "text",
name:attr, name: that.name,
value:value.toString(), value: value.toString(),
keyup: function(){ keyup: function(){
var undo_link=this.nextElementSibling; var undo_link=this.nextElementSibling;
undo_link.style.display ="inline"; undo_link.style.display ="inline";
@@ -788,13 +767,7 @@ function _ipa_create_text_input(attr, value, param_info, rights)
"class":"ui-state-highlight ui-corner-all", "class":"ui-state-highlight ui-corner-all",
style:"display:none", style:"display:none",
click: function(){ click: function(){
var key = this.previousElementSibling.name; var previous_value = that.values || '';
var entity_divs = $(this).parents('.entity-container');
var entry_attrs = ipa_details_cache[entity_divs[0].id];
index = calculate_dd_index($(this));
var previous_value = entry_attrs[key] || "";
if (index >= previous_value.length){ if (index >= previous_value.length){
previous_value = ''; previous_value = '';
}else{ }else{
@@ -830,31 +803,35 @@ function ipa_details_reset(container)
} }
} }
/* Event handlers */ function ipa_details_field_create_add_link(title, rights, index) {
function _ipa_add_on_click(obj) var that = this;
{
var jobj = $(obj);
var attr = jobj.attr('title');
var par = jobj.parent();
var obj_name = jobj.closest('.entity-container').attr('title');
var param_info = ipa_get_param_info(obj_name, ''); var link = $('<a/>', {
//TODO rights need to be inherited 'href': 'jslink',
//And used to control presnece of the add link 'title': title,
var input = _ipa_create_text_input(attr, '', param_info, 'rswco'); 'html': 'Add',
'click': function () {
par.prepend(input); var param_info = ipa_get_param_info(that.entity_name, '');
jobj.next('input').focus(); var input = _ipa_create_text_input.call(that, '', param_info, rights, index);
jobj.remove();
par.after( ipa_create_other_dd(attr,_ipa_a_add_template.replace('A', attr)));
return (false); link.replaceWith(input);
input.focus();
var dd = ipa_create_other_dd(that.name);
dd.append(ipa_details_field_create_add_link.call(that, that.name, rights, index+1));
dd.appendTo(that.container);
return false;
}
});
return link;
} }
function _ipa_remove_on_click(obj) function _ipa_remove_on_click(obj)
{ {
var jobj = $(obj); var jobj = $(obj);

View File

@@ -142,6 +142,8 @@ function ipa_entity(spec) {
} }
}; };
that.entity_init = that.init;
return that; return that;
} }

View File

@@ -20,67 +20,332 @@
/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */ /* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
ipa_entity_set_search_definition('host', [ function ipa_host() {
['fqdn', 'Name', null],
['description', 'Description', null],
['enrolled', 'Enrolled?', null],
['manages', 'Manages?', null]
]);
ipa_entity_set_add_definition('host', [ var that = ipa_entity({
'dialog-add-host', 'Add New Host', [ 'name': 'host'
['fqdn', 'Name', null] });
]
]);
ipa_entity_set_details_definition('host', [ that.init = function() {
ipa_stanza({name:'details', label:'Host Details'}).
input({name:'fqdn', label:'Fully Qualified Domain Name'}).
input({name:'krbprincipalname', label:'Kerberos Principal'}).
input({name:'serverhostname', label:'Server Host Name'}),
ipa_stanza({name:'enrollment', label:'Enrollment'}).
input({name:'enrollment_status', label:'Status',
load:host_enrollment_status_load}),
ipa_stanza({name:'certificate', label:'Host Certificate'}).
input({name:'certificate_status', label:'Status',
load:host_usercertificate_load})
]);
ipa_entity_set_association_definition('host', { that.create_association({
'hostgroup': { associator: 'serial' }, 'name': 'hostgroup',
'rolegroup': { associator: 'serial' } 'associator': 'serial'
}); });
function host_enrollment_status_load(container, result) { that.create_association({
// skip enrollment_status 'name': 'rolegroup',
'associator': 'serial'
});
var dialog = ipa_host_add_dialog({
'name': 'add',
'title': 'Add New Host'
});
that.add_dialog(dialog);
dialog.init();
var facet = ipa_host_search_facet({
'name': 'search',
'label': 'Search'
});
that.add_facet(facet);
facet = ipa_host_details_facet({
'name': 'details',
'label': 'Details'
});
that.add_facet(facet);
facet = ipa_association_facet({
'name': 'associate'
});
that.add_facet(facet);
that.entity_init();
};
return that;
} }
function host_usercertificate_load(container, result) { IPA.add_entity(ipa_host());
var dt = $('dt[title='+this.name+']', container); function ipa_host_add_dialog(spec) {
if (!dt.length) return;
var panel = certificate_status_panel({ spec = spec || {};
'entity_type': 'host',
'entity_label': 'Host', var that = ipa_add_dialog(spec);
'result': result,
'get_entity_pkey': function(result) { that.init = function() {
that.add_dialog_init();
that.add_field(ipa_text_widget({
'name': 'fqdn',
'label': 'Name',
'size': 40,
'undo': false
}));
};
return that;
}
function ipa_host_search_facet(spec) {
spec = spec || {};
var that = ipa_search_facet(spec);
that.init = function() {
this.create_column({name:'fqdn', label:'Name'});
this.create_column({name:'description', label:'Description'});
this.create_column({name:'enrolled', label:'Enrolled?'});
this.create_column({name:'manages', label:'Manages?'});
that.search_facet_init();
};
return that;
}
function ipa_host_details_facet(spec) {
spec = spec || {};
var that = ipa_details_facet(spec);
that.init = function() {
var section = ipa_details_list_section({
name: 'details',
label: 'Host Details'
});
that.add_section(section);
section.create_field({
name: 'fqdn',
label: 'Fully Qualified Domain Name'
});
section.create_field({
name: 'krbprincipalname',
label: 'Kerberos Principal'
});
section.create_field({
name: 'serverhostname',
label: 'Server Host Name'
});
section = ipa_details_list_section({
name: 'enrollment',
label: 'Enrollment'
});
that.add_section(section);
section.add_field(host_provisioning_status_widget({
name: 'provisioning_status',
label: 'Status'
}));
section = ipa_details_list_section({
name:'certificate',
label:'Host Certificate'
});
that.add_section(section);
section.add_field(host_certificate_status_widget({
name: 'certificate_status',
label: 'Status'
}));
that.details_facet_init();
};
return that;
}
function host_provisioning_status_widget(spec) {
spec = spec || {};
var that = ipa_widget(spec);
that.create = function(container) {
that.widget_create(container);
var table = $('<table/>').appendTo(container);
var tr = $('<tr/>').appendTo(table);
var td = $('<td/>').appendTo(tr);
var li = $('<li/>', {
'class': 'key-status-valid'
}).appendTo(td);
td = $('<td/>').appendTo(tr);
td.append('Kerberos Key Present, Host Provisioned:');
td = $('<td/>').appendTo(tr);
$('<input/>', {
'type': 'button',
'name': 'unprovision',
'value': 'Delete Key, Unprovision'
}).appendTo(td);
tr = $('<tr/>').appendTo(table);
td = $('<td/>').appendTo(tr);
li = $('<li/>', {
'class': 'key-status-missing'
}).appendTo(td);
td = $('<td/>').appendTo(tr);
td.append('Kerberos Key Not Present');
td = $('<td/>').appendTo(tr);
tr = $('<tr/>').appendTo(table);
td = $('<td/>').appendTo(tr);
td = $('<td/>').appendTo(tr);
td.append('Enroll via One-Time-Password:');
td = $('<td/>').appendTo(tr);
$('<input/>', {
'type': 'text',
'name': 'otp',
'size': 10
}).appendTo(td);
$('<input/>', {
'type': 'button',
'name': 'enroll',
'value': 'Set OTP'
}).appendTo(td);
};
that.setup = function(container) {
that.container = container;
that.valid = $('li.key-status-valid', that.container);
that.missing = $('li.key-status-missing', that.container);
var button = $('input[name=unprovision]', that.container);
that.unprovision_button = ipa_button({
'label': 'Delete Key, Unprovision',
'click': that.unprovision
});
button.replaceWith(that.unprovision_button);
that.otp_input = $('input[name=otp]', that.container);
that.enroll_button = $('input[name=enroll]', that.container);
button = ipa_button({
'label': 'Set OTP',
'click': that.set_otp
});
that.enroll_button.replaceWith(button);
that.enroll_button = button;
};
that.unprovision = function() {
var label = IPA.metadata[that.entity_name].label;
var dialog = ipa_dialog({
'title': 'Unprovisioning '+label
});
dialog.create = function() {
dialog.container.append(
'To confirm your intention to unprovision this host, '+
'click the "Unprovision" button.');
};
dialog.add_button('Unprovision', function() {
var pkey = that.result['fqdn'][0];
ipa_cmd(that.entity_name+'_disable', [pkey], {},
function(data, text_status, xhr) {
set_status('missing');
dialog.close();
},
function(xhr, text_status, error_thrown) {
dialog.close();
}
);
});
dialog.add_button('Cancel', function() {
dialog.close();
});
dialog.init();
dialog.open(that.container);
return false;
};
that.set_otp = function() {
// TODO: enroll via OTP
alert(that.otp.val());
};
that.load = function(container, result) {
that.result = result;
var krblastpwdchange = result['krblastpwdchange'];
set_status(krblastpwdchange ? 'valid' : 'missing');
};
function set_status(status) {
that.valid.toggleClass('key-status-active', status == 'valid');
that.missing.toggleClass('key-status-active', status == 'missing');
that.unprovision_button.css('visibility', status == 'valid' ? 'visible' : 'hidden');
that.otp_input.css('visibility', status == 'missing' ? 'visible' : 'hidden');
that.enroll_button.css('visibility', status == 'missing' ? 'visible' : 'hidden');
}
return that;
}
function host_certificate_status_widget(spec) {
spec = spec || {};
var that = certificate_status_widget(spec);
that.init = function() {
that.entity_label = IPA.metadata[that.entity_name].label;
that.get_entity_pkey = function(result) {
var values = result['fqdn']; var values = result['fqdn'];
return values ? values[0] : null; return values ? values[0] : null;
}, };
'get_entity_name': function(result) {
return this.get_entity_pkey(result); that.get_entity_name = function(result) {
}, return that.get_entity_pkey(result);
'get_entity_principal': function(result) { };
that.get_entity_principal = function(result) {
var values = result['krbprincipalname']; var values = result['krbprincipalname'];
return values ? values[0] : null; return values ? values[0] : null;
}, };
'get_entity_certificate': function(result) {
that.get_entity_certificate = function(result) {
var values = result['usercertificate']; var values = result['usercertificate'];
return values ? values[0].__base64__ : null; return values ? values[0].__base64__ : null;
} }
}); };
var dd = ipa_create_first_dd(this.name, panel); return that;
dt.after(dd);
} }

View File

@@ -411,6 +411,20 @@ span.main-separator{
.strikethrough { text-decoration: line-through; } .strikethrough { text-decoration: line-through; }
.key-status-valid {
list-style-type: circle;
color: #008000;
}
.key-status-missing {
list-style-type: circle;
color: #daa520;
}
.key-status-active {
list-style-type: disc;
}
.certificate-status-valid { .certificate-status-valid {
list-style-type: circle; list-style-type: circle;
color: #008000; color: #008000;

View File

@@ -319,6 +319,8 @@ function ipa_search_facet(spec) {
} }
} }
that.search_facet_init = that.init;
return that; return that;
} }

View File

@@ -26,8 +26,6 @@ function ipa_service() {
'name': 'service' 'name': 'service'
}); });
that.superior_init = that.superior('init');
that.init = function() { that.init = function() {
that.create_association({ that.create_association({
@@ -60,7 +58,7 @@ function ipa_service() {
}); });
that.add_facet(facet); that.add_facet(facet);
that.superior_init(); that.entity_init();
}; };
return that; return that;
@@ -74,24 +72,22 @@ function ipa_service_add_dialog(spec) {
var that = ipa_add_dialog(spec); var that = ipa_add_dialog(spec);
that.superior_init = that.superior('init');
that.init = function() { that.init = function() {
this.superior_init(); that.add_dialog_init();
this.add_field(ipa_widget({ that.add_field(ipa_widget({
name: 'krbprincipalname', name: 'krbprincipalname',
label: 'Principal' label: 'Principal'
})); }));
this.add_field(ipa_text_widget({ that.add_field(ipa_text_widget({
'name': 'service', 'label': 'Service', 'name': 'service', 'label': 'Service',
'size': 20, 'size': 20,
'undo': false 'undo': false
})); }));
this.add_field(ipa_text_widget({ that.add_field(ipa_text_widget({
'name': 'host', 'name': 'host',
'label': 'Host Name', 'label': 'Host Name',
'size': 40, 'size': 40,
@@ -159,12 +155,10 @@ function ipa_service_search_facet(spec) {
var that = ipa_search_facet(spec); var that = ipa_search_facet(spec);
that.superior_init = that.superior('init');
that.init = function() { that.init = function() {
this.create_column({name:'krbprincipalname', label:'Principal'}); this.create_column({name:'krbprincipalname', label:'Principal'});
that.superior_init(); that.search_facet_init();
}; };
return that; return that;
@@ -176,13 +170,11 @@ function ipa_service_details_facet(spec) {
var that = ipa_details_facet(spec); var that = ipa_details_facet(spec);
that.superior_init = that.superior('init');
that.init = function() { that.init = function() {
var section = ipa_details_list_section({ var section = ipa_details_list_section({
name:'details', name: 'details',
label:'Service Details' label: 'Service Details'
}); });
that.add_section(section); that.add_section(section);
@@ -204,85 +196,195 @@ function ipa_service_details_facet(spec) {
}); });
section = ipa_details_list_section({ section = ipa_details_list_section({
name:'provisioning', name: 'provisioning',
label:'Provisioning' label: 'Provisioning'
}); });
that.add_section(section); that.add_section(section);
section.create_field({ section.add_field(service_provisioning_status_widget({
name: 'provisioning_status', name: 'provisioning_status',
label: 'Status', label: 'Status'
load: service_provisioning_status_load }));
});
section = ipa_details_list_section({ section = ipa_details_list_section({
name:'certificate', name: 'certificate',
label:'Service Certificate' label: 'Service Certificate'
}); });
that.add_section(section); that.add_section(section);
section.create_field({ section.add_field(service_certificate_status_widget({
name: 'certificate_status', name: 'certificate_status',
label: 'Status', label: 'Status'
load: service_usercertificate_load }));
});
that.superior_init(); that.details_facet_init();
}; };
return that; return that;
} }
function service_service_load(container, result) { function service_service_load(container, result) {
var dt = $('dt[title='+this.name+']', container);
if (!dt.length) return; $('dd', container).remove();
var dd = ipa_create_first_dd(this.name);
dd.appendTo(container);
var krbprincipalname = result['krbprincipalname'][0]; var krbprincipalname = result['krbprincipalname'][0];
var service = krbprincipalname.replace(/\/.*$/, ''); var service = krbprincipalname.replace(/\/.*$/, '');
var dd = ipa_create_first_dd(this.name, service); dd.append(service);
dt.after(dd);
} }
function service_host_load(container, result) { function service_host_load(container, result) {
var dt = $('dt[title='+this.name+']', container);
if (!dt.length) return; $('dd', container).remove();
var dd = ipa_create_first_dd(this.name);
dd.appendTo(container);
var krbprincipalname = result['krbprincipalname'][0]; var krbprincipalname = result['krbprincipalname'][0];
var host = krbprincipalname.replace(/^.*\//, '').replace(/@.*$/, ''); var host = krbprincipalname.replace(/^.*\//, '').replace(/@.*$/, '');
var dd = ipa_create_first_dd(this.name, host); dd.append(host);
dt.after(dd);
} }
function service_provisioning_status_load(container, result) { function service_provisioning_status_widget(spec) {
// skip provisioning_status
spec = spec || {};
var that = ipa_widget(spec);
that.create = function(container) {
that.widget_create(container);
var table = $('<table/>').appendTo(container);
var tr = $('<tr/>').appendTo(table);
var td = $('<td/>').appendTo(tr);
var li = $('<li/>', {
'class': 'key-status-valid'
}).appendTo(td);
td = $('<td/>').appendTo(tr);
td.append('Kerberos Key Present, Service Provisioned:');
td = $('<td/>').appendTo(tr);
$('<input/>', {
'type': 'button',
'name': 'unprovision',
'value': 'Delete Key, Unprovision'
}).appendTo(td);
tr = $('<tr/>').appendTo(table);
td = $('<td/>').appendTo(tr);
li = $('<li/>', {
'class': 'key-status-missing'
}).appendTo(td);
td = $('<td/>').appendTo(tr);
td.append('Kerberos Key Not Present');
};
that.setup = function(container) {
that.container = container;
that.valid = $('li.key-status-valid', that.container);
that.missing = $('li.key-status-missing', that.container);
var button = $('input[name=unprovision]', that.container);
that.unprovision_button = ipa_button({
'label': 'Delete Key, Unprovision',
'click': that.unprovision
});
button.replaceWith(that.unprovision_button);
};
that.unprovision = function() {
var label = IPA.metadata[that.entity_name].label;
var dialog = ipa_dialog({
'title': 'Unprovisioning '+label
});
dialog.create = function() {
dialog.container.append(
'To confirm your intention to unprovision this service, '+
'click the "Unprovision" button.');
};
dialog.add_button('Unprovision', function() {
var pkey = that.result['krbprincipalname'][0];
ipa_cmd(that.entity_name+'_disable', [pkey], {},
function(data, text_status, xhr) {
set_status('missing');
dialog.close();
},
function(xhr, text_status, error_thrown) {
dialog.close();
}
);
});
dialog.add_button('Cancel', function() {
dialog.close();
});
dialog.init();
dialog.open(that.container);
return false;
};
that.load = function(container, result) {
that.result = result;
var krblastpwdchange = result['krblastpwdchange'];
set_status(krblastpwdchange ? 'valid' : 'missing');
};
function set_status(status) {
that.valid.toggleClass('key-status-active', status == 'valid');
that.missing.toggleClass('key-status-active', status == 'missing');
that.unprovision_button.css('visibility', status == 'valid' ? 'visible' : 'hidden');
}
return that;
} }
function service_usercertificate_load(container, result) { function service_certificate_status_widget(spec) {
var dt = $('dt[title='+this.name+']', container); spec = spec || {};
if (!dt.length) return;
var panel = certificate_status_panel({ var that = certificate_status_widget(spec);
'entity_type': 'service',
'entity_label': 'Service', that.init = function() {
'result': result,
'get_entity_pkey': function(result) { that.entity_label = IPA.metadata[that.entity_name].label;
that.get_entity_pkey = function(result) {
var values = result['krbprincipalname']; var values = result['krbprincipalname'];
return values ? values[0] : null; return values ? values[0] : null;
}, };
'get_entity_name': function(result) {
var value = this.get_entity_pkey(result); that.get_entity_name = function(result) {
var value = that.get_entity_pkey(result);
return value ? value.replace(/@.*$/, '') : null; return value ? value.replace(/@.*$/, '') : null;
}, };
'get_entity_principal': function(result) {
return this.get_entity_pkey(result); that.get_entity_principal = function(result) {
}, return that.get_entity_pkey(result);
'get_entity_certificate': function(result) { };
that.get_entity_certificate = function(result) {
var values = result['usercertificate']; var values = result['usercertificate'];
return values ? values[0].__base64__ : null; return values ? values[0].__base64__ : null;
} };
}); };
var dd = ipa_create_first_dd(this.name, panel); return that;
dt.after(dd);
} }

View File

@@ -44,7 +44,7 @@ test("Testing ipa_details_section.create().", function() {
var container = $("<div/>"); var container = $("<div/>");
section.create(container); section.create(container);
var dl = container.find('dl'); var dl = $('dl', container);
same( same(
dl.length, 1, dl.length, 1,
@@ -63,15 +63,26 @@ test("Testing ipa_details_section.create().", function() {
); );
for (var i=0; i<fields.length; i++) { for (var i=0; i<fields.length; i++) {
var field = fields[i];
var dt = dts.get(i); var dt = dts.get(i);
same( same(
dt.title, fields[i].name, dt.innerHTML, field.label+':',
'Checking field '+i+'\'s title' 'Checking field '+field.name+'\'s label'
); );
same( var span = $('span[name='+field.name+']', dl);
dt.innerHTML, fields[i].label+':',
'Checking field '+i+'\'s label' ok(
span.length,
'Checking span tag for field '+field.name
);
var dd = $('dd', span);
ok(
dd.length == 0,
'Checking dd tag for field '+field.name
); );
} }
}); });
@@ -184,18 +195,13 @@ test("Testing details lifecycle: create, setup, load.", function(){
'dl tag for identity is created' 'dl tag for identity is created'
); );
var dts= identity.find('dt'); var dts = identity.find('dt');
same( same(
dts.length, 6, dts.length, 6,
'Checking dt tags for identity' 'Checking dt tags for identity'
); );
same(
dts[5].title, facet.sections[0].fields[5].name,
'Checking dt title'
);
container.attr('id','user'); container.attr('id','user');
ok ( ok (
@@ -219,10 +225,14 @@ test("Testing details lifecycle: create, setup, load.", function(){
test("Testing _ipa_create_text_input().", function(){ test("Testing _ipa_create_text_input().", function(){
var field = ipa_details_field({
'name': "name"
});
var name = "name"; var name = "name";
var value="value"; var value="value";
var rights = 'rscwo' var rights = 'rscwo'
var input = _ipa_create_text_input(name, value, null,rights); var input = _ipa_create_text_input.call(field, value, null,rights);
ok(input,"input not null"); ok(input,"input not null");
var text = input.find('input'); var text = input.find('input');
@@ -235,10 +245,14 @@ test("Testing _ipa_create_text_input().", function(){
test("Testing _ipa_create_text_input() read only .", function(){ test("Testing _ipa_create_text_input() read only .", function(){
var field = ipa_details_field({
'name': "name"
});
var name = "name"; var name = "name";
var value="value"; var value="value";
var rights = 'rsc' var rights = 'rsc'
var input = _ipa_create_text_input(name, value, null,rights); var input = _ipa_create_text_input.call(field, value, null,rights);
ok(input,"input not null"); ok(input,"input not null");
var text = input.find('input'); var text = input.find('input');
@@ -271,22 +285,26 @@ test("Testing ipa_details_section_setup again()",function(){
section.setup(container); section.setup(container);
section.load(result); section.load(result);
ok(container.find('hr'),'hr');
//var h2= container.find('h2'); //var h2= container.find('h2');
//ok(h2); //ok(h2);
//ok(h2[0].innerHTML.indexOf(section.label) > 1,"find name in html"); //ok(h2[0].innerHTML.indexOf(section.label) > 1,"find name in html");
var dl = container.find('dl'); var dl = $('dl', container);
ok( ok(
dl.length, dl.length,
'dl is created' 'dl is created'
); );
var dt = $('dt', dl);
same( same(
dl[0].children.length, 3, dt.length, 3,
'3 spans' '3 dt'
);
var span = dt.next();
same(
span.length, 3,
'3 span'
); );
same( same(
@@ -295,16 +313,13 @@ test("Testing ipa_details_section_setup again()",function(){
); );
same( same(
dl[0].children[0].children[0].title, fields[0].name, dt[0].innerHTML, fields[0].label+":",
'title matches name'
);
same(
dl[0].children[0].children[0].innerHTML, fields[0].label+":",
'inner HTML matches label' 'inner HTML matches label'
); );
var dd = $('dd', span[0]);
same( same(
dl[0].children[2].children[0].title, fields[2].name, dd.length, 1,
'title matches fields[2] name' '1 dd'
); );
}); });

View File

@@ -26,7 +26,7 @@ ipa_entity_set_search_definition('user', [
['uidnumber', 'UID', null], ['uidnumber', 'UID', null],
['mail', 'EMAIL', null], ['mail', 'EMAIL', null],
['telephonenumber', 'Phone', null], ['telephonenumber', 'Phone', null],
['title', 'Job Title', null], ['title', 'Job Title', null]
]); ]);
ipa_entity_set_add_definition('user', [ ipa_entity_set_add_definition('user', [
@@ -89,10 +89,13 @@ ipa_entity_set_association_definition('user', {
function user_status_load(container, result) { function user_status_load(container, result) {
var lock_field = 'nsaccountlock';
var dt = $('dt[title='+this.name+']', container); $('dd', container).remove();
if (!dt.length) return;
var dd = ipa_create_first_dd(this.name);
dd.appendTo(container);
var lock_field = 'nsaccountlock';
var locked = result[lock_field] && var locked = result[lock_field] &&
result[lock_field][0].toLowerCase() === 'true'; result[lock_field][0].toLowerCase() === 'true';
@@ -134,8 +137,7 @@ function user_status_load(container, result) {
return (false); return (false);
} }
}); });
status_field.appendTo(dd);
dt.after(ipa_create_first_dd(this.name, status_field));
} }
@@ -191,17 +193,20 @@ function resetpwd_on_click(){
} }
function user_password_load(container, result) { function user_password_load(container, result) {
var dt = $('dt[title='+this.name+']', container);
if (!dt.length) return;
dt.after(ipa_create_first_dd( $('dd', container).remove();
this.name,
$('<a/>',{ var dd = ipa_create_first_dd(this.name);
href:"jslink", dd.appendTo(container);
click:resetpwd_on_click,
title:'userpassword', var link = $('<a/>',{
text: 'reset password' href:"jslink",
}))); click:resetpwd_on_click,
title:'userpassword',
text: 'reset password'
});
link.appendTo(dd);
} }
var select_temp = '<select title="st"></select>'; var select_temp = '<select title="st"></select>';
@@ -215,17 +220,18 @@ var states = [
'WA', 'WV', 'WI', 'WY', '' 'WA', 'WV', 'WI', 'WY', ''
]; ];
function user_state_load(container, result) { function user_state_load(container, result) {
var dt = $('dt[title='+this.name+']', container);
if (!dt.length) return;
var next = dt.next(); $('dd', container).remove();
next.css('clear', 'none');
next.css('width', '70px');
var dd = ipa_create_first_dd(this.name, select_temp); //var next = dt.next();
dt.after(dd); //next.css('clear', 'none');
//next.css('width', '70px');
var sel = dt.next().children().first(); var dd = ipa_create_first_dd(this.name);
dd.append(select_temp);
dd.appendTo(container);
var sel = dd.children().first();
for (var i = 0; i < states.length; ++i) for (var i = 0; i < states.length; ++i)
sel.append(option_temp.replace(/V/g, states[i])); sel.append(option_temp.replace(/V/g, states[i]));

View File

@@ -109,6 +109,7 @@ function ipa_widget(spec) {
}; };
// methods that should be invoked by subclasses // methods that should be invoked by subclasses
that.widget_create = that.create;
that.widget_setup = that.setup; that.widget_setup = that.setup;
return that; return that;