Board owners can now change their usernames and set recovery email during creation process and while logged in.

This commit is contained in:
Fredrick Brennan 2015-05-06 19:27:27 +08:00
parent b96b33e548
commit 92168dd21e
8 changed files with 83 additions and 27 deletions

View File

@ -21,6 +21,7 @@ $title = $_POST['title'];
$subtitle = $_POST['subtitle']; $subtitle = $_POST['subtitle'];
$username = $_POST['username']; $username = $_POST['username'];
$password = $_POST['password']; $password = $_POST['password'];
$email = $_POST['email'];
$resp = file_get_contents($config['captcha']['provider_check'] . "?" . http_build_query([ $resp = file_get_contents($config['captcha']['provider_check'] . "?" . http_build_query([
'mode' => 'check', 'mode' => 'check',
@ -39,6 +40,8 @@ if (!preg_match('/^[a-zA-Z0-9._]{1,30}$/', $username))
error(_('Invalid username')); error(_('Invalid username'));
if ($resp !== '1') if ($resp !== '1')
error($config['error']['captcha']); error($config['error']['captcha']);
if (!filter_var($email, FILTER_VALIDATE_EMAIL))
$email = '';
foreach (listBoards() as $i => $board) { foreach (listBoards() as $i => $board) {
if ($board['uri'] == $uri) if ($board['uri'] == $uri)
@ -66,12 +69,13 @@ error(_('The username you\'ve tried to enter already exists!'));
$salt = generate_salt(); $salt = generate_salt();
$password = hash('sha256', $salt . sha1($password)); $password = hash('sha256', $salt . sha1($password));
$query = prepare('INSERT INTO ``mods`` VALUES (NULL, :username, :password, :salt, :type, :boards)'); $query = prepare('INSERT INTO ``mods`` VALUES (NULL, :username, :password, :salt, :type, :boards, :email)');
$query->bindValue(':username', $username); $query->bindValue(':username', $username);
$query->bindValue(':password', $password); $query->bindValue(':password', $password);
$query->bindValue(':salt', $salt); $query->bindValue(':salt', $salt);
$query->bindValue(':type', 20); $query->bindValue(':type', 20);
$query->bindValue(':boards', $uri); $query->bindValue(':boards', $uri);
$query->bindValue(':email', $email);
$query->execute() or error(db_error($query)); $query->execute() or error(db_error($query));
$query = prepare('INSERT INTO ``boards`` (`uri`, `title`, `subtitle`) VALUES (:uri, :title, :subtitle)'); $query = prepare('INSERT INTO ``boards`` (`uri`, `title`, `subtitle`) VALUES (:uri, :title, :subtitle)');

View File

@ -1530,7 +1530,7 @@
// Edit any users' login information // Edit any users' login information
$config['mod']['editusers'] = ADMIN; $config['mod']['editusers'] = ADMIN;
// Change user's own password // Change user's own password
$config['mod']['change_password'] = JANITOR; $config['mod']['edit_profile'] = JANITOR;
// Delete a user // Delete a user
$config['mod']['deleteusers'] = ADMIN; $config['mod']['deleteusers'] = ADMIN;
// Create a user // Create a user

View File

@ -1914,11 +1914,11 @@ function mod_deletebyip($boardName, $post, $global = false) {
function mod_user($uid) { function mod_user($uid) {
global $config, $mod; global $config, $mod;
if (!hasPermission($config['mod']['editusers']) && !(hasPermission($config['mod']['change_password']) && $uid == $mod['id'])) if (!hasPermission($config['mod']['editusers']) && !(hasPermission($config['mod']['edit_profile']) && $uid == $mod['id']))
error($config['error']['noaccess']); error($config['error']['noaccess']);
if (in_array($mod['boards'][0], array('infinity', 'z'))) if (in_array($mod['boards'][0], array('infinity', 'z')))
error('This board has password changing disabled.'); error('This board has profile changing disabled.');
$query = prepare('SELECT * FROM ``mods`` WHERE `id` = :id'); $query = prepare('SELECT * FROM ``mods`` WHERE `id` = :id');
$query->bindValue(':id', $uid); $query->bindValue(':id', $uid);
@ -1997,8 +1997,8 @@ function mod_user($uid) {
return; return;
} }
if (hasPermission($config['mod']['change_password']) && $uid == $mod['id'] && isset($_POST['password'])) { if (hasPermission($config['mod']['edit_profile']) && $uid == $mod['id']) {
if ($_POST['password'] != '') { if (isset($_POST['password']) && $_POST['password'] != '') {
$salt = generate_salt(); $salt = generate_salt();
$password = hash('sha256', $salt . sha1($_POST['password'])); $password = hash('sha256', $salt . sha1($_POST['password']));
@ -2013,13 +2013,50 @@ function mod_user($uid) {
login($user['username'], $_POST['password']); login($user['username'], $_POST['password']);
setCookies(); setCookies();
} }
if (isset($_POST['username']) && $user['username'] !== $_POST['username']) {
if ($_POST['username'] == '')
error(sprintf($config['error']['required'], 'username'));
if (!preg_match('/^[a-zA-Z0-9._]{1,30}$/', $_POST['username']))
error(_('Invalid username'));
$query = prepare('SELECT `username` FROM ``mods``');
$query->execute() or error(db_error($query));
$users = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($users as $i => $v) {
if (strtolower($_POST['username']) == strtolower($v['username'])) {
error(_('Refusing to change your username because another user is already using it.'));
}
}
$query = prepare('UPDATE ``mods`` SET `username` = :username WHERE `id` = :id');
$query->bindValue(':id', $uid);
$query->bindValue(':username', $_POST['username']);
$query->execute() or error(db_error($query));
if (hasPermission($config['mod']['manageusers'])) modLog('Renamed user "' . utf8tohtml($user['username']) . '" <small>(#' . $user['id'] . ')</small> to "' . utf8tohtml($_POST['username']) . '"');
header('Location: ?/users', true, $config['redirect_http']); }
else
header('Location: ?/', true, $config['redirect_http']); if (isset($_POST['email']) && $user['email'] !== $_POST['email'] && (empty($_POST['email']) || filter_var($_POST['email'], FILTER_VALIDATE_EMAIL))) {
// account was renamed
$query = prepare('UPDATE ``mods`` SET `email` = :email WHERE `id` = :id');
$query->bindValue(':id', $uid);
$query->bindValue(':email', $_POST['email']);
$query->execute() or error(db_error($query));
return; modLog('Changed user\'s email "' . utf8tohtml($user['email']) . '" <small>(#' . $user['id'] . ')</small> to "' . utf8tohtml($_POST['email']) . '"');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (hasPermission($config['mod']['manageusers']))
header('Location: ?/users', true, $config['redirect_http']);
else
header('Location: ?/', true, $config['redirect_http']);
return;
}
} }
if (hasPermission($config['mod']['modlog'])) { if (hasPermission($config['mod']['modlog'])) {
@ -2032,21 +2069,18 @@ function mod_user($uid) {
} }
if ($mod['type'] >= ADMIN){ if ($mod['type'] >= ADMIN){
$boards = listBoards(); $boards = listBoards();
} else { } else {
$boards2 = explode(',', $user['boards']); $boards2 = explode(',', $user['boards']);
foreach($boards2 as $string){
$boards[] = array("uri"=>$string, "title"=>"MY BOARD");
}
foreach ($boards2 as $string){
$boards[] = array("uri"=>$string, "title" => _("My board"));
}
} }
$user['boards'] = explode(',', $user['boards']); $user['boards'] = explode(',', $user['boards']);
mod_page(_('Edit user'), 'mod/user.html', array( mod_page(_('Edit user profile'), 'mod/user.html', array(
'user' => $user, 'user' => $user,
'logs' => $log, 'logs' => $log,
'boards' => $boards, 'boards' => $boards,
@ -2114,7 +2148,7 @@ function mod_users() {
if (!hasPermission($config['mod']['manageusers'])) if (!hasPermission($config['mod']['manageusers']))
error($config['error']['noaccess']); error($config['error']['noaccess']);
$query = query("SELECT ``m``.`id`, ``m``.`username`, ``m``.`boards`, ``m``.`type`, $query = query("SELECT ``m``.`id`, ``m``.`username`, ``m``.`boards`, ``m``.`type`, ``m``.`email`,
``ml``.`time` last, ``ml``.`text` action ``ml``.`time` last, ``ml``.`text` action
FROM ``mods`` AS m FROM ``mods`` AS m
LEFT JOIN ( LEFT JOIN (
@ -2125,7 +2159,7 @@ function mod_users() {
FROM ``modlogs`` FROM ``modlogs``
GROUP BY `mod` GROUP BY `mod`
) AS ml2 USING (`mod`, time) ) AS ml2 USING (`mod`, time)
) AS ml ON m.id = ml.`mod` ORDER BY ``m``.`type` DESC;") or error(db_error()); ) AS ml ON m.id = ml.`mod` GROUP BY ``m``.`id` ORDER BY ``m``.`type` DESC;") or error(db_error());
$users = $query->fetchAll(PDO::FETCH_ASSOC); $users = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($users as &$user) { foreach ($users as &$user) {

View File

@ -138,6 +138,7 @@ CREATE TABLE IF NOT EXISTS `mods` (
`salt` char(32) CHARACTER SET ascii NOT NULL, `salt` char(32) CHARACTER SET ascii NOT NULL,
`type` smallint(2) NOT NULL, `type` smallint(2) NOT NULL,
`boards` text CHARACTER SET utf8 NOT NULL, `boards` text CHARACTER SET utf8 NOT NULL,
`email` varchar(1024) DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`,`username`) UNIQUE KEY `id` (`id`,`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ; ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;

View File

@ -7,6 +7,7 @@
<tr><th>Subtitle</th><td><input name="subtitle" type="text"> <span class="unimportant">{% trans %}(must be < 200 chars){% endtrans %}</td></tr> <tr><th>Subtitle</th><td><input name="subtitle" type="text"> <span class="unimportant">{% trans %}(must be < 200 chars){% endtrans %}</td></tr>
<tr><th>{% trans %}Username{% endtrans %}</th><td><input name="username" type="text"> <span class="unimportant">{% trans %}(must contain only alphanumeric, periods and underscores){% endtrans %}</span></td></tr> <tr><th>{% trans %}Username{% endtrans %}</th><td><input name="username" type="text"> <span class="unimportant">{% trans %}(must contain only alphanumeric, periods and underscores){% endtrans %}</span></td></tr>
<tr><th>{% trans %}Password{% endtrans %}</th><td><input name="password" type="text" value="{{ password }}" readonly> <span class="unimportant">{% trans %}(write this down){% endtrans %}</span></td></tr> <tr><th>{% trans %}Password{% endtrans %}</th><td><input name="password" type="text" value="{{ password }}" readonly> <span class="unimportant">{% trans %}(write this down){% endtrans %}</span></td></tr>
<tr><th>{% trans %}Email{% endtrans %}</th><td><input name="email" type="text" value=""> <span class="unimportant">{% trans %}(optional, for board recovery){% endtrans %}</span></td></tr>
<tr><th>{% trans %}CAPTCHA{% endtrans %}</th><td>{{ captcha['html'] }}<br/> <tr><th>{% trans %}CAPTCHA{% endtrans %}</th><td>{{ captcha['html'] }}<br/>
<input class="captcha_text" name="captcha_text" size="25" maxlength="6" autocomplete="off" type="text"> <input class="captcha_text" name="captcha_text" size="25" maxlength="6" autocomplete="off" type="text">
<input class="captcha_cookie" name="captcha_cookie" type="hidden" autocomplete="off" value="{{ captcha['cookie']|e }}"><br/></td></tr> <input class="captcha_cookie" name="captcha_cookie" type="hidden" autocomplete="off" value="{{ captcha['cookie']|e }}"><br/></td></tr>

View File

@ -66,7 +66,7 @@
{% if mod|hasPermission(config.mod.manageusers) %} {% if mod|hasPermission(config.mod.manageusers) %}
<li><a href="?/users">{% trans 'Manage users' %}</a></li> <li><a href="?/users">{% trans 'Manage users' %}</a></li>
{% elseif mod|hasPermission(config.mod.change_password) %} {% elseif mod|hasPermission(config.mod.change_password) %}
<li><a href="?/users/{{ mod.id }}">{% trans 'Change password' %}</a></li> <li><a href="?/users/{{ mod.id }}">{% trans 'Edit profile' %}</a> <span class="unimportant hint">(username, email, password)</span></li>
{% endif %} {% endif %}
{% if mod|hasPermission(config.mod.themes) %} {% if mod|hasPermission(config.mod.themes) %}
<li><a href="?/themes">{% trans 'Manage themes' %}</a></li> <li><a href="?/themes">{% trans 'Manage themes' %}</a></li>

View File

@ -8,9 +8,9 @@
<input type="hidden" name="token" value="{{ token }}"> <input type="hidden" name="token" value="{{ token }}">
<table> <table>
<tr> <tr>
<th>{% trans 'Username' %}</th> <th>{% trans 'Username' %}<br/>{% if not mod|hasPermission(config.mod.editusers) %}<small style="font-weight:normal">({% trans 'warning: changing your username<br/>will log you out and change all occurrences<br/>of your old username to the new one in<br/>your board\'s logs' %}){% endif %}</th>
<td> <td>
{% if new or mod|hasPermission(config.mod.editusers) %} {% if new or mod|hasPermission(config.mod.edit_profile) %}
<input size="20" maxlength="30" type="text" name="username" value="{{ user.username|e }}" autocomplete="off"> <input size="20" maxlength="30" type="text" name="username" value="{{ user.username|e }}" autocomplete="off">
{% else %} {% else %}
{{ user.username|e }} {{ user.username|e }}
@ -20,13 +20,23 @@
<tr> <tr>
<th>{% trans 'Password' %}{% if not new %} <small style="font-weight:normal">({% trans 'new; optional' %})</small>{% endif %}</th> <th>{% trans 'Password' %}{% if not new %} <small style="font-weight:normal">({% trans 'new; optional' %})</small>{% endif %}</th>
<td> <td>
{% if new or (mod|hasPermission(config.mod.editusers) or (mod|hasPermission(config.mod.change_password) and user.id == mod.id)) %} {% if new or (mod|hasPermission(config.mod.editusers) or (mod|hasPermission(config.mod.edit_profile) and user.id == mod.id)) %}
<input size="20" maxlength="30" type="password" name="password" value="" autocomplete="off"> <input size="20" maxlength="30" type="password" name="password" value="" autocomplete="off">
{% else %} {% else %}
- -
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
<tr>
<th>{% trans 'Email' %}<br/> <small style="font-weight:normal">({% trans 'if you forget your board password<br/>email admin@8chan.co from this<br/>address to request a reset; optional' %})</small></th>
<td>
{% if new or (mod|hasPermission(config.mod.editusers) or (mod|hasPermission(config.mod.edit_profile) and user.id == mod.id)) %}
<input size="20" maxlength="1024" type="text" name="email" value="{{ user.email|e }}" autocomplete="off">
{% else %}
-
{% endif %}
</td>
</tr>
{% if new %} {% if new %}
<tr> <tr>
<th>{% trans 'Group' %}</th> <th>{% trans 'Group' %}</th>
@ -42,6 +52,7 @@
</td> </td>
</tr> </tr>
{% endif %} {% endif %}
{% if mod|hasPermission(config.mod.editusers) %}
<tr> <tr>
<th>{% trans 'Boards' %}</th> <th>{% trans 'Boards' %}</th>
<td> <td>
@ -73,6 +84,7 @@
</ul> </ul>
</td> </td>
</tr> </tr>
{% endif %}
</table> </table>
<ul style="padding:0;text-align:center;list-style:none"> <ul style="padding:0;text-align:center;list-style:none">

View File

@ -3,6 +3,7 @@
<th>{% trans 'ID' %}</th> <th>{% trans 'ID' %}</th>
<th>{% trans 'Username' %}</th> <th>{% trans 'Username' %}</th>
<th>{% trans 'Type' %}</th> <th>{% trans 'Type' %}</th>
<th>{% trans 'Email' %}</th>
<th>{% trans 'Boards' %}</th> <th>{% trans 'Boards' %}</th>
{% if mod|hasPermission(config.mod.modlog) %} {% if mod|hasPermission(config.mod.modlog) %}
<th>{% trans 'Last action' %}</th> <th>{% trans 'Last action' %}</th>
@ -27,6 +28,9 @@
<em>{% trans 'Unknown' %}</em> ({{ user.type }}) <em>{% trans 'Unknown' %}</em> ({{ user.type }})
{% endif %} {% endif %}
</td> </td>
<td>
{{ user.email|e }}
</td>
<td> <td>
{% if user.boards == '' %} {% if user.boards == '' %}
<em>{% trans 'none' %}</em> <em>{% trans 'none' %}</em>