function execute($par) { /** * Some satellite ISPs use broken precaching schemes that log people out straight after * they're logged in (bug 17790). Luckily, there's a way to detect such requests. */ if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '&') !== false) { wfDebug("Special:Userlogout request {$_SERVER['REQUEST_URI']} looks suspicious, denying.\n"); throw new HttpError(400, $this->msg('suspicious-userlogout'), $this->msg('loginerror')); } $this->setHeaders(); $this->outputHeader(); // Make sure it's possible to log out $session = MediaWiki\Session\SessionManager::getGlobalSession(); if (!$session->canSetUser()) { throw new ErrorPageError('cannotlogoutnow-title', 'cannotlogoutnow-text', [$session->getProvider()->describe(RequestContext::getMain()->getLanguage())]); } $user = $this->getUser(); $oldName = $user->getName(); $user->logout(); $loginURL = SpecialPage::getTitleFor('Userlogin')->getFullURL($this->getRequest()->getValues('returnto', 'returntoquery')); $out = $this->getOutput(); $out->addWikiMsg('logouttext', $loginURL); // Hook. $injected_html = ''; Hooks::run('UserLogoutComplete', [&$user, &$injected_html, $oldName]); $out->addHTML($injected_html); $out->returnToMain(); }
function onView() { $this->getOutput()->disable(); $request = $this->getRequest(); $response = $request->response(); $config = $this->context->getConfig(); if (!$request->checkUrlExtension()) { return; } if ($this->getOutput()->checkLastModified($this->page->getTouched())) { return; // Client cache fresh and headers sent, nothing more to do. } $gen = $request->getVal('gen'); if ($gen == 'css' || $gen == 'js') { $this->gen = true; } $contentType = $this->getContentType(); $maxage = $request->getInt('maxage', $config->get('SquidMaxage')); $smaxage = $request->getIntOrNull('smaxage'); if ($smaxage === null) { if ($contentType == 'text/css' || $contentType == 'text/javascript') { // CSS/JS raw content has its own CDN max age configuration. // Note: Title::getCdnUrls() includes action=raw for css/js pages, // so if using the canonical url, this will get HTCP purges. $smaxage = intval($config->get('ForcedRawSMaxage')); } else { // No CDN cache for anything else $smaxage = 0; } } $response->header('Content-type: ' . $contentType . '; charset=UTF-8'); // Output may contain user-specific data; // vary generated content for open sessions on private wikis $privateCache = !User::isEveryoneAllowed('read') && ($smaxage == 0 || MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent()); // Don't accidentally cache cookies if user is logged in (T55032) $privateCache = $privateCache || $this->getUser()->isLoggedIn(); $mode = $privateCache ? 'private' : 'public'; $response->header('Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage); $text = $this->getRawText(); // Don't return a 404 response for CSS or JavaScript; // 404s aren't generally cached and it would create // extra hits when user CSS/JS are on and the user doesn't // have the pages. if ($text === false && $contentType == 'text/x-wiki') { $response->statusHeader(404); } if (!Hooks::run('RawPageViewBeforeOutput', array(&$this, &$text))) { wfDebug(__METHOD__ . ": RawPageViewBeforeOutput hook broke raw page output.\n"); } echo $text; }
public function execute() { // Make sure it's possible to log out $session = MediaWiki\Session\SessionManager::getGlobalSession(); if (!$session->canSetUser()) { $this->dieUsage('Cannot log out when using ' . $session->getProvider()->describe(Language::factory('en')), 'cannotlogout'); } $user = $this->getUser(); $oldName = $user->getName(); $user->logout(); // Give extensions to do something after user logout $injected_html = ''; Hooks::run('UserLogoutComplete', array(&$user, &$injected_html, $oldName)); }
/** * @covers RequestContext::importScopedSession */ public function testImportScopedSession() { // Make sure session handling is started if (!MediaWiki\Session\PHPSessionHandler::isInstalled()) { MediaWiki\Session\PHPSessionHandler::install(MediaWiki\Session\SessionManager::singleton()); } $oldSessionId = session_id(); $context = RequestContext::getMain(); $oInfo = $context->exportSession(); $this->assertEquals('127.0.0.1', $oInfo['ip'], "Correct initial IP address."); $this->assertEquals(0, $oInfo['userId'], "Correct initial user ID."); $this->assertFalse(MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent(), 'Global session isn\'t persistent to start'); $user = User::newFromName('UnitTestContextUser'); $user->addToDatabase(); $sinfo = array('sessionId' => 'd612ee607c87e749ef14da4983a702cd', 'userId' => $user->getId(), 'ip' => '192.0.2.0', 'headers' => array('USER-AGENT' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0')); // importScopedSession() sets these variables $this->setMwGlobals(array('wgUser' => new User(), 'wgRequest' => new FauxRequest())); $sc = RequestContext::importScopedSession($sinfo); // load new context $info = $context->exportSession(); $this->assertEquals($sinfo['ip'], $info['ip'], "Correct IP address."); $this->assertEquals($sinfo['headers'], $info['headers'], "Correct headers."); $this->assertEquals($sinfo['sessionId'], $info['sessionId'], "Correct session ID."); $this->assertEquals($sinfo['userId'], $info['userId'], "Correct user ID."); $this->assertEquals($sinfo['ip'], $context->getRequest()->getIP(), "Correct context IP address."); $this->assertEquals($sinfo['headers'], $context->getRequest()->getAllHeaders(), "Correct context headers."); $this->assertEquals($sinfo['sessionId'], MediaWiki\Session\SessionManager::getGlobalSession()->getId(), "Correct context session ID."); if (\MediaWiki\Session\PhpSessionHandler::isEnabled()) { $this->assertEquals($sinfo['sessionId'], session_id(), "Correct context session ID."); } else { $this->assertEquals($oldSessionId, session_id(), "Unchanged PHP session ID."); } $this->assertEquals(true, $context->getUser()->isLoggedIn(), "Correct context user."); $this->assertEquals($sinfo['userId'], $context->getUser()->getId(), "Correct context user ID."); $this->assertEquals('UnitTestContextUser', $context->getUser()->getName(), "Correct context user name."); unset($sc); // restore previous context $info = $context->exportSession(); $this->assertEquals($oInfo['ip'], $info['ip'], "Correct restored IP address."); $this->assertEquals($oInfo['headers'], $info['headers'], "Correct restored headers."); $this->assertEquals($oInfo['sessionId'], $info['sessionId'], "Correct restored session ID."); $this->assertEquals($oInfo['userId'], $info['userId'], "Correct restored user ID."); $this->assertFalse(MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent(), 'Global session isn\'t persistent after restoring the context'); }
public function execute() { $session = MediaWiki\Session\SessionManager::getGlobalSession(); // Handle bot password logout specially if ($session->getProvider() instanceof BotPasswordSessionProvider) { $session->unpersist(); return; } // Make sure it's possible to log out if (!$session->canSetUser()) { $this->dieUsage('Cannot log out when using ' . $session->getProvider()->describe(Language::factory('en')), 'cannotlogout'); } $user = $this->getUser(); $oldName = $user->getName(); $user->logout(); // Give extensions to do something after user logout $injected_html = ''; Hooks::run('UserLogoutComplete', [&$user, &$injected_html, $oldName]); }
/** * Import an client IP address, HTTP headers, user ID, and session ID * * This sets the current session, $wgUser, and $wgRequest from $params. * Once the return value falls out of scope, the old context is restored. * This method should only be called in contexts where there is no session * ID or end user receiving the response (CLI or HTTP job runners). This * is partly enforced, and is done so to avoid leaking cookies if certain * error conditions arise. * * This is useful when background scripts inherit context when acting on * behalf of a user. In general the 'sessionId' parameter should be set * to an empty string unless session importing is *truly* needed. This * feature is somewhat deprecated. * * @note suhosin.session.encrypt may interfere with this method. * * @param array $params Result of RequestContext::exportSession() * @return ScopedCallback * @throws MWException * @since 1.21 */ public static function importScopedSession(array $params) { if (strlen($params['sessionId']) && MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent()) { // Sanity check to avoid sending random cookies for the wrong users. // This method should only called by CLI scripts or by HTTP job runners. throw new MWException("Sessions can only be imported when none is active."); } elseif (!IP::isValid($params['ip'])) { throw new MWException("Invalid client IP address '{$params['ip']}'."); } if ($params['userId']) { // logged-in user $user = User::newFromId($params['userId']); $user->load(); if (!$user->getId()) { throw new MWException("No user with ID '{$params['userId']}'."); } } else { // anon user $user = User::newFromName($params['ip'], false); } $importSessionFunc = function (User $user, array $params) { global $wgRequest, $wgUser; $context = RequestContext::getMain(); // Commit and close any current session if (MediaWiki\Session\PHPSessionHandler::isEnabled()) { session_write_close(); // persist session_id(''); // detach $_SESSION = []; // clear in-memory array } // Get new session, if applicable $session = null; if (strlen($params['sessionId'])) { // don't make a new random ID $manager = MediaWiki\Session\SessionManager::singleton(); $session = $manager->getSessionById($params['sessionId'], true) ?: $manager->getEmptySession(); } // Remove any user IP or agent information, and attach the request // with the new session. $context->setRequest(new FauxRequest([], false, $session)); $wgRequest = $context->getRequest(); // b/c // Now that all private information is detached from the user, it should // be safe to load the new user. If errors occur or an exception is thrown // and caught (leaving the main context in a mixed state), there is no risk // of the User object being attached to the wrong IP, headers, or session. $context->setUser($user); $wgUser = $context->getUser(); // b/c if ($session && MediaWiki\Session\PHPSessionHandler::isEnabled()) { session_id($session->getId()); MediaWiki\quietCall('session_start'); } $request = new FauxRequest([], false, $session); $request->setIP($params['ip']); foreach ($params['headers'] as $name => $value) { $request->setHeader($name, $value); } // Set the current context to use the new WebRequest $context->setRequest($request); $wgRequest = $context->getRequest(); // b/c }; // Stash the old session and load in the new one $oUser = self::getMain()->getUser(); $oParams = self::getMain()->exportSession(); $oRequest = self::getMain()->getRequest(); $importSessionFunc($user, $params); // Set callback to save and close the new session and reload the old one return new ScopedCallback(function () use($importSessionFunc, $oUser, $oParams, $oRequest) { global $wgRequest; $importSessionFunc($oUser, $oParams); // Restore the exact previous Request object (instead of leaving FauxRequest) RequestContext::getMain()->setRequest($oRequest); $wgRequest = RequestContext::getMain()->getRequest(); // b/c }); }
public function testBotPassword() { global $wgServer, $wgSessionProviders; if (!isset($wgServer)) { $this->markTestIncomplete('This test needs $wgServer to be set in LocalSettings.php'); } $this->setMwGlobals(array('wgSessionProviders' => array_merge($wgSessionProviders, array(array('class' => 'MediaWiki\\Session\\BotPasswordSessionProvider', 'args' => array(array('priority' => 40))))), 'wgEnableBotPasswords' => true, 'wgBotPasswordsDatabase' => false, 'wgCentralIdLookupProvider' => 'local', 'wgGrantPermissions' => array('test' => array('read' => true)))); // Make sure our session provider is present $manager = TestingAccessWrapper::newFromObject(MediaWiki\Session\SessionManager::singleton()); if (!isset($manager->sessionProviders['MediaWiki\\Session\\BotPasswordSessionProvider'])) { $tmp = $manager->sessionProviders; $manager->sessionProviders = null; $manager->sessionProviders = $tmp + $manager->getProviders(); } $this->assertNotNull(MediaWiki\Session\SessionManager::singleton()->getProvider('MediaWiki\\Session\\BotPasswordSessionProvider'), 'sanity check'); $user = self::$users['sysop']; $centralId = CentralIdLookup::factory()->centralIdFromLocalUser($user->getUser()); $this->assertNotEquals(0, $centralId, 'sanity check'); $passwordFactory = new PasswordFactory(); $passwordFactory->init(RequestContext::getMain()->getConfig()); // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only $passwordFactory->setDefaultType('A'); $pwhash = $passwordFactory->newFromPlaintext('foobaz'); $dbw = wfGetDB(DB_MASTER); $dbw->insert('bot_passwords', array('bp_user' => $centralId, 'bp_app_id' => 'foo', 'bp_password' => $pwhash->toString(), 'bp_token' => '', 'bp_restrictions' => MWRestrictions::newDefault()->toJson(), 'bp_grants' => '["test"]'), __METHOD__); $lgName = $user->username . BotPassword::getSeparator() . 'foo'; $ret = $this->doApiRequest(array('action' => 'login', 'lgname' => $lgName, 'lgpassword' => 'foobaz')); $result = $ret[0]; $this->assertNotInternalType('bool', $result); $this->assertNotInternalType('null', $result['login']); $a = $result['login']['result']; $this->assertEquals('NeedToken', $a); $token = $result['login']['token']; $ret = $this->doApiRequest(array('action' => 'login', 'lgtoken' => $token, 'lgname' => $lgName, 'lgpassword' => 'foobaz'), $ret[2]); $result = $ret[0]; $this->assertNotInternalType('bool', $result); $a = $result['login']['result']; $this->assertEquals('Success', $a); }
// any necessary initialisation in the fully initialised environment foreach ($wgExtensionFunctions as $func) { // Allow closures in PHP 5.3+ if (is_object($func) && $func instanceof Closure) { $profName = $fname . '-extensions-closure'; } elseif (is_array($func)) { if (is_object($func[0])) { $profName = $fname . '-extensions-' . get_class($func[0]) . '::' . $func[1]; } else { $profName = $fname . '-extensions-' . implode('::', $func); } } else { $profName = $fname . '-extensions-' . strval($func); } $ps_ext_func = Profiler::instance()->scopedProfileIn($profName); call_user_func($func); Profiler::instance()->scopedProfileOut($ps_ext_func); } // If the session user has a 0 id but a valid name, that means we need to // autocreate it. $sessionUser = MediaWiki\Session\SessionManager::getGlobalSession()->getUser(); if ($sessionUser->getId() === 0 && User::isValidUserName($sessionUser->getName())) { $ps_autocreate = Profiler::instance()->scopedProfileIn($fname . '-autocreate'); MediaWiki\Session\SessionManager::autoCreateUser($sessionUser); Profiler::instance()->scopedProfileOut($ps_autocreate); } unset($sessionUser); wfDebug("Fully initialised\n"); $wgFullyInitialised = true; Profiler::instance()->scopedProfileOut($ps_extensions); Profiler::instance()->scopedProfileOut($ps_setup);
/** * Send caching headers * @param boolean $isError Whether an error response is being output * @since 1.26 added $isError parameter */ protected function sendCacheHeaders($isError) { $response = $this->getRequest()->response(); $out = $this->getOutput(); $config = $this->getConfig(); if ($config->get('VaryOnXFP')) { $out->addVaryHeader('X-Forwarded-Proto'); } if (!$isError && $this->mModule && ($this->getRequest()->getMethod() === 'GET' || $this->getRequest()->getMethod() === 'HEAD')) { $etag = $this->mModule->getConditionalRequestData('etag'); if ($etag !== null) { $response->header("ETag: {$etag}"); } $lastMod = $this->mModule->getConditionalRequestData('last-modified'); if ($lastMod !== null) { $response->header('Last-Modified: ' . wfTimestamp(TS_RFC2822, $lastMod)); } } // The logic should be: // $this->mCacheControl['max-age'] is set? // Use it, the module knows better than our guess. // !$this->mModule || $this->mModule->isWriteMode(), and mCacheMode is private? // Use 0 because we can guess caching is probably the wrong thing to do. // Use $this->getParameter( 'maxage' ), which already defaults to 0. $maxage = 0; if (isset($this->mCacheControl['max-age'])) { $maxage = $this->mCacheControl['max-age']; } elseif ($this->mModule && !$this->mModule->isWriteMode() || $this->mCacheMode !== 'private') { $maxage = $this->getParameter('maxage'); } $privateCache = 'private, must-revalidate, max-age=' . $maxage; if ($this->mCacheMode == 'private') { $response->header("Cache-Control: {$privateCache}"); return; } $useKeyHeader = $config->get('UseKeyHeader'); if ($this->mCacheMode == 'anon-public-user-private') { $out->addVaryHeader('Cookie'); $response->header($out->getVaryHeader()); if ($useKeyHeader) { $response->header($out->getKeyHeader()); if ($out->haveCacheVaryCookies()) { // Logged in, mark this request private $response->header("Cache-Control: {$privateCache}"); return; } // Logged out, send normal public headers below } elseif (MediaWiki\Session\SessionManager::getGlobalSession()->isPersistent()) { // Logged in or otherwise has session (e.g. anonymous users who have edited) // Mark request private $response->header("Cache-Control: {$privateCache}"); return; } // else no Key and anonymous, send public headers below } // Send public headers $response->header($out->getVaryHeader()); if ($useKeyHeader) { $response->header($out->getKeyHeader()); } // If nobody called setCacheMaxAge(), use the (s)maxage parameters if (!isset($this->mCacheControl['s-maxage'])) { $this->mCacheControl['s-maxage'] = $this->getParameter('smaxage'); } if (!isset($this->mCacheControl['max-age'])) { $this->mCacheControl['max-age'] = $this->getParameter('maxage'); } if (!$this->mCacheControl['s-maxage'] && !$this->mCacheControl['max-age']) { // Public cache not requested // Sending a Vary header in this case is harmless, and protects us // against conditional calls of setCacheMaxAge(). $response->header("Cache-Control: {$privateCache}"); return; } $this->mCacheControl['public'] = true; // Send an Expires header $maxAge = min($this->mCacheControl['s-maxage'], $this->mCacheControl['max-age']); $expiryUnixTime = $maxAge == 0 ? 1 : time() + $maxAge; $response->header('Expires: ' . wfTimestamp(TS_RFC2822, $expiryUnixTime)); // Construct the Cache-Control header $ccHeader = ''; $separator = ''; foreach ($this->mCacheControl as $name => $value) { if (is_bool($value)) { if ($value) { $ccHeader .= $separator . $name; $separator = ', '; } } else { $ccHeader .= $separator . "{$name}={$value}"; $separator = ', '; } } $response->header("Cache-Control: {$ccHeader}"); }
/** * Try to log the user in * @param string $username Combined user name and app ID * @param string $password Supplied password * @param WebRequest $request * @return Status On success, the good status's value is the new Session object */ public static function login($username, $password, WebRequest $request) { global $wgEnableBotPasswords; if (!$wgEnableBotPasswords) { return Status::newFatal('botpasswords-disabled'); } $manager = MediaWiki\Session\SessionManager::singleton(); $provider = $manager->getProvider('MediaWiki\\Session\\BotPasswordSessionProvider'); if (!$provider) { return Status::newFatal('botpasswords-no-provider'); } // Split name into name+appId $sep = self::getSeparator(); if (strpos($username, $sep) === false) { return Status::newFatal('botpasswords-invalid-name', $sep); } list($name, $appId) = explode($sep, $username, 2); // Find the named user $user = User::newFromName($name); if (!$user || $user->isAnon()) { return Status::newFatal('nosuchuser', $name); } // Get the bot password $bp = self::newFromUser($user, $appId); if (!$bp) { return Status::newFatal('botpasswords-not-exist', $name, $appId); } // Check restrictions $status = $bp->getRestrictions()->check($request); if (!$status->isOk()) { return Status::newFatal('botpasswords-restriction-failed'); } // Check the password if (!$bp->getPassword()->equals($password)) { return Status::newFatal('wrongpassword'); } // Ok! Create the session. return Status::newGood($provider->newSessionForRequest($user, $bp, $request)); }
protected function tearDown() { global $wgRequest, $wgSQLMode; $status = ob_get_status(); if (isset($status['name']) && $status['name'] === 'MediaWikiTestCase::wfResetOutputBuffersBarrier') { ob_end_flush(); } $this->called['tearDown'] = true; // Cleaning up temporary files foreach ($this->tmpFiles as $fileName) { if (is_file($fileName) || is_link($fileName)) { unlink($fileName); } elseif (is_dir($fileName)) { wfRecursiveRemoveDir($fileName); } } if ($this->needsDB() && $this->db) { // Clean up open transactions while ($this->db->trxLevel() > 0) { $this->db->rollback(__METHOD__, 'flush'); } if ($this->db->getType() === 'mysql') { $this->db->query("SET sql_mode = " . $this->db->addQuotes($wgSQLMode)); } } // Restore mw globals foreach ($this->mwGlobals as $key => $value) { $GLOBALS[$key] = $value; } $this->mwGlobals = []; $this->restoreLoggers(); if (self::$serviceLocator && MediaWikiServices::getInstance() !== self::$serviceLocator) { MediaWikiServices::forceGlobalInstance(self::$serviceLocator); } // TODO: move global state into MediaWikiServices RequestContext::resetMain(); if (session_id() !== '') { session_write_close(); session_id(''); } $wgRequest = new FauxRequest(); MediaWiki\Session\SessionManager::resetCache(); MediaWiki\Auth\AuthManager::resetCache(); $phpErrorLevel = intval(ini_get('error_reporting')); if ($phpErrorLevel !== $this->phpErrorLevel) { ini_set('error_reporting', $this->phpErrorLevel); $oldHex = strtoupper(dechex($this->phpErrorLevel)); $newHex = strtoupper(dechex($phpErrorLevel)); $message = "PHP error_reporting setting was left dirty: " . "was 0x{$oldHex} before test, 0x{$newHex} after test!"; $this->fail($message); } parent::tearDown(); }
if (is_object($func[0])) { $profName = $fname . '-extensions-' . get_class($func[0]) . '::' . $func[1]; } else { $profName = $fname . '-extensions-' . implode('::', $func); } } else { $profName = $fname . '-extensions-' . strval($func); } $ps_ext_func = Profiler::instance()->scopedProfileIn($profName); call_user_func($func); Profiler::instance()->scopedProfileOut($ps_ext_func); } // If the session user has a 0 id but a valid name, that means we need to // autocreate it. if (!defined('MW_NO_SESSION') && !$wgCommandLineMode) { $sessionUser = MediaWiki\Session\SessionManager::getGlobalSession()->getUser(); if ($sessionUser->getId() === 0 && User::isValidUserName($sessionUser->getName())) { $ps_autocreate = Profiler::instance()->scopedProfileIn($fname . '-autocreate'); $res = MediaWiki\Auth\AuthManager::singleton()->autoCreateUser($sessionUser, MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_SESSION, true); Profiler::instance()->scopedProfileOut($ps_autocreate); \MediaWiki\Logger\LoggerFactory::getInstance('authevents')->info('Autocreation attempt', ['event' => 'autocreate', 'status' => $res]); unset($res); } unset($sessionUser); } if (!$wgCommandLineMode) { Pingback::schedulePingback(); } wfDebug("Fully initialised\n"); $wgFullyInitialised = true; Profiler::instance()->scopedProfileOut($ps_extensions);
/** * Initialize the session data. Sets the initial result to queued. */ public function initializeSessionData() { $session = MediaWiki\Session\SessionManager::getGlobalSession(); $data = self::getSessionData($session, $this->params['sessionKey']); $data['result'] = 'Queued'; self::setSessionData($session, $this->params['sessionKey'], $data); }
public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->dieUsage('Cannot create account when the same-origin policy is not applied', 'aborted'); } // $loginForm->addNewaccountInternal will throw exceptions // if wiki is read only (already handled by api), user is blocked or does not have rights. // Use userCan in order to hit GlobalBlock checks (according to Special:userlogin) $loginTitle = SpecialPage::getTitleFor('Userlogin'); if (!$loginTitle->userCan('createaccount', $this->getUser())) { $this->dieUsage('You do not have the right to create a new account', 'permdenied-createaccount'); } if ($this->getUser()->isBlockedFromCreateAccount()) { $this->dieUsage('You cannot create a new account because you are blocked', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($this->getUser()->getBlock()))); } $params = $this->extractRequestParams(); // Make sure session is persisted MediaWiki\Session\SessionManager::getGlobalSession()->persist(); if ($params['mailpassword'] && !$params['email']) { $this->dieUsageMsg('noemail'); } if ($params['language'] && !Language::isSupportedLanguage($params['language'])) { $this->dieUsage('Invalid language parameter', 'langinvalid'); } $context = new DerivativeContext($this->getContext()); $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('type' => 'signup', 'uselang' => $params['language'], 'wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpRetype' => $params['password'], 'wpDomain' => $params['domain'], 'wpEmail' => $params['email'], 'wpRealName' => $params['realname'], 'wpCreateaccountToken' => $params['token'], 'wpCreateaccount' => $params['mailpassword'] ? null : '1', 'wpCreateaccountMail' => $params['mailpassword'] ? '1' : null))); $loginForm = new LoginForm(); $loginForm->setContext($context); Hooks::run('AddNewAccountApiForm', array($this, $loginForm)); $loginForm->load(); $status = $loginForm->addNewAccountInternal(); LoggerFactory::getInstance('authmanager')->info('Account creation attempt via API', array('event' => 'accountcreation', 'status' => $status)); $result = array(); if ($status->isGood()) { // Success! $user = $status->getValue(); if ($params['language']) { $user->setOption('language', $params['language']); } if ($params['mailpassword']) { // If mailpassword was set, disable the password and send an email. $user->setPassword(null); $status->merge($loginForm->mailPasswordInternal($user, false, 'createaccount-title', 'createaccount-text')); } elseif ($this->getConfig()->get('EmailAuthentication') && Sanitizer::validateEmail($user->getEmail())) { // Send out an email authentication message if needed $status->merge($user->sendConfirmationMail()); } // Save settings (including confirmation token) $user->saveSettings(); Hooks::run('AddNewAccount', array($user, $params['mailpassword'])); if ($params['mailpassword']) { $logAction = 'byemail'; } elseif ($this->getUser()->isLoggedIn()) { $logAction = 'create2'; } else { $logAction = 'create'; } $user->addNewUserLogEntry($logAction, (string) $params['reason']); // Add username, id, and token to result. $result['username'] = $user->getName(); $result['userid'] = $user->getId(); $result['token'] = $user->getToken(); } $apiResult = $this->getResult(); if ($status->hasMessage('sessionfailure') || $status->hasMessage('nocookiesfornew')) { // Token was incorrect, so add it to result, but don't throw an exception // since not having the correct token is part of the normal // flow of events. $result['token'] = LoginForm::getCreateaccountToken(); $result['result'] = 'NeedToken'; } elseif (!$status->isOK()) { // There was an error. Die now. $this->dieStatus($status); } elseif (!$status->isGood()) { // Status is not good, but OK. This means warnings. $result['result'] = 'Warning'; // Add any warnings to the result $warnings = $status->getErrorsByType('warning'); if ($warnings) { foreach ($warnings as &$warning) { ApiResult::setIndexedTagName($warning['params'], 'param'); } ApiResult::setIndexedTagName($warnings, 'warning'); $result['warnings'] = $warnings; } } else { // Everything was fine. $result['result'] = 'Success'; } // Give extensions a chance to modify the API result data Hooks::run('AddNewAccountApiResult', array($this, $loginForm, &$result)); $apiResult->addValue(null, 'createaccount', $result); }
if (is_object($func[0])) { $profName = $fname . '-extensions-' . get_class($func[0]) . '::' . $func[1]; } else { $profName = $fname . '-extensions-' . implode('::', $func); } } else { $profName = $fname . '-extensions-' . strval($func); } $ps_ext_func = Profiler::instance()->scopedProfileIn($profName); call_user_func($func); Profiler::instance()->scopedProfileOut($ps_ext_func); } // If the session user has a 0 id but a valid name, that means we need to // autocreate it. if (!defined('MW_NO_SESSION') && !$wgCommandLineMode) { $sessionUser = MediaWiki\Session\SessionManager::getGlobalSession()->getUser(); if ($sessionUser->getId() === 0 && User::isValidUserName($sessionUser->getName())) { $ps_autocreate = Profiler::instance()->scopedProfileIn($fname . '-autocreate'); MediaWiki\Session\SessionManager::autoCreateUser($sessionUser); Profiler::instance()->scopedProfileOut($ps_autocreate); } unset($sessionUser); } wfDebug("Fully initialised\n"); $wgFullyInitialised = true; // T125455 if (!defined('MW_NO_SESSION') && !$wgCommandLineMode) { MediaWiki\Session\SessionManager::singleton()->checkIpLimits(); } Profiler::instance()->scopedProfileOut($ps_extensions); Profiler::instance()->scopedProfileOut($ps_setup);
/** * @param string $comment * @param string $pageText * @param bool $watch * @param User $user * @return string */ protected function insertJob($comment, $pageText, $watch, $user) { $sessionKey = $this->stashSession(); $job = new UploadFromUrlJob($this->getTitle(), array('url' => $this->mUrl, 'comment' => $comment, 'pageText' => $pageText, 'watch' => $watch, 'userName' => $user->getName(), 'leaveMessage' => $this->mAsync == 'async-leavemessage', 'ignoreWarnings' => $this->mIgnoreWarnings, 'sessionId' => MediaWiki\Session\SessionManager::getGlobalSession()->getId(), 'sessionKey' => $sessionKey)); $job->initializeSessionData(); JobQueueGroup::singleton()->push($job); return $sessionKey; }
/** * Executes the log-in attempt using the parameters passed. If * the log-in succeeds, it attaches a cookie to the session * and outputs the user id, username, and session token. If a * log-in fails, as the result of a bad password, a nonexistent * user, or any other reason, the host is cached with an expiry * and no log-in attempts will be accepted until that expiry * is reached. The expiry is $this->mLoginThrottle. */ public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied')); return; } $params = $this->extractRequestParams(); $result = array(); // Make sure session is persisted $session = MediaWiki\Session\SessionManager::getGlobalSession(); $session->persist(); // Make sure it's possible to log in if (!$session->canSetUser()) { $this->getResult()->addValue(null, 'login', array('result' => 'Aborted', 'reason' => 'Cannot log in when using ' . $session->getProvider()->describe(Language::factory('en')))); return; } $authRes = false; $context = new DerivativeContext($this->getContext()); $loginType = 'N/A'; // Check login token $token = LoginForm::getLoginToken(); if (!$token) { LoginForm::setLoginToken(); $authRes = LoginForm::NEED_TOKEN; } elseif (!$params['token']) { $authRes = LoginForm::NEED_TOKEN; } elseif ($token !== $params['token']) { $authRes = LoginForm::WRONG_TOKEN; } // Try bot passwords if ($authRes === false && $this->getConfig()->get('EnableBotPasswords') && strpos($params['name'], BotPassword::getSeparator()) !== false) { $status = BotPassword::login($params['name'], $params['password'], $this->getRequest()); if ($status->isOk()) { $session = $status->getValue(); $authRes = LoginForm::SUCCESS; $loginType = 'BotPassword'; } else { LoggerFactory::getInstance('authmanager')->info('BotPassword login failed: ' . $status->getWikiText()); } } // Normal login if ($authRes === false) { $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), array('wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => ''))); $loginForm = new LoginForm(); $loginForm->setContext($context); $authRes = $loginForm->authenticateUserData(); $loginType = 'LoginForm'; } switch ($authRes) { case LoginForm::SUCCESS: $user = $context->getUser(); $this->getContext()->setUser($user); $user->setCookies($this->getRequest(), null, true); ApiQueryInfo::resetTokenCache(); // Run hooks. // @todo FIXME: Split back and frontend from this hook. // @todo FIXME: This hook should be placed in the backend $injected_html = ''; Hooks::run('UserLoginComplete', array(&$user, &$injected_html)); $result['result'] = 'Success'; $result['lguserid'] = intval($user->getId()); $result['lgusername'] = $user->getName(); // @todo: These are deprecated, and should be removed at some // point (1.28 at the earliest, and see T121527). They were ok // when the core cookie-based login was the only thing, but // CentralAuth broke that a while back and // SessionManager/AuthManager are *really* going to break it. $result['lgtoken'] = $user->getToken(); $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case LoginForm::NEED_TOKEN: $result['result'] = 'NeedToken'; $result['token'] = LoginForm::getLoginToken(); // @todo: See above about deprecation $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case LoginForm::WRONG_TOKEN: $result['result'] = 'WrongToken'; break; case LoginForm::NO_NAME: $result['result'] = 'NoName'; break; case LoginForm::ILLEGAL: $result['result'] = 'Illegal'; break; case LoginForm::WRONG_PLUGIN_PASS: $result['result'] = 'WrongPluginPass'; break; case LoginForm::NOT_EXISTS: $result['result'] = 'NotExists'; break; // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. case LoginForm::RESET_PASS: case LoginForm::WRONG_PASS: $result['result'] = 'WrongPass'; break; case LoginForm::EMPTY_PASS: $result['result'] = 'EmptyPass'; break; case LoginForm::CREATE_BLOCKED: $result['result'] = 'CreateBlocked'; $result['details'] = 'Your IP address is blocked from account creation'; $block = $context->getUser()->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::THROTTLED: $result['result'] = 'Throttled'; $throttle = $this->getConfig()->get('PasswordAttemptThrottle'); $result['wait'] = intval($throttle['seconds']); break; case LoginForm::USER_BLOCKED: $result['result'] = 'Blocked'; $block = User::newFromName($params['name'])->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::ABORTED: $result['result'] = 'Aborted'; $result['reason'] = $loginForm->mAbortLoginErrorMsg; break; default: ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}"); } $this->getResult()->addValue(null, 'login', $result); LoggerFactory::getInstance('authmanager')->info('Login attempt', array('event' => 'login', 'successful' => $authRes === LoginForm::SUCCESS, 'loginType' => $loginType, 'status' => LoginForm::$statusCodes[$authRes])); }
protected function tearDown() { // Avoid leaking session over tests MediaWiki\Session\SessionManager::getGlobalSession()->clear(); parent::tearDown(); }
protected function tearDown() { global $wgRequest; $status = ob_get_status(); if (isset($status['name']) && $status['name'] === 'MediaWikiTestCase::wfResetOutputBuffersBarrier') { ob_end_flush(); } $this->called['tearDown'] = true; // Cleaning up temporary files foreach ($this->tmpFiles as $fileName) { if (is_file($fileName) || is_link($fileName)) { unlink($fileName); } elseif (is_dir($fileName)) { wfRecursiveRemoveDir($fileName); } } if ($this->needsDB() && $this->db) { // Clean up open transactions while ($this->db->trxLevel() > 0) { $this->db->rollback(__METHOD__, 'flush'); } } // Restore mw globals foreach ($this->mwGlobals as $key => $value) { $GLOBALS[$key] = $value; } $this->mwGlobals = array(); RequestContext::resetMain(); MediaHandler::resetCache(); if (session_id() !== '') { session_write_close(); session_id(''); } $wgRequest = new FauxRequest(); MediaWiki\Session\SessionManager::resetCache(); $phpErrorLevel = intval(ini_get('error_reporting')); if ($phpErrorLevel !== $this->phpErrorLevel) { ini_set('error_reporting', $this->phpErrorLevel); $oldHex = strtoupper(dechex($this->phpErrorLevel)); $newHex = strtoupper(dechex($phpErrorLevel)); $message = "PHP error_reporting setting was left dirty: " . "was 0x{$oldHex} before test, 0x{$newHex} after test!"; $this->fail($message); } parent::tearDown(); }
public function show() { // Send a cookie so anons get talk message notifications MediaWiki\Session\SessionManager::getGlobalSession()->persist(); parent::show(); }
/** * Executes the log-in attempt using the parameters passed. If * the log-in succeeds, it attaches a cookie to the session * and outputs the user id, username, and session token. If a * log-in fails, as the result of a bad password, a nonexistent * user, or any other reason, the host is cached with an expiry * and no log-in attempts will be accepted until that expiry * is reached. The expiry is $this->mLoginThrottle. */ public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied']); return; } $params = $this->extractRequestParams(); $result = []; // Make sure session is persisted $session = MediaWiki\Session\SessionManager::getGlobalSession(); $session->persist(); // Make sure it's possible to log in if (!$session->canSetUser()) { $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when using ' . $session->getProvider()->describe(Language::factory('en'))]); return; } $authRes = false; $context = new DerivativeContext($this->getContext()); $loginType = 'N/A'; // Check login token $token = $session->getToken('', 'login'); if ($token->wasNew() || !$params['token']) { $authRes = 'NeedToken'; } elseif (!$token->match($params['token'])) { $authRes = 'WrongToken'; } // Try bot passwords if ($authRes === false && $this->getConfig()->get('EnableBotPasswords') && strpos($params['name'], BotPassword::getSeparator()) !== false) { $status = BotPassword::login($params['name'], $params['password'], $this->getRequest()); if ($status->isOK()) { $session = $status->getValue(); $authRes = 'Success'; $loginType = 'BotPassword'; } else { $authRes = 'Failed'; $message = $status->getMessage(); LoggerFactory::getInstance('authmanager')->info('BotPassword login failed: ' . $status->getWikiText(false, false, 'en')); } } if ($authRes === false) { if ($this->getConfig()->get('DisableAuthManager')) { // Non-AuthManager login $context->setRequest(new DerivativeRequest($this->getContext()->getRequest(), ['wpName' => $params['name'], 'wpPassword' => $params['password'], 'wpDomain' => $params['domain'], 'wpLoginToken' => $params['token'], 'wpRemember' => ''])); $loginForm = new LoginForm(); $loginForm->setContext($context); $authRes = $loginForm->authenticateUserData(); $loginType = 'LoginForm'; switch ($authRes) { case LoginForm::SUCCESS: $authRes = 'Success'; break; case LoginForm::NEED_TOKEN: $authRes = 'NeedToken'; break; } } else { // Simplified AuthManager login, for backwards compatibility $manager = AuthManager::singleton(); $reqs = AuthenticationRequest::loadRequestsFromSubmission($manager->getAuthenticationRequests(AuthManager::ACTION_LOGIN, $this->getUser()), ['username' => $params['name'], 'password' => $params['password'], 'domain' => $params['domain'], 'rememberMe' => true]); $res = AuthManager::singleton()->beginAuthentication($reqs, 'null:'); switch ($res->status) { case AuthenticationResponse::PASS: if ($this->getConfig()->get('EnableBotPasswords')) { $warn = 'Main-account login via action=login is deprecated and may stop working ' . 'without warning.'; $warn .= ' To continue login with action=login, see [[Special:BotPasswords]].'; $warn .= ' To safely continue using main-account login, see action=clientlogin.'; } else { $warn = 'Login via action=login is deprecated and may stop working without warning.'; $warn .= ' To safely log in, see action=clientlogin.'; } $this->setWarning($warn); $authRes = 'Success'; $loginType = 'AuthManager'; break; case AuthenticationResponse::FAIL: // Hope it's not a PreAuthenticationProvider that failed... $authRes = 'Failed'; $message = $res->message; \MediaWiki\Logger\LoggerFactory::getInstance('authentication')->info(__METHOD__ . ': Authentication failed: ' . $message->plain()); break; default: $authRes = 'Aborted'; break; } } } $result['result'] = $authRes; switch ($authRes) { case 'Success': if ($this->getConfig()->get('DisableAuthManager')) { $user = $context->getUser(); $this->getContext()->setUser($user); $user->setCookies($this->getRequest(), null, true); } else { $user = $session->getUser(); } ApiQueryInfo::resetTokenCache(); // Deprecated hook $injected_html = ''; Hooks::run('UserLoginComplete', [&$user, &$injected_html]); $result['lguserid'] = intval($user->getId()); $result['lgusername'] = $user->getName(); // @todo: These are deprecated, and should be removed at some // point (1.28 at the earliest, and see T121527). They were ok // when the core cookie-based login was the only thing, but // CentralAuth broke that a while back and // SessionManager/AuthManager *really* break it. $result['lgtoken'] = $user->getToken(); $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case 'NeedToken': $result['token'] = $token->toString(); $this->setWarning('Fetching a token via action=login is deprecated. ' . 'Use action=query&meta=tokens&type=login instead.'); $this->logFeatureUsage('action=login&!lgtoken'); // @todo: See above about deprecation $result['cookieprefix'] = $this->getConfig()->get('CookiePrefix'); $result['sessionid'] = $session->getId(); break; case 'WrongToken': break; case 'Failed': $result['reason'] = $message->useDatabase('false')->inLanguage('en')->text(); break; case 'Aborted': $result['reason'] = 'Authentication requires user interaction, ' . 'which is not supported by action=login.'; if ($this->getConfig()->get('EnableBotPasswords')) { $result['reason'] .= ' To be able to login with action=login, see [[Special:BotPasswords]].'; $result['reason'] .= ' To continue using main-account login, see action=clientlogin.'; } else { $result['reason'] .= ' To log in, see action=clientlogin.'; } break; // Results from LoginForm for when $wgDisableAuthManager is true // Results from LoginForm for when $wgDisableAuthManager is true case LoginForm::WRONG_TOKEN: $result['result'] = 'WrongToken'; break; case LoginForm::NO_NAME: $result['result'] = 'NoName'; break; case LoginForm::ILLEGAL: $result['result'] = 'Illegal'; break; case LoginForm::WRONG_PLUGIN_PASS: $result['result'] = 'WrongPluginPass'; break; case LoginForm::NOT_EXISTS: $result['result'] = 'NotExists'; break; // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin: // The e-mailed temporary password should not be used for actual logins. case LoginForm::RESET_PASS: case LoginForm::WRONG_PASS: $result['result'] = 'WrongPass'; break; case LoginForm::EMPTY_PASS: $result['result'] = 'EmptyPass'; break; case LoginForm::CREATE_BLOCKED: $result['result'] = 'CreateBlocked'; $result['details'] = 'Your IP address is blocked from account creation'; $block = $context->getUser()->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::THROTTLED: $result['result'] = 'Throttled'; $result['wait'] = intval($loginForm->mThrottleWait); break; case LoginForm::USER_BLOCKED: $result['result'] = 'Blocked'; $block = User::newFromName($params['name'])->getBlock(); if ($block) { $result = array_merge($result, ApiQueryUserInfo::getBlockInfo($block)); } break; case LoginForm::ABORTED: $result['result'] = 'Aborted'; $result['reason'] = $loginForm->mAbortLoginErrorMsg; break; default: ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}"); } $this->getResult()->addValue(null, 'login', $result); if ($loginType === 'LoginForm' && isset(LoginForm::$statusCodes[$authRes])) { $authRes = LoginForm::$statusCodes[$authRes]; } LoggerFactory::getInstance('authmanager')->info('Login attempt', ['event' => 'login', 'successful' => $authRes === 'Success', 'loginType' => $loginType, 'status' => $authRes]); }
/** * Executes the log-in attempt using the parameters passed. If * the log-in succeeds, it attaches a cookie to the session * and outputs the user id, username, and session token. If a * log-in fails, as the result of a bad password, a nonexistent * user, or any other reason, the host is cached with an expiry * and no log-in attempts will be accepted until that expiry * is reached. The expiry is $this->mLoginThrottle. */ public function execute() { // If we're in a mode that breaks the same-origin policy, no tokens can // be obtained if ($this->lacksSameOriginSecurity()) { $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when the same-origin policy is not applied']); return; } try { $this->requirePostedParameters(['password', 'token']); } catch (UsageException $ex) { // Make this a warning for now, upgrade to an error in 1.29. $this->setWarning($ex->getMessage()); $this->logFeatureUsage('login-params-in-query-string'); } $params = $this->extractRequestParams(); $result = []; // Make sure session is persisted $session = MediaWiki\Session\SessionManager::getGlobalSession(); $session->persist(); // Make sure it's possible to log in if (!$session->canSetUser()) { $this->getResult()->addValue(null, 'login', ['result' => 'Aborted', 'reason' => 'Cannot log in when using ' . $session->getProvider()->describe(Language::factory('en'))]); return; } $authRes = false; $context = new DerivativeContext($this->getContext()); $loginType = 'N/A'; // Check login token $token = $session->getToken('', 'login'); if ($token->wasNew() || !$params['token']) { $authRes = 'NeedToken'; } elseif (!$token->match($params['token'])) { $authRes = 'WrongToken'; } // Try bot passwords if ($authRes === false && $this->getConfig()->get('EnableBotPasswords') && ($botLoginData = BotPassword::canonicalizeLoginData($params['name'], $params['password']))) { $status = BotPassword::login($botLoginData[0], $botLoginData[1], $this->getRequest()); if ($status->isOK()) { $session = $status->getValue(); $authRes = 'Success'; $loginType = 'BotPassword'; } elseif (!$botLoginData[2]) { $authRes = 'Failed'; $message = $status->getMessage(); LoggerFactory::getInstance('authentication')->info('BotPassword login failed: ' . $status->getWikiText(false, false, 'en')); } } if ($authRes === false) { // Simplified AuthManager login, for backwards compatibility $manager = AuthManager::singleton(); $reqs = AuthenticationRequest::loadRequestsFromSubmission($manager->getAuthenticationRequests(AuthManager::ACTION_LOGIN, $this->getUser()), ['username' => $params['name'], 'password' => $params['password'], 'domain' => $params['domain'], 'rememberMe' => true]); $res = AuthManager::singleton()->beginAuthentication($reqs, 'null:'); switch ($res->status) { case AuthenticationResponse::PASS: if ($this->getConfig()->get('EnableBotPasswords')) { $warn = 'Main-account login via action=login is deprecated and may stop working ' . 'without warning.'; $warn .= ' To continue login with action=login, see [[Special:BotPasswords]].'; $warn .= ' To safely continue using main-account login, see action=clientlogin.'; } else { $warn = 'Login via action=login is deprecated and may stop working without warning.'; $warn .= ' To safely log in, see action=clientlogin.'; } $this->setWarning($warn); $authRes = 'Success'; $loginType = 'AuthManager'; break; case AuthenticationResponse::FAIL: // Hope it's not a PreAuthenticationProvider that failed... $authRes = 'Failed'; $message = $res->message; \MediaWiki\Logger\LoggerFactory::getInstance('authentication')->info(__METHOD__ . ': Authentication failed: ' . $message->inLanguage('en')->plain()); break; default: \MediaWiki\Logger\LoggerFactory::getInstance('authentication')->info(__METHOD__ . ': Authentication failed due to unsupported response type: ' . $res->status, $this->getAuthenticationResponseLogData($res)); $authRes = 'Aborted'; break; } } $result['result'] = $authRes; switch ($authRes) { case 'Success': $user = $session->getUser(); ApiQueryInfo::resetTokenCache(); // Deprecated hook $injected_html = ''; Hooks::run('UserLoginComplete', [&$user, &$injected_html, true]); $result['lguserid'] = intval($user->getId()); $result['lgusername'] = $user->getName(); break; case 'NeedToken': $result['token'] = $token->toString(); $this->setWarning('Fetching a token via action=login is deprecated. ' . 'Use action=query&meta=tokens&type=login instead.'); $this->logFeatureUsage('action=login&!lgtoken'); break; case 'WrongToken': break; case 'Failed': $result['reason'] = $message->useDatabase('false')->inLanguage('en')->text(); break; case 'Aborted': $result['reason'] = 'Authentication requires user interaction, ' . 'which is not supported by action=login.'; if ($this->getConfig()->get('EnableBotPasswords')) { $result['reason'] .= ' To be able to login with action=login, see [[Special:BotPasswords]].'; $result['reason'] .= ' To continue using main-account login, see action=clientlogin.'; } else { $result['reason'] .= ' To log in, see action=clientlogin.'; } break; default: ApiBase::dieDebug(__METHOD__, "Unhandled case value: {$authRes}"); } $this->getResult()->addValue(null, 'login', $result); if ($loginType === 'LoginForm' && isset(LoginForm::$statusCodes[$authRes])) { $authRes = LoginForm::$statusCodes[$authRes]; } LoggerFactory::getInstance('authevents')->info('Login attempt', ['event' => 'login', 'successful' => $authRes === 'Success', 'loginType' => $loginType, 'status' => $authRes]); }