Added policies into user details page.

The user details page has been modified to show the password policy
and Kerberos ticket policy that apply to the user. The policies are
currently displayed as read-only.

Ticket #703
This commit is contained in:
Endi Sukma Dewata
2011-12-19 18:31:35 -06:00
committed by Petr Vobornik
parent 0e037f24ce
commit 74e31cd985
11 changed files with 459 additions and 160 deletions

View File

@@ -512,11 +512,11 @@ IPA.details_facet = function(spec) {
}; };
that.on_update_success = function(data, text_status, xhr) { that.update_on_success = function(data, text_status, xhr) {
that.load(data); that.load(data);
}; };
that.on_update_error = function(xhr, text_status, error_thrown) { that.update_on_error = function(xhr, text_status, error_thrown) {
}; };
that.add_fields_to_command = function(update_info, command) { that.add_fields_to_command = function(update_info, command) {
@@ -559,9 +559,8 @@ IPA.details_facet = function(spec) {
var new_update_info = IPA.update_info_builder.copy(update_info); var new_update_info = IPA.update_info_builder.copy(update_info);
if (update_info.fields.length > 0) { if (update_info.fields.length > 0) {
new_update_info.append_command( var command = that.create_fields_update_command(update_info);
that.create_fields_update_command(update_info), new_update_info.append_command(command, IPA.config.default_priority);
IPA.config.default_priority);
} }
new_update_info.commands.sort(function(a, b) { new_update_info.commands.sort(function(a, b) {
@@ -609,12 +608,12 @@ IPA.details_facet = function(spec) {
var command = that.create_update_command(); var command = that.create_update_command();
command.on_success = function(data, text_status, xhr) { command.on_success = function(data, text_status, xhr) {
that.on_update_success(data, text_status, xhr); that.update_on_success(data, text_status, xhr);
if (on_success) on_success.call(this, data, text_status, xhr); if (on_success) on_success.call(this, data, text_status, xhr);
}; };
command.on_error = function(xhr, text_status, error_thrown) { command.on_error = function(xhr, text_status, error_thrown) {
that.on_update_error(xhr, text_status, error_thrown); that.update_on_error(xhr, text_status, error_thrown);
if (on_error) on_error.call(this, xhr, text_status, error_thrown); if (on_error) on_error.call(this, xhr, text_status, error_thrown);
}; };
@@ -641,7 +640,16 @@ IPA.details_facet = function(spec) {
return command; return command;
}; };
that.refresh = function() { that.refresh_on_success = function(data, text_status, xhr) {
that.load(data);
};
that.refresh_on_error = function(xhr, text_status, error_thrown) {
that.redirect_error(error_thrown);
that.report_error(error_thrown);
};
that.refresh = function(on_success, on_error) {
that.pkey = IPA.nav.get_state(that.entity.name+'-pkey'); that.pkey = IPA.nav.get_state(that.entity.name+'-pkey');
@@ -653,12 +661,13 @@ IPA.details_facet = function(spec) {
var command = that.create_refresh_command(); var command = that.create_refresh_command();
command.on_success = function(data, text_status, xhr) { command.on_success = function(data, text_status, xhr) {
that.load(data); that.refresh_on_success(data, text_status, xhr);
if (on_success) on_success.call(this, data, text_status, xhr);
}; };
command.on_error = function(xhr, text_status, error_thrown) { command.on_error = function(xhr, text_status, error_thrown) {
that.redirect_error(error_thrown); that.refresh_on_error(xhr, text_status, error_thrown);
that.report_error(error_thrown); if (on_error) on_error.call(this, xhr, text_status, error_thrown);
}; };
command.execute(); command.execute();
@@ -677,10 +686,9 @@ IPA.details_facet = function(spec) {
var fields = that.fields.get_fields(); var fields = that.fields.get_fields();
for (var i = 0; i < fields.length; i++) { for (var i = 0; i < fields.length; i++) {
var field = fields[i]; var field = fields[i];
if(field.get_update_info) { if (field.get_update_info) {
update_info = IPA.update_info_builder.merge( var ui = field.get_update_info();
update_info, update_info = IPA.update_info_builder.merge(update_info, ui);
field.get_update_info());
} }
} }
@@ -726,6 +734,7 @@ IPA.details_facet = function(spec) {
// methods that should be invoked by subclasses // methods that should be invoked by subclasses
that.details_facet_create_update_command = that.create_update_command; that.details_facet_create_update_command = that.create_update_command;
that.details_facet_create_refresh_command = that.create_refresh_command; that.details_facet_create_refresh_command = that.create_refresh_command;
that.details_facet_refresh_on_success = that.refresh_on_success;
that.details_facet_load = that.load; that.details_facet_load = that.load;
return that; return that;
@@ -739,12 +748,13 @@ IPA.update_info = function(spec) {
that.commands = spec.commands || []; that.commands = spec.commands || [];
that.append_field = function(field, value) { that.append_field = function(field, value) {
that.fields.push(IPA.update_info_builder.new_field_info(field, value)); var field_info = IPA.update_info_builder.new_field_info(field, value);
that.fields.push(field_info);
}; };
that.append_command = function (command, priority) { that.append_command = function (command, priority) {
that.commands.push(IPA.update_info_builder.new_command_info(command, var command_info = IPA.update_info_builder.new_command_info(command, priority);
priority)); that.commands.push(command_info);
}; };
return that; return that;

View File

@@ -704,7 +704,7 @@ IPA.dns.record_details_facet = function(spec) {
var that = IPA.details_facet(spec); var that = IPA.details_facet(spec);
that.on_update_success = function(data, text_status, xhr) { that.update_on_success = function(data, text_status, xhr) {
if (!data.result.result.idnsname) { if (!data.result.result.idnsname) {
that.reset(); that.reset();

View File

@@ -198,10 +198,10 @@ IPA.field = function(spec) {
that.get_update_info = function() { that.get_update_info = function() {
var update_info = IPA.update_info_builder.new_update_info(); var update_info = IPA.update_info_builder.new_update_info();
if(that.is_dirty()) { if (that.is_dirty()) {
update_info.fields.push(IPA.update_info_builder.new_field_info( var values = that.save();
that, var field_info = IPA.update_info_builder.new_field_info(that, values);
that.save())); update_info.fields.push(field_info);
} }
return update_info; return update_info;
}; };
@@ -679,6 +679,7 @@ IPA.enable_field = function(spec) {
return that; return that;
}; };
// TODO: Add support for nested fields
IPA.field_container = function(spec) { IPA.field_container = function(spec) {
spec = spec || {}; spec = spec || {};

View File

@@ -513,11 +513,11 @@ IPA.hbacrule_details_facet = function(spec) {
var that = IPA.details_facet(spec); var that = IPA.details_facet(spec);
that.on_update_success = function(data, text_status, xhr) { that.update_on_success = function(data, text_status, xhr) {
that.refresh(); that.refresh();
}; };
that.on_update_error = function(xhr, text_status, error_thrown) { that.update_on_error = function(xhr, text_status, error_thrown) {
that.refresh(); that.refresh();
}; };

View File

@@ -561,96 +561,104 @@ IPA.batch_command = function (spec) {
that.execute = function() { that.execute = function() {
that.errors.clear(); that.errors.clear();
IPA.command({ var command = IPA.command({
name: that.name, name: that.name,
entity: that.entity, entity: that.entity,
method: that.method, method: that.method,
args: that.args, args: that.args,
options: that.options, options: that.options,
retry: that.retry, retry: that.retry
on_success: function(data, text_status, xhr) { });
for (var i=0; i<that.commands.length; i++) { command.on_success = that.batch_command_on_success;
var command = that.commands[i]; command.on_error = that.batch_command_on_error;
var result = data.result.results[i];
var name = ''; command.execute();
var message = ''; };
if (!result) { that.batch_command_on_success = function(data, text_status, xhr) {
name = IPA.get_message('errors.internal_error', 'Internal Error')+' '+xhr.status;
message = result ? xhr.statusText : IPA.get_message('errors.internal_error', 'Internal Error');
that.errors.add(command, name, message, text_status); for (var i=0; i<that.commands.length; i++) {
var command = that.commands[i];
var result = data.result.results[i];
if (command.on_error) command.on_error.call( var name = '';
this, var message = '';
xhr,
text_status,
{
name: name,
message: message
}
);
} else if (result.error) { if (!result) {
name = IPA.get_message('errors.ipa_error', 'IPA Error')+(result.error.code ? ' '+result.error.code : ''); name = IPA.get_message('errors.internal_error', 'Internal Error')+' '+xhr.status;
message = result.error.message || result.error; message = result ? xhr.statusText : IPA.get_message('errors.internal_error', 'Internal Error');
that.errors.add(command, name, message, text_status); that.errors.add(command, name, message, text_status);
if (command.on_error) command.on_error.call( if (command.on_error) command.on_error.call(
this, this,
xhr, xhr,
text_status, text_status,
{ {
name: name, name: name,
code: result.error.code, message: message
message: message,
data: result
}
);
} else {
var failed = that.get_failed(command, result, text_status, xhr);
that.errors.add_range(failed);
if (command.on_success) command.on_success.call(this, result, text_status, xhr);
} }
} );
//check for partial errors and show error dialog
if(that.show_error && that.errors.errors.length > 0) {
var ajax = this;
var dialog = IPA.error_dialog({
xhr: xhr,
text_status: text_status,
error_thrown: {
name: IPA.get_message('dialogs.batch_error_title', 'Operations Error'),
message: that.error_message
},
command: that,
errors: that.errors.errors,
visible_buttons: ['ok']
});
dialog.on_ok = function() { } else if (result.error) {
dialog.close(); name = IPA.get_message('errors.ipa_error', 'IPA Error')+(result.error.code ? ' '+result.error.code : '');
if (that.on_success) that.on_success.call(ajax, data, text_status, xhr); message = result.error.message || result.error;
};
dialog.open(); that.errors.add(command, name, message, text_status);
} else { if (command.on_error) command.on_error.call(
if (that.on_success) that.on_success.call(this, data, text_status, xhr); this,
} xhr,
}, text_status,
on_error: function(xhr, text_status, error_thrown) { {
// TODO: undefined behavior name: name,
if (that.on_error) { code: result.error.code,
that.on_error.call(this, xhr, text_status, error_thrown); message: message,
} data: result
}
);
} else {
var failed = that.get_failed(command, result, text_status, xhr);
that.errors.add_range(failed);
if (command.on_success) command.on_success.call(this, result, text_status, xhr);
} }
}).execute(); }
//check for partial errors and show error dialog
if (that.show_error && that.errors.errors.length > 0) {
var ajax = this;
var dialog = IPA.error_dialog({
xhr: xhr,
text_status: text_status,
error_thrown: {
name: IPA.get_message('dialogs.batch_error_title', 'Operations Error'),
message: that.error_message
},
command: that,
errors: that.errors.errors,
visible_buttons: [ 'ok' ]
});
dialog.on_ok = function() {
dialog.close();
if (that.on_success) that.on_success.call(ajax, data, text_status, xhr);
};
dialog.open();
} else {
if (that.on_success) that.on_success.call(this, data, text_status, xhr);
}
};
that.batch_command_on_error = function(xhr, text_status, error_thrown) {
// TODO: undefined behavior
if (that.on_error) {
that.on_error.call(this, xhr, text_status, error_thrown);
}
}; };
return that; return that;

View File

@@ -628,11 +628,11 @@ IPA.sudorule_details_facet = function(spec) {
options.facet = that; options.facet = that;
}; };
that.on_update_success = function(data, text_status, xhr) { that.update_on_success = function(data, text_status, xhr) {
that.refresh(); that.refresh();
}; };
that.on_update_error = function(xhr, text_status, error_thrown) { that.update_on_error = function(xhr, text_status, error_thrown) {
that.refresh(); that.refresh();
}; };

View File

@@ -260,7 +260,7 @@
"identity": "Host Group Settings" "identity": "Host Group Settings"
}, },
"krbtpolicy": { "krbtpolicy": {
"identity": "Kerberos ticket policy" "identity": "Kerberos Ticket Policy"
}, },
"netgroup": { "netgroup": {
"identity": "Netgroup Settings" "identity": "Netgroup Settings"

View File

@@ -0,0 +1,135 @@
{
"error": null,
"id": null,
"result": {
"count": 2,
"results": [
{
"error": null,
"result": {
"attributelevelrights": {
"aci": "rscwo",
"cn": "rscwo",
"krbmaxpwdlife": "rscwo",
"krbminpwdlife": "rscwo",
"krbpwdfailurecountinterval": "rscwo",
"krbpwdhistorylength": "rscwo",
"krbpwdlockoutduration": "rscwo",
"krbpwdmaxfailure": "rscwo",
"krbpwdmindiffchars": "rscwo",
"krbpwdminlength": "rscwo",
"nsaccountlock": "rscwo",
"objectclass": "rscwo"
},
"cn": [
"global_policy"
],
"dn": "cn=global_policy,cn=dev.example.com,cn=kerberos,dc=dev,dc=example,dc=com",
"krbmaxpwdlife": [
"90"
],
"krbminpwdlife": [
"1"
],
"krbpwdfailurecountinterval": [
"60"
],
"krbpwdhistorylength": [
"0"
],
"krbpwdlockoutduration": [
"10"
],
"krbpwdmaxfailure": [
"3"
],
"krbpwdmindiffchars": [
"0"
],
"krbpwdminlength": [
"8"
],
"objectclass": [
"top",
"nsContainer",
"krbPwdPolicy"
]
},
"summary": null,
"value": "global_policy"
},
{
"error": null,
"result": {
"attributelevelrights": {
"aci": "rscwo",
"cn": "rscwo",
"krbadmservers": "rscwo",
"krbdefaultencsalttypes": "rscwo",
"krbkdcservers": "rscwo",
"krbldapservers": "rscwo",
"krbmaxrenewableage": "rscwo",
"krbmaxticketlife": "rscwo",
"krbmkey": "none",
"krbprinccontainerref": "rscwo",
"krbprincnamingattr": "rscwo",
"krbpwdpolicyreference": "rsc",
"krbpwdservers": "rscwo",
"krbsearchscope": "rscwo",
"krbsubtrees": "rscwo",
"krbsupportedencsalttypes": "rscwo",
"krbticketflags": "rsc",
"krbticketpolicyreference": "rsc",
"krbupenabled": "rsc",
"nsaccountlock": "rscwo",
"objectclass": "rscwo"
},
"cn": [
"DEV.EXAMPLE.COM"
],
"dn": "cn=dev.example.com,cn=kerberos,dc=dev,dc=example,dc=com",
"krbdefaultencsalttypes": [
"aes256-cts:special",
"aes128-cts:special",
"des3-hmac-sha1:special",
"arcfour-hmac:special"
],
"krbmaxrenewableage": [
"604800"
],
"krbmaxticketlife": [
"86400"
],
"krbsearchscope": [
"2"
],
"krbsubtrees": [
"dc=dev,dc=example,dc=com"
],
"krbsupportedencsalttypes": [
"aes256-cts:normal",
"aes256-cts:special",
"aes128-cts:normal",
"aes128-cts:special",
"des3-hmac-sha1:normal",
"des3-hmac-sha1:special",
"arcfour-hmac:normal",
"arcfour-hmac:special",
"des-hmac-sha1:normal",
"des-cbc-md5:normal",
"des-cbc-crc:normal",
"des-cbc-crc:v4",
"des-cbc-crc:afs3"
],
"objectclass": [
"top",
"krbrealmcontainer",
"krbticketpolicyaux"
]
},
"summary": null,
"value": ""
}
]
}
}

View File

@@ -110,6 +110,12 @@
"krblastpwdchange": [ "krblastpwdchange": [
"20101105172205Z" "20101105172205Z"
], ],
"krbmaxrenewableage": [
"604800"
],
"krbmaxticketlife": [
"86400"
],
"krbpasswordexpiration": [ "krbpasswordexpiration": [
"20101105172205Z" "20101105172205Z"
], ],

View File

@@ -55,65 +55,133 @@ IPA.user.entity = function(spec) {
'title' 'title'
] ]
}). }).
details_facet({ sections: [ details_facet({
{ factory: IPA.user.details_facet,
name: 'identity', sections: [
label: IPA.messages.details.identity, {
fields: [ name: 'identity',
'title', label: IPA.messages.details.identity,
'givenname', fields: [
'sn', 'title',
'cn', 'givenname',
'displayname', 'sn',
'initials' 'cn',
] 'displayname',
}, 'initials'
{ ]
name: 'account', },
fields: [ {
{ name: 'account',
factory: IPA.user_status_widget, fields: [
name: 'nsaccountlock', {
label: IPA.messages.objects.user.account_status factory: IPA.user_status_widget,
}, name: 'nsaccountlock',
'uid', label: IPA.messages.objects.user.account_status
{ factory: IPA.user_password_widget, name: 'userpassword' }, },
'uidnumber', 'uid',
'gidnumber', {
'loginshell', factory: IPA.user_password_widget,
'homedirectory' name: 'userpassword'
] },
}, 'uidnumber',
{ 'gidnumber',
name: 'contact', 'loginshell',
fields: [ 'homedirectory'
{ type: 'multivalued', name: 'mail' }, ]
{ type: 'multivalued', name: 'telephonenumber' }, },
{ type: 'multivalued', name: 'pager' }, {
{ type: 'multivalued', name: 'mobile' }, name: 'pwpolicy',
{ type: 'multivalued', name: 'facsimiletelephonenumber' } label: IPA.messages.objects.pwpolicy.identity,
] fields: [
}, {
{ name: 'krbmaxpwdlife',
name: 'mailing', label: IPA.get_entity_param('pwpolicy', 'krbmaxpwdlife').label,
fields: ['street', 'l', 'st', 'postalcode'] read_only: true
}, },
{ {
name: 'employee', name: 'krbminpwdlife',
fields: [ label: IPA.get_entity_param('pwpolicy', 'krbminpwdlife').label,
'ou', read_only: true
{ },
type: 'entity_select', {
name: 'manager', name: 'krbpwdhistorylength',
other_entity: 'user', label: IPA.get_entity_param('pwpolicy', 'krbpwdhistorylength').label,
other_field: 'uid' read_only: true
} },
] {
}, name: 'krbpwdmindiffchars',
{ label: IPA.get_entity_param('pwpolicy', 'krbpwdmindiffchars').label,
name: 'misc', read_only: true
fields: ['carlicense'] },
}] {
name: 'krbpwdminlength',
label: IPA.get_entity_param('pwpolicy', 'krbpwdminlength').label,
read_only: true
},
{
name: 'krbpwdmaxfailure',
label: IPA.get_entity_param('pwpolicy', 'krbpwdmaxfailure').label,
read_only: true
},
{
name: 'krbpwdfailurecountinterval',
label: IPA.get_entity_param('pwpolicy', 'krbpwdfailurecountinterval').label,
read_only: true
},
{
name: 'krbpwdlockoutduration',
label: IPA.get_entity_param('pwpolicy', 'krbpwdlockoutduration').label,
read_only: true
}
]
},
{
name: 'krbtpolicy',
label: IPA.messages.objects.krbtpolicy.identity,
fields: [
{
name: 'krbmaxrenewableage',
label: IPA.get_entity_param('krbtpolicy', 'krbmaxrenewableage').label,
read_only: true
},
{
name: 'krbmaxticketlife',
label: IPA.get_entity_param('krbtpolicy', 'krbmaxticketlife').label,
read_only: true
}
]
},
{
name: 'contact',
fields: [
{ type: 'multivalued', name: 'mail' },
{ type: 'multivalued', name: 'telephonenumber' },
{ type: 'multivalued', name: 'pager' },
{ type: 'multivalued', name: 'mobile' },
{ type: 'multivalued', name: 'facsimiletelephonenumber' }
]
},
{
name: 'mailing',
fields: ['street', 'l', 'st', 'postalcode']
},
{
name: 'employee',
fields: [
'ou',
{
type: 'entity_select',
name: 'manager',
other_entity: 'user',
other_field: 'uid'
}
]
},
{
name: 'misc',
fields: [ 'carlicense' ]
}
]
}). }).
association_facet({ association_facet({
name: 'memberof_group', name: 'memberof_group',
@@ -186,6 +254,77 @@ IPA.user.entity = function(spec) {
return that; return that;
}; };
IPA.user.details_facet = function(spec) {
spec = spec || {};
var that = IPA.details_facet(spec);
that.refresh_on_success = function(data, text_status, xhr) {
that.details_facet_refresh_on_success(data, text_status, xhr);
var batch = IPA.batch_command({
name: 'user_get_policies'
});
var pkey = IPA.nav.get_state(that.entity.name+'-pkey');
var pwpolicy_command = IPA.command({
entity: 'pwpolicy',
method: 'show',
options: {
user: pkey,
all: true,
rights: true
}
});
pwpolicy_command.on_success = function(data, text_status, xhr) {
// TODO: Use nested fields: that.fields.get_field('pwpolicy').get_fields();
var fields = that.fields.get_fields();
for (var i=0; i<fields.length; i++) {
var field = fields[i];
// load result into pwpolicy fields
if (field.widget_name.match(/^pwpolicy\./)) {
field.load(data.result);
}
}
};
batch.add_command(pwpolicy_command);
var krbtpolicy_command = IPA.command({
entity: 'krbtpolicy',
method: 'show',
args: [ pkey ],
options: {
all: true,
rights: true
}
});
krbtpolicy_command.on_success = function(data, text_status, xhr) {
// TODO: Use nested fields: that.fields.get_field('krbtpolicy').get_fields();
var fields = that.fields.get_fields();
for (var i=0; i<fields.length; i++) {
var field = fields[i];
// load result into krbtpolicy fields
if (field.widget_name.match(/^krbtpolicy\./)) {
field.load(data.result);
}
}
};
batch.add_command(krbtpolicy_command);
batch.execute();
};
return that;
};
IPA.user_adder_dialog = function(spec) { IPA.user_adder_dialog = function(spec) {
var that = IPA.entity_adder_dialog(spec); var that = IPA.entity_adder_dialog(spec);

View File

@@ -398,7 +398,7 @@ class i18n_messages(Command):
"identity": _("Host Group Settings"), "identity": _("Host Group Settings"),
}, },
"krbtpolicy": { "krbtpolicy": {
"identity": _("Kerberos ticket policy"), "identity": _("Kerberos Ticket Policy"),
}, },
"netgroup": { "netgroup": {
"identity": _("Netgroup Settings"), "identity": _("Netgroup Settings"),