mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-03 12:39:25 +01:00
Admin: Change bulk password reset to long task
This commit is contained in:
parent
9a60e1e890
commit
b879b5eb7e
@ -118,138 +118,10 @@ class admin_passwordreset
|
||||
$emailadmin = null;
|
||||
foreach($content['users'] as $account_id)
|
||||
{
|
||||
if (($account = $GLOBALS['egw']->accounts->read($account_id)))
|
||||
$result = $this->resetAccount($account_id, $content, $change_pw, $current_hash, $msg, $changed);
|
||||
if($result === false)
|
||||
{
|
||||
//_debug_array($account); //break;
|
||||
if ($content['random_pw'])
|
||||
{
|
||||
if (($minlength=$GLOBALS['egw_info']['server']['force_pwd_length']) < 8)
|
||||
{
|
||||
$minlength = 8;
|
||||
}
|
||||
$n = 0;
|
||||
do {
|
||||
$password = Api\Auth::randomstring($minlength,
|
||||
$GLOBALS['egw_info']['server']['force_pwd_strength'] >= 4);
|
||||
error_log(__METHOD__."() minlength=$minlength, n=$n, password=$password");
|
||||
} while (++$n < 100 && Api\Auth::crackcheck($password, null, null, null, $account));
|
||||
$old_password = null;
|
||||
}
|
||||
elseif ($change_pw && !preg_match('/^{plain}/i',$account['account_pwd']) &&
|
||||
($current_hash != 'plain' || $current_hash == 'plain' && $account['account_pwd'][0] == '{'))
|
||||
{
|
||||
$msg .= lang('Account "%1" has NO plaintext password!',$account['account_lid'])."\n";
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$old_password = $password = preg_replace('/^{plain}/i','',$account['account_pwd']);
|
||||
}
|
||||
// change password, if requested
|
||||
try {
|
||||
if ($change_pw && !$GLOBALS['egw']->auth->change_password($old_password,$password,$account_id))
|
||||
{
|
||||
$msg .= lang('Failed to change password for account "%1"!',$account['account_lid'])."\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch(Exception $e) {
|
||||
$msg .= lang('Failed to change password for account "%1"!',$account['account_lid']).' '.$e->getMessage()."\n";
|
||||
continue;
|
||||
}
|
||||
// force password change on next login
|
||||
if ((string)$content['mustchangepassword'] !== '' && !(!$content['mustchangepassword'] && $change_pw))
|
||||
{
|
||||
// dont use password here, as the use of passwords indicates the usage of the functionality in usermode
|
||||
$GLOBALS['egw']->auth->setLastPwdChange($account_id, null, $content['mustchangepassword'] ? 0 : time());
|
||||
}
|
||||
// allow or forbid to change password, if requested
|
||||
if ((string)$content['changepassword'] !== '')
|
||||
{
|
||||
if(!$content['changepassword'])
|
||||
{
|
||||
$GLOBALS['egw']->acl->add_repository('preferences','nopasswordchange',$account_id,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw']->acl->delete_repository('preferences','nopasswordchange',$account_id);
|
||||
}
|
||||
}
|
||||
$account['account_password'] = $password;
|
||||
|
||||
if ((string)$content['mail']['activate'] !== '' || (string)$content['mail']['quota'] !== '' ||
|
||||
strpos($content['mail']['domain'], '.') !== false)
|
||||
{
|
||||
if (!isset($emailadmin))
|
||||
{
|
||||
$emailadmin = Api\Mail\Account::get_default();
|
||||
if (!Api\Mail\Account::is_multiple($emailadmin))
|
||||
{
|
||||
$msg = lang('No default account found!');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (($userData = $emailadmin->getUserData ($account_id)))
|
||||
{
|
||||
if ((string)$content['mail']['activate'] !== '')
|
||||
{
|
||||
$userData['accountStatus'] = $content['mail']['activate'] ? 'active' : '';
|
||||
}
|
||||
if ((string)$content['mail']['quota'] !== '')
|
||||
{
|
||||
$userData['quotaLimit'] = $content['mail']['quota'];
|
||||
}
|
||||
if (strpos($content['mail']['domain'], '.') !== false)
|
||||
{
|
||||
$userData['mailLocalAddress'] = preg_replace('/@'.preg_quote($emailadmin->acc_domain).'$/', '@'.$content['mail']['domain'], $userData['mailLocalAddress']);
|
||||
|
||||
foreach($userData['mailAlternateAddress'] as &$alias)
|
||||
{
|
||||
$alias = preg_replace('/@'.preg_quote($emailadmin->acc_domain).'$/', '@'.$content['mail']['domain'], $alias);
|
||||
}
|
||||
}
|
||||
$emailadmin->saveUserData($account_id, $userData);
|
||||
}
|
||||
else
|
||||
{
|
||||
$msg .= lang('No profile defined for user %1', '#'.$account_id.' '.$account['account_fullname']."\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$changed[] = $account;
|
||||
|
||||
if ($content['notify'])
|
||||
{
|
||||
if (strpos($account['account_email'],'@') === false)
|
||||
{
|
||||
$msg .= lang('Account "%1" has no email address --> not notified!',$account['account_lid']);
|
||||
continue;
|
||||
}
|
||||
$send = new Api\Mailer();
|
||||
$send->AddAddress($account['account_email'],$account['account_fullname']);
|
||||
$replacements = array();
|
||||
foreach($this->replacements as $name => $label)
|
||||
{
|
||||
$replacements['$$'.$name.'$$'] = $account['account_'.$name];
|
||||
}
|
||||
$send->addHeader('Subject', strtr($content['subject'], $replacements));
|
||||
$send->setBody(strtr($content['body'], $replacements));
|
||||
if (!empty($GLOBALS['egw_info']['user']['account_email']))
|
||||
{
|
||||
$send->addHeader('From', Api\Mailer::add_personal(
|
||||
$GLOBALS['egw_info']['user']['account_email'],
|
||||
$GLOBALS['egw_info']['user']['account_fullname']));
|
||||
}
|
||||
try
|
||||
{
|
||||
$send->Send();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$msg .= lang('Notifying account "%1" %2 failed!',$account['account_lid'],$account['account_email']).
|
||||
': '.strip_tags(str_replace('<p>', "\n", $e->getMessage()))."\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($changed)
|
||||
@ -290,6 +162,149 @@ class admin_passwordreset
|
||||
));
|
||||
}
|
||||
|
||||
protected function resetAccount($account_id, $content, $change_pw, $current_hash, &$msg, &$changed)
|
||||
{
|
||||
if(($account = $GLOBALS['egw']->accounts->read($account_id)))
|
||||
{
|
||||
if($content['random_pw'])
|
||||
{
|
||||
if(($minlength = $GLOBALS['egw_info']['server']['force_pwd_length']) < 8)
|
||||
{
|
||||
$minlength = 8;
|
||||
}
|
||||
$n = 0;
|
||||
do
|
||||
{
|
||||
$password = Api\Auth::randomstring($minlength,
|
||||
$GLOBALS['egw_info']['server']['force_pwd_strength'] >= 4
|
||||
);
|
||||
error_log(__METHOD__ . "() minlength=$minlength, n=$n, password=$password");
|
||||
}
|
||||
while(++$n < 100 && Api\Auth::crackcheck($password, null, null, null, $account));
|
||||
$old_password = null;
|
||||
}
|
||||
elseif($change_pw && !preg_match('/^{plain}/i', $account['account_pwd']) &&
|
||||
($current_hash != 'plain' || $current_hash == 'plain' && $account['account_pwd'][0] == '{'))
|
||||
{
|
||||
$msg .= lang('Account "%1" has NO plaintext password!', $account['account_lid']) . "\n";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
$old_password = $password = preg_replace('/^{plain}/i', '', $account['account_pwd']);
|
||||
}
|
||||
// change password, if requested
|
||||
try
|
||||
{
|
||||
if($change_pw && !$GLOBALS['egw']->auth->change_password($old_password, $password, $account_id))
|
||||
{
|
||||
$msg .= lang('Failed to change password for account "%1"!', $account['account_lid']) . "\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$msg .= lang('Failed to change password for account "%1"!', $account['account_lid']) . ' ' . $e->getMessage() . "\n";
|
||||
return;
|
||||
}
|
||||
// force password change on next login
|
||||
if((string)$content['mustchangepassword'] !== '' && !(!$content['mustchangepassword'] && $change_pw))
|
||||
{
|
||||
// dont use password here, as the use of passwords indicates the usage of the functionality in usermode
|
||||
$GLOBALS['egw']->auth->setLastPwdChange($account_id, null, $content['mustchangepassword'] ? 0 : time());
|
||||
}
|
||||
// allow or forbid to change password, if requested
|
||||
if((string)$content['changepassword'] !== '')
|
||||
{
|
||||
if(!$content['changepassword'])
|
||||
{
|
||||
$GLOBALS['egw']->acl->add_repository('preferences', 'nopasswordchange', $account_id, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw']->acl->delete_repository('preferences', 'nopasswordchange', $account_id);
|
||||
}
|
||||
}
|
||||
$account['account_password'] = $password;
|
||||
|
||||
if((string)$content['mail']['activate'] !== '' || (string)$content['mail']['quota'] !== '' ||
|
||||
strpos($content['mail']['domain'], '.') !== false)
|
||||
{
|
||||
if(!isset($emailadmin))
|
||||
{
|
||||
$emailadmin = Api\Mail\Account::get_default();
|
||||
if(!Api\Mail\Account::is_multiple($emailadmin))
|
||||
{
|
||||
$msg = lang('No default account found!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(($userData = $emailadmin->getUserData($account_id)))
|
||||
{
|
||||
if((string)$content['mail']['activate'] !== '')
|
||||
{
|
||||
$userData['accountStatus'] = $content['mail']['activate'] ? 'active' : '';
|
||||
}
|
||||
if((string)$content['mail']['quota'] !== '')
|
||||
{
|
||||
$userData['quotaLimit'] = $content['mail']['quota'];
|
||||
}
|
||||
if(strpos($content['mail']['domain'], '.') !== false)
|
||||
{
|
||||
$userData['mailLocalAddress'] = preg_replace('/@' . preg_quote($emailadmin->acc_domain) . '$/', '@' . $content['mail']['domain'], $userData['mailLocalAddress']);
|
||||
|
||||
foreach($userData['mailAlternateAddress'] as &$alias)
|
||||
{
|
||||
$alias = preg_replace('/@' . preg_quote($emailadmin->acc_domain) . '$/', '@' . $content['mail']['domain'], $alias);
|
||||
}
|
||||
}
|
||||
$emailadmin->saveUserData($account_id, $userData);
|
||||
}
|
||||
else
|
||||
{
|
||||
$msg .= lang('No profile defined for user %1', '#' . $account_id . ' ' . $account['account_fullname'] . "\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
$changed[] = $account;
|
||||
|
||||
if($content['notify'])
|
||||
{
|
||||
if(strpos($account['account_email'], '@') === false)
|
||||
{
|
||||
$msg .= lang('Account "%1" has no email address --> not notified!', $account['account_lid']);
|
||||
return;
|
||||
}
|
||||
$send = new Api\Mailer();
|
||||
$send->AddAddress($account['account_email'], $account['account_fullname']);
|
||||
$replacements = array();
|
||||
foreach($this->replacements as $name => $label)
|
||||
{
|
||||
$replacements['$$' . $name . '$$'] = $account['account_' . $name];
|
||||
}
|
||||
$send->addHeader('Subject', strtr($content['subject'], $replacements));
|
||||
$send->setBody(strtr($content['body'], $replacements));
|
||||
if(!empty($GLOBALS['egw_info']['user']['account_email']))
|
||||
{
|
||||
$send->addHeader('From', Api\Mailer::add_personal(
|
||||
$GLOBALS['egw_info']['user']['account_email'],
|
||||
$GLOBALS['egw_info']['user']['account_fullname']
|
||||
)
|
||||
);
|
||||
}
|
||||
try
|
||||
{
|
||||
$send->Send();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$msg .= lang('Notifying account "%1" %2 failed!', $account['account_lid'], $account['account_email']) .
|
||||
': ' . strip_tags(str_replace('<p>', "\n", $e->getMessage())) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function ajax_clear_credentials($action_id, $account_ids)
|
||||
{
|
||||
$msg = [];
|
||||
@ -351,4 +366,32 @@ class admin_passwordreset
|
||||
Framework::message(implode("\n",$msg), 'success');
|
||||
Framework::redirect_link('/index.php', 'menuaction=admin.admin_ui.index','admin');
|
||||
}
|
||||
|
||||
public function ajax_reset($content)
|
||||
{
|
||||
$msg = '';
|
||||
$changed = [];
|
||||
if(!($account_repository = $GLOBALS['egw_info']['server']['account_repository']) &&
|
||||
!($account_repository = $GLOBALS['egw_info']['server']['auth_type']))
|
||||
{
|
||||
$account_repository = 'sql';
|
||||
}
|
||||
if(!($current_hash = $GLOBALS['egw_info']['server'][$account_repository . '_encryption_type']))
|
||||
{
|
||||
$current_hash = 'md5';
|
||||
}
|
||||
$change_pw = $content['random_pw'] || $content['hash'] && $content['hash'] != $current_hash;
|
||||
|
||||
$result = $this->resetAccount($content['user'], $content['values'], $change_pw, $current_hash, $msg, $changed);
|
||||
|
||||
if(count($changed) == 1)
|
||||
{
|
||||
Api\Json\Response::get()->data($msg !== "" ? $msg : $GLOBALS['egw']->accounts->id2name($content['user']));
|
||||
}
|
||||
else
|
||||
{
|
||||
Api\Json\Response::get()->error($msg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1749,6 +1749,44 @@ class AdminApp extends EgwApp
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch reset multiple account passwords
|
||||
*
|
||||
* JS callback for admin_passwordreset so we can do longtask. Values come from the current admin etemplate.
|
||||
*/
|
||||
async bulkPasswordReset()
|
||||
{
|
||||
const data = [];
|
||||
const values = this.et2.getInstanceManager().getValues(this.et2);
|
||||
let users = values.users ?? [];
|
||||
delete values.users;
|
||||
|
||||
|
||||
if(users.includes("~all~"))
|
||||
{
|
||||
// Doesn't always give _all_ accounts
|
||||
const accounts = await egw.accounts("accounts");
|
||||
debugger;
|
||||
}
|
||||
if(users.length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(let i = 0; i < users.length; i++)
|
||||
{
|
||||
data.push({values, user: users[i]});
|
||||
}
|
||||
|
||||
Et2Dialog.long_task(
|
||||
null, "", "Bulk Password Reset",
|
||||
"admin.admin_passwordreset.ajax_reset",
|
||||
data, this.egw
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
app.classes.admin = AdminApp;
|
@ -14,8 +14,9 @@
|
||||
<et2-description></et2-description>
|
||||
</row>
|
||||
<row>
|
||||
<et2-select-account id="users" rows="15" multiple="1"></et2-select-account>
|
||||
<et2-description></et2-description>
|
||||
<et2-select-account id="users" rows="15" multiple="1">
|
||||
<!--<option value="~all~">All users</option>-->
|
||||
</et2-select-account>
|
||||
</row>
|
||||
<row>
|
||||
<groupbox id="actions">
|
||||
@ -59,8 +60,8 @@
|
||||
</et2-vbox>
|
||||
</row>
|
||||
<row>
|
||||
<et2-button label="Start" id="start"></et2-button>
|
||||
<et2-button label="Download CSV" id="download_csv" onclick="widget.getInstanceManager().postSubmit()" noSubmit="true"></et2-button>
|
||||
<et2-button label="Start" id="start" noSubmit="true" onclick="app.admin.bulkPasswordReset"></et2-button>
|
||||
<!--<et2-button label="Download CSV" id="download_csv" onclick="widget.getInstanceManager().postSubmit()" noSubmit="true"></et2-button>-->
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
Loading…
Reference in New Issue
Block a user