Hello community, here is the log from the commit of package yast2-users checked in at Wed Dec 20 10:31:20 CET 2006. -------- --- yast2-users/yast2-users.changes 2006-12-04 16:40:28.000000000 +0100 +++ /mounts/work_src_done/STABLE/yast2-users/yast2-users.changes 2006-12-20 07:23:48.000000000 +0100 @@ -1,0 +2,8 @@ +Thu Dec 7 13:24:44 CET 2006 - jsuchome@suse.cz + +- new LDAP plugins for Password Policy and Shadow Account (F301179) +- when enabling plugins, remove plugin from "plugins_to_remove" list +- help text and wizard caption for authentication settings +- 2.15.1 + +------------------------------------------------------------------- Old: ---- yast2-users-2.15.0.tar.bz2 New: ---- yast2-users-2.15.1.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-users.spec ++++++ --- /var/tmp/diff_new_pack.5AacHD/_old 2006-12-20 10:31:08.000000000 +0100 +++ /var/tmp/diff_new_pack.5AacHD/_new 2006-12-20 10:31:08.000000000 +0100 @@ -1,5 +1,5 @@ # -# spec file for package yast2-users (Version 2.15.0) +# spec file for package yast2-users (Version 2.15.1) # # Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany. # This file and all modifications and additions to the pristine @@ -11,15 +11,15 @@ # norootforbuild Name: yast2-users -Version: 2.15.0 +Version: 2.15.1 Release: 1 License: GNU General Public License (GPL) Group: System/YaST BuildRoot: %{_tmppath}/%{name}-%{version}-build -Source0: yast2-users-2.15.0.tar.bz2 +Source0: yast2-users-2.15.1.tar.bz2 prefix: /usr BuildRequires: cracklib-devel doxygen gcc-c++ perl-Digest-SHA1 perl-XML-Writer update-desktop-files yast2 yast2-core-devel yast2-devtools yast2-ldap-client yast2-mail-aliases yast2-perl-bindings yast2-security yast2-testsuite -Requires: yast2 yast2-perl-bindings yast2-country yast2-pam yast2-security yast2-mail-aliases cracklib perl-Digest-SHA1 perl-gettext yast2-ldap-client +Requires: yast2 yast2-perl-bindings yast2-country yast2-pam yast2-security yast2-mail-aliases cracklib perl-Digest-SHA1 perl-X500-DN perl-gettext yast2-ldap-client Obsoletes: yast2-config-users y2c_users yast2-trans-users y2t_users yast2-trans-inst-user yast2-trans-users y2t_inst-user Provides: yast2-config-users y2c_users yast2-trans-users y2t_users yast2-trans-inst-user yast2-trans-users y2t_inst-user #BuildArchitectures: noarch @@ -42,7 +42,7 @@ Jiri Suchomel <jsuchome@suse.cz> %prep -%setup -n yast2-users-2.15.0 +%setup -n yast2-users-2.15.1 %build %{prefix}/bin/y2tool y2autoconf @@ -86,6 +86,11 @@ %doc %{prefix}/share/doc/packages/yast2-users %changelog -n yast2-users +* Thu Dec 07 2006 - jsuchome@suse.cz +- new LDAP plugins for Password Policy and Shadow Account (F301179) +- when enabling plugins, remove plugin from "plugins_to_remove" list +- help text and wizard caption for authentication settings +- 2.15.1 * Mon Dec 04 2006 - jsuchome@suse.cz - differ GenericName from Name in desktop files (#223549) - check root password for CA constraints (F300438) ++++++ yast2-users-2.15.0.tar.bz2 -> yast2-users-2.15.1.tar.bz2 ++++++ diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/VERSION new/yast2-users-2.15.1/VERSION --- old/yast2-users-2.15.0/VERSION 2006-12-04 16:26:54.000000000 +0100 +++ new/yast2-users-2.15.1/VERSION 2006-12-07 13:25:36.000000000 +0100 @@ -1 +1 @@ -2.15.0 +2.15.1 diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/Makefile.am new/yast2-users-2.15.1/src/Makefile.am --- old/yast2-users-2.15.0/src/Makefile.am 2006-11-27 10:27:00.000000000 +0100 +++ new/yast2-users-2.15.1/src/Makefile.am 2006-12-05 10:22:48.000000000 +0100 @@ -18,7 +18,9 @@ UsersUI.ycp \ UsersPasswd.pm \ UsersPlugins.pm \ - UsersPluginLDAPAll.pm + UsersPluginLDAPAll.pm \ + UsersPluginLDAPShadowAccount.pm \ + UsersPluginLDAPPasswordPolicy.pm ynclude_DATA = \ complex.ycp \ @@ -36,7 +38,9 @@ inst_user.ycp \ inst_auth.ycp \ users_auto.ycp \ - users_plugin_ldap_all.ycp + users_plugin_ldap_all.ycp \ + users_plugin_ldap_passwordpolicy.ycp \ + users_plugin_ldap_shadowaccount.ycp desktop_DATA = \ users.desktop \ diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/Makefile.in new/yast2-users-2.15.1/src/Makefile.in --- old/yast2-users-2.15.0/src/Makefile.in 2006-11-27 10:32:24.000000000 +0100 +++ new/yast2-users-2.15.1/src/Makefile.in 2006-12-05 11:24:50.000000000 +0100 @@ -230,7 +230,9 @@ UsersUI.ycp \ UsersPasswd.pm \ UsersPlugins.pm \ - UsersPluginLDAPAll.pm + UsersPluginLDAPAll.pm \ + UsersPluginLDAPShadowAccount.pm \ + UsersPluginLDAPPasswordPolicy.pm ynclude_DATA = \ complex.ycp \ @@ -248,7 +250,9 @@ inst_user.ycp \ inst_auth.ycp \ users_auto.ycp \ - users_plugin_ldap_all.ycp + users_plugin_ldap_all.ycp \ + users_plugin_ldap_passwordpolicy.ycp \ + users_plugin_ldap_shadowaccount.ycp desktop_DATA = \ users.desktop \ diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/Users.pm new/yast2-users-2.15.1/src/Users.pm --- old/yast2-users-2.15.0/src/Users.pm 2006-09-21 16:11:08.000000000 +0200 +++ new/yast2-users-2.15.1/src/Users.pm 2006-12-11 14:03:47.000000000 +0100 @@ -2496,6 +2496,17 @@ "plugins" => [ $plugin ] }; + my $plugins_to_remove = $group{"plugins_to_remove"}; + if (contains ($plugins_to_remove, $plugin, 1)) { + my @plugins_updated = (); + foreach my $p (@$plugins_to_remove) { + if ($p ne $plugin) { + push @plugins_updated, $p; + } + } + $group{"plugins_to_remove"} = \@plugins_updated; + } + if (($group{"what"} || "") eq "add_group") { my $result = UsersPlugins->Apply ("AddBefore", $args, \%group); @@ -2583,6 +2594,17 @@ "plugins" => [ $plugin ] }; + my $plugins_to_remove = $user{"plugins_to_remove"}; + if (contains ($plugins_to_remove, $plugin, 1)) { + my @plugins_updated = (); + foreach my $p (@$plugins_to_remove) { + if ($p ne $plugin) { + push @plugins_updated, $p; + } + } + $user{"plugins_to_remove"} = \@plugins_updated; + } + if (($user{"what"} || "") eq "add_user") { my $result = UsersPlugins->Apply ("AddBefore", $args, \%user); diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/UsersLDAP.pm new/yast2-users-2.15.1/src/UsersLDAP.pm --- old/yast2-users-2.15.0/src/UsersLDAP.pm 2006-10-23 15:32:46.000000000 +0200 +++ new/yast2-users-2.15.1/src/UsersLDAP.pm 2006-12-18 13:13:58.000000000 +0100 @@ -10,6 +10,7 @@ use YaST::YCP qw(:LOGGING); use YaPI; +use Data::Dumper; textdomain ("users"); @@ -130,6 +131,8 @@ my $user_scope = YaST::YCP::Integer (2); my $group_scope = YaST::YCP::Integer (2); +# store the 'usage' flag of LDAP attribute +my $attribute_usage = {}; ##------------------------------------ ##------------------- global imports @@ -1141,8 +1144,17 @@ $val = ""; } else { - y2warning ("Attribute '$key' is not allowed by schema."); - next; + if (not defined ($attribute_usage->{'$key'})) { + my $at = SCR->Read (".ldap.schema.at", {"name" => $key}); + $attribute_usage->{'$key'} = $at->{'usage'}; + $attribute_usage->{'$key'} = 0 if not defined $at->{'usage'}; + } + # 1, 2 and 3 are operational attributes, they do not require object class + # 0=userApplications, 1=directoryOperation, 2=distributedOperation, 3=dSAOperation + if ($attribute_usage->{'$key'} < 1) { + y2warning ("Attribute '$key' is not allowed by schema."); + next; + } } } if ($key eq $member_attribute && ref ($val) eq "HASH") { @@ -1169,6 +1181,7 @@ } $ret{$key} = $val; } +y2internal ("final map: ", Dumper [\%ret]); return \%ret; } diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/UsersPluginLDAPAll.pm new/yast2-users-2.15.1/src/UsersPluginLDAPAll.pm --- old/yast2-users-2.15.0/src/UsersPluginLDAPAll.pm 2006-09-12 15:33:15.000000000 +0200 +++ new/yast2-users-2.15.1/src/UsersPluginLDAPAll.pm 2006-12-07 10:12:29.000000000 +0100 @@ -28,7 +28,7 @@ # default object classes of LDAP users my @user_object_class = - ("top","posixaccount","shadowaccount", "inetorgperson"); + ("top","posixaccount", "inetorgperson"); # default object classes of LDAP groups my @group_object_class = @@ -135,11 +135,11 @@ my $self = shift; my $what = "user"; # plugin summary (table item) - my $ret = __("Edit Remaining Attributes of LDAP User"); + my $ret = __("Edit Remaining LDAP Attributes"); if (defined $_[0]->{"what"} && $_[0]->{"what"} eq "group") { # plugin summary (table item) - $ret = __("Edit Remaining Attributes of LDAP Group"); + $ret = __("Edit Remaining LDAP Attributes"); } return $ret; } @@ -272,40 +272,19 @@ } sub Enable { - my $self = shift; - my $config = $_[0]; - my $data = $_[1]; - - my $pw = $data->{"userpassword"}; - - if ((defined $pw) && $pw =~ m/^\!/) { - $pw =~ s/^\!//; - $data->{"userpassword"} = $pw; - } - $data->{"shadowexpire"} = ""; + my ($self, $config, $data) = @_; y2debug ("Enable LDAPAll called"); return $data; } # this will be called from Users::DisableUser -# set "shadowExpire" to "0", -# set a "!" before the hash-value in the "userpassword" BEGIN { $TYPEINFO{Disable} = ["function", ["map", "string", "any"], "any", "any"]; } sub Disable { - my $self = shift; - my $config = $_[0]; - my $data = $_[1]; - - my $pw = $data->{"userpassword"}; - - if ((defined $pw) && $pw !~ m/^\!/) { - $data->{"userpassword"} = "!".$pw; - } - $data->{"shadowexpire"} = 0; + my ($self, $config, $data) = @_; y2debug ("Disable LDAPAll called"); return $data; } diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/UsersPluginLDAPPasswordPolicy.pm new/yast2-users-2.15.1/src/UsersPluginLDAPPasswordPolicy.pm --- old/yast2-users-2.15.0/src/UsersPluginLDAPPasswordPolicy.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-users-2.15.1/src/UsersPluginLDAPPasswordPolicy.pm 2006-12-19 16:11:46.000000000 +0100 @@ -0,0 +1,362 @@ +#! /usr/bin/perl -w +# +# Example of plugin module +# This is the API part of UsersPluginLDAPPasswordPolicy plugin +# - configuration of Password Policy of LDAP user (feature 301179) +# +# For documentation and examples of function arguments and return values, see +# UsersPluginLDAPAll.pm + +package UsersPluginLDAPPasswordPolicy; + +use strict; + +use YaST::YCP qw(:LOGGING); +use YaPI; +use Data::Dumper; +use X500::DN; + +textdomain("users"); + +our %TYPEINFO; + +##-------------------------------------- +##--------------------- global imports + +YaST::YCP::Import ("SCR"); +YaST::YCP::Import ("Ldap"); + +##-------------------------------------- +##--------------------- global variables + +# name of conflicting plugin +my $shadow_plugin = "UsersPluginLDAPShadowAccount"; + +# error message, returned when some plugin function fails +my $error = ""; + +# internal name +my $name = "UsersPluginLDAPPasswordPolicy"; + +# if Password Policy is enabled on the server +my $ppolicy_enabled = undef; + +##---------------------------------------- +##--------------------- internal functions + +# internal function: +# check if given key (second parameter) is contained in a list (1st parameter) +# if 3rd parameter is true (>0), ignore case +sub contains { + my ($list, $key, $ignorecase) = @_; + if (!defined $list || ref ($list) ne "ARRAY" || @{$list} == 0) { + return 0; + } + if ($ignorecase) { + if ( grep /^\Q$key\E$/i, @{$list} ) { + return 1; + } + } else { + if ( grep /^\Q$key\E$/, @{$list} ) { + return 1; + } + } + return 0; +} + +# update the object data when removing plugin +# TODO is it possible when plugin is not removable? +sub remove_plugin_data { + + my ($config, $data) = @_; + my @updated_oc; + if (defined $data->{'pwdpolicysubentry'}) { + $data->{'pwdpolicysubentry'} = ""; + } + return $data; +} + +##------------------------------------------ +##--------------------- global API functions + +# return names of provided functions +BEGIN { $TYPEINFO{Interface} = ["function", ["list", "string"], "any", "any"];} +sub Interface { + + my $self = shift; + my @interface = ( + "GUIClient", + "Check", + "Name", + "Summary", + "Restriction", + "WriteBefore", + "Write", + "AddBefore", + "Add", + "EditBefore", + "Edit", + "Interface", + "Disable", + "Enable", + "PluginPresent", + "PluginRemovable", + "Error", + ); + return \@interface; +} + +# return error message, generated by plugin +BEGIN { $TYPEINFO{Error} = ["function", "string", "any", "any"];} +sub Error { + + return $error; +} + + +# return plugin name, used for GUI (translated) +BEGIN { $TYPEINFO{Name} = ["function", "string", "any", "any"];} +sub Name { + + # plugin name + return __("LDAP Password Policy"); +} + +##------------------------------------ +# return plugin summary (to be shown in table with all plugins) +BEGIN { $TYPEINFO{Summary} = ["function", "string", "any", "any"];} +sub Summary { + + # user plugin summary (table item) + return __("Edit Password Policy"); +} + +##------------------------------------ +# checks the current data map of user (2nd parameter) and returns +# true if given user has this plugin +BEGIN { $TYPEINFO{PluginPresent} = ["function", "boolean", "any", "any"];} +sub PluginPresent { + + my ($self, $config, $data) = @_; + + # check for PasswordPolicy at server + if (not defined $ppolicy_enabled) { + $ppolicy_enabled = SCR->Execute (".ldap.ppolicy", { + "hostname" => Ldap->GetFirstServer (Ldap->server ()), + "bind_dn" => Ldap->GetDomain () + }); + y2milestone ("Password Policy enabled globaly: $ppolicy_enabled"); + } + if (contains ($data->{'plugins'}, $name, 1) || # already checked, still no data + contains ((keys %$data), "pwdpolicysubentry", 1)) { # checking for data + y2milestone ("LDAPPasswordPolicy plugin present"); + return 1; + } elsif ($ppolicy_enabled) { + y2debug ("Password Policy enabled globaly"); + return 1; + } else { + y2debug ("LDAPPasswordPolicy plugin not present"); + return 0; + } +} + +##------------------------------------ +# Is it possible to remove this plugin from user? +BEGIN { $TYPEINFO{PluginRemovable} = ["function", "boolean", "any", "any"];} +sub PluginRemovable { + + return YaST::YCP::Boolean (0); +} + + +##------------------------------------ +# return name of YCP client defining YCP GUI +BEGIN { $TYPEINFO{GUIClient} = ["function", "string", "any", "any"];} +sub GUIClient { + + return "users_plugin_ldap_passwordpolicy"; +} + +##------------------------------------ +# Type of objects this plugin is restricted to. +# Plugin is restricted to LDAP users +BEGIN { $TYPEINFO{Restriction} = ["function", + ["map", "string", "any"], "any", "any"];} +sub Restriction { + + return { + "ldap" => 1, + "user" => 1 + }; +} + + +##------------------------------------ +# check if required atributes of LDAP entry are present and have correct form +# parameter is (whole) map of entry (user) +# return error message +BEGIN { $TYPEINFO{Check} = ["function", + "string", + "any", + "any"]; +} +sub Check { + + my ($self, $config, $data) = @_; + my $pwdpolicysubentry = $data->{'pwdpolicysubentry'}; + if (defined $pwdpolicysubentry && $pwdpolicysubentry ne "") { + + # validate DN + if (not defined X500::DN->ParseRFC2253 ($pwdpolicysubentry)) { + # error popup, %s is object DN + return sprintf (__("Invalid DN syntax of \"%s\"."), $pwdpolicysubentry); + } + + # ldap.init has been done before + my $search = SCR->Read (".ldap.search", { + "base_dn" => $pwdpolicysubentry, + "attrs" => [ "objectclass" ], + "map" => 1 + }); + if (not defined $search) { + my $error = SCR->Read (".ldap.error"); + # error popup, first %s is object DN, second is additional error message + return sprintf (__("Error while searching for \"%s\": +%s"), $pwdpolicysubentry, $error->{'msg'}); + } + my $oc = $search->{$pwdpolicysubentry}{'objectclass'}; + if (defined $oc && ref ($oc) eq "ARRAY") { + if (not contains ($oc, "pwdpolicy", 1)) { + # error popup, %s is object DN + return sprintf (__("The object \"%s\" +is not a Password Policy object"), $pwdpolicysubentry); + } + } + } + return ""; +} + +# this will be called from Users::EnableUser +BEGIN { $TYPEINFO{Enable} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub Enable { + + my ($self, $config, $data) = @_; + y2debug ("Enable LDAPAll called"); + + $data->{'pwdAccountLockedTime'} = ""; + return $data; +} + +# this will be called from Users::DisableUser +BEGIN { $TYPEINFO{Disable} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub Disable { + + my ($self, $config, $data) = @_; + y2debug ("Disable LDAPAll called"); + + $data->{'pwdAccountLockedTime'} = 0; + return $data; +} + + +# this will be called at the beggining of Users::Add +# Could be called multiple times for one user +BEGIN { $TYPEINFO{AddBefore} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub AddBefore { + + my ($self, $config, $data) = @_; + + if (!contains ($data->{'plugins_to_remove'}, $name, 1) && + contains ($data->{'plugins'}, $shadow_plugin, 1)) { + # error popup + $error = __("It is not possible to add this plugin when +the plugin for Shadow Account attributes is in use."); + return undef; + } + return $data; +} + + +# This will be called just after Users::Add - the data map probably contains +# the values which we could use to create new ones +# Could be called multiple times for one user! +BEGIN { $TYPEINFO{Add} = ["function", ["map", "string", "any"], "any", "any"];} +sub Add { + + my ($self, $config, $data) = @_; + if (contains ($data->{'plugins_to_remove'}, $name, 1)) { + y2milestone ("removing plugin $name..."); + $data = remove_plugin_data ($config, $data); + } + y2debug("Add LDAPAll called"); + return $data; +} + +# this will be called at the beggining of Users::Edit +BEGIN { $TYPEINFO{EditBefore} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub EditBefore { + + my ($self, $config, $data) = @_; + # $data: only new data that will be copied to current user map + # data of original user are saved as a submap of $config + # data with key "org_data" + + # in $data hash, there could be "plugins_to_remove": list of plugins which + # has to be removed from the user + if (!contains ($data->{'plugins_to_remove'}, $name, 1) && + contains ($data->{'plugins'}, $shadow_plugin, 1)) { + # error popup + $error = __("It is not possible to add this plugin when +the plugin for Shadow Account attributes is in use."); + return undef; + } + return $data; +} + +# this will be called just after Users::Edit +BEGIN { $TYPEINFO{Edit} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub Edit { + + my ($self, $config, $data) = @_; + if (contains ($data->{'plugins_to_remove'}, $name, 1)) { + y2milestone ("removing plugin $name..."); + $data = remove_plugin_data ($config, $data); + } + y2debug ("Edit LDAPAll called"); + return $data; +} + + + +# what should be done before user is finally written to LDAP +BEGIN { $TYPEINFO{WriteBefore} = ["function", "boolean", "any", "any"];} +sub WriteBefore { + + y2debug ("WriteBefore LDAPAll called"); + return YaST::YCP::Boolean (1); +} + +# what should be done after user is finally written to LDAP +BEGIN { $TYPEINFO{Write} = ["function", "boolean", "any", "any"];} +sub Write { + + y2debug ("Write LDAPAll called"); + return YaST::YCP::Boolean (1); +} +1 +# EOF diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/UsersPluginLDAPShadowAccount.pm new/yast2-users-2.15.1/src/UsersPluginLDAPShadowAccount.pm --- old/yast2-users-2.15.0/src/UsersPluginLDAPShadowAccount.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-users-2.15.1/src/UsersPluginLDAPShadowAccount.pm 2006-12-11 13:58:01.000000000 +0100 @@ -0,0 +1,416 @@ +#! /usr/bin/perl -w +# +# Example of plugin module +# This is the API part of UsersPluginLDAPShadowAccount plugin +# - configuration of ShadowAccount object class of LDAP users +# +# For documentation and examples of function arguments and return values, see +# UsersPluginLDAPAll.pm + +package UsersPluginLDAPShadowAccount; + +use strict; + +use YaST::YCP qw(:LOGGING); +use YaPI; +use Data::Dumper; + +textdomain("users"); + +our %TYPEINFO; + +##-------------------------------------- +##--------------------- global imports + +YaST::YCP::Import ("Ldap"); +YaST::YCP::Import ("SCR"); +YaST::YCP::Import ("UsersLDAP"); + +##-------------------------------------- +##--------------------- global variables + +# object classes handled by this plugin +my $user_object_class = "shadowaccount"; + +# conflicting plugin name +my $pwdpolicy_plugin = "UsersPluginLDAPPasswordPolicy"; + +# error message, returned when some plugin function fails +my $error = ""; + +# internal name +my $name = "UsersPluginLDAPShadowAccount"; + +##---------------------------------------- +##--------------------- internal functions + +# check if given key (second parameter) is contained in a list (1st parameter) +# if 3rd parameter is true (>0), ignore case +sub contains { + my ($list, $key, $ignorecase) = @_; + if (!defined $list || ref ($list) ne "ARRAY" || @{$list} == 0) { + return 0; + } + if ($ignorecase) { + if ( grep /^\Q$key\E$/i, @{$list} ) { + return 1; + } + } else { + if ( grep /^\Q$key\E$/, @{$list} ) { + return 1; + } + } + return 0; +} + +# provide current value for shadowlastchange attribute +sub last_change_is_now { + + my %out = %{SCR->Execute (".target.bash_output", "date +%s")}; + my $seconds = $out{"stdout"} || "0"; + chomp $seconds; + return sprintf ("%u", $seconds / (60*60*24)); +} + +# update the list of current object classes when adding plugin +sub update_object_classes { + + my ($config, $data) = @_; + + if (defined $data->{"objectclass"} && ref $data->{"objectclass"} eq "ARRAY") + { + my @orig_object_class = @{$data->{"objectclass"}}; + if (!contains (\@orig_object_class, $user_object_class, 1)) { + push @orig_object_class, $user_object_class; + $data->{"objectclass"} = \@orig_object_class; + } + # set default values for new variables + my $shadow = UsersLDAP->GetDefaultShadow (); + foreach my $attr (keys %$shadow) { + if (!defined $data->{$attr} || $data->{$attr} eq "") { + $data->{$attr} = $shadow->{$attr}; + } + } + if (!defined $data->{"shadowlastchange"}) { + $data->{"shadowlastchange"} = last_change_is_now (); + } + } + return $data; +} + +# update the object data when removing plugin +sub remove_plugin_data { + + my ($config, $data) = @_; + my @updated_oc; + foreach my $oc (@{$data->{'objectclass'}}) { + if (lc($oc) ne $user_object_class) { + push @updated_oc, $oc; + } + } + $data->{'objectclass'} = \@updated_oc; + return $data; +} + +##------------------------------------------ +##--------------------- global API functions + +# return names of provided functions +BEGIN { $TYPEINFO{Interface} = ["function", ["list", "string"], "any", "any"];} +sub Interface { + + my $self = shift; + my @interface = ( + "GUIClient", + "Check", + "Name", + "Summary", + "Restriction", + "WriteBefore", + "Write", + "AddBefore", + "Add", + "EditBefore", + "Edit", + "Interface", + "Disable", + "Enable", + "PluginPresent", + "PluginRemovable", + "Error", + ); + return \@interface; +} + +# return error message, generated by plugin +BEGIN { $TYPEINFO{Error} = ["function", "string", "any", "any"];} +sub Error { + + return $error; +} + + +# return plugin name, used for GUI (translated) +BEGIN { $TYPEINFO{Name} = ["function", "string", "any", "any"];} +sub Name { + + # plugin name + return __("Shadow Account Configuration"); +} + +##------------------------------------ +# return plugin summary (to be shown in table with all plugins) +BEGIN { $TYPEINFO{Summary} = ["function", "string", "any", "any"];} +sub Summary { + + # user plugin summary (table item) + return __("Edit Shadow Account attributes"); +} + +##------------------------------------ +# checks the current data map of user (2nd parameter) and returns +# true if given user has our plugin +BEGIN { $TYPEINFO{PluginPresent} = ["function", "boolean", "any", "any"];} +sub PluginPresent { + + my ($self, $config, $data) = @_; + + if (contains ($data->{'objectclass'}, $user_object_class, 1)) { + y2milestone ("LDAPShadowAccount plugin present"); + return 1; + } else { + y2debug ("LDAPShadowAccount plugin not present"); + return 0; + } +} + +##------------------------------------ +# Is it possible to remove this plugin from user? +BEGIN { $TYPEINFO{PluginRemovable} = ["function", "boolean", "any", "any"];} +sub PluginRemovable { + + return YaST::YCP::Boolean (1); +} + + +##------------------------------------ +# return name of YCP client defining YCP GUI +BEGIN { $TYPEINFO{GUIClient} = ["function", "string", "any", "any"];} +sub GUIClient { + + return "users_plugin_ldap_shadowaccount"; +} + +##------------------------------------ +# Type of objects this plugin is restricted to. +# Plugin is restricted to LDAP users +BEGIN { $TYPEINFO{Restriction} = ["function", + ["map", "string", "any"], "any", "any"];} +sub Restriction { + + return { + "ldap" => 1, + "user" => 1 + }; +} + + +##------------------------------------ +# check if all required atributes of LDAP entry are present +# parameter is (whole) map of user +# return error message +BEGIN { $TYPEINFO{Check} = ["function", + "string", + "any", + "any"]; +} +sub Check { + + my ($self, $config, $data) = @_; + + # attribute conversion + my @required_attrs = (); + my @object_classes = (); + if (defined $data->{"objectclass"} && ref $data->{"objectclass"} eq "ARRAY") + { + @object_classes = @{$data->{"objectclass"}}; + } + + # get the attributes required for entry's object classes + foreach my $class (@object_classes) { + my $req = Ldap->GetRequiredAttributes ($class); + if (defined $req && ref ($req) eq "ARRAY") { + foreach my $r (@{$req}) { + if (!contains (\@required_attrs, $r, 1)) { + push @required_attrs, $r; + } + } + } + } + my $action = $data->{"what"} || ""; + # check the presence of required attributes + foreach my $req (@required_attrs) { + my $attr = lc ($req); + my $val = $data->{$attr}; + if (substr ($action, 0, 5) eq "edit_" && !defined $val) { + # when editing using YaPI, attribute dosn't have to be loaded + next; + } + if (!defined $val || $val eq "" || + (ref ($val) eq "ARRAY" && + ((@{$val} == 0) || (@{$val} == 1 && $val->[0] eq "")))) { + # error popup (user forgot to fill in some attributes) + return sprintf (__("The attribute '%s' is required for this object according +to its LDAP configuration, but it is currently empty."), $attr); + } + } + return ""; +} + +# this will be called from Users::EnableUser +BEGIN { $TYPEINFO{Enable} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub Enable { + + my ($self, $config, $data) = @_; + my $pw = $data->{"userpassword"}; + + if ((defined $pw) && $pw =~ m/^\!/) { + $pw =~ s/^\!//; + $data->{"userpassword"} = $pw; + } + $data->{"shadowexpire"} = ""; + y2debug ("Enable LDAPAll called"); + return $data; +} + +# this will be called from Users::DisableUser +# set "shadowExpire" to "0", +# set a "!" before the hash-value in the "userpassword" +BEGIN { $TYPEINFO{Disable} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub Disable { + + my ($self, $config, $data) = @_; + + my $pw = $data->{"userpassword"}; + + if ((defined $pw) && $pw !~ m/^\!/) { + $data->{"userpassword"} = "!".$pw; + } + $data->{"shadowexpire"} = 0; + y2debug ("Disable LDAPAll called"); + return $data; +} + + +# this will be called at the beggining of Users::Add +# Could be called multiple times for one user! +BEGIN { $TYPEINFO{AddBefore} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub AddBefore { + + my ($self, $config, $data) = @_; + + # conflict with PasswordPolicy plugin + if (!contains ($data->{'plugins_to_remove'}, $name, 1) && + contains ($data->{'plugins'}, $pwdpolicy_plugin, 1)) + { + # error popup + $error = __("It is not possible to add this plugin when +the plugin for Password Policy is in use."); + return undef; + } + return $data; +} + + +# This will be called just after Users::Add - the data map probably contains +# the values which we could use to create new ones +# Could be called multiple times for one user! +BEGIN { $TYPEINFO{Add} = ["function", ["map", "string", "any"], "any", "any"];} +sub Add { + + my ($self, $config, $data) = @_; + if (contains ($data->{'plugins_to_remove'}, $name, 1)) { + y2milestone ("removing plugin $name ..."); + $data = remove_plugin_data ($config, $data); + } + else { + $data = update_object_classes ($config, $data); + } + return $data; +} + +# this will be called at the beggining of Users::Edit +BEGIN { $TYPEINFO{EditBefore} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub EditBefore { + + my ($self, $config, $data) = @_; + # $data: only new data that will be copied to current user map + # data of original user are saved as a submap of $config + # data with key "org_data" + + # in $data hash, there could be "plugins_to_remove": list of plugins which + # has to be removed from the user + + # conflict with PasswordPolicy plugin + if (!contains ($data->{'plugins_to_remove'}, $name, 1) && + contains ($data->{'plugins'}, $pwdpolicy_plugin, 1)) + { + # error popup + $error = __("It is not possible to add this plugin when +the plugin for Password Policy is in use."); + return undef; + } + return $data; +} + +# this will be called just after Users::Edit +BEGIN { $TYPEINFO{Edit} = ["function", + ["map", "string", "any"], + "any", "any"]; +} +sub Edit { + + my ($self, $config, $data) = @_; + + if (contains ($data->{'plugins_to_remove'}, $name, 1)) { + y2milestone ("removing plugin $name ..."); + $data = remove_plugin_data ($config, $data); + } + else { + $data = update_object_classes ($config, $data); + } + y2debug ("Edit LDAPAll called"); + return $data; +} + + + +# what should be done before user is finally written to LDAP +BEGIN { $TYPEINFO{WriteBefore} = ["function", "boolean", "any", "any"];} +sub WriteBefore { + + y2debug ("WriteBefore LDAPAll called"); + return YaST::YCP::Boolean (1); +} + +# what should be done after user is finally written to LDAP +BEGIN { $TYPEINFO{Write} = ["function", "boolean", "any", "any"];} +sub Write { + + y2debug ("Write LDAPAll called"); + return YaST::YCP::Boolean (1); +} +1 +# EOF diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/cmdline.ycp new/yast2-users-2.15.1/src/cmdline.ycp --- old/yast2-users-2.15.0/src/cmdline.ycp 2006-12-01 13:43:22.000000000 +0100 +++ new/yast2-users-2.15.1/src/cmdline.ycp 2006-12-04 16:40:28.000000000 +0100 @@ -4,7 +4,7 @@ * Summary: Command line interface functions. * Authors: Jiri Suchomel <jsuchome@suse.cz> * - * $Id: cmdline.ycp 31989 2006-07-26 07:42:34Z jsuchome $ + * $Id: cmdline.ycp 34733 2006-12-04 15:40:26Z jsuchome $ * * All command line interface functions. */ diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/dialogs.ycp new/yast2-users-2.15.1/src/dialogs.ycp --- old/yast2-users-2.15.0/src/dialogs.ycp 2006-09-18 17:53:18.000000000 +0200 +++ new/yast2-users-2.15.1/src/dialogs.ycp 2006-12-07 09:44:22.000000000 +0100 @@ -37,30 +37,6 @@ string default_pw = "******"; /** - * helper function: return the 'any' value as integer - */ -define integer GetInt (any value, integer default_value) { - - if (value == nil) - return default_value; - if (is (value, integer)) - return (integer) value; - if (is (value, string) && value != "") - return tointeger ((string)value); - return default_value; -} - -/** - * helper function: return the 'any' value as string - */ -define string GetString (any value, string default_value) { - - if (value == nil) - return default_value; - return sformat ("%1", value); -} - -/** * Upperase letters were used in username! (see bug #26409) * In these popup, ask user what to do. */ @@ -567,11 +543,12 @@ `HSpacing (3), `VBox ( `VStretch(), - `Top(`Left (`Label (sformat ( - // label - _("Last Password Change: %1"), last_change )))), - `VSpacing (1), + `Left (`Label ("")), `HSquash(`VBox( + `Left (`Label (sformat ( + // label + _("Last Password Change: %1"), last_change ))), + `VSpacing (1), `IntField (`id ("shadowwarning"), // intfield label _("Days &before Password Expiration to Issue Warning"), @@ -681,7 +658,7 @@ `item(`id(`details), _("&Details") ), ]; - if (!do_not_edit) + if (!do_not_edit && user_type != "ldap") { // tab label tabs = add (tabs,`item(`id(`passwordsettings),_("Pass&word Settings"))); @@ -1461,20 +1438,6 @@ { UI::ReplaceWidget(`tabContents, get_password_term ()); Wizard::SetHelpText (EditUserPasswordDialogHelp()); - if (user_type == "ldap") - { - list ocs = maplist ( - string oc, user["objectclass"]:[], ``(tolower (oc))); - if (!contains (ocs, "shadowaccount")) - { - ocs = add (ocs, "shadowaccount"); - user["objectclass"] = ocs; - foreach (string k, any v, Users::GetDefaultShadow ("ldap"), { - if (!haskey (user, k)) - user[k] = v; - }); - } - } current = ret; } if (ret == `plugins) diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/inst_root.ycp new/yast2-users-2.15.1/src/inst_root.ycp --- old/yast2-users-2.15.0/src/inst_root.ycp 2006-11-29 09:32:38.000000000 +0100 +++ new/yast2-users-2.15.1/src/inst_root.ycp 2006-12-04 16:40:28.000000000 +0100 @@ -14,7 +14,7 @@ * * Authors: Klaus Kämpf <kkaempf@suse.de> * - * $Id: inst_root.ycp 31699 2006-06-29 09:28:00Z jsuchome $ + * $Id: inst_root.ycp 34733 2006-12-04 15:40:26Z jsuchome $ */ { textdomain "users"; diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/inst_user.ycp new/yast2-users-2.15.1/src/inst_user.ycp --- old/yast2-users-2.15.0/src/inst_user.ycp 2006-09-21 16:11:08.000000000 +0200 +++ new/yast2-users-2.15.1/src/inst_user.ycp 2006-12-15 15:25:41.000000000 +0100 @@ -24,8 +24,10 @@ any ret = `back; - // hide the inst_auth content - Wizard::SetContents ("", `Empty (), "", + // dialog caption + string caption = _("User Authentication Method"); + // help text (shown in the 'busy' situation) + Wizard::SetContents (caption, `Empty (), _("Initialization of module for configuration of authentication..."), GetInstArgs::enable_back(), GetInstArgs::enable_next() ); diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/routines.ycp new/yast2-users-2.15.1/src/routines.ycp --- old/yast2-users-2.15.0/src/routines.ycp 2006-09-18 17:53:18.000000000 +0200 +++ new/yast2-users-2.15.1/src/routines.ycp 2006-12-05 13:07:49.000000000 +0100 @@ -11,6 +11,31 @@ textdomain "users"; /** + * helper function: return the 'any' value as integer + */ +define integer GetInt (any value, integer default_value) { + + if (value == nil) + return default_value; + if (is (value, integer)) + return (integer) value; + if (is (value, string) && value != "") + return tointeger ((string)value); + return default_value; +} + +/** + * helper function: return the 'any' value as string + */ +define string GetString (any value, string default_value) { + + if (value == nil) + return default_value; + return sformat ("%1", value); +} + + +/** * Split cn (fullname) in forename and surname. * @param what `surname or `forename * @param cn fullname diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/users_plugin_ldap_passwordpolicy.ycp new/yast2-users-2.15.1/src/users_plugin_ldap_passwordpolicy.ycp --- old/yast2-users-2.15.0/src/users_plugin_ldap_passwordpolicy.ycp 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-users-2.15.1/src/users_plugin_ldap_passwordpolicy.ycp 2006-12-18 14:39:30.000000000 +0100 @@ -0,0 +1,157 @@ +/** + * File: + * include/users/users_plugin_ldap_passwordpolicy.ycp + * + * Package: + * Configuration of Users + * + * Summary: + * This is GUI part of UsersPluginLDAPPasswordPolicy + * - plugin for editing LDAP user password policy (see feature 301179) + * + * Authors: + * Jiri Suchomel <jsuchome@suse.cz> + * + * $Id$ + */ + + +{ + textdomain "users"; + + import "Label"; + import "Report"; + import "Users"; + import "UsersPluginLDAPPasswordPolicy"; // plugin module + import "Wizard"; + + any ret = nil; + string func = ""; + map<string,any> config = $[]; + map<string,any> data = $[]; + + /* Check arguments */ + if(size(WFM::Args()) > 0 && is(WFM::Args(0), string)) { + func = (string) WFM::Args(0); + if(size(WFM::Args()) > 1 && is(WFM::Args(1), map)) + config = (map<string,any>)WFM::Args(1); + if(size(WFM::Args()) > 2 && is(WFM::Args(2), map)) + data = (map<string,any>)WFM::Args(2); + } + y2milestone("----------------------------------------"); + y2milestone("users plugin started: LDAPPasswordPolicy"); + + y2debug ("func=%1", func); + y2debug ("config=%1", config); + y2debug ("data=%1", data); + + if (func == "Summary") { + ret = UsersPluginLDAPPasswordPolicy::Summary (config, $[]); + } + else if (func == "Name") { + ret = UsersPluginLDAPPasswordPolicy::Name (config, $[]); + } + else if (func == "Dialog") { + // define the dialog for this plugin and return it's contents + + string caption = UsersPluginLDAPPasswordPolicy::Name (config, $[]); + map<string, any> tmp_data = $[]; + + // helptext + string help_text = _("help text for LDAPPasswordPolicy plugin FIXME"); + + boolean pwdreset = data["pwdreset"]:"0" == "1"; + string pwdpolicysubentry = data["pwdpolicysubentry"]:""; + + term contents = `HBox ( + `HSpacing (3), + `VBox ( + `HBox ( + // text entry label + `TextEntry (`id ("pwdpolicysubentry"), + _("DN of &Password Policy object"), pwdpolicysubentry), + `VBox ( + `Label (""), + `PushButton (`id (`browse), Label::BrowseButton ()) + ) + ), + `Left ( + `CheckBox (`id ("pwdreset"), _("&Reset Password"), pwdreset) + ) + ), + `HSpacing (3) + ); + + Wizard::CreateDialog (); + Wizard::SetDesktopIcon("users"); + + // dialog caption + Wizard::SetContentsButtons(_("Password Policy Settings"), + contents, help_text, Label::CancelButton(), Label::AcceptButton()); + + Wizard::HideAbortButton (); + + ret = `next; + repeat + { + ret = UI::UserInput(); + if (ret == `browse) + { +// Popup::Message ("not implemented"); + continue; + } + if (ret == `next) + { + string new_pwdpolicysubentry = (string) + UI::QueryWidget (`id ("pwdpolicysubentry"), `Value); + if (new_pwdpolicysubentry != pwdpolicysubentry) + tmp_data["pwdpolicysubentry"] = new_pwdpolicysubentry; + + boolean new_pwdreset = (boolean) UI::QueryWidget (`id ("pwdreset"), `Value); + if (new_pwdreset != pwdreset) + tmp_data["pwdreset"] = new_pwdreset; + + if (tmp_data == $[]) + break; + + string err = UsersPluginLDAPPasswordPolicy::Check (config, tmp_data); + + if (err != "") + { + Report::Error (err); + ret = `notnext; + continue; + } + + // if this plugin wasn't in default set, we must save its name + if (!contains (data["plugins"]:[], "UsersPluginLDAPPasswordPolicy")) + { + tmp_data["plugins"] = add (tmp_data["plugins"]:[], + "UsersPluginLDAPPasswordPolicy"); + } + if (data["what"]:"" == "edit_user") + { + Users::EditUser (tmp_data); + } + else if (data["what"]:"" == "add_user") + { + Users::AddUser (tmp_data); + } + } + } until (is(ret,symbol) && + contains ([`next, `abort, `back, `cancel], (symbol) ret)); + + Wizard::CloseDialog (); + } + /* unknown function */ + else { + y2error("unknown function: %1", func); + ret = false; + } + + y2debug ("ret=%1", ret); + y2milestone("users plugin finished"); + y2milestone("----------------------------------------"); + + return ret; +} diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/users_plugin_ldap_shadowaccount.ycp new/yast2-users-2.15.1/src/users_plugin_ldap_shadowaccount.ycp --- old/yast2-users-2.15.0/src/users_plugin_ldap_shadowaccount.ycp 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-users-2.15.1/src/users_plugin_ldap_shadowaccount.ycp 2006-12-07 11:04:01.000000000 +0100 @@ -0,0 +1,240 @@ +/** + * File: + * include/users/users_plugin_ldap_shadowaccount.ycp + * + * Package: + * Configuration of Users + * + * Summary: + * This is GUI part of UsersPluginLDAPShadowAccount + * - plugin for editing ShadowAccount LDAP user attributes. + * + * Authors: + * Jiri Suchomel <jsuchome@suse.cz> + * + * $Id$ + */ + + +{ + textdomain "users"; + + import "Label"; + import "Popup"; + import "Report"; + import "Users"; + import "UsersPluginLDAPShadowAccount"; // plugin module + import "Wizard"; + + include "users/helps.ycp"; + include "users/routines.ycp"; + + any ret = nil; + string func = ""; + map<string,any> config = $[]; + map<string,any> data = $[]; + + /* Check arguments */ + if(size(WFM::Args()) > 0 && is(WFM::Args(0), string)) { + func = (string) WFM::Args(0); + if(size(WFM::Args()) > 1 && is(WFM::Args(1), map)) + config = (map<string,any>)WFM::Args(1); + if(size(WFM::Args()) > 2 && is(WFM::Args(2), map)) + data = (map<string,any>)WFM::Args(2); + } + y2milestone("----------------------------------------"); + y2milestone("users plugin started: LDAPShadowAccount"); + + y2debug ("func=%1", func); + y2debug ("config=%1", config); + y2debug ("data=%1", data); + + if (func == "Summary") { + ret = UsersPluginLDAPShadowAccount::Summary (config, $[]); + } + else if (func == "Name") { + ret = UsersPluginLDAPShadowAccount::Name (config, $[]); + } + // define the dialog for this plugin and return it's contents + else if (func == "Dialog") { + + string caption = UsersPluginLDAPShadowAccount::Name (config, $[]); + map<string, any> tmp_data = $[]; + + string help_text = EditUserPasswordDialogHelp (); + + // date of password expiration + string exp_date = ""; + + string last_change = GetString (data["shadowlastchange"]:nil, "0"); + string expires = GetString (data["shadowexpire"]:nil, "0"); + if (expires == "") + expires = "0"; + + integer inact = GetInt (data["shadowinactive"]:nil, 0); + integer max = GetInt (data["shadowmax"]:nil, 0); + integer min = GetInt (data["shadowmin"]:nil, 0); + integer warn = GetInt (data["shadowwarning"]:nil, 0); + + if (last_change != "0") + { + map out = (map)SCR::Execute (.target.bash_output, sformat ("date --date='1970-01-01 00:00:01 %1 days' +\"%%x\"", last_change)); + // label (date of last password change) + last_change = out["stdout"]:_("Unknown"); + } + else + { + // label (date of last password change) + last_change = _("Never"); + } + if (expires != "0" && expires != "-1" && expires != "") + { + map out = (map)SCR::Execute (.target.bash_output, sformat ("date --date='1970-01-01 00:00:01 %1 days' ", expires) + "+\"%Y-%m-%d\""); + // remove \n from the end + exp_date = deletechars (out["stdout"]:"", "\n"); + } + term contents = `HBox ( + `HSpacing (3), + `VBox ( + `VStretch(), + `Left (`Label ("")), + `HSquash(`VBox( + `Left (`Label (sformat ( + // label + _("Last Password Change: %1"), last_change ))), + `VSpacing (1), + `IntField (`id ("shadowwarning"), + // intfield label + _("Days &before Password Expiration to Issue Warning"), + -1, 99999, warn), + `VSpacing (0.5), + `IntField (`id ("shadowinactive"), + // intfield label + _("Days after Password Expires with Usable &Login"), + -1, 99999, inact), + `VSpacing (0.5), + `IntField (`id ("shadowmax"), + // intfield label + _("Ma&ximum Number of Days for the Same Password"), + -1, 99999, max), + `VSpacing (0.5), + `IntField (`id ("shadowmin"), + // intfield label + _("&Minimum Number of Days for the Same Password"), + -1, 99999, min), + `VSpacing (0.5), + `TextEntry (`id ("shadowexpire"), + // textentry label + _("Ex&piration Date"), exp_date) + )), + `VStretch ()), + `HSpacing (3) + ); + + Wizard::CreateDialog (); + Wizard::SetDesktopIcon("users"); + + // dialog caption + Wizard::SetContentsButtons (_("Shadow Account Settings"), + contents, EditUserPasswordDialogHelp (), + Label::CancelButton(), Label::AcceptButton()); + + Wizard::HideAbortButton (); + + ret = `next; + repeat + { + ret = UI::UserInput(); + if (ret == `next) + { + string exp = (string) + UI::QueryWidget (`id ("shadowexpire"), `Value); + if (exp != "" && + !regexpmatch (exp,"[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]")) + { + // popup text: Don't reorder the letters YYYY-MM-DD!!! + // The date must stay in this format + Popup::Message(_("The expiration date must be in the format YYYY-MM-DD.")); + UI::SetFocus (`id ("shadowexpire")); + continue; + } + + foreach (string shadowsymbol, + ["shadowwarning","shadowmax","shadowmin", "shadowinactive"], + { + string sval = sformat ("%1", + UI::QueryWidget (`id(shadowsymbol), `Value)); + if (sformat ("%1", data[shadowsymbol]:"") != sval) + { + tmp_data[shadowsymbol] = sval; + } + }); + + string new_exp_date = (string) + UI::QueryWidget(`id("shadowexpire"),`Value); + if (new_exp_date != exp_date) + { + exp_date = new_exp_date; + if (exp_date == "") + { + tmp_data["shadowexpire"] = ""; + } + else + { + map out = (map)SCR::Execute(.target.bash_output, + sformat("date --date='%1 UTC' ", exp_date) + "+%s"); + string seconds_s = deletechars(out["stdout"]:"0","\n"); + if (seconds_s != "") + { + integer days = (tointeger (seconds_s)) / (60*60*24); + tmp_data["shadowexpire"] = sformat("%1", days); + } + } + } + string err = UsersPluginLDAPShadowAccount::Check ( + config, + (map<string,any>) union (data, tmp_data)); + + if (err != "") + { + Report::Error (err); + ret = `notnext; + continue; + } + + if (tmp_data == $[]) + { + break; + } + // if this plugin wasn't in default set, we must save its name + if (!contains (data["plugins"]:[], "UsersPluginLDAPShadowAccount")) + { + tmp_data["plugins"] = add (tmp_data["plugins"]:[], + "UsersPluginLDAPShadowAccount"); + } + if (data["what"]:"" == "edit_user") + { + Users::EditUser (tmp_data); + } + else if (data["what"]:"" == "add_user") + { + Users::AddUser (tmp_data); + } + } + } until (is(ret,symbol) && + contains ([`next, `abort, `back, `cancel], (symbol) ret)); + + Wizard::CloseDialog (); + } + /* unknown function */ + else { + y2error("unknown function: %1", func); + ret = false; + } + + y2debug ("ret=%1", ret); + y2milestone("users plugin finished"); + y2milestone("----------------------------------------"); + + return ret; +} diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/yast2-users-2.15.0/src/widgets.ycp new/yast2-users-2.15.1/src/widgets.ycp --- old/yast2-users-2.15.0/src/widgets.ycp 2006-11-24 10:47:38.000000000 +0100 +++ new/yast2-users-2.15.1/src/widgets.ycp 2006-12-05 14:57:13.000000000 +0100 @@ -305,7 +305,10 @@ user_attributes : group_attributes) ), `HSpacing (), - `ComboBox (`id(`eq), "", equality), + `VBox ( + `Label (""), + `ComboBox (`id(`eq), "", equality) + ), `HSpacing (), // textentry label `TextEntry (`id(`val), _("&Value"), "") ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... --------------------------------------------------------------------- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org