the browser-facing portion of osu!
at master 8.5 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 6declare(strict_types=1); 7 8namespace Tests\Libraries\SessionVerification; 9 10use App\Libraries\Session\Store as SessionStore; 11use App\Libraries\SessionVerification; 12use App\Mail\UserVerification as UserVerificationMail; 13use App\Models\LoginAttempt; 14use App\Models\OAuth\Client; 15use App\Models\OAuth\Token; 16use App\Models\User; 17use Tests\TestCase; 18 19class ControllerTest extends TestCase 20{ 21 public function testIssue(): void 22 { 23 \Mail::fake(); 24 $user = User::factory()->create(); 25 26 $this 27 ->be($user) 28 ->get(route('account.edit')) 29 ->assertStatus(401) 30 ->assertViewIs('users.verify'); 31 32 $record = LoginAttempt::find('127.0.0.1'); 33 34 \Mail::assertQueued(UserVerificationMail::class, 1); 35 $this->assertTrue($record->containsUser($user, 'verify')); 36 $this->assertFalse(\Session::isVerified()); 37 } 38 39 public function testReissue(): void 40 { 41 \Mail::fake(); 42 $user = User::factory()->create(); 43 $session = \Session::instance(); 44 45 $this 46 ->be($user) 47 ->withPersistentSession($session) 48 ->get(route('account.edit')); 49 50 $state = SessionVerification\State::fromSession($session); 51 52 $this 53 ->withPersistentSession($session) 54 ->post(route('account.reissue-code')) 55 ->assertSuccessful(); 56 57 \Mail::assertQueued(UserVerificationMail::class, 2); 58 $this->assertNotSame($state->key, SessionVerification\State::fromSession($session)->key); 59 } 60 61 public function testReissueOAuthVerified(): void 62 { 63 \Mail::fake(); 64 $token = Token::factory()->create(['verified' => true]); 65 66 $this 67 ->actingWithToken($token) 68 ->post(route('api.verify.reissue')) 69 ->assertStatus(422); 70 71 \Mail::assertNotQueued(UserVerificationMail::class); 72 $this->assertNull(SessionVerification\State::fromSession($token)); 73 } 74 75 public function testReissueVerified(): void 76 { 77 \Mail::fake(); 78 $user = User::factory()->create(); 79 $session = \Session::instance(); 80 $session->markVerified(); 81 82 $this 83 ->be($user) 84 ->withPersistentSession($session) 85 ->post(route('account.reissue-code')) 86 ->assertStatus(422); 87 88 \Mail::assertNotQueued(UserVerificationMail::class); 89 $this->assertNull(SessionVerification\State::fromSession($session)); 90 } 91 92 public function testVerify(): void 93 { 94 $user = User::factory()->create(); 95 $session = \Session::instance(); 96 97 $this 98 ->be($user) 99 ->withPersistentSession($session) 100 ->get(route('account.edit')) 101 ->assertStatus(401) 102 ->assertViewIs('users.verify'); 103 104 $key = SessionVerification\State::fromSession($session)->key; 105 106 $this 107 ->withPersistentSession($session) 108 ->post(route('account.verify'), ['verification_key' => $key]) 109 ->assertSuccessful(); 110 111 $record = LoginAttempt::find('127.0.0.1'); 112 113 $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); 114 $this->assertTrue($session->isVerified()); 115 $this->assertNull(SessionVerification\State::fromSession($session)); 116 } 117 118 public function testVerifyLink(): void 119 { 120 $user = User::factory()->create(); 121 $session = \Session::instance(); 122 $sessionId = $session->getId(); 123 124 $this 125 ->be($user) 126 ->withPersistentSession($session) 127 ->get(route('account.edit')) 128 ->assertStatus(401) 129 ->assertViewIs('users.verify'); 130 131 $linkKey = SessionVerification\State::fromSession($session)->linkKey; 132 133 $guestSession = SessionStore::findOrNew(); 134 $this 135 ->withPersistentSession($guestSession) 136 ->get(route('account.verify', ['key' => $linkKey])) 137 ->assertSuccessful(); 138 139 $record = LoginAttempt::find('127.0.0.1'); 140 141 $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); 142 $this->assertTrue(SessionStore::findOrNew($sessionId)->isVerified()); 143 } 144 145 public function testVerifyLinkMismatch(): void 146 { 147 $user = User::factory()->create(); 148 $session = \Session::instance(); 149 $sessionId = $session->getId(); 150 151 $this 152 ->be($user) 153 ->withPersistentSession($session) 154 ->get(route('account.edit')) 155 ->assertStatus(401) 156 ->assertViewIs('users.verify'); 157 158 $guestSession = SessionStore::findOrNew(); 159 $this 160 ->withPersistentSession($guestSession) 161 ->get(route('account.verify', ['key' => 'invalid'])) 162 ->assertStatus(404); 163 164 $this->assertFalse(SessionStore::findOrNew($sessionId)->isVerified()); 165 } 166 167 public function testVerifyLinkOAuth(): void 168 { 169 $token = Token::factory()->create([ 170 'client_id' => Client::factory()->create(['password_client' => true]), 171 'verified' => false, 172 ]); 173 174 $this 175 ->actingWithToken($token) 176 ->get(route('api.me')) 177 ->assertSuccessful(); 178 179 $linkKey = SessionVerification\State::fromSession($token)->linkKey; 180 181 \Auth::logout(); 182 $this 183 ->withPersistentSession(SessionStore::findOrNew()) 184 ->get(route('account.verify', ['key' => $linkKey])) 185 ->assertSuccessful(); 186 187 $record = LoginAttempt::find('127.0.0.1'); 188 189 $this->assertFalse($record->containsUser($token->user, 'verify-mismatch:')); 190 $this->assertTrue($token->fresh()->isVerified()); 191 } 192 193 public function testVerifyMismatch(): void 194 { 195 $user = User::factory()->create(); 196 $session = \Session::instance(); 197 198 $this 199 ->be($user) 200 ->withPersistentSession($session) 201 ->get(route('account.edit')) 202 ->assertStatus(401) 203 ->assertViewIs('users.verify'); 204 205 $record = LoginAttempt::find('127.0.0.1'); 206 $this->assertFalse($record->containsUser($user, 'verify-mismatch:')); 207 208 $this 209 ->withPersistentSession($session) 210 ->post(route('account.verify'), ['verification_key' => 'invalid']) 211 ->assertStatus(422); 212 213 $record = LoginAttempt::find('127.0.0.1'); 214 215 $this->assertTrue($record->containsUser($user, 'verify-mismatch:')); 216 $this->assertFalse($session->isVerified()); 217 } 218 219 public function testVerifyOAuth(): void 220 { 221 $token = Token::factory()->create([ 222 'client_id' => Client::factory()->create(['password_client' => true]), 223 'verified' => false, 224 ]); 225 226 $this 227 ->actingWithToken($token) 228 ->get(route('api.me')) 229 ->assertSuccessful(); 230 231 $key = SessionVerification\State::fromSession($token)->key; 232 233 $this 234 ->actingWithToken($token) 235 ->post(route('api.verify', ['verification_key' => $key])) 236 ->assertSuccessful(); 237 238 $record = LoginAttempt::find('127.0.0.1'); 239 240 $this->assertFalse($record->containsUser($token->user, 'verify-mismatch:')); 241 $this->assertTrue($token->fresh()->isVerified()); 242 } 243 244 public function testVerifyOAuthVerified(): void 245 { 246 \Mail::fake(); 247 $token = Token::factory()->create(['verified' => true]); 248 249 $this 250 ->actingWithToken($token) 251 ->post(route('api.verify', ['verification_key' => 'invalid'])) 252 ->assertSuccessful(); 253 254 $this->assertNull(SessionVerification\State::fromSession($token)); 255 \Mail::assertNotQueued(UserVerificationMail::class); 256 } 257 258 public function testVerifyVerified(): void 259 { 260 \Mail::fake(); 261 $user = User::factory()->create(); 262 $session = \Session::instance(); 263 $session->markVerified(); 264 265 $this 266 ->be($user) 267 ->withPersistentSession($session) 268 ->post(route('account.verify'), ['verification_key' => 'invalid']) 269 ->assertSuccessful(); 270 271 $this->assertNull(SessionVerification\State::fromSession($session)); 272 \Mail::assertNotQueued(UserVerificationMail::class); 273 } 274}