2007-11-27 04:20:28 +01:00
|
|
|
<?php
|
|
|
|
/**
|
2016-04-27 21:12:20 +02:00
|
|
|
* EGgroupware admin - admin command: edit/add a user
|
2007-11-27 04:20:28 +01:00
|
|
|
*
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
|
|
|
* @package admin
|
2018-08-03 11:49:40 +02:00
|
|
|
* @copyright (c) 2007-18 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
2007-11-27 04:20:28 +01:00
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
*/
|
|
|
|
|
2016-04-27 21:12:20 +02:00
|
|
|
use EGroupware\Api;
|
|
|
|
|
2007-11-27 04:20:28 +01:00
|
|
|
/**
|
|
|
|
* admin command: edit/add a user
|
|
|
|
*/
|
2010-03-16 17:33:28 +01:00
|
|
|
class admin_cmd_edit_user extends admin_cmd_change_pw
|
2007-11-27 04:20:28 +01:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
2016-04-27 21:12:20 +02:00
|
|
|
* @param string|int|array $account account name or id (!$account to add a new account), or array with all parameters
|
2014-09-24 08:55:44 +02:00
|
|
|
* @param array $set =null array with all data to change
|
|
|
|
* @param string $password =null password
|
2016-04-27 21:12:20 +02:00
|
|
|
* @param boolean $run_addaccount_hook =null default run addaccount for new Api\Accounts and editaccount for existing ones
|
2018-08-03 11:49:40 +02:00
|
|
|
* @param array $old =null array to log old values of $set
|
2007-11-27 04:20:28 +01:00
|
|
|
*/
|
2018-08-03 11:49:40 +02:00
|
|
|
function __construct($account, $set=null, $password=null, $run_addaccount_hook=null, array $old=null)
|
2007-11-27 04:20:28 +01:00
|
|
|
{
|
|
|
|
if (!is_array($account))
|
|
|
|
{
|
2014-03-18 16:10:57 +01:00
|
|
|
//error_log(__METHOD__."(".array2string($account).', '.array2string($set).", ...)");
|
2007-11-27 04:20:28 +01:00
|
|
|
$account = array(
|
|
|
|
'account' => $account,
|
|
|
|
'set' => $set,
|
|
|
|
'password' => is_null($password) ? $set['account_passwd'] : $password,
|
2010-08-20 22:28:59 +02:00
|
|
|
'run_addaccount_hook' => $run_addaccount_hook,
|
2018-08-03 11:49:40 +02:00
|
|
|
'old' => $old,
|
2007-11-27 04:20:28 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
admin_cmd::__construct($account);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* change the password of a given user
|
2010-03-16 17:33:28 +01:00
|
|
|
*
|
2014-09-24 08:55:44 +02:00
|
|
|
* @param boolean $check_only =false only run the checks (and throw the exceptions), but not the command itself
|
2007-11-27 04:20:28 +01:00
|
|
|
* @return string success message
|
2016-04-27 21:12:20 +02:00
|
|
|
* @throws Api\Exception\NoPermission\Admin
|
|
|
|
* @throws Api\Exception\WrongUserinput(lang("Unknown account: %1 !!!",$this->account),15);
|
|
|
|
* @throws Api\Exception\WrongUserinput(lang('Error changing the password for %1 !!!',$this->account),99);
|
2007-11-27 04:20:28 +01:00
|
|
|
*/
|
|
|
|
protected function exec($check_only=false)
|
|
|
|
{
|
|
|
|
// check creator is still admin and not explicitly forbidden to edit accounts/groups
|
|
|
|
if ($this->creator) $this->_check_admin('account_access',$this->account ? 16 : 4);
|
|
|
|
|
|
|
|
admin_cmd::_instanciate_accounts();
|
|
|
|
|
|
|
|
$data = $this->set;
|
|
|
|
$data['account_type'] = 'u';
|
|
|
|
|
|
|
|
if ($this->account) // existing account
|
|
|
|
{
|
|
|
|
$data['account_id'] = admin_cmd::parse_account($this->account);
|
2014-03-18 16:10:57 +01:00
|
|
|
//error_log(__METHOD__."($check_only) this->account=".array2string($this->account).', data[account_id]='.array2string($data['account_id']).", ...)");
|
|
|
|
|
2010-04-21 14:28:27 +02:00
|
|
|
$data['old_loginid'] = admin_cmd::$accounts->id2name($data['account_id']);
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
|
|
|
if (!$data['account_lid'] && (!$this->account || !is_null($data['account_lid'])))
|
|
|
|
{
|
2016-04-27 21:12:20 +02:00
|
|
|
throw new Api\Exception\WrongUserinput(lang('You must enter a loginid'),9);
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
2010-03-16 17:33:28 +01:00
|
|
|
// Check if an account already exists as system user, and if it does deny creation
|
|
|
|
if ($GLOBALS['egw_info']['server']['account_repository'] == 'ldap' &&
|
2013-05-27 16:30:22 +02:00
|
|
|
!$GLOBALS['egw_info']['server']['ldap_allow_systemusernames'] && !$data['account_id'] &&
|
2010-03-16 17:33:28 +01:00
|
|
|
function_exists('posix_getpwnam') && posix_getpwnam($data['account_lid']))
|
|
|
|
{
|
2016-04-27 21:12:20 +02:00
|
|
|
throw new Api\Exception\WrongUserinput(lang('There already is a system-user with this name. User\'s should not have the same name as a systemuser'),99);
|
2010-03-16 17:33:28 +01:00
|
|
|
}
|
2007-11-27 04:20:28 +01:00
|
|
|
if (!$data['account_lastname'] && (!$this->account || !is_null($data['account_lastname'])))
|
|
|
|
{
|
2019-02-26 16:38:05 +01:00
|
|
|
throw new Api\Exception\WrongUserinput(lang('You must enter a lastname'), 13);
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
2010-03-16 17:33:28 +01:00
|
|
|
if (!is_null($data['account_lid']) && ($id = admin_cmd::$accounts->name2id($data['account_lid'],'account_lid','u')) &&
|
2014-03-18 16:10:57 +01:00
|
|
|
(string)$id !== (string)$data['account_id'])
|
2007-11-27 04:20:28 +01:00
|
|
|
{
|
2019-02-26 16:38:05 +01:00
|
|
|
throw new Api\Exception\WrongUserinput(lang('That loginid has already been taken'), 11);
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
|
|
|
if (isset($data['account_passwd_2']) && $data['account_passwd'] != $data['account_passwd_2'])
|
|
|
|
{
|
2019-02-26 16:38:05 +01:00
|
|
|
throw new Api\Exception\WrongUserinput(lang('The two passwords are not the same'), 12);
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
2014-06-04 22:02:01 +02:00
|
|
|
$expires = self::_parse_expired($data['account_expires'],(boolean)$this->account);
|
|
|
|
if ($expires === 0) // deactivated
|
|
|
|
{
|
|
|
|
$data['account_expires'] = -1;
|
|
|
|
$data['account_status'] = '';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$data['account_expires'] = $expires;
|
|
|
|
$data['account_status'] = is_null($expires) ? null : ($expires == -1 || $expires > time() ? 'A' : '');
|
|
|
|
}
|
2010-03-16 17:33:28 +01:00
|
|
|
|
2007-11-27 04:20:28 +01:00
|
|
|
$data['changepassword'] = admin_cmd::parse_boolean($data['changepassword'],$this->account ? null : true);
|
|
|
|
$data['anonymous'] = admin_cmd::parse_boolean($data['anonymous'],$this->account ? null : false);
|
2010-10-18 15:09:38 +02:00
|
|
|
if ($data['mustchangepassword'] && $data['changepassword'])
|
|
|
|
{
|
|
|
|
$data['account_lastpwd_change']=0;
|
|
|
|
}
|
2010-03-16 17:33:28 +01:00
|
|
|
|
2007-11-27 04:20:28 +01:00
|
|
|
if (!$data['account_primary_group'] && $this->account)
|
|
|
|
{
|
|
|
|
$data['account_primary_group'] = null; // dont change
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!$data['account_primary_group'] && admin_cmd::$accounts->exists('Default') == 2)
|
|
|
|
{
|
|
|
|
$data['account_primary_group'] = 'Default';
|
|
|
|
}
|
|
|
|
$data['account_primary_group'] = admin_cmd::parse_account($data['account_primary_group'],false);
|
|
|
|
}
|
|
|
|
if (!$data['account_groups'] && $this->account)
|
|
|
|
{
|
|
|
|
$data['account_groups'] = null; // dont change
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!$data['account_groups'] && admin_cmd::$accounts->exists('Default') == 2)
|
|
|
|
{
|
|
|
|
$data['account_groups'] = array('Default');
|
|
|
|
}
|
|
|
|
$data['account_groups'] = admin_cmd::parse_accounts($data['account_groups'],false);
|
|
|
|
}
|
|
|
|
if ($check_only) return true;
|
2010-03-16 17:33:28 +01:00
|
|
|
|
2007-11-27 04:20:28 +01:00
|
|
|
if ($this->account)
|
|
|
|
{
|
2013-04-23 15:47:20 +02:00
|
|
|
// invalidate account, before reading it, to code with changed to DB or LDAP outside EGw
|
2016-04-27 21:12:20 +02:00
|
|
|
Api\Accounts::cache_invalidate($data['account_id']);
|
2007-11-27 04:20:28 +01:00
|
|
|
if (!($old = admin_cmd::$accounts->read($data['account_id'])))
|
|
|
|
{
|
2016-04-27 21:12:20 +02:00
|
|
|
throw new Api\Exception\WrongUserinput(lang("Unknown account: %1 !!!",$this->account),15);
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
|
|
|
// as the current account class always sets all values, we have to add the not specified ones
|
|
|
|
foreach($data as $name => &$value)
|
|
|
|
{
|
|
|
|
if (is_null($value)) $value = $old[$name];
|
|
|
|
}
|
|
|
|
}
|
2014-09-24 08:55:44 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
unset($data['account_id']); // otherwise add will fail under postgres
|
|
|
|
}
|
2016-04-27 21:12:20 +02:00
|
|
|
// hook allowing apps to intercept adding/editing Api\Accounts before saving them
|
|
|
|
Api\Hooks::process($data+array(
|
2014-06-04 22:02:01 +02:00
|
|
|
'location' => $this->account ? 'pre_editaccount' : 'pre_addaccount',
|
|
|
|
),False,True); // called for every app now, not only enabled ones)
|
|
|
|
|
2007-11-27 04:20:28 +01:00
|
|
|
if (!($data['account_id'] = admin_cmd::$accounts->save($data)))
|
|
|
|
{
|
|
|
|
//_debug_array($data);
|
2016-04-27 21:12:20 +02:00
|
|
|
throw new Api\Db\Exception(lang("Error saving account!"),11);
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
2014-03-18 16:10:57 +01:00
|
|
|
// make new account_id available to caller
|
2014-03-28 17:56:35 +01:00
|
|
|
$update = (boolean)$this->account;
|
2014-03-18 16:10:57 +01:00
|
|
|
if (!$this->account) $this->account = $data['account_id'];
|
|
|
|
|
2007-11-27 04:20:28 +01:00
|
|
|
if ($data['account_groups'])
|
|
|
|
{
|
|
|
|
admin_cmd::$accounts->set_memberships($data['account_groups'],$data['account_id']);
|
|
|
|
}
|
|
|
|
if (!is_null($data['anonymous']))
|
|
|
|
{
|
|
|
|
admin_cmd::_instanciate_acl();
|
|
|
|
if ($data['anonymous'])
|
|
|
|
{
|
|
|
|
admin_cmd::$acl->add_repository('phpgwapi','anonymous',$data['account_id'],1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
admin_cmd::$acl->delete_repository('phpgwapi','anonymous',$data['account_id']);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!is_null($data['changepassword']))
|
|
|
|
{
|
|
|
|
if (!$data['changepassword'])
|
|
|
|
{
|
|
|
|
admin_cmd::$acl->add_repository('preferences','nopasswordchange',$data['account_id'],1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
admin_cmd::$acl->delete_repository('preferences','nopasswordchange',$data['account_id']);
|
|
|
|
}
|
|
|
|
}
|
2012-03-29 20:33:33 +02:00
|
|
|
// if we have a password and it's not a hash, and auth_type != account_repository
|
|
|
|
if (!is_null($this->password) &&
|
|
|
|
!preg_match('/^\\{[a-z5]{3,5}\\}.+/i',$this->password) &&
|
|
|
|
!preg_match('/^[0-9a-f]{32}$/',$this->password) && // md5 hash
|
|
|
|
admin_cmd::$accounts->config['auth_type'] != admin_cmd::$accounts->config['account_repository'])
|
2007-11-27 04:20:28 +01:00
|
|
|
{
|
|
|
|
admin_cmd_change_pw::exec(); // calling the exec method of the admin_cmd_change_pw
|
|
|
|
}
|
|
|
|
$data['account_passwd'] = $this->password;
|
|
|
|
$GLOBALS['hook_values'] =& $data;
|
2016-04-27 21:12:20 +02:00
|
|
|
Api\Hooks::process($GLOBALS['hook_values']+array(
|
2014-03-28 17:56:35 +01:00
|
|
|
'location' => $update && $this->run_addaccount_hook !== true ? 'editaccount' : 'addaccount'
|
2007-11-27 04:20:28 +01:00
|
|
|
),False,True); // called for every app now, not only enabled ones)
|
2010-03-16 17:33:28 +01:00
|
|
|
|
2016-04-27 21:12:20 +02:00
|
|
|
return lang("Account %1 %2", $data['account_lid'] ? $data['account_lid'] : Api\Accounts::id2name($this->account),
|
2014-03-28 17:56:35 +01:00
|
|
|
$update ? lang('updated') : lang("created with id #%1", $this->account));
|
2007-11-27 04:20:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a title / string representation for a given command, eg. to display it
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function __tostring()
|
|
|
|
{
|
|
|
|
return lang('%1 user %2',$this->account ? lang('Edit') : lang('Add'),
|
|
|
|
admin_cmd::display_account($this->account ? $this->account : $this->set['account_lid']));
|
|
|
|
}
|
2010-03-16 17:33:28 +01:00
|
|
|
|
2019-03-14 18:57:07 +01:00
|
|
|
/**
|
2019-03-19 15:34:44 +01:00
|
|
|
* Get name of eTemplate used to make the change to derive UI for history
|
2019-03-14 18:57:07 +01:00
|
|
|
*
|
2019-03-19 15:34:44 +01:00
|
|
|
* @return string|null etemplate name
|
2019-03-14 18:57:07 +01:00
|
|
|
*/
|
2019-03-19 15:34:44 +01:00
|
|
|
function get_etemplate_name()
|
2019-03-14 18:57:07 +01:00
|
|
|
{
|
2019-03-19 15:34:44 +01:00
|
|
|
return 'admin.account';
|
2019-03-14 18:57:07 +01:00
|
|
|
}
|
|
|
|
|
2007-11-27 04:20:28 +01:00
|
|
|
/**
|
|
|
|
* parse the expired string and return the expired date as timestamp
|
|
|
|
*
|
2016-04-27 21:12:20 +02:00
|
|
|
* @param string $str date, 'never', 'already' or '' (=dont change, or default of never of new Api\Accounts)
|
2014-09-24 08:55:44 +02:00
|
|
|
* @param boolean $existing
|
2007-11-27 04:20:28 +01:00
|
|
|
* @return int timestamp, 0 for already, -1 for never or null for dont change
|
2016-04-27 21:12:20 +02:00
|
|
|
* @throws Api\Exception\WrongUserinput(lang('Invalid formated date "%1"!',$datein),6);
|
2007-11-27 04:20:28 +01:00
|
|
|
*/
|
|
|
|
private function _parse_expired($str,$existing)
|
|
|
|
{
|
|
|
|
switch($str)
|
|
|
|
{
|
|
|
|
case '':
|
2010-03-16 17:33:28 +01:00
|
|
|
if ($existing) return null;
|
2016-04-27 21:12:20 +02:00
|
|
|
// fall through --> default for new Api\Accounts is never
|
2007-11-27 04:20:28 +01:00
|
|
|
case 'never':
|
|
|
|
return -1;
|
|
|
|
case 'already':
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return admin_cmd::parse_date($str);
|
|
|
|
}
|
|
|
|
}
|