Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ Lets administrators create user accounts from the ACP.
## Features

- New **Add User** page under **ACP → Users and Groups**.
- Set username, email, password (left blank, one is generated), language and birthday.
- Set username, email, password (left blank, a random one is generated and never emailed), language and birthday.
- Choose the user's group and optionally make it their default group; optionally add them to *Newly registered users*.
- Follows the board's activation setting: the new user gets their login details by email, or with admin activation you can activate the account on the spot.
- Follows the board's activation setting: the new user gets an email with a link to set their own password, or with admin activation you can activate the account on the spot.
- Every account created is recorded in the admin log.

## Requirements
Expand Down
103 changes: 47 additions & 56 deletions acp/adduser_module.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,35 @@ public function main($id, $mode)
// Create a new password for our user only if there is nothing for a password already
if (empty($data['new_password']) && empty($data['password_confirm']))
{
if ($this->config['pass_complex'] == 'PASS_TYPE_ANY' || $this->config['pass_complex'] == 'PASS_TYPE_CASE')
// The password is never emailed, the user sets their own via the reset
// link. Draw it from random_int rather than from the current time, and
// take one character from every class validate_password() demands.
$pools = ['abcdefghijkmnopqrstuvwxyz', 'ABCDEFGHJKLMNPQRSTUVWXYZ', '23456789'];
if (!in_array($this->config['pass_complex'], ['PASS_TYPE_ANY', 'PASS_TYPE_CASE', 'PASS_TYPE_ALPHA'], true))
{
$new_password = str_split(base64_encode(md5(time() . $data['username'])), $this->config['min_pass_chars'] + rand(3, 5));
$data['new_password'] = $data['password_confirm'] = $new_password[0];
// PASS_TYPE_SYMBOL, or an invalid setting, which phpBB treats as the strictest one
$pools[] = '{}[];:,./<>?_+~!@#';
}
else if ($this->config['pass_complex'] == 'PASS_TYPE_ALPHA')
$all = implode('', $pools);
$length = max(20, (int) $this->config['min_pass_chars']);
$new_password = '';
foreach ($pools as $pool)
{
$new_password = $this->generate_password($this->config['min_pass_chars'] + rand(3, 5), 'PASS_TYPE_ALPHA');
$data['new_password'] = $data['password_confirm'] = $new_password;
$new_password .= $pool[random_int(0, strlen($pool) - 1)];
}
else
for ($i = strlen($new_password); $i < $length; $i++)
{
$new_password .= $all[random_int(0, strlen($all) - 1)];
}
// str_shuffle() draws from the Mersenne Twister, so shuffle by hand
for ($i = strlen($new_password) - 1; $i > 0; $i--)
{
$new_password = $this->generate_password($this->config['min_pass_chars'] + rand(3, 5), 'PASS_TYPE_SYMBOL');
$data['new_password'] = $data['password_confirm'] = $new_password;
$j = random_int(0, $i);
$swap = $new_password[$i];
$new_password[$i] = $new_password[$j];
$new_password[$j] = $swap;
}
$data['new_password'] = $data['password_confirm'] = $new_password;
}

// Validate entries
Expand Down Expand Up @@ -281,12 +295,32 @@ public function main($id, $mode)
$messenger->headers('X-AntiAbuse: Username - ' . $this->user->data['username']);
$messenger->headers('X-AntiAbuse: User IP - ' . $this->user->ip);

// Send a reset link instead of the password: the user picks their own.
// route() ends in append_sid(), which would attach the session id of the
// admin creating the account. That must not travel by email.
$reset_expires = \phpbb\user::get_token_expiration();
$reset_token = strtolower(gen_rand_string(32));
$this->db->sql_query('UPDATE ' . USERS_TABLE . "
SET reset_token = '" . $this->db->sql_escape($reset_token) . "',
reset_token_expiration = " . (int) $reset_expires . '
WHERE user_id = ' . (int) $this->user_id);
global $_SID;
$sid_backup = $_SID;
$_SID = '';
$reset_link = generate_board_url(true) . $phpbb_container->get('controller.helper')->route(
'phpbb_ucp_reset_password_controller',
['u' => (int) $this->user_id, 'token' => $reset_token],
false
);
$_SID = $sid_backup;

$messenger->assign_vars([
'WELCOME_MSG' => htmlspecialchars_decode(sprintf($this->user->lang['WELCOME_SUBJECT'], $this->config['sitename'])),
'USERNAME' => htmlspecialchars_decode($data['username']),
'PASSWORD' => htmlspecialchars_decode($data['new_password']),
'WELCOME_MSG' => htmlspecialchars_decode(sprintf($this->user->lang['WELCOME_SUBJECT'], $this->config['sitename'])),
'USERNAME' => htmlspecialchars_decode($data['username']),
'U_RESET_PASSWORD' => $reset_link,
'RESET_EXPIRES' => $this->user->format_date($reset_expires, str_replace('|', '', $this->user->lang['DATETIME_FORMAT'])),

'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$this->user_id&k=$this->user_actkey",
'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$this->user_id&k=$this->user_actkey",
]);

$messenger->send(NOTIFY_EMAIL);
Expand Down Expand Up @@ -401,49 +435,6 @@ public function main($id, $mode)
$cp->generate_profile_fields('profile', $this->user->get_iso_lang_id());
}

// Function to generate passwords
private function generate_password($length, $type)
{
$lowercase = "abcdefghijklmnopqrstuvwxyz";
$uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$numbers = "1234567890";
$specialcharacters = "{}[];:,./<>?_+~!@#";

$pword_string = '';

$max = strlen($lowercase) - 1;

for ($x = 0; $x < abs($length/3); $x++)
{
$pword_string .= $lowercase[mt_rand(0, $max)];
}

$max = strlen($uppercase) - 1;

for ($x = 0; $x < abs($length/3); $x++)
{
$pword_string .= $uppercase[mt_rand(0, $max)];
}

$max = strlen($numbers) - 1;

for ($x = 0; $x < abs($length/3); $x++)
{
$pword_string .= $numbers[mt_rand(0, $max)];
}

if ($type == 'PASS_TYPE_SYMBOL')
{
$max = strlen($specialcharacters) - 1;

for ($x = 0; $x < abs($length/3); $x++)
{
$pword_string .= $specialcharacters[mt_rand(0, $max)];
}
}

return str_shuffle($pword_string);
}

// Function to return groups that are allowed
private function get_groups($group_selected)
Expand Down
10 changes: 5 additions & 5 deletions language/en/email/user_added_admin_welcome_inactive.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ Subject: You have been added to "{SITENAME}"

{WELCOME_MSG}

Please keep this e-mail for your records. Your account information is as follows:
You need your username to log in. Keep it:

----------------------------
Username: {USERNAME}

Board URL: {U_BOARD}

Password: {PASSWORD}
----------------------------

Your account is currently inactive and will need to be approved by an administrator before you can log in. Another e-mail will be sent when this has occurred.

Your password has been securely stored in our database and cannot be retrieved. In the event that it is forgotten, you will be able to reset it using the e-mail address associated with your account.
Use this link to set your own password:

{U_RESET_PASSWORD}

We strongly recommend that you change your password once you log into the forum.
The link is valid until {RESET_EXPIRES}. After that, use “Forgot password” at {U_BOARD}.


{EMAIL_SIG}
10 changes: 5 additions & 5 deletions language/en/email/user_added_inactive.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ Subject: You have been added to "{SITENAME}"

{WELCOME_MSG}

Please keep this e-mail for your records. Your account information is as follows:
You need your username to log in. Keep it:

----------------------------
Username: {USERNAME}

Board URL: {U_BOARD}

Password: {PASSWORD}
----------------------------

Please visit the following link in order to activate your account:

{U_ACTIVATE}

Your password has been securely stored in our database and cannot be retrieved. In the event that it is forgotten, you will be able to reset it using the e-mail address associated with your account.
Use this link to set your own password:

{U_RESET_PASSWORD}

We strongly recommend that you change your password once you log into the forum.
The link is valid until {RESET_EXPIRES}. After that, use “Forgot password” at {U_BOARD}.


{EMAIL_SIG}
10 changes: 5 additions & 5 deletions language/en/email/user_added_welcome.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ Subject: You have been added to "{SITENAME}"

{WELCOME_MSG}

Please keep this e-mail for your records. Your account information is as follows:
You need your username to log in. Keep it:

----------------------------
Username: {USERNAME}

Board URL: {U_BOARD}

Password: {PASSWORD}
----------------------------

Your password has been securely stored in our database and cannot be retrieved. In the event that it is forgotten, you will be able to reset it using the e-mail address associated with your account.
Use this link to set your own password:

{U_RESET_PASSWORD}

We strongly recommend that you change your password once you log into the forum.
The link is valid until {RESET_EXPIRES}. After that, use “Forgot password” at {U_BOARD}.


{EMAIL_SIG}
8 changes: 4 additions & 4 deletions language/en/info_acp_adduser.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@
// ACP Module
'ACP_ADD_USER' => 'Add User',
'DIR_NOT_EXIST' => 'The language you have chosen %s does not have the files needed for the extension. Please translate them and upload to the %s directory of the extension.',
'ACP_ACCOUNT_ADDED' => 'The user account has been created. The user may now login with the username and password sent to the email address you provided.',
'ACP_ACCOUNT_ADDED' => 'The user account has been created. A link was sent to the email address you provided; the user sets their own password with it. The email states how long the link is valid.',
'ACP_ACCOUNT_INACTIVE' => 'The user account has been created. However, the forum settings require the user to activate their account.<br>An activation key has been sent to the email address you provided for the user.',
'ACP_ACCOUNT_INACTIVE_ADMIN' => 'The user account has been created. However, the forum settings require account activation by an administrator.<br>An email has been sent to the Administrators and the user will be informed when their account has been activated',
'ACP_ADMIN_ACTIVATE' => 'An email will be dispatched to an Administrator for account activation. Alternatively you may check the activate account box below to activate the account instantly once created. The user will receive an email containing account login details.',
'ACP_ADMIN_ACTIVATE' => 'An email will be dispatched to an Administrator for account activation. Alternatively you may check the activate account box below to activate the account instantly once created. The user will receive a link to set their own password.',
'ACP_EMAIL_ACTIVATE' => 'Once the account has been created, the user will receive an email containing an activation link to activate the account.',
'ACP_INSTANT_ACTIVATE' => 'The account will be activated instantly. The user will receive an email with account login details.',
'ACP_INSTANT_ACTIVATE' => 'The account will be activated instantly. The user will receive a link to set their own password.',

'ADD_USER' => 'Add User',
'ADD_USER_EXPLAIN' => 'Create a new user account. If your activation settings are to Admin Activation only, you will have the option to activate the user instantly.',
Expand All @@ -56,7 +56,7 @@
'GROUP_ADD' => 'Making a selection here will add the user to the group selected as well as to the registered users group.',
'GROUP_DEFAULT_EXPLAIN' => 'Checking this box will set the group selected above to be the users default.',
'CONTINUE_EDIT_USER' => '%1$sClick here to manage %2$s’s profile%3$s',
'PASSWORD_EXPLAIN' => 'If left blank a password will be auto generated.',
'PASSWORD_EXPLAIN' => 'If left blank a password will be generated. It is never emailed — the user sets their own password with the link.',
'ENABLE_NEWUSER' => 'Enable new user',
'ENABLE_NEWUSER_EXPLAIN' => 'If set as yes the user will be added to the newly registered user group',

Expand Down
Loading