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.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) {
@@ -559,9 +559,8 @@ IPA.details_facet = function(spec) {
var new_update_info = IPA.update_info_builder.copy(update_info);
if (update_info.fields.length > 0) {
new_update_info.append_command(
that.create_fields_update_command(update_info),
IPA.config.default_priority);
var command = that.create_fields_update_command(update_info);
new_update_info.append_command(command, IPA.config.default_priority);
}
new_update_info.commands.sort(function(a, b) {
@@ -609,12 +608,12 @@ IPA.details_facet = function(spec) {
var command = that.create_update_command();
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);
};
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);
};
@@ -641,7 +640,16 @@ IPA.details_facet = function(spec) {
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');
@@ -653,12 +661,13 @@ IPA.details_facet = function(spec) {
var command = that.create_refresh_command();
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) {
that.redirect_error(error_thrown);
that.report_error(error_thrown);
that.refresh_on_error(xhr, text_status, error_thrown);
if (on_error) on_error.call(this, xhr, text_status, error_thrown);
};
command.execute();
@@ -677,10 +686,9 @@ IPA.details_facet = function(spec) {
var fields = that.fields.get_fields();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if(field.get_update_info) {
update_info = IPA.update_info_builder.merge(
update_info,
field.get_update_info());
if (field.get_update_info) {
var ui = field.get_update_info();
update_info = IPA.update_info_builder.merge(update_info, ui);
}
}
@@ -726,6 +734,7 @@ IPA.details_facet = function(spec) {
// methods that should be invoked by subclasses
that.details_facet_create_update_command = that.create_update_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;
return that;
@@ -739,12 +748,13 @@ IPA.update_info = function(spec) {
that.commands = spec.commands || [];
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.commands.push(IPA.update_info_builder.new_command_info(command,
priority));
var command_info = IPA.update_info_builder.new_command_info(command, priority);
that.commands.push(command_info);
};
return that;

View File

@@ -704,7 +704,7 @@ IPA.dns.record_details_facet = function(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) {
that.reset();

View File

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

View File

@@ -513,11 +513,11 @@ IPA.hbacrule_details_facet = function(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.on_update_error = function(xhr, text_status, error_thrown) {
that.update_on_error = function(xhr, text_status, error_thrown) {
that.refresh();
};

View File

@@ -561,96 +561,104 @@ IPA.batch_command = function (spec) {
that.execute = function() {
that.errors.clear();
IPA.command({
var command = IPA.command({
name: that.name,
entity: that.entity,
method: that.method,
args: that.args,
options: that.options,
retry: that.retry,
on_success: function(data, text_status, xhr) {
retry: that.retry
});
for (var i=0; i<that.commands.length; i++) {
var command = that.commands[i];
var result = data.result.results[i];
command.on_success = that.batch_command_on_success;
command.on_error = that.batch_command_on_error;
var name = '';
var message = '';
command.execute();
};
if (!result) {
name = IPA.get_message('errors.internal_error', 'Internal Error')+' '+xhr.status;
message = result ? xhr.statusText : IPA.get_message('errors.internal_error', 'Internal Error');
that.batch_command_on_success = function(data, text_status, xhr) {
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(
this,
xhr,
text_status,
{
name: name,
message: message
}
);
var name = '';
var message = '';
} else if (result.error) {
name = IPA.get_message('errors.ipa_error', 'IPA Error')+(result.error.code ? ' '+result.error.code : '');
message = result.error.message || result.error;
if (!result) {
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);
that.errors.add(command, name, message, text_status);
if (command.on_error) command.on_error.call(
this,
xhr,
text_status,
{
name: name,
code: result.error.code,
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);
if (command.on_error) command.on_error.call(
this,
xhr,
text_status,
{
name: name,
message: message
}
}
//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);
};
} else if (result.error) {
name = IPA.get_message('errors.ipa_error', 'IPA Error')+(result.error.code ? ' '+result.error.code : '');
message = result.error.message || result.error;
dialog.open();
that.errors.add(command, name, message, text_status);
} else {
if (that.on_success) that.on_success.call(this, data, text_status, xhr);
}
},
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);
}
if (command.on_error) command.on_error.call(
this,
xhr,
text_status,
{
name: name,
code: result.error.code,
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;

View File

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

View File

@@ -260,7 +260,7 @@
"identity": "Host Group Settings"
},
"krbtpolicy": {
"identity": "Kerberos ticket policy"
"identity": "Kerberos Ticket Policy"
},
"netgroup": {
"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": [
"20101105172205Z"
],
"krbmaxrenewableage": [
"604800"
],
"krbmaxticketlife": [
"86400"
],
"krbpasswordexpiration": [
"20101105172205Z"
],

View File

@@ -55,65 +55,133 @@ IPA.user.entity = function(spec) {
'title'
]
}).
details_facet({ sections: [
{
name: 'identity',
label: IPA.messages.details.identity,
fields: [
'title',
'givenname',
'sn',
'cn',
'displayname',
'initials'
]
},
{
name: 'account',
fields: [
{
factory: IPA.user_status_widget,
name: 'nsaccountlock',
label: IPA.messages.objects.user.account_status
},
'uid',
{ factory: IPA.user_password_widget, name: 'userpassword' },
'uidnumber',
'gidnumber',
'loginshell',
'homedirectory'
]
},
{
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']
}]
details_facet({
factory: IPA.user.details_facet,
sections: [
{
name: 'identity',
label: IPA.messages.details.identity,
fields: [
'title',
'givenname',
'sn',
'cn',
'displayname',
'initials'
]
},
{
name: 'account',
fields: [
{
factory: IPA.user_status_widget,
name: 'nsaccountlock',
label: IPA.messages.objects.user.account_status
},
'uid',
{
factory: IPA.user_password_widget,
name: 'userpassword'
},
'uidnumber',
'gidnumber',
'loginshell',
'homedirectory'
]
},
{
name: 'pwpolicy',
label: IPA.messages.objects.pwpolicy.identity,
fields: [
{
name: 'krbmaxpwdlife',
label: IPA.get_entity_param('pwpolicy', 'krbmaxpwdlife').label,
read_only: true
},
{
name: 'krbminpwdlife',
label: IPA.get_entity_param('pwpolicy', 'krbminpwdlife').label,
read_only: true
},
{
name: 'krbpwdhistorylength',
label: IPA.get_entity_param('pwpolicy', 'krbpwdhistorylength').label,
read_only: true
},
{
name: 'krbpwdmindiffchars',
label: IPA.get_entity_param('pwpolicy', 'krbpwdmindiffchars').label,
read_only: true
},
{
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({
name: 'memberof_group',
@@ -186,6 +254,77 @@ IPA.user.entity = function(spec) {
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) {
var that = IPA.entity_adder_dialog(spec);