ACC SHELL
/**
* File: include/users/dialogs.ycp
* Package: Configuration of users and groups
* Summary: Dialogs definitions
* Authors: Johannes Buchhold <jbuch@suse.de>,
* Jiri Suchomel <jsuchome@suse.cz>
*
* $Id: dialogs.ycp 61042 2010-02-26 13:48:03Z jsuchome $
*/
{
textdomain "users";
import "Autologin";
import "GetInstArgs";
import "FileUtils";
import "Label";
import "Ldap";
import "LdapPopup";
import "Message";
import "Package";
import "Popup";
import "ProductFeatures";
import "Report";
import "Stage";
import "String";
import "Users";
import "UsersCache";
import "UsersLDAP";
import "UsersPlugins";
import "UsersRoutines";
import "UsersSimple";
import "Wizard";
include "users/helps.ycp";
include "users/routines.ycp";
string default_pw = "******";
/**
* Upperase letters were used in username! (see bug #26409)
* In these popup, ask user what to do.
*/
define symbol AskForUppercasePopup (string username) {
symbol ret = `ok;
if (username != tolower (username) && !Users::NotAskUppercase () &&
Package::InstalledAny (["sendmail", "postfix"]))
{
// The login name contains uppercase 1/3
string text = _("<p>
You have used uppercase letters in the user login entry.</p>") +
// The login name contains uppercase 2/3
_("<p>This could cause problems with delivering mail
to this user, because mail systems generally do not
support case-sensitive names.<br>
You could solve this problem by editing the alias table.</p>
") +
// The login name contains uppercase 3/3
_("<p>Really use the entered value?</p>");
UI::OpenDialog (`opt(`decorated), `HBox(`VSpacing (14),
`VBox (
`HSpacing(50),
`RichText (`id(`rt), text),
`CheckBox (`id(`ch), `opt(`notify),
Message::DoNotShowMessageAgain()),
`HBox(
`PushButton (`id(`ok),`opt(`key_F10), Label::YesButton()),
`PushButton (`id(`no),`opt(`key_F9), Label::NoButton())
)
))
);
do {
ret = (symbol) UI::UserInput();
}
while (!contains ([`cancel, `ok, `no], ret));
if (ret != `cancel)
{
Users::SetAskUppercase ((boolean)UI::QueryWidget(`id(`ch),`Value));
}
UI::CloseDialog();
}
return ret;
}
/**
* Ask user for current password, see bugs 242531, 244718
* @return string or nil when dialog was canceled
*/
string AskForOldPassword () {
UI::OpenDialog (`opt(`decorated), `HBox (`HSpacing (0.5),
`VBox (
`VSpacing (0.5),
// password entry label
`Password (`id (`pw1), `opt (`hstretch), _("To access the data required to modify
the encryption settings for this user,
enter the user's current password.")),
`Password (`id(`pw2),`opt (`hstretch), Label::ConfirmPassword(),""),
`HBox(
`PushButton (`id(`ok),`opt(`key_F10), Label::OKButton()),
`PushButton (`id(`cancel),`opt(`key_F9), Label::CancelButton())
),
`VSpacing (0.5)
), `HSpacing (0.5))
);
any ret = `cancel;
repeat
{
ret = UI::UserInput ();
if (ret == `ok)
{
if (UI::QueryWidget (`id(`pw1), `Value) != UI::QueryWidget (`id(`pw2), `Value))
{
Report::Error(_("The passwords do not match.
Try again."));
ret = `notnext;
continue;
}
}
} until (ret == `ok || ret == `cancel);
string pw = (string) UI::QueryWidget (`id(`pw1), `Value);
UI::CloseDialog();
return (ret == `ok) ? pw : nil;
}
/**
* Dialog for adding or editing a user.
* @param what "add_user" or "edit_user"
* @return symbol for wizard sequencer
*/
define symbol EditUserDialog (string what) {
// user has returned to the "add user dialog" during installation workflow:
if (Users::StartDialog ("user_add") && installation () && Users::UseNextTime ())
{
Users::RestoreCurrentUser ();
Users::SetUseNextTime (false);
}
map display_info = UI::GetDisplayInfo ();
boolean text_mode = display_info["TextMode"]:false;
map<string,any>user = Users::GetCurrentUser ();
string error_msg = "";
if (user == $[])
{
error_msg = Users::AddUser ($[]);
if (error_msg != "")
{
Popup::Error (error_msg);
return `back;
}
user = Users::GetCurrentUser ();
}
string action = user["modified"]:"";
if (action == "")
action = (what == "add_user") ? "added" : "edited";
string user_type = user["type"]:"local";
string username = user["uid"]:"";
string cn = "";
// in LDAP, cn is list of strings
if (is (user["cn"]:nil, list))
cn = user["cn",0]:"";
else
cn = user["cn"]:"";
string tmp_fullname = cn; // for login proposing
string default_home = Users::GetDefaultHome (user_type);
string home = user["homeDirectory"]:default_home;
string org_home = user["org_homeDirectory"]:home;
string default_mode =
sformat ("%1", 777 - tointeger (String::CutZeros (Users::GetUmask ())));
string mode = user["home_mode"]:default_mode;
integer default_crypted_size = 100;
integer crypted_home_size = GetInt (user["crypted_home_size"]:nil, 0);
integer org_crypted_home_size = GetInt (user["org_user","crypted_home_size"]:nil, 0);
string password = (string)user["userPassword"]:nil;
string org_username = user["org_uid"]:username;
integer uid = GetInt (user["uidNumber"]:nil, nil);
integer gid =
GetInt (user["gidNumber"]:nil, Users::GetDefaultGID (user_type));
boolean enabled = user["enabled"]:true;
if (user["disabled"]:false)
enabled = false;
string shell = user["loginShell"]:"";
string defaultgroup = user["groupname"]:"";
// additional parts of GECOS (shown by `finger <username>`) (passwd only)
string addit_data = user["addit_data"]:"";
// this user gets root's mail
boolean root_mail = haskey (Users::GetRootAliases (), username);
boolean root_mail_checked = root_mail;
// if user's password should be set to root
boolean root_pw = false;
// only for LDAP users:
string sn = "";
if (haskey (user, "sn"))
{
if (is (user["sn"]:nil, list))
sn = user["sn",0]:SplitFullName(`sn, cn);
else
sn = user["sn"]:SplitFullName(`sn, cn);
}
string givenname = "";
if (haskey (user, "givenName"))
{
if (is (user["givenName"]:nil, list))
givenname = user["givenName",0]:SplitFullName(`givenname, cn);
else if (is (user["givenName"]:nil, string))
givenname = user["givenName"]:SplitFullName(`givenname, cn);
}
boolean create_home = user["create_home"]:true;
boolean chown_home = user["chown_home"]:true;
boolean no_skel = user["no_skeleton"]:false;
boolean do_not_edit = (user_type == "nis");
boolean crypted_home_enabled=
UsersRoutines::CryptedHomesEnabled () &&
((user_type == "ldap" && Ldap::file_server) ||
(user_type == "local" || user_type == "system"));
boolean complex_layout = installation () && Users::StartDialog ("user_add");
map<string,integer> groups = user["grouplist"]:$[];
list available_shells = Users::AllShells ();
string grouplist = "";
string new_type = user_type;
map<string,map<string,integer> > all_groupnames =
UsersCache::GetAllGroupnames ();
// backup NIS groups of user (they are not shown in details dialog)
map<string,integer> nis_groups = $[];
foreach (string group, integer val, groups, {
if (all_groupnames ["nis", group]:0 == 1)
nis_groups [group] = 1;
});
// of local group list of remote user was modified
boolean grouplist_modified = false;
// date of passwrod expiration
string exp_date = "";
string plugin_client = "";
string plugin = "";
map client2plugin = $[];
// names of plugin GUI clients
list<string> clients = [];
/**
* initialize local variables with current state of user
*/
define void reinit_userdata () {
user_type = user["type"]:user_type;
username = user["uid"]:username;
if (is (user["cn"]:nil, list))
cn = user["cn",0]:cn;
else
cn = user["cn"]:cn;
home = user["homeDirectory"]:home;
org_home = user["org_homeDirectory"]:org_home;
crypted_home_size = GetInt (user["crypted_home_size"]:nil, 0);
mode = user["home_mode"]:default_mode;
password = user["userPassword"]:password;
org_username = user["org_uid"]:org_username;
uid = GetInt (user["uidNumber"]:nil, uid);
gid = GetInt (user["gidNumber"]:nil, gid);
enabled = user["enabled"]:true;
if (user["disabled"]:false)
enabled = false;
shell = user["loginShell"]:shell;
defaultgroup = user["groupname"]:defaultgroup;
addit_data = user["addit_data"]:addit_data;
if (haskey (user, "sn"))
{
if (is (user["sn"]:nil, list))
sn = user["sn",0]:SplitFullName(`sn, cn);
else
sn = user["sn"]:SplitFullName(`sn, cn);
}
if (haskey (user, "givenName"))
{
if (is (user["givenName"]:nil, list))
givenname = user["givenName",0]:SplitFullName(`givenname, cn);
else if (is (user["givenName"]:nil, string))
givenname = user["givenName"]:SplitFullName(`givenname, cn);
}
chown_home = user["chown_home"]:chown_home;
no_skel = user["no_skeleton"]:no_skel;
groups = user["grouplist"]:$[];
do_not_edit = (user_type == "nis");
}
/**
* helper function: show a popup if existing home directory should be used
* and its ownership should be changed
*/
map ask_chown_home (string dir, boolean chown_default) {
UI::OpenDialog (`opt(`decorated), `HBox(`HSpacing (1), `VBox (
`VSpacing (0.2),
// popup label, %1 is path to directory
`Label (sformat (_("The home directory (%1) already exists.
Use it anyway?"), dir)),
`Left (
// checkbox label
`CheckBox (`id(`chown_home), _("&Change directory owner"),
chown_default)
),
`HBox(
`PushButton (`id(`yes), `opt(`default), Label::YesButton()),
`PushButton (`id(`no), Label::NoButton())
),
`VSpacing (0.2)
), `HSpacing (1)));
any ui = UI::UserInput ();
map retmap = $[
"retval" : ui == `yes
];
if (ui == `yes)
retmap["chown_home"] = UI::QueryWidget (`id (`chown_home),`Value);
UI::CloseDialog ();
return retmap;
}
/**
* generate contents for User Data Dialog
*/
define term get_edit_term () {
// text entry
string fullnamelabel = _("User's &Full Name");
term name_entries = what == "add_user" ?
`InputField (`id (`cn), `opt (`notify), fullnamelabel, cn) :
`InputField (`id (`cn), fullnamelabel, cn);
if (user_type == "ldap")
{
name_entries = `HBox (
// text entry
`InputField (`id(`givenname), _("&First Name"), givenname),
`HSpacing (0.8),
// text entry
`InputField (`id(`sn), _("&Last Name"), sn)
);
}
term fields = `VBox(
// label text
do_not_edit ? `Label(_("For remote users, only additional group memberships can be changed.")) : `VSpacing (0),
do_not_edit ? `VSpacing (1) : `VSpacing (0),
name_entries,
`InputField (`id (`username), (what == "add_user") ?
`opt (`notify, `hstretch) : `opt (`hstretch),
// input field for login name
_("&Username"), username
),
`VSpacing (),
`Password(`id(`pw1), `opt (`hstretch), Label::Password(), ""),
`Password(`id(`pw2), `opt (`hstretch), Label::ConfirmPassword(), "")
);
term optionbox = `VBox (
// checkbox label
`Left (`CheckBox (`id (`root_mail),_("Receive S&ystem Mail"),
root_mail_checked))
);
if (complex_layout)
{
optionbox = add (optionbox,
// checkbox label
`Left( `CheckBox (`id (`autologin),_("A&utomatic Login"),
Autologin::used) )
);
any root_pw_feature = ProductFeatures::GetFeature ("globals", "root_password_as_first_user");
if (root_pw_feature != "")
optionbox = add (optionbox,
`Left (`CheckBox (`id (`root_pw),
// checkbox label
_("U&se this password for system administrator"), root_pw_feature == true)
));
}
else if (!do_not_edit && !installation ())
{
optionbox = add (optionbox,
// check box label
`Left(`CheckBox (`id(`ena), _("D&isable User Login"), !enabled))
);
}
term contents = `VBox (
`VSpacing(),
`VBox (
`VSpacing( 0.5 ),
`HBox (
`HSpacing (2),
`VBox (
`HSquash ( fields ),
`VSpacing( 0.5 ),
`HBox (
`HStretch (),
`HCenter (`HVSquash (optionbox)),
`HStretch ()
)
),
`HSpacing( 2 )
),
`VSpacing (0.5)
)
);
if (complex_layout)
{
contents = add ( contents, `VBox (
`HCenter(`PushButton(`id(`additional), `opt(`key_F3),
// push button
_("User &Management") ) ),
`VSpacing (0.5))
);
}
return `HVCenter (contents);
}
/**
* generate contents for User Details Dialog
*/
define term get_details_term () {
list available_groups = [];
list additional_groups = [];
list additional_ldap_groups = [];
boolean defaultgroup_shown = false;
// fill the list available_groups and set the user default group true
foreach (string grouptype, map<string,integer> groupmap, all_groupnames,
{
if (grouptype == "local" || grouptype == "system" ||
(grouptype == "ldap" && user_type == "ldap"))
{
foreach (string group, integer val, groupmap, {
if (user_type == "ldap")
{
if (grouptype == "ldap")
{
if ( group == defaultgroup )
{
available_groups = add (available_groups,
`item( `id(group), group, true));
defaultgroup_shown = true;
}
else
available_groups = add (available_groups,
`item( `id(group), group));
if ( haskey (groups, group))
additional_ldap_groups = add (additional_ldap_groups,
`item( `id(group), group, true ));
else
additional_ldap_groups = add (additional_ldap_groups,
`item( `id(group), group, false));
}
else
{
// if there is a group with same name, use only that
// with type "ldap"
if ( all_groupnames ["ldap",group]:0 == 1 )
return;
if ( haskey (groups, group))
additional_groups = add (additional_groups,
`item( `id(group), group, true ));
else
additional_groups = add (additional_groups,
`item( `id(group), group, false));
}
}
else
{
if ( group == defaultgroup )
{
available_groups = add (available_groups,
`item( `id(group), group, true));
defaultgroup_shown = true;
}
else
available_groups = add (available_groups,
`item( `id(group), group));
if ( haskey (groups, group))
additional_groups = add (additional_groups,
`item( `id(group), group, true ));
else
additional_groups = add (additional_groups,
`item( `id(group), group, false));
}
});
}
});
// show default group, even if the type is 'wrong' (#43433)
if (!defaultgroup_shown)
{
if (all_groupnames ["local", defaultgroup]:0 == 1 ||
all_groupnames ["system", defaultgroup]:0 == 1)
{
available_groups = add (available_groups,
`item( `id(defaultgroup), defaultgroup, true));
}
}
if (defaultgroup == "")
{
available_groups = add (available_groups,
// group name is not known (combobox item):
`item( `id(""), _("(Unknown)"), true));
}
term edit_defaultgroup = `ComboBox(`id(`defaultgroup), `opt(`hstretch),
// combobox label
_("De&fault Group"), available_groups );
term edit_shell = `ComboBox(`id(`shell), `opt(`hstretch, `editable),
// combobox label
_("Login &Shell"), available_shells );
term additional_data = `Empty();
if (user_type == "system" || user_type == "local")
additional_data = `Top (`InputField (`id(`addd), `opt(`hstretch),
// textentry label
_("Addi&tional User Information"), addit_data)
);
term browse = `VBox(
`Label (""),
// button label
`PushButton( `id(`browse), `opt(`key_F6), _("B&rowse...")),
action != "edited" ? `Empty () : `Label ("")
);
term home_w = `VBox(
// textentry label
`InputField (`id(`home),`opt(`hstretch),_("&Home Directory"), home),
action != "edited" ? `Empty () :
`HBox (`HSpacing (), `Left (`CheckBox (`id (`move_home),
// check box label
_("&Move to New Location"), create_home))
)
);
term new_user_term = action != "added" ? `VBox () : `VBox (
`InputField (`id(`mode), `opt (`hstretch),
// textentry label
_("Home Directory &Permission Mode"), mode),
// check box label
`HBox (`HSpacing (), `Left (
`CheckBox (`id(`skel), _("E&mpty Home"), no_skel))
)
);
term crypted_home_term = crypted_home_enabled ? `HBox (
`VBox (
`Label (""),
`HBox (`HSpacing (), `Left (
`CheckBox (`id(`crypted_home), `opt (`notify),
// check box label
_("&Use Encrypted Home Directory"), crypted_home_size > 0))
)
),
// IntField label
`IntField (`id (`dirsize), _("&Directory Size in MB"), 10, 2147483647, crypted_home_size) // for max value, see bug 244631 :-)
) : `HBox ();
return `HBox (
`HSpacing(1),
`VBox(
// label
do_not_edit ? `Label(_("For remote users, only additional
group memberships can be changed.")) : `VSpacing (0),
`VSpacing(0.5),
`HBox(
text_mode ? `Empty () : `HSpacing (1),
`HWeight (3, `VBox(
`VSpacing (0.5),
`Top(`InputField( `id(`uid), `opt (`hstretch),
// textentry label
_("User &ID (uid)"), sformat("%1",uid ))),
`Top(`VBox(
`HBox ( home_w, browse),
new_user_term,
crypted_home_term
)),
additional_data,
`Top(edit_shell),
`Top(edit_defaultgroup),
`VStretch()
)),
text_mode ? `Empty () : `HSpacing (2),
`HWeight (2, `VBox (
`VSpacing (0.5),
`MultiSelectionBox( `id(`grouplist),
// selection box label
_("Additional Gr&oups"), additional_groups),
(user_type == "ldap")
? `MultiSelectionBox( `id(`ldapgrouplist),
// selection box label
_("&LDAP Groups"), additional_ldap_groups)
: `Empty()
)),
text_mode ? `Empty () : `HSpacing (1)
),
`VSpacing(0.5)
),
`HSpacing(1)
);
}
/**
* generate contents for Password Settings Dialog
*/
define term get_password_term () {
string last_change = GetString (user["shadowLastChange"]:nil, "0");
string last_change_label= "";
string expires = GetString (user["shadowExpire"]:nil, "0");
if (expires == "")
expires = "0";
integer inact = GetInt (user["shadowInactive"]:nil, -1);
integer max = GetInt (user["shadowMax"]:nil, -1);
integer min = GetInt (user["shadowMin"]:nil, -1);
integer warn = GetInt (user["shadowWarning"]:nil, -1);
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_label = out["stdout"]:_("Unknown");
}
else
{
// label (date of last password change)
last_change_label = _("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");
}
return `HBox (
`HSpacing (3),
`VBox (
`VStretch(),
`Left (`Label ("")),
`HSquash(`VBox(
`Left (`Label (sformat (
// label
_("Last Password Change: %1"), last_change_label ))),
`VSpacing (0.2),
`Left (
// check box label
`CheckBox (`id (`force_pw), _("Force Password Change"),
last_change == "0")
),
`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),
`InputField (`id ("shadowExpire"), `opt (`hstretch),
// textentry label
_("Ex&piration Date"), exp_date)
)),
`VStretch ()),
`HSpacing (3)
);
}
/**
* generate contents for Plugins Dialog
*/
define term get_plugins_term () {
plugin_client = clients[0]:"";
plugin = client2plugin[plugin_client]:plugin_client;
list items = [];
foreach (string cl, clients, {
any summary = WFM::CallFunction (cl, ["Summary", $["what" : "user"]]);
string pl = client2plugin[cl]:cl;
if (is (summary, string))
items = add (items, `item(`id(cl),
contains (user["plugins"]:[], pl) ?
UI::Glyph (`CheckMark) : " ",
summary)
);
});
return `HBox (`HSpacing (0.5), `VBox (
`Table (`id(`table), `opt(`notify), `header (" ",
// table header
_("Plug-In Description")), items
),
`HBox (
`PushButton (`id(`change), `opt(`key_F3),
// pushbutton label
_("Add &or Remove Plug-In")),
// pushbutton label
`Right (`PushButton(`id(`run), `opt(`key_F6), _("&Launch")))
),
`VSpacing (0.5)
), `HSpacing (0.5));
}
map dialog_labels = $[
"add_user": $[
// dialog caption:
"local": _("New Local User"),
// dialog caption:
"system": _("New System User"),
// dialog caption:
"ldap": _("New LDAP User")
],
"edit_user": $[
// dialog caption:
"local": _("Existing Local User"),
// dialog caption:
"system": _("Existing System User"),
// dialog caption:
"ldap": _("Existing LDAP User"),
// dialog caption:
"nis": _("Existing NIS User")
]
];
list<term> tabs = [
// tab label
`item(`id(`edit), _("Us&er Data"), true),
// tab label
`item(`id(`details), _("&Details") ),
];
if (!do_not_edit && user_type != "ldap")
{
// tab label
tabs = add (tabs,`item(`id(`passwordsettings),_("Pass&word Settings")));
}
// Now initialize the list of plugins: we must know now if there is some available.
// UsersPlugins will filter out plugins we cannot use for given type
map plugin_clients = UsersPlugins::Apply ("GUIClient",
$[ "what" : "user", "type" : user_type ], $[]
);
// remove empty clients
plugin_clients = filter (string plugin, string client,
(map<string,string>) plugin_clients, ``(client != ""));
clients = maplist (string plugin, string client, (map<string,string>) plugin_clients, {
client2plugin [client] = plugin;
return client;
});
if (clients != [])
{
// tab label
tabs = add (tabs, `item(`id(`plugins), _("Plu&g-Ins") ));
}
term dialog_contents = `VBox (
`DumbTab (`id(`tabs), tabs,
`ReplacePoint(`id(`tabContents ), get_edit_term ()))
);
boolean has_tabs = true;
if (!UI::HasSpecialWidget (`DumbTab))
{
has_tabs = false;
term tabbar = `HBox ();
foreach (term it, tabs, {
string label = it[1]:"";
tabbar = add (tabbar,`PushButton (it[0]:`id(label), label));
});
dialog_contents = `VBox (`Left(tabbar),
`Frame ("", `ReplacePoint(`id(`tabContents), get_edit_term ()))
);
}
if (complex_layout)
{
dialog_contents = `ReplacePoint(`id(`tabContents), get_edit_term ());
Wizard::SetContents (
dialog_labels [ what, user_type ]:"",
dialog_contents,
EditUserDialogHelp (complex_layout, user_type, what),
GetInstArgs::enable_back(),
GetInstArgs::enable_next()
);
}
else{
Wizard::SetContentsButtons (
dialog_labels [ what, user_type ]:"",
dialog_contents,
EditUserDialogHelp (complex_layout, user_type, what),
Label::CancelButton(),
Label::OKButton()
);
Wizard::HideAbortButton ();
}
symbol ret = `edit;
symbol current = nil;
boolean login_modified = false;
list tabids = [ `edit, `details, `passwordsettings, `plugins ];
map ldap_user_defaults = UsersLDAP::GetUserDefaults ();
// switch focus to specified tab (after error message) and widget inside
define void focus_tab (symbol tab, any widget) {
if (has_tabs)
UI::ChangeWidget (`id (`tabs), `CurrentItem, tab);
UI::SetFocus (`id (widget));
ret = `notnext;
}
// map with id's of confirmed questions
map<string,any> ui_map = $[];
while (true)
{
// map returned from Check*UI functions
map error_map = $[];
// error message
string error = "";
if (current != nil)
{
ret = (symbol) UI::UserInput ();
}
if ((ret == `abort || ret == `cancel) && ReallyAbort () != `abort)
{
ret = `notnext;
continue;
}
if (contains ([`abort,`back,`cancel], ret))
break;
if (ret == `ok)
ret = `next;
boolean tab = contains (tabids, ret);
if (tab && ret == current)
{
continue;
}
// ------------------- handle actions inside the tabs
// 1. click inside User Data dialog or moving outside of it
if (current == `edit)
{
username = (string) UI::QueryWidget(`id(`username), `Value);
// empty username during installation (-> go to next module)
if (username == "" && ret ==`next && Users::StartDialog("user_add"))
{
// The user login field is empty, this is allowed if the
// system is part of a network with (e.g.) NIS user management.
// yes-no popup headline
if (Popup::YesNoHeadline(_("Empty User Login"),
// yes-no popup contents
_("Leaving the user name empty only makes sense
in a network environment with an authentication server.
Leave it empty?")))
{
ret = `nextmodule;
break;
}
focus_tab (current, `username);
continue;
}
// now gather user data from dialog
if (user_type == "ldap")
{
// Form the fullname for LDAP user
// sn (surname) and cn (fullname) are required attributes,
// they cannot be empty
givenname = (string) UI::QueryWidget(`id(`givenname), `Value);
sn = (string) UI::QueryWidget(`id(`sn ), `Value);
// create default cn/sn if they are not marked for substitution
if (sn == "" &&
(what == "edit_user" ||
!haskey (ldap_user_defaults, "sn")))
{
if (givenname == "")
{
sn = username;
}
else
{
sn = givenname;
givenname = "";
}
}
if (cn == "" &&
// no substitution when editing: TODO bug 238282
(what == "edit_user" ||
// cn should not be substitued:
!haskey (ldap_user_defaults, "cn")))
{
// if 'givenname' or 'sn' should be substitued, wait for it
// and do not create cn now:
if (!haskey (ldap_user_defaults, "sn") &&
!haskey (ldap_user_defaults, "givenName"))
{
cn = givenname + ((givenname != "") ? " " : "") + sn;
}
}
UI::ChangeWidget(`id(`givenname), `Value, givenname);
UI::ChangeWidget(`id(`sn), `Value, sn);
}
else
{
cn = (string) UI::QueryWidget(`id(`cn), `Value);
error = UsersSimple::CheckFullname (cn);
if (error != "")
{
Report::Error (error);
focus_tab (current, `cn);
continue;
}
}
if (haskey (user, "givenName") && is (user["givenName"]:nil, list))
user ["givenName",0] = givenname;
else
user ["givenName"] = givenname;
if (haskey (user, "sn") && is (user["sn"]:nil, list))
user["sn",0] = sn;
else
user ["sn"] = sn;
if (haskey (user, "cn") && is (user["cn"]:nil, list))
user["cn",0] = cn;
else
user ["cn"] = cn;
// generate a login name from the full name
// (not for LDAP, there are customized rules...)
if (ret == `cn)
{
string uname =
(string) UI::QueryWidget (`id (`username), `Value);
if (login_modified && uname == "")
login_modified = false; // reenable suggestion
if (!login_modified)
{
string full = (string)UI::QueryWidget (`id (ret), `Value);
full = splitstring (full, " ")[0]:"";
full = UsersSimple::Transliterate (full);
UI::ChangeWidget (`id (`username), `Value, tolower (
filterchars (full, UsersSimple::ValidLognameChars ()))
);
}
}
if (ret == `username)
{
login_modified = true;
}
// in continue mode: move to 'User Management' without adding user
if (ret == `additional)
{
if (username == "" &&
((user_type == "ldap" && cn == "" && givenname == "") ||
(user_type != "ldap" && cn == ""))
)
ret = `nosave;
}
}
// now check if currently added user data are correct
// (going out from User Data tab)
if (current == `edit && !do_not_edit &&
(ret == `next || ret == `additional || tab))
{
// --------------------------------- username checks, part 1/2
error = Users::CheckUsername (username);
if (error != "")
{
Report::Error (error);
focus_tab (current, `username);
continue;
}
user["uid"] = username;
// --------------------------------- uid check (for nil value)
if (!tab && uid == nil)
{
error = Users::CheckUID (uid);
if (error != "")
{
Report::Error (error);
focus_tab (current, `details);
continue;
}
}
// --------------------------------- password checks
string pw1 = (string) UI::QueryWidget(`id(`pw1), `Value);
string pw2 = (string) UI::QueryWidget(`id(`pw2), `Value);
if (pw1 != pw2)
{
// The two user password information do not match
// error popup
Report::Error(_("The passwords do not match.
Try again."));
focus_tab (current, `pw1);
continue;
}
if ((pw1 != "" || !tab) && pw1 != default_pw)
{
error = UsersSimple::CheckPassword (pw1, user_type);
if (error != "")
{
Report::Error (error);
focus_tab (current, `pw1);
continue;
}
list<string> errors = UsersSimple::CheckPasswordUI ($[
"uid" : username,
"userPassword" : pw1,
"type" : user_type
]);
if (errors != [])
{
string message = mergestring (errors, "\n\n") +
// last part of message popup
"\n\n" + _("Really use this password?");
if (!Popup::YesNo (message))
{
focus_tab (current, `pw1);
continue;
}
}
// now saving plain text password
if (user["encrypted"]:false)
user["encrypted"] = false;
user ["userPassword"] = pw1;
user ["shadowLastChange"] = Users::LastChangeIsNow();
password = pw1;
}
// build default home dir
if (home == "" || home == default_home || issubstring (home,"%"))
{
// LDAP: maybe value of homedirectory should be substituted?
if (user_type == "ldap" && issubstring (home, "%"))
{
user = UsersLDAP::SubstituteValues ("user", user);
home = user["homeDirectory"]:default_home;
}
if (home == default_home || home == "")
home = default_home + username;
}
if (ret != `details && username != org_username)
{
string generated_home = default_home + username;
if (user_type == "ldap" && issubstring (default_home, "%"))
{
map tmp_user = UsersLDAP::SubstituteValues ("user", user);
generated_home = tmp_user["homeDirectory"]:home;
}
if (home != generated_home &&
(what == "add_user" || Popup::YesNo (sformat (
// popup question
_("Change home directory to %1?"), generated_home))))
{
home = generated_home;
}
}
// -------------------------------------- directory checks
if (!tab && home != org_home)
{
error = Users::CheckHome (home);
if (error != "")
{
Report::Error (error);
ret = `notnext;
continue;
}
boolean failed = false;
do
{
error_map = Users::CheckHomeUI (uid, home, ui_map);
if (error_map != $[])
{
if (error_map["question_id"]:"" == "chown" &&
!haskey (error_map, "owned"))
{
map ret = ask_chown_home (home, chown_home);
if (ret["retval"]:false)
{
ui_map["chown"] = home;
chown_home = ret["chown_home"]:chown_home;
}
else
failed = true;
}
else
{
if (!Popup::YesNo (error_map ["question"]:""))
failed = true;
else
ui_map[ error_map["question_id"]:"" ] = home;
}
}
} while (error_map != $[] && !failed);
if (failed)
{
ret = `notnext;
continue;
}
}
user["homeDirectory"] = home;
user["chown_home"] = chown_home;
// --------------------------------- username checks, part 2/2
if (what == "add_user" || username != org_username)
{
if (AskForUppercasePopup (username) != `ok)
{
focus_tab (current, `username);
continue;
}
}
// --------------------------------- autologin (during installation)
if (Users::StartDialog ("user_add") && installation ())
{
if (Autologin::available)
{
Autologin::user = (boolean)
UI::QueryWidget(`id (`autologin),`Value) ? username: "";
Autologin::used = (boolean)
UI::QueryWidget(`id (`autologin),`Value);
Autologin::modified = true;
}
}
else if (UI::WidgetExists (`id (`ena)))
{
// -------------------------------------- enable/disable checks
boolean new_enabled = !(boolean)
UI::QueryWidget(`id(`ena), `Value);
if (enabled != new_enabled)
{
enabled = new_enabled;
if (enabled)
{
user["enabled"] = true;
if (haskey (user,"disabled"))
user ["disabled"] = false;
}
else
{
user["disabled"] = true;
if (haskey (user,"enabled"))
user ["enabled"] = false;
}
}
}
root_mail_checked =
(boolean) UI::QueryWidget (`id (`root_mail), `Value);
root_pw = UI::WidgetExists (`id (`root_pw)) &&
(boolean) UI::QueryWidget (`id (`root_pw), `Value);
// save the username for possible check if it was changed
// and home directory should be re-generated
if (org_username == "")
org_username = username;
}
// indide Details dialog
if (current == `details && ret == `browse)
{
string dir = home;
if (SCR::Read(.target.size, home ) == -1)
{
dir = Users::GetDefaultHome (new_type);
}
dir = UI::AskForExistingDirectory (dir, "");
if (dir != nil)
{
if ((findlastof (dir, "/") + 1) == size(dir))
dir = substring (dir, 0, size(dir)-1);
UI::ChangeWidget (`id(`home), `Value, dir);
}
}
if (current == `details && ret == `crypted_home)
{
boolean checked = (boolean) UI::QueryWidget (`id (`crypted_home), `Value);
if (!checked && UserLogged (org_username))
{
// error popup
Report::Error(_("The home directory for this user cannot be decrypted,
because the user is currently logged in.
Log the user out first."));
UI::ChangeWidget (`id (`crypted_home), `Value, true);
continue;
}
if (checked && (integer) UI::QueryWidget (`id (`dirsize), `Value) == 10)
UI::ChangeWidget (`id (`dirsize), `Value, default_crypted_size);
UI::ChangeWidget (`id (`dirsize), `Enabled, checked);
}
// going from Details dialog
if (current == `details && (ret == `next || tab))
{
string new_shell = (string)UI::QueryWidget(`id(`shell), `Value);
string new_uid = (string)UI::QueryWidget(`id(`uid), `Value);
string new_defaultgroup = (string)
UI::QueryWidget(`id(`defaultgroup),`Value);
string new_home = (string) UI::QueryWidget(`id(`home), `Value);
if (what == "add_user")
{
no_skel = (boolean) UI::QueryWidget(`id(`skel),`Value);
mode = (string) UI::QueryWidget(`id(`mode), `Value);
}
if ((findlastof (new_home, "/") + 1) == size (new_home))
{
new_home = substring (new_home, 0, size(new_home)-1);
}
if (do_not_edit)
{
new_home = home;
new_shell = shell;
new_uid = sformat("%1", uid);
new_defaultgroup = defaultgroup;
}
integer new_i_uid = tointeger (new_uid);
// additional data in GECOS field (passwd only)
if (new_type == "local" || new_type == "system")
{
addit_data = (string) UI::QueryWidget(`id(`addd), `Value);
string error = Users::CheckGECOS (addit_data);
if (error != "")
{
Report::Error (error);
focus_tab (current, `addd);
ret = `notnext;
continue;
}
}
// check the uid
if (new_i_uid != uid)
{
string error = Users::CheckUID (new_i_uid);
if (error != "")
{
Report::Error (error);
focus_tab (current, `uid);
continue;
}
boolean failed = false;
do
{
error_map = Users::CheckUIDUI (new_i_uid, ui_map);
if (error_map != $[])
{
if (!Popup::YesNo (error_map ["question"]:""))
{
focus_tab (current, `uid);
failed = true;
}
else
{
ui_map[ error_map["question_id"]:"" ] = new_i_uid;
if(contains(["local","system"],
error_map["question_id"]:""))
{
new_type = error_map["question_id"]:"local";
UsersCache::SetUserType (new_type);
}
}
}
} while (error_map != $[] && !failed);
if (failed)
{
focus_tab (current, `uid);
continue;
}
} // end of uid checks
if (defaultgroup != new_defaultgroup)
{
map g = Users::GetGroupByName (new_defaultgroup, new_type);
if (g == $[])
g = Users::GetGroupByName (new_defaultgroup, "");
gid = GetInt (g["gidNumber"]:nil, gid);
}
// check the homedirectory
if (home != new_home || what == "add_user")
{
string error = Users::CheckHome (new_home);
if (error != "")
{
Report::Error (error);
focus_tab (current, `home);
continue;
}
boolean failed = false;
do
{
error_map = Users::CheckHomeUI(new_i_uid, new_home, ui_map);
if (error_map != $[])
{
if (error_map["question_id"]:"" == "chown" &&
!haskey (error_map, "owned"))
{
map ret = ask_chown_home (new_home, chown_home);
if (ret["retval"]:false)
{
ui_map["chown"] = new_home;
chown_home = ret["chown_home"]:chown_home;
}
else
failed = true;
}
else
{
if (!Popup::YesNo (error_map ["question"]:""))
failed = true;
else
ui_map[ error_map["question_id"]:""] = new_home;
}
}
} while (error_map != $[] && !failed);
if (failed)
{
focus_tab (current, `home);
continue;
}
}
if (crypted_home_enabled)
{
integer home_size = (integer)UI::QueryWidget (`id (`dirsize), `Value);
if ((boolean)UI::QueryWidget (`id (`crypted_home), `Value))
{
if (home_size == 0)
{
// error popup
Popup::Error (_("Enter the size for the home directory."));
focus_tab (current, `dirsize);
continue;
}
crypted_home_size = home_size;
}
else crypted_home_size = 0;
}
error_map = Users::CheckShellUI (new_shell, ui_map);
if (error_map != $[])
{
if (!Popup::YesNo (error_map ["question"]:""))
{
focus_tab (current, `shell);
continue;
}
else
ui_map[ error_map["question_id"]:"" ] = new_shell;
}
// generate new map of groups (NIS groups were not shown!)
map<string,integer> new_groups = listmap (
string g, (list<string>)
UI::QueryWidget(`id(`grouplist), `SelectedItems), ``($[g:1])
);
if (new_type == "ldap")
{
foreach (string group, (list<string>)
UI::QueryWidget (`id(`ldapgrouplist),`SelectedItems), {
new_groups = add (new_groups, group, 1);
});
}
// now add NIS groups again (were not shown in dialog)
foreach (string group, integer val, nis_groups, {
if (!haskey (new_groups, group))
new_groups = add (new_groups, group, 1);
});
// TODO remove from local g. when there is nis g. with same name
if (do_not_edit && !grouplist_modified && groups != new_groups)
grouplist_modified = true;
if (new_home == "/var/lib/nobody")
{
create_home = false;
chown_home = false;
}
if (UI::WidgetExists (`id (`move_home)) &&
UI::QueryWidget (`id (`move_home), `Value) == false)
create_home = false;
home = new_home;
shell = new_shell;
uid = new_i_uid;
groups = new_groups;
defaultgroup = new_defaultgroup;
user_type = new_type;
user["homeDirectory"] = new_home;
user["loginShell"] = new_shell;
user["gidNumber"] = gid;
user["uidNumber"] = new_i_uid;
user["grouplist"] = new_groups;
user["groupname"] = new_defaultgroup;
user["type"] = new_type;
user["create_home"] = create_home;
user["chown_home"] = chown_home;
user["addit_data"] = addit_data;
user["no_skeleton"] = no_skel;
user["home_mode"] = mode;
user["crypted_home_size"] = crypted_home_size;
}
if (current == `passwordsettings && (ret == `next || tab))
{
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."));
focus_tab (current, "shadowExpire");
continue;
}
foreach (string shadowsymbol,
["shadowWarning", "shadowMax", "shadowMin", "shadowInactive"],
{
if (user[shadowsymbol]:nil != UI::QueryWidget (
`id(shadowsymbol), `Value))
{
user[shadowsymbol] = sformat ("%1",
UI::QueryWidget(`id(shadowsymbol), `Value));
}
});
string new_exp_date = (string)
UI::QueryWidget(`id("shadowExpire"),`Value);
if (new_exp_date != exp_date)
{
exp_date = new_exp_date;
if (exp_date == "")
{
user["shadowExpire"] = (user_type == "ldap") ? "" : "0";
}
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);
user["shadowExpire"] = sformat("%1", days);
}
}
}
if (UI::QueryWidget (`id (`force_pw), `Value) == true)
{
// force password change
user["shadowLastChange"] = "0";
}
}
// inside plugins dialog
if (current == `plugins)
{
plugin_client = (string) UI::QueryWidget (`id(`table),`CurrentItem);
if (plugin_client != nil)
{
plugin = client2plugin[plugin_client]:plugin_client;
}
if (ret == `table || ret == `change)
{
ret = contains (user["plugins"]:[], plugin) ? `del : `add;
}
if (ret == `del)
{
map out = UsersPlugins::Apply ("PluginRemovable",
$[ "what" : "user",
"type" : user_type,
"plugins": [ plugin ],
], $[]);
// check if plugin _could_ be deleted!
if (haskey (out, plugin) && ! (out[plugin]:false))
{
// popup message
Popup::Message (_("This plug-in cannot be removed."));
ret = `not_next;
continue;
}
}
if (ret == `add || ret == `del || ret == `run)
{
// functions for adding/deleting/launching plugin work on
// Users::user_in_work, so we must update it before
if (what == "edit_user")
{
Users::EditUser (user);
}
else
{
Users::AddUser (user);
}
}
if (ret == `add)
{
error = Users::AddUserPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
user = Users::GetCurrentUser ();
reinit_userdata ();
UI::ChangeWidget (`id(`table), `Item (plugin_client,0),
UI::Glyph (`CheckMark));
}
if (ret == `del)
{
error = Users::RemoveUserPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
user = Users::GetCurrentUser ();
reinit_userdata ();
UI::ChangeWidget (`id(`table), `Item (plugin_client,0), " ");
}
if (ret == `run)
{
boolean plugin_added = false;
// first, add the plugin if necessary
if (!contains (user["plugins"]:[], plugin))
{
error = Users::AddUserPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
plugin_added = true;
user = Users::GetCurrentUser ();
reinit_userdata ();
}
any plugin_ret = WFM::CallFunction (
plugin_client, ["Dialog", $[ "what" : "user" ], user ]);
if (plugin_ret == `next)
{
// update the map of changed user
user = Users::GetCurrentUser ();
reinit_userdata ();
UI::ChangeWidget (`id(`table), `Item (plugin_client,0), UI::Glyph (`CheckMark));
}
// for `cancel we must remove the plugin if it was added because of `run
else if (plugin_added)
{
error = Users::RemoveUserPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
user = Users::GetCurrentUser ();
reinit_userdata ();
}
}
}
// ------------------- now handle switching between the tabs
if (ret == `edit)
{
Wizard::SetHelpText (
EditUserDialogHelp (installation (), user_type, what));
UI::ReplaceWidget(`tabContents, get_edit_term ());
// update the contets of User Data Dialog
if (do_not_edit)
{
UI::ChangeWidget (`id(`cn), `Enabled, false);
UI::ChangeWidget (`id(`username), `Enabled, false);
UI::ChangeWidget (`id(`pw1), `Enabled, false);
UI::ChangeWidget (`id(`pw2), `Enabled, false);
}
if (what == "add_user")
{
if (user_type == "ldap")
UI::SetFocus(`id(`givenname));
else
UI::SetFocus(`id(`cn));
}
if (password != nil || what == "edit_user")
{
UI::ChangeWidget(`id(`pw1), `Value, default_pw);
UI::ChangeWidget(`id(`pw2), `Value, default_pw);
}
if (complex_layout && !Autologin::available)
{
UI::ChangeWidget(`id(`autologin), `Enabled, false);
UI::ChangeWidget(`id(`autologin), `Value, false);
}
// LDAP users can be disabled only with certain plugins (bnc#557714)
if (UI::WidgetExists (`id (`ena)) && user_type == "ldap")
{
boolean ena = (
contains (user["plugins"]:[], "UsersPluginLDAPShadowAccount") ||
contains (user["plugins"]:[], "UsersPluginLDAPPasswordPolicy"));
UI::ChangeWidget (`id (`ena), `Enabled, ena);
}
current = ret;
}
if (ret == `details)
{
UI::ReplaceWidget(`tabContents, get_details_term ());
Wizard::SetHelpText (EditUserDetailsDialogHelp (user_type, what));
if (do_not_edit)
{
UI::ChangeWidget (`id (`uid), `Enabled, false);
UI::ChangeWidget (`id (`home), `Enabled, false);
UI::ChangeWidget (`id (`move_home), `Enabled, false);
UI::ChangeWidget (`id (`shell), `Enabled, false);
UI::ChangeWidget (`id (`defaultgroup), `Enabled, false);
UI::ChangeWidget (`id (`browse), `Enabled, false);
}
if (user_type == "ldap" && !Ldap::file_server)
{
UI::ChangeWidget (`id (`browse), `Enabled, false);
if (UI::WidgetExists (`id (`move_home)))
UI::ChangeWidget (`id (`move_home), `Enabled, false);
}
if (!FileUtils::Exists (home) && UI::WidgetExists (`id (`move_home)))
{
UI::ChangeWidget (`id (`move_home), `Enabled, false);
}
if (UI::WidgetExists (`id (`mode)))
{
UI::ChangeWidget (`id (`mode), `ValidChars, "01234567");
UI::ChangeWidget (`id (`mode), `InputMaxLength, 3);
}
UI::ChangeWidget(`id(`shell), `Value, shell);
if (UI::WidgetExists (`id (`crypted_home)))
UI::ChangeWidget (`id (`dirsize), `Enabled,
(boolean) UI::QueryWidget (`id (`crypted_home), `Value));
current = ret;
}
if (ret == `passwordsettings)
{
UI::ReplaceWidget(`tabContents, get_password_term ());
if (GetString (user["shadowLastChange"]:nil, "0") == "0")
{
// forcing password change cannot be undone
UI::ChangeWidget (`id (`force_pw), `Enabled, false);
}
Wizard::SetHelpText (EditUserPasswordDialogHelp());
current = ret;
}
if (ret == `plugins)
{
UI::ReplaceWidget(`tabContents, get_plugins_term ());
Wizard::SetHelpText (PluginDialogHelp ());
UI::ChangeWidget (`id(`table),`CurrentItem, plugin_client);
current = ret;
}
if ((ret == `next || ret == `additional) &&
// for do_not_edit, there may be a change in groups (Details dialog)
(!do_not_edit || grouplist_modified))
{
// --------------------------------- final check
error = Users::CheckUser (user);
if (error != "")
{
Report::Error (error);
ret = `notnext;
continue;
}
if ((crypted_home_enabled && action == "edited" &&
user["current_text_userpassword"]:nil == nil) &&
(
crypted_home_size != org_crypted_home_size
||
(crypted_home_size > 0 &&
(org_username != username || org_home != home ||
// only password was changed
user["encrypted"]:false == false)
)
)
)
{
// do not ask when enabling for first time and password was already entered
if ((user["encrypted"]:false == false || user["text_userpassword"]:nil != nil) &&
org_crypted_home_size == 0)
{
user["current_text_userpassword"] = (user["text_userpassword"]:nil != nil) ?
user["text_userpassword"]:nil : user["userPassword"]:"";
}
else
{
string old_pw = AskForOldPassword ();
if (old_pw != nil)
{
user["current_text_userpassword"] = old_pw;
}
else
{
ret = `notnext;
continue;
}
}
}
// --------------------------------- save the settings
if (haskey (user, "check_error"))
{
user = remove (user, "check_error");
}
if ( what == "edit_user" )
{
error_msg = Users::EditUser (user);
}
else
{
error_msg = Users::AddUser (user);
}
if (error_msg != "")
{
Report::Error (error_msg);
ret = `notnext;
continue;
}
// check if autologin is not set for some user
if (what == "add_user" && !complex_layout &&
// ask only when there is still one user (bnc#332729)
size (UsersCache::GetUsernames ("local")) == 1)
{
Autologin::AskForDisabling (
// popup text
_("Now you have added a new user."));
}
if (root_mail_checked)
{
if (username != org_username)
Users::RemoveRootAlias (org_username);
Users::AddRootAlias (username);
}
else if (root_mail) // not checked now, but checked before
{
if (username != org_username)
Users::RemoveRootAlias (org_username);
else
Users::RemoveRootAlias (username);
}
if (username == "root")
Users::SaveRootPassword (false);
else if (root_pw)
{
// set root's password
Users::SetRootPassword (password);
Users::SaveRootPassword (true);
}
}
if (contains ([`next,`abort,`back,`cancel,`additional,`nosave], ret))
break;
}
if (ret == `additional || ret == `nosave)
{
// during installation, store the data of first user
// (to show it when clicking `back from Summary dialog)
Users::SaveCurrentUser ();
Users::SetStartDialog ("users");
}
return ret;
}
/**
* Dialog for adding/editing group
* @param what "add_group" or "edit_group"
* @return symbol for wizard sequencer
*/
define symbol EditGroupDialog (string what) {
// create a local copy of current group
map<string,any> group = Users::GetCurrentGroup ();
string groupname = group["cn"]:"";
string password = (string) group["userPassword"]:nil;
integer gid = GetInt (group["gidNumber"]:nil, -1);
// these are the users with this group as a default:
map<string,any> more_users = group["more_users"]:$[];
// these are users from /etc/group:
map<string,any> userlist = group["userlist"]:$[];
string group_type = group["type"]:"";
string new_type = group_type;
list additional_users = [];
string member_attribute = UsersLDAP::GetMemberAttribute ();
if (group_type == "ldap")
{
userlist = group[member_attribute]:$[];
}
boolean more = size (more_users) > 0;
map dialog_labels = $[
"add_group": $[
// dialog caption:
"local": _("New Local Group"),
// dialog caption:
"system": _("New System Group"),
// dialog caption:
"ldap": _("New LDAP Group")
],
"edit_group": $[
// dialog caption:
"local": _("Existing Local Group"),
// dialog caption:
"system": _("Existing System Group"),
// dialog caption:
"ldap": _("Existing LDAP Group")
]
];
string plugin_client = "";
string plugin = "";
map client2plugin = $[];
list<string> clients = [];
/**
* initialize local variables with current state of group
*/
define void reinit_groupdata () {
groupname = group["cn"]:groupname;
password = group["userPassword"]:password;
gid = GetInt (group["gidNumber"]:nil, gid);
more_users = group["more_users"]:more_users;
userlist = group["userlist"]:userlist;
group_type = group["type"]:group_type;
if (group_type == "ldap")
{
userlist = group[member_attribute]:$[];
}
}
/**
* generate contents for Group Data Dialog
*/
define term get_edit_term () {
integer i = 0;
list more_users_items = [];
foreach (string u, any val, more_users, {
if (i <42)
more_users_items = add (more_users_items,`item (`id(u),u,true));
if (i == 42)
more_users_items = add (more_users_items,
`item (`id("-"), "...", false ));
i = i + 1;
});
return `HBox (
`HWeight (1, `VBox(
`VSpacing(1),
`Top (`InputField (`id (`groupname), `opt (`hstretch),
// textentry label
_("Group &Name"), groupname)),
`Top (`InputField (`id (`gid), `opt (`hstretch),
// textentry label
_("Group &ID (gid)"), sformat("%1", gid) )),
`VSpacing(1),
`Bottom (
`Password(`id(`pw1), `opt (`hstretch), Label::Password (), "")),
`Bottom (
`Password(`id(`pw2), `opt (`hstretch), Label::ConfirmPassword(),
"")
),
`VSpacing(1)
)),
`HSpacing(2),
`HWeight (1, `VBox(
`VSpacing(1),
`ReplacePoint (`id(`rpuserlist),
// selection box label
`MultiSelectionBox (`id(`userlist), _("Group &Members"), [])
),
more ? `VSpacing(1) : `VSpacing (0),
more ? `MultiSelectionBox (`id(`more_users), "",
more_users_items) : `VSpacing (0),
`VSpacing(1)
)));
}
/**
* generate contents for Plugins Dialog
*/
define term get_plugins_term () {
plugin_client = clients[0]:"";
plugin = client2plugin[plugin_client]:plugin_client;
list items = [];
foreach (string cl, clients, {
any summary = WFM::CallFunction (cl, ["Summary", $["what" : "group"]]);
string pl = client2plugin[cl]:cl;
if (is (summary, string))
items = add (items, `item(`id(cl),
contains (group["plugins"]:[], pl) ?
UI::Glyph (`CheckMark) : " ",
summary)
);
});
return `HBox (`HSpacing (0.5), `VBox (
`Table (`id(`table), `opt(`notify), `header (" ",
// table header
_("Plug-In Description")), items
),
`HBox (
`PushButton (`id(`change), `opt(`key_F3),
// pushbutton label
_("Add &or Remove Plug-In")),
// pushbutton label
`Right (`PushButton(`id(`run), `opt(`key_F6), _("&Launch")))
),
`VSpacing (0.5)
), `HSpacing (0.5));
}
list<term> tabs = [];
term dialog_contents = `Empty ();
// Now initialize the list of plugins: we must know now if there is some available.
// UsersPlugins will filter out plugins we cannot use for given type
map plugin_clients = UsersPlugins::Apply ("GUIClient",
$[ "what" : "group", "type" : group_type ], $[]
);
// remove empty clients
plugin_clients = filter (string plugin, string client,
(map<string,string>) plugin_clients, ``(client != ""));
clients = maplist (string plugin, string client, (map<string,string>) plugin_clients, {
client2plugin [client] = plugin;
return client;
});
boolean use_tabs = (size (clients) > 0);
boolean has_tabs = true;
if (use_tabs)
{
tabs = [
// tab label
`item(`id(`edit), _("Group &Data"), true),
// tab label
`item(`id(`plugins), _("Plu&g-Ins") )
];
dialog_contents = `VBox (
`DumbTab (`id(`tabs), tabs,
`ReplacePoint(`id(`tabContents ), get_edit_term ()))
);
if (!UI::HasSpecialWidget (`DumbTab))
{
has_tabs = false;
term tabbar = `HBox ();
foreach (term it, tabs, {
string label = it[1]:"";
tabbar = add (tabbar,`PushButton (it[0]:`id(label), label));
});
dialog_contents = `VBox (`Left(tabbar),
`Frame ("", `ReplacePoint(`id(`tabContents), get_edit_term ()))
);
}
}
else
{
dialog_contents = get_edit_term ();
}
Wizard::SetContentsButtons (
dialog_labels [ what, group_type ]:"",
dialog_contents,
EditGroupDialogHelp (more),
Label::CancelButton(), Label::OKButton());
Wizard::HideAbortButton ();
symbol ret = `edit;
symbol current = nil;
list tabids = [`edit, `plugins ];
// switch focus to specified tab (after error message) and widget inside
define void focus_tab (symbol tab, any widget) {
if (use_tabs && has_tabs)
UI::ChangeWidget (`id (`tabs), `CurrentItem, tab);
UI::SetFocus (`id (widget));
ret = `notnext;
}
repeat
{
// map returned from Check*UI functions
map error_map = $[];
// map with id's of confirmed questions
map<string,any> ui_map = $[];
// error message
string error = "";
if (current != nil)
{
ret = (symbol) UI::UserInput ();
}
if ((ret == `abort || ret == `cancel) && ReallyAbort () != `abort)
{
ret = `notnext;
continue;
}
if (contains ([`abort,`back,`cancel], ret))
break;
boolean tab = contains (tabids, ret);
if (tab && ret == current)
{
continue;
}
// 1. click inside Group Data dialog or moving outside of it
if (current == `edit && (ret == `next || tab))
{
string pw1 = (string) UI::QueryWidget(`id(`pw1), `Value);
string pw2 = (string)UI::QueryWidget(`id(`pw2),`Value);
string new_gid = (string)UI::QueryWidget(`id(`gid), `Value);
integer new_i_gid = tointeger(new_gid);
string new_groupname = (string)
UI::QueryWidget(`id(`groupname), `Value);
// --------------------------------- groupname checks
string error = Users::CheckGroupname (new_groupname);
if (error != "")
{
Report::Error (error);
focus_tab (current, `groupname);
continue;
}
// --------------------------------- password checks
if ( pw1 != pw2 )
{
// The two group password information do not match
// error popup
Report::Error(_("The passwords do not match.
Try again.")) ;
focus_tab (current, `pw1);
continue;
}
if ( pw1 != "" && pw1 != default_pw )
{
error = UsersSimple::CheckPassword (pw1, group_type);
if (error != "")
{
Report::Error (error);
focus_tab (current, `pw1);
continue;
}
list<string> errors = UsersSimple::CheckPasswordUI ($[
"cn" : new_groupname,
"userPassword" : pw1,
"type" : group_type
]);
if (errors != [])
{
string message = mergestring (errors, "\n\n") +
// last part of message popup
"\n\n" + _("Really use this password?");
if (!Popup::YesNo (message))
{
focus_tab (current, `pw1);
continue;
}
}
password = pw1;
if (group["encrypted"]:false)
group["encrypted"] = false;
}
// --------------------------------- gid checks
if ( new_i_gid != gid)
{
error = Users::CheckGID (new_i_gid);
if (error != "")
{
Report::Error (error);
focus_tab (current, `gid);
continue;
}
boolean failed = false;
do
{
error_map = Users::CheckGIDUI (new_i_gid, ui_map);
if (error_map != $[])
{
if (!Popup::YesNo (error_map ["question"]:""))
{
failed = true;
}
else
{
ui_map[ error_map["question_id"]:"" ] = new_i_gid;
if(contains(["local","system"],
error_map["question_id"]:""))
{
new_type = error_map["question_id"]:"local";
UsersCache::SetGroupType (new_type);
}
}
}
} while (error_map != $[] && !failed);
if (failed)
{
focus_tab (current, `gid);
continue;
}
}
// --------------------------------- update userlist
map new_userlist = listmap (string user, (list<string>)
UI::QueryWidget (`id(`userlist), `SelectedItems), ``($[user: 1])
);
// --------------------------------- now everything should be OK
group["cn"] = new_groupname;
group["userPassword"] = password;
group["more_users"] = more_users;
group["gidNumber"] = new_i_gid;
group["type"] = new_type;
if (group_type == "ldap")
{
group[member_attribute] = new_userlist;
}
else
{
group["userlist"] = new_userlist;
}
reinit_groupdata ();
}
// inside plugins dialog
if (current == `plugins)
{
plugin_client = (string) UI::QueryWidget (`id(`table),`CurrentItem);
if (plugin_client != nil)
{
plugin = client2plugin[plugin_client]:plugin_client;
}
if (ret == `table || ret == `change)
{
ret = contains (group["plugins"]:[], plugin) ? `del : `add;
}
if (ret == `del)
{
map out = UsersPlugins::Apply ("PluginRemovable",
$[ "what" : "group",
"type" : group_type,
"plugins": [ plugin ],
], $[]);
// check if plugin _could_ be deleted!
if (haskey (out, plugin) && ! (out[plugin]:false))
{
// popup message
Popup::Message (_("This plug-in cannot be removed."));
ret = `not_next;
continue;
}
}
if (ret == `add || ret == `del || ret == `run)
{
// functions for adding/deleting/launching plugin work on
// Users::group_in_work, so we must update it before
if (what == "edit_group")
{
Users::EditGroup (group);
}
else
{
Users::AddGroup (group);
}
}
if (ret == `add)
{
error = Users::AddGroupPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
group = Users::GetCurrentGroup ();
reinit_groupdata ();
UI::ChangeWidget (`id(`table), `Item (plugin_client,0),
UI::Glyph (`CheckMark));
}
if (ret == `del)
{
error = Users::RemoveGroupPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
group = Users::GetCurrentGroup ();
reinit_groupdata ();
UI::ChangeWidget (`id(`table), `Item (plugin_client,0), " ");
}
if (ret == `run)
{
boolean plugin_added = false;
// first, add the plugin if necessary
if (!contains (group["plugins"]:[], plugin))
{
error = Users::AddGroupPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
plugin_added = true;
group = Users::GetCurrentGroup ();
reinit_groupdata ();
}
any plugin_ret = WFM::CallFunction (
plugin_client, ["Dialog", $[ "what" : "group" ], group ]);
if (plugin_ret == `next)
{
// update the map of changed group
group = Users::GetCurrentGroup ();
reinit_groupdata ();
UI::ChangeWidget (`id(`table), `Item (plugin_client,0), UI::Glyph (`CheckMark));
}
else if (plugin_added)
{
error = Users::RemoveGroupPlugin (plugin);
if (error != "")
{
Popup::Error (error);
ret = `notnext;
continue;
}
group = Users::GetCurrentGroup ();
reinit_groupdata ();
}
}
}
// initialize Edit Group tab
if (ret == `edit)
{
if (use_tabs)
{
Wizard::SetHelpText (EditGroupDialogHelp (more));
UI::ReplaceWidget (`tabContents, get_edit_term ());
}
if (what == "add_group") UI::SetFocus(`id(`groupname));
if (what == "edit_group")
{
if (password != nil)
{
UI::ChangeWidget(`id(`pw1), `Value, default_pw);
UI::ChangeWidget(`id(`pw2), `Value, default_pw);
}
}
if (more)
{
// set of users having this group as default - cannot be edited!
UI::ChangeWidget (`id(`more_users), `Enabled, false);
}
additional_users = UsersCache::BuildAdditional (group);
// add items later (when there is a huge amount of them, it takes
// long time to display, so display at least the rest of the dialog)
if (size (additional_users) > 0)
{
UI::ReplaceWidget (`id(`rpuserlist),
`MultiSelectionBox( `id(`userlist), _("Group &Members"),
additional_users)
);
}
current = ret;
}
if (ret == `plugins)
{
UI::ReplaceWidget (`tabContents, get_plugins_term ());
Wizard::SetHelpText (PluginDialogHelp ());
UI::ChangeWidget (`id(`table),`CurrentItem, plugin_client);
current = ret;
}
// save the changes
if (ret == `next)
{
error = Users::CheckGroup (group);
if (error != "")
{
Report::Error (error);
ret = `notnext;
continue;
}
if (what == "edit_group")
error = Users::EditGroup (group);
else
error = Users::AddGroup (group);
if (error != "")
{
Report::Error (error);
ret = `notnext;
continue;
}
}
} until (contains ([`next, `abort, `back, `cancel], ret));
return ret;
}
/**
* Just giving paramaters for commiting user
* @return symbol for wizard sequencer
*/
define symbol UserSave() {
Users::CommitUser ();
// adding only one user during install
if (installation () && Users::StartDialog ("user_add") )
return `save;
else
return `next;
}
/**
* Check the group parameters and commit it if all is OK
* @return symbol for wizard sequencer
*/
define symbol GroupSave() {
map <string,any> group = Users::GetCurrentGroup ();
// do not check group which should be deleted
if (group["what"]:"" != "delete_group")
{
string error = Users::CheckGroup (group);
if (error != "")
{
Report::Error (error);
return `back;
}
}
Users::CommitGroup ();
return `next;
}
/* EOF */
}
ACC SHELL 2018