public function doRun() { if (!class_exists('RenameuserSQL')) { throw new Exception('Extension:Renameuser is not installed'); } $from = $this->params['from']; $to = $this->params['to']; $this->updateStatus('inprogress'); if (isset($this->params['force']) && $this->params['force']) { // If we're dealing with an invalid username, load the data ourselves to avoid // any normalization at all done by User or Title. $row = wfGetDB(DB_MASTER)->selectRow('user', User::selectFields(), array('user_name' => $from), __METHOD__); $oldUser = User::newFromRow($row); } else { $oldUser = User::newFromName($from); } $rename = new RenameuserSQL($from, $to, $oldUser->getId(), $this->getRenameUser(), array('checkIfUserExists' => false, 'debugPrefix' => 'GlobalRename', 'reason' => $this->params['reason'])); if (!$rename->rename()) { // This should never happen! // If it does happen, the user will be locked out of their account // until a sysadmin intervenes... throw new Exception('RenameuserSQL::rename returned false.'); } if ($this->params['movepages']) { $this->movePages($oldUser); } if ($this->params['promotetoglobal']) { $this->promoteToGlobal(); } $this->done(); }
/** * Get all sandboxed users. * @return UserArray List of users. */ public static function getUsers() { $dbw = wfGetDB(DB_MASTER); $tables = array('user', 'user_groups'); $fields = User::selectFields(); $conds = array('ug_group' => 'translate-sandboxed', 'ug_user = user_id'); $res = $dbw->select($tables, $fields, $conds, __METHOD__); return UserArray::newFromResult($res); }
/** * @param $ids array * @return UserArrayFromResult */ static function newFromIDs($ids) { $ids = array_map('intval', (array) $ids); // paranoia if (!$ids) { // Database::select() doesn't like empty arrays return new ArrayIterator(array()); } $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('user', User::selectFields(), array('user_id' => array_unique($ids)), __METHOD__); return self::newFromResult($res); }
/** * @since 1.25 * @param array $names * @return UserArrayFromResult */ static function newFromNames($names) { $names = array_map('strval', (array) $names); // paranoia if (!$names) { // Database::select() doesn't like empty arrays return new ArrayIterator([]); } $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('user', User::selectFields(), ['user_name' => array_unique($names)], __METHOD__); return self::newFromResult($res); }
protected function preprocessResults($results) { $names = array(); foreach ($results as $result) { $names[] = $result->utr_name; } if (!$names) { return; } $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select(array('user', 'ipblocks'), User::selectFields(), array('user_name' => array_unique($names), 'ipb_deleted IS NULL OR ipb_deleted = 0'), __METHOD__, array(), array('ipblocks' => array('LEFT JOIN', 'user_id = ipb_user'))); $userArray = UserArray::newFromResult($res); $lb = new LinkBatch(); foreach ($userArray as $user) { $this->users[$user->getName()] = $user; $lb->addObj($user->getUserPage()); $lb->addObj($user->getTalkPage()); } $lb->execute(); }
public function execute() { $params = $this->extractRequestParams(); if (!is_null($params['prop'])) { $this->prop = array_flip($params['prop']); } else { $this->prop = []; } $users = (array) $params['users']; $goodNames = $done = []; $result = $this->getResult(); // Canonicalize user names foreach ($users as $u) { $n = User::getCanonicalName($u); if ($n === false || $n === '') { $vals = ['name' => $u, 'invalid' => true]; $fit = $result->addValue(['query', $this->getModuleName()], null, $vals); if (!$fit) { $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done))); $goodNames = []; break; } $done[] = $u; } else { $goodNames[] = $n; } } $result = $this->getResult(); if (count($goodNames)) { $this->addTables('user'); $this->addFields(User::selectFields()); $this->addWhereFld('user_name', $goodNames); $this->showHiddenUsersAddBlockInfo(isset($this->prop['blockinfo'])); $data = []; $res = $this->select(__METHOD__); $this->resetQueryParams(); // get user groups if needed if (isset($this->prop['groups']) || isset($this->prop['rights'])) { $userGroups = []; $this->addTables('user'); $this->addWhereFld('user_name', $goodNames); $this->addTables('user_groups'); $this->addJoinConds(['user_groups' => ['INNER JOIN', 'ug_user=user_id']]); $this->addFields(['user_name', 'ug_group']); $userGroupsRes = $this->select(__METHOD__); foreach ($userGroupsRes as $row) { $userGroups[$row->user_name][] = $row->ug_group; } } foreach ($res as $row) { // create user object and pass along $userGroups if set // that reduces the number of database queries needed in User dramatically if (!isset($userGroups)) { $user = User::newFromRow($row); } else { if (!isset($userGroups[$row->user_name]) || !is_array($userGroups[$row->user_name])) { $userGroups[$row->user_name] = []; } $user = User::newFromRow($row, ['user_groups' => $userGroups[$row->user_name]]); } $name = $user->getName(); $data[$name]['userid'] = $user->getId(); $data[$name]['name'] = $name; if (isset($this->prop['editcount'])) { $data[$name]['editcount'] = $user->getEditCount(); } if (isset($this->prop['registration'])) { $data[$name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $user->getRegistration()); } if (isset($this->prop['groups'])) { $data[$name]['groups'] = $user->getEffectiveGroups(); } if (isset($this->prop['implicitgroups'])) { $data[$name]['implicitgroups'] = $user->getAutomaticGroups(); } if (isset($this->prop['rights'])) { $data[$name]['rights'] = $user->getRights(); } if ($row->ipb_deleted) { $data[$name]['hidden'] = true; } if (isset($this->prop['blockinfo']) && !is_null($row->ipb_by_text)) { $data[$name]['blockid'] = (int) $row->ipb_id; $data[$name]['blockedby'] = $row->ipb_by_text; $data[$name]['blockedbyid'] = (int) $row->ipb_by; $data[$name]['blockedtimestamp'] = wfTimestamp(TS_ISO_8601, $row->ipb_timestamp); $data[$name]['blockreason'] = $row->ipb_reason; $data[$name]['blockexpiry'] = $row->ipb_expiry; } if (isset($this->prop['emailable'])) { $data[$name]['emailable'] = $user->canReceiveEmail(); } if (isset($this->prop['gender'])) { $gender = $user->getOption('gender'); if (strval($gender) === '') { $gender = 'unknown'; } $data[$name]['gender'] = $gender; } if (isset($this->prop['centralids'])) { $data[$name] += ApiQueryUserInfo::getCentralUserInfo($this->getConfig(), $user, $params['attachedwiki']); } if (!is_null($params['token'])) { $tokenFunctions = $this->getTokenFunctions(); foreach ($params['token'] as $t) { $val = call_user_func($tokenFunctions[$t], $user); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $data[$name][$t . 'token'] = $val; } } } } } $context = $this->getContext(); // Second pass: add result data to $retval foreach ($goodNames as $u) { if (!isset($data[$u])) { $data[$u] = ['name' => $u]; $urPage = new UserrightsPage(); $urPage->setContext($context); $iwUser = $urPage->fetchUser($u); if ($iwUser instanceof UserRightsProxy) { $data[$u]['interwiki'] = true; if (!is_null($params['token'])) { $tokenFunctions = $this->getTokenFunctions(); foreach ($params['token'] as $t) { $val = call_user_func($tokenFunctions[$t], $iwUser); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $data[$u][$t . 'token'] = $val; } } } } else { $data[$u]['missing'] = true; if (isset($this->prop['cancreate'])) { $status = MediaWiki\Auth\AuthManager::singleton()->canCreateAccount($u); $data[$u]['cancreate'] = $status->isGood(); if (!$status->isGood()) { $data[$u]['cancreateerror'] = $this->getErrorFormatter()->arrayFromStatus($status); } } } } else { if (isset($this->prop['groups']) && isset($data[$u]['groups'])) { ApiResult::setArrayType($data[$u]['groups'], 'array'); ApiResult::setIndexedTagName($data[$u]['groups'], 'g'); } if (isset($this->prop['implicitgroups']) && isset($data[$u]['implicitgroups'])) { ApiResult::setArrayType($data[$u]['implicitgroups'], 'array'); ApiResult::setIndexedTagName($data[$u]['implicitgroups'], 'g'); } if (isset($this->prop['rights']) && isset($data[$u]['rights'])) { ApiResult::setArrayType($data[$u]['rights'], 'array'); ApiResult::setIndexedTagName($data[$u]['rights'], 'r'); } } $fit = $result->addValue(['query', $this->getModuleName()], null, $data[$u]); if (!$fit) { $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done))); break; } $done[] = $u; } $result->addIndexedTagName(['query', $this->getModuleName()], 'user'); }
/** * Process the form. At this point we know that the user passes all the criteria in * userCanExecute(), and if the data array contains 'Username', etc, then Username * resets are allowed. * @param $data array * @throws MWException * @throws ThrottledError|PermissionsError * @return Bool|Array */ public function onSubmit(array $data) { global $wgAuth; if (isset($data['Domain'])) { if ($wgAuth->validDomain($data['Domain'])) { $wgAuth->setDomain($data['Domain']); } else { $wgAuth->setDomain('invaliddomain'); } } if (isset($data['Capture']) && !$this->getUser()->isAllowed('passwordreset')) { // The user knows they don't have the passwordreset permission, // but they tried to spoof the form. That's naughty throw new PermissionsError('passwordreset'); } /** * @var $firstUser User * @var $users User[] */ if (isset($data['Username']) && $data['Username'] !== '') { $method = 'username'; $users = array(User::newFromName($data['Username'])); } elseif (isset($data['Email']) && $data['Email'] !== '' && Sanitizer::validateEmail($data['Email'])) { $method = 'email'; $res = wfGetDB(DB_SLAVE)->select('user', User::selectFields(), array('user_email' => $data['Email']), __METHOD__); if ($res) { $users = array(); foreach ($res as $row) { $users[] = User::newFromRow($row); } } else { // Some sort of database error, probably unreachable throw new MWException('Unknown database error in ' . __METHOD__); } } else { // The user didn't supply any data return false; } // Check for hooks (captcha etc), and allow them to modify the users list $error = array(); if (!wfRunHooks('SpecialPasswordResetOnSubmit', array(&$users, $data, &$error))) { return array($error); } if (count($users) == 0) { if ($method == 'email') { // Don't reveal whether or not an email address is in use return true; } else { return array('noname'); } } $firstUser = $users[0]; if (!$firstUser instanceof User || !$firstUser->getID()) { // Don't parse username as wikitext (bug 65501) return array(array('nosuchuser', wfEscapeWikiText($data['Username']))); } // Check against the rate limiter if ($this->getUser()->pingLimiter('mailpassword')) { throw new ThrottledError(); } // Check against password throttle foreach ($users as $user) { if ($user->isPasswordReminderThrottled()) { global $wgPasswordReminderResendTime; # Round the time in hours to 3 d.p., in case someone is specifying # minutes or seconds. return array(array('throttled-mailpassword', round($wgPasswordReminderResendTime, 3))); } } global $wgNewPasswordExpiry; // All the users will have the same email address if ($firstUser->getEmail() == '') { // This won't be reachable from the email route, so safe to expose the username return array(array('noemail', wfEscapeWikiText($firstUser->getName()))); } // We need to have a valid IP address for the hook, but per bug 18347, we should // send the user's name if they're logged in. $ip = $this->getRequest()->getIP(); if (!$ip) { return array('badipaddress'); } $caller = $this->getUser(); wfRunHooks('User::mailPasswordInternal', array(&$caller, &$ip, &$firstUser)); $username = $caller->getName(); $msg = IP::isValid($username) ? 'passwordreset-emailtext-ip' : 'passwordreset-emailtext-user'; // Send in the user's language; which should hopefully be the same $userLanguage = $firstUser->getOption('language'); $passwords = array(); foreach ($users as $user) { $password = $user->randomPassword(); $user->setNewpassword($password); $user->saveSettings(); $passwords[] = $this->msg('passwordreset-emailelement', $user->getName(), $password)->inLanguage($userLanguage)->text(); // We'll escape the whole thing later } $passwordBlock = implode("\n\n", $passwords); $this->email = $this->msg($msg)->inLanguage($userLanguage); $this->email->params($username, $passwordBlock, count($passwords), '<' . Title::newMainPage()->getCanonicalURL() . '>', round($wgNewPasswordExpiry / 86400)); $title = $this->msg('passwordreset-emailtitle'); $this->result = $firstUser->sendMail($title->text(), $this->email->text()); if (isset($data['Capture']) && $data['Capture']) { // Save the user, will be used if an error occurs when sending the email $this->firstUser = $firstUser; } else { // Blank the email if the user is not supposed to see it $this->email = null; } if ($this->result->isGood()) { return true; } elseif (isset($data['Capture']) && $data['Capture']) { // The email didn't send, but maybe they knew that and that's why they captured it return true; } else { // @todo FIXME: The email wasn't sent, but we have already set // the password throttle timestamp, so they won't be able to try // again until it expires... :( return array(array('mailerror', $this->result->getMessage())); } }
public function execute() { $params = $this->extractRequestParams(); if (!is_null($params['prop'])) { $this->prop = array_flip($params['prop']); } else { $this->prop = array(); } $users = (array) $params['users']; $goodNames = $done = array(); $result = $this->getResult(); // Canonicalize user names foreach ($users as $u) { $n = User::getCanonicalName($u); if ($n === false || $n === '') { $vals = array('name' => $u, 'invalid' => ''); $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); if (!$fit) { $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done))); $goodNames = array(); break; } $done[] = $u; } else { $goodNames[] = $n; } } $result = $this->getResult(); if (count($goodNames)) { $this->addTables('user'); $this->addFields(User::selectFields()); $this->addWhereFld('user_name', $goodNames); if (isset($this->prop['groups']) || isset($this->prop['rights'])) { $this->addTables('user_groups'); $this->addJoinConds(array('user_groups' => array('LEFT JOIN', 'ug_user=user_id'))); $this->addFields('ug_group'); } $this->showHiddenUsersAddBlockInfo(isset($this->prop['blockinfo'])); $data = array(); $res = $this->select(__METHOD__); foreach ($res as $row) { $user = User::newFromRow($row); $name = $user->getName(); $data[$name]['userid'] = $user->getId(); $data[$name]['name'] = $name; if (isset($this->prop['editcount'])) { $data[$name]['editcount'] = intval($user->getEditCount()); } if (isset($this->prop['registration'])) { $data[$name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $user->getRegistration()); } if (isset($this->prop['groups'])) { if (!isset($data[$name]['groups'])) { $data[$name]['groups'] = $user->getAutomaticGroups(); } if (!is_null($row->ug_group)) { // This row contains only one group, others will be added from other rows $data[$name]['groups'][] = $row->ug_group; } } if (isset($this->prop['implicitgroups']) && !isset($data[$name]['implicitgroups'])) { $data[$name]['implicitgroups'] = $user->getAutomaticGroups(); } if (isset($this->prop['rights'])) { if (!isset($data[$name]['rights'])) { $data[$name]['rights'] = User::getGroupPermissions($user->getAutomaticGroups()); } if (!is_null($row->ug_group)) { $data[$name]['rights'] = array_unique(array_merge($data[$name]['rights'], User::getGroupPermissions(array($row->ug_group)))); } } if ($row->ipb_deleted) { $data[$name]['hidden'] = ''; } if (isset($this->prop['blockinfo']) && !is_null($row->ipb_by_text)) { $data[$name]['blockid'] = $row->ipb_id; $data[$name]['blockedby'] = $row->ipb_by_text; $data[$name]['blockedbyid'] = $row->ipb_by; $data[$name]['blockreason'] = $row->ipb_reason; $data[$name]['blockexpiry'] = $row->ipb_expiry; } if (isset($this->prop['emailable']) && $user->canReceiveEmail()) { $data[$name]['emailable'] = ''; } if (isset($this->prop['gender'])) { $gender = $user->getOption('gender'); if (strval($gender) === '') { $gender = 'unknown'; } $data[$name]['gender'] = $gender; } if (!is_null($params['token'])) { $tokenFunctions = $this->getTokenFunctions(); foreach ($params['token'] as $t) { $val = call_user_func($tokenFunctions[$t], $user); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $data[$name][$t . 'token'] = $val; } } } } } // Second pass: add result data to $retval foreach ($goodNames as $u) { if (!isset($data[$u])) { $data[$u] = array('name' => $u); $urPage = new UserrightsPage(); $iwUser = $urPage->fetchUser($u); if ($iwUser instanceof UserRightsProxy) { $data[$u]['interwiki'] = ''; if (!is_null($params['token'])) { $tokenFunctions = $this->getTokenFunctions(); foreach ($params['token'] as $t) { $val = call_user_func($tokenFunctions[$t], $iwUser); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $data[$u][$t . 'token'] = $val; } } } } else { $data[$u]['missing'] = ''; } } else { if (isset($this->prop['groups']) && isset($data[$u]['groups'])) { $result->setIndexedTagName($data[$u]['groups'], 'g'); } if (isset($this->prop['implicitgroups']) && isset($data[$u]['implicitgroups'])) { $result->setIndexedTagName($data[$u]['implicitgroups'], 'g'); } if (isset($this->prop['rights']) && isset($data[$u]['rights'])) { $result->setIndexedTagName($data[$u]['rights'], 'r'); } } $fit = $result->addValue(array('query', $this->getModuleName()), null, $data[$u]); if (!$fit) { $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done))); break; } $done[] = $u; } return $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'user'); }
/** * @param string $email * @return User[] * @throws MWException On unexpected database errors */ protected function getUsersByEmail($email) { $res = wfGetDB(DB_REPLICA)->select('user', User::selectFields(), ['user_email' => $email], __METHOD__); if (!$res) { // Some sort of database error, probably unreachable throw new MWException('Unknown database error in ' . __METHOD__); } $users = []; foreach ($res as $row) { $users[] = User::newFromRow($row); } return $users; }