the browser-facing portion of osu!
at master 4.2 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace App\Http\Controllers; 7 8use App\Libraries\User\CountryChange; 9use App\Libraries\User\DatadogLoginAttempt; 10use App\Libraries\User\ForceReactivation; 11use App\Models\Country; 12use App\Models\User; 13use App\Transformers\CurrentUserTransformer; 14use Auth; 15use romanzipp\Turnstile\Validator as TurnstileValidator; 16 17class SessionsController extends Controller 18{ 19 public function __construct() 20 { 21 $this->middleware('guest', ['only' => [ 22 'store', 23 ]]); 24 25 parent::__construct(); 26 } 27 28 public function store() 29 { 30 $request = request(); 31 32 $params = get_params($request->all(), null, ['username:string', 'password:string', 'remember:bool', 'cf-turnstile-response:string']); 33 $username = presence(trim($params['username'] ?? null)); 34 $password = presence($params['password'] ?? null); 35 $remember = $params['remember'] ?? false; 36 37 if ($username === null) { 38 DatadogLoginAttempt::log('missing_username'); 39 40 abort(422); 41 } 42 43 if ($password === null) { 44 DatadogLoginAttempt::log('missing_password'); 45 46 abort(422); 47 } 48 49 if (captcha_login_triggered()) { 50 $token = presence($params['cf-turnstile-response'] ?? null); 51 $validCaptcha = false; 52 53 if ($token !== null) { 54 $validCaptcha = (new TurnstileValidator())->validate($token)->isValid(); 55 } 56 57 if (!$validCaptcha) { 58 if ($token === null) { 59 DatadogLoginAttempt::log('missing_captcha'); 60 } else { 61 DatadogLoginAttempt::log('invalid_captcha'); 62 } 63 64 return $this->triggerCaptcha(osu_trans('users.login.invalid_captcha'), 422); 65 } 66 } 67 68 $ip = $request->getClientIp(); 69 70 $user = User::findForLogin($username); 71 72 if ($user === null && strpos($username, '@') !== false && !$GLOBALS['cfg']['osu']['user']['allow_email_login']) { 73 $authError = osu_trans('users.login.email_login_disabled'); 74 } else { 75 $authError = User::attemptLogin($user, $password, $ip); 76 } 77 78 if ($authError === null) { 79 $forceReactivation = new ForceReactivation($user, $request); 80 81 if ($forceReactivation->isRequired()) { 82 DatadogLoginAttempt::log('password_reset'); 83 $forceReactivation->run(); 84 85 \Session::flash('password_reset_start', [ 86 'reason' => $forceReactivation->getReason(), 87 'username' => $username, 88 ]); 89 90 return ujs_redirect(route('password-reset')); 91 } 92 93 // try fixing user country if it's currently set to unknown 94 if ($user->country_acronym === Country::UNKNOWN) { 95 try { 96 CountryChange::handle($user, request_country(), 'automated unknown country fixup on login'); 97 } catch (\Throwable $e) { 98 // report failures but continue anyway 99 log_error($e); 100 } 101 } 102 103 DatadogLoginAttempt::log(null); 104 $this->login($user, $remember); 105 106 return [ 107 'csrf_token' => csrf_token(), 108 'header' => view('layout._header_user')->render(), 109 'header_popup' => view('layout._popup_user')->render(), 110 'user' => json_item($user, new CurrentUserTransformer()), 111 ]; 112 } 113 114 if (captcha_login_triggered()) { 115 return $this->triggerCaptcha($authError); 116 } 117 118 return error_popup($authError, 403); 119 } 120 121 public function destroy() 122 { 123 if (Auth::check()) { 124 logout(); 125 } 126 127 return []; 128 } 129 130 private function triggerCaptcha($message, $returnCode = 403) 131 { 132 return response([ 133 'error' => $message, 134 'captcha_triggered' => true, 135 ], $returnCode); 136 } 137}