. */ namespace Fisharebest\Webtrees; use Fisharebest\Webtrees\Controller\PageController; use Fisharebest\Webtrees\Functions\FunctionsDate; use Fisharebest\Webtrees\Functions\FunctionsEdit; use Fisharebest\Webtrees\Functions\FunctionsPrint; use PDO; /** * Defined in session.php * * @global Tree $WT_TREE */ global $WT_TREE; define('WT_SCRIPT_NAME', 'admin_users.php'); require './includes/session.php'; $controller = new PageController; $controller->restrictAccess(Auth::isAdmin()); // Valid values for form variables $ALL_EDIT_OPTIONS = array( 'none' => /* I18N: Listbox entry; name of a role */ I18N::translate('Visitor'), 'access' => /* I18N: Listbox entry; name of a role */ I18N::translate('Member'), 'edit' => /* I18N: Listbox entry; name of a role */ I18N::translate('Editor'), 'accept' => /* I18N: Listbox entry; name of a role */ I18N::translate('Moderator'), 'admin' => /* I18N: Listbox entry; name of a role */ I18N::translate('Manager'), ); // Form actions switch (Filter::post('action')) { case 'save': if (Filter::checkCsrf()) { $user_id = Filter::postInteger('user_id'); $user = User::find($user_id); $username = Filter::post('username'); $real_name = Filter::post('real_name'); $email = Filter::postEmail('email'); $pass1 = Filter::post('pass1', WT_REGEX_PASSWORD); $pass2 = Filter::post('pass2', WT_REGEX_PASSWORD); $theme = Filter::post('theme', implode('|', array_keys(Theme::themeNames())), ''); $language = Filter::post('language'); $timezone = Filter::post('timezone'); $contact_method = Filter::post('contact_method'); $comment = Filter::post('comment'); $auto_accept = Filter::postBool('auto_accept'); $canadmin = Filter::postBool('canadmin'); $visible_online = Filter::postBool('visible_online'); $verified = Filter::postBool('verified'); $approved = Filter::postBool('approved'); if ($user_id === 0) { // Create a new user if (User::findByUserName($username)) { FlashMessages::addMessage(I18N::translate('Duplicate username. A user with that username already exists. Please choose another username.')); } elseif (User::findByEmail($email)) { FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); } elseif ($pass1 !== $pass2) { FlashMessages::addMessage(I18N::translate('The passwords do not match.')); } else { $user = User::create($username, $real_name, $email, $pass1); $user->setPreference('reg_timestamp', date('U'))->setPreference('sessiontime', '0'); Log::addAuthenticationLog('User ->' . $username . '<- created'); } } else { $user = User::find($user_id); if ($user && $username && $real_name) { $user->setEmail($email); $user->setUserName($username); $user->setRealName($real_name); if ($pass1 !== null && $pass1 === $pass2) { $user->setPassword($pass1); } } } if ($user) { // Approving for the first time? Send a confirmation email if ($approved && !$user->getPreference('verified_by_admin') && $user->getPreference('sessiontime') == 0) { I18N::init($user->getPreference('language')); Mail::systemMessage( $WT_TREE, $user, I18N::translate('Approval of account at %s', WT_BASE_URL), I18N::translate('The administrator at the webtrees site %s has approved your application for an account. You may now sign in by accessing the following link: %s', WT_BASE_URL, WT_BASE_URL) ); } $user ->setPreference('theme', $theme) ->setPreference('language', $language) ->setPreference('TIMEZONE', $timezone) ->setPreference('contactmethod', $contact_method) ->setPreference('comment', $comment) ->setPreference('auto_accept', $auto_accept ? '1' : '0') ->setPreference('visibleonline', $visible_online ? '1' : '0') ->setPreference('verified', $verified ? '1' : '0') ->setPreference('verified_by_admin', $approved ? '1' : '0'); // We cannot change our own admin status. Another admin will need to do it. if ($user->getUserId() !== Auth::id()) { $user->setPreference('canadmin', $canadmin ? '1' : '0'); } foreach (Tree::getAll() as $tree) { $tree->setUserPreference($user, 'gedcomid', Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)); $tree->setUserPreference($user, 'canedit', Filter::post('canedit' . $tree->getTreeId(), implode('|', array_keys($ALL_EDIT_OPTIONS)))); if (Filter::post('gedcomid' . $tree->getTreeId(), WT_REGEX_XREF)) { $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', Filter::postInteger('RELATIONSHIP_PATH_LENGTH' . $tree->getTreeId(), 0, 10, 0)); } else { // Do not allow a path length to be set if the individual ID is not $tree->setUserPreference($user, 'RELATIONSHIP_PATH_LENGTH', null); } } } } header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); return; } switch (Filter::get('action')) { case 'load_json': // Generate an AJAX/JSON response for datatables to load a block of rows $search = Filter::postArray('search'); $search = $search['value']; $start = Filter::postInteger('start'); $length = Filter::postInteger('length'); $order = Filter::postArray('order'); $sql_select = "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS '', u.user_id, user_name, real_name, email, us1.setting_value, us2.setting_value, NULL, us3.setting_value, NULL, us4.setting_value, us5.setting_value" . " FROM `##user` u" . " LEFT JOIN `##user_setting` us1 ON (u.user_id=us1.user_id AND us1.setting_name='language')" . " LEFT JOIN `##user_setting` us2 ON (u.user_id=us2.user_id AND us2.setting_name='reg_timestamp')" . " LEFT JOIN `##user_setting` us3 ON (u.user_id=us3.user_id AND us3.setting_name='sessiontime')" . " LEFT JOIN `##user_setting` us4 ON (u.user_id=us4.user_id AND us4.setting_name='verified')" . " LEFT JOIN `##user_setting` us5 ON (u.user_id=us5.user_id AND us5.setting_name='verified_by_admin')" . " WHERE u.user_id > 0"; $args = array(); if ($search) { $sql_select .= " AND (user_name LIKE CONCAT('%', :search_1, '%') OR real_name LIKE CONCAT('%', :search_2, '%') OR email LIKE CONCAT('%', :search_3, '%'))"; $args['search_1'] = $search; $args['search_2'] = $search; $args['search_3'] = $search; } if ($order) { $sql_select .= " ORDER BY "; foreach ($order as $key => $value) { if ($key > 0) { $sql_select .= ','; } // Datatables numbers columns 0, 1, 2 // MySQL numbers columns 1, 2, 3 switch ($value['dir']) { case 'asc': $sql_select .= (1 + $value['column']) . " ASC "; break; case 'desc': $sql_select .= (1 + $value['column']) . " DESC "; break; } } } else { $sql_select = " ORDER BY 1 ASC"; } if ($length) { Auth::user()->setPreference('admin_users_page_size', $length); $sql_select .= " LIMIT :limit OFFSET :offset"; $args['limit'] = $length; $args['offset'] = $start; } // This becomes a JSON list, not array, so need to fetch with numeric keys. $data = Database::prepare($sql_select)->execute($args)->fetchAll(PDO::FETCH_NUM); $installed_languages = array(); foreach (I18N::installedLocales() as $installed_locale) { $installed_languages[$installed_locale->languageTag()] = $installed_locale->endonym(); } // Reformat various columns for display foreach ($data as &$datum) { $user_id = $datum[1]; $user_name = $datum[2]; if ($user_id != Auth::id()) { $admin_options = '