the browser-facing portion of osu!
at master 12 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 Tests\Controllers; 7 8use App\Models\Country; 9use App\Models\User; 10use Tests\TestCase; 11 12class UsersControllerTest extends TestCase 13{ 14 public function testIndexForApi() 15 { 16 $user = User::factory()->create(); 17 $userB = User::factory()->create(); 18 19 $this->actAsScopedUser($user, ['*']); 20 21 $this 22 ->get(route('api.users.index', ['ids' => [$user->getKey(), $userB->getKey()]])) 23 ->assertSuccessful() 24 ->assertJsonPath('users.0.id', $user->getKey()) 25 ->assertJsonPath('users.1.id', $userB->getKey()); 26 } 27 28 /** 29 * Checks whether an OK status is returned when the 30 * profile order update request is valid. 31 */ 32 public function testStore() 33 { 34 $previousCount = User::count(); 35 36 $locale = array_rand_val($GLOBALS['cfg']['app']['available_locales']); 37 38 $this->expectCountChange(fn () => User::count(), 1); 39 $this 40 ->json('POST', route('users.store'), [ 41 'user' => [ 42 'username' => 'user1', 43 'user_email' => 'user1@example.com', 44 'password' => 'hunter22', 45 ], 46 ], [ 47 'accept-language' => $locale, 48 'user-agent' => $GLOBALS['cfg']['osu']['client']['user_agent'], 49 ])->assertJsonFragment([ 50 'username' => 'user1', 51 'country_code' => Country::UNKNOWN, 52 ]); 53 54 $user = User::where('username', 'user1')->first(); 55 $this->assertSame($locale, $user->user_lang); 56 } 57 58 public function testStoreRegModeWebOnly() 59 { 60 config_set('osu.user.registration_mode.client', false); 61 config_set('osu.user.registration_mode.web', true); 62 $this->expectCountChange(fn () => User::count(), 0); 63 64 $this 65 ->json('POST', route('users.store'), [ 66 'user' => [ 67 'username' => 'user1', 68 'user_email' => 'user1@example.com', 69 'password' => 'hunter22', 70 ], 71 ], [ 72 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], 73 ])->assertStatus(403) 74 ->assertJsonFragment([ 75 'error' => osu_trans('users.store.from_web'), 76 ]); 77 } 78 79 /** 80 * Passing check=1 only validates user and not create. 81 */ 82 public function testStoreDryRunValid() 83 { 84 $previousCount = User::count(); 85 86 $this 87 ->json('POST', route('users.store'), [ 88 'check' => '1', 89 'user' => [ 90 'username' => 'user1', 91 'user_email' => 'user1@example.com', 92 'password' => 'hunter22', 93 ], 94 ], [ 95 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], 96 ])->assertSuccessful(); 97 98 $this->assertSame($previousCount, User::count()); 99 } 100 101 /** 102 * Invalid parameter returns 422. 103 */ 104 public function testStoreInvalid() 105 { 106 $previousCount = User::count(); 107 108 $this 109 ->json('POST', route('users.store'), [ 110 'check' => '1', 111 'user' => [ 112 'username' => '', 113 'user_email' => 'user1@example.com', 114 'password' => 'hunter22', 115 ], 116 ], [ 117 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], 118 ])->assertStatus(422) 119 ->assertJsonFragment([ 120 'form_error' => ['user' => ['username' => ['Username is required.']]], 121 ]); 122 123 $this 124 ->json('POST', route('users.store'), [ 125 'user' => [ 126 'username' => '', 127 'user_email' => 'user1@example.com', 128 'password' => 'hunter22', 129 ], 130 ], [ 131 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], 132 ])->assertStatus(422) 133 ->assertJsonFragment([ 134 'form_error' => ['user' => ['username' => ['Username is required.']]], 135 ]); 136 137 $this->assertSame($previousCount, User::count()); 138 } 139 140 public function testStoreWebRegModeClientOnly() 141 { 142 config_set('osu.user.registration_mode.client', true); 143 config_set('osu.user.registration_mode.web', false); 144 145 $this->expectCountChange(fn () => User::count(), 0); 146 147 $this->post(route('users.store'), [ 148 'user' => [ 149 'username' => 'user1', 150 'user_email' => 'user1@example.com', 151 'password' => 'hunter22', 152 ], 153 ])->assertStatus(403) 154 ->assertJsonFragment([ 155 'error' => osu_trans('users.store.from_client'), 156 ]); 157 } 158 159 public function testStoreWeb(): void 160 { 161 config_set('osu.user.registration_mode.web', true); 162 $this->expectCountChange(fn () => User::count(), 1); 163 164 $this->post(route('users.store-web'), [ 165 'user' => [ 166 'username' => 'user1', 167 'user_email' => 'user1@example.com', 168 'user_email_confirmation' => 'user1@example.com', 169 'password' => 'hunter22', 170 'password_confirmation' => 'hunter22', 171 ], 172 ])->assertRedirect(route('home')); 173 } 174 175 /** 176 * @dataProvider dataProviderForStoreWebInvalidParams 177 */ 178 public function testStoreWebInvalidParams($username, $email, $emailConfirmation, $password, $passwordConfirmation): void 179 { 180 config_set('osu.user.registration_mode.web', true); 181 $this->expectCountChange(fn () => User::count(), 0); 182 183 $this->post(route('users.store-web'), [ 184 'user' => [ 185 'username' => $username, 186 'user_email' => $email, 187 'user_email_confirmation' => $emailConfirmation, 188 'password' => $password, 189 'password_confirmation' => $passwordConfirmation, 190 ], 191 ])->assertStatus(422); 192 } 193 194 public function testStoreWebLoggedIn(): void 195 { 196 config_set('osu.user.registration_mode.web', true); 197 $user = User::factory()->create(); 198 199 $this->expectCountChange(fn () => User::count(), 0); 200 201 $this->actingAsVerified($user)->post(route('users.store-web'), [ 202 'user' => [ 203 'username' => 'user1', 204 'user_email' => 'user1@example.com', 205 'user_email_confirmation' => 'user1@example.com', 206 'password' => 'hunter22', 207 'password_confirmation' => 'hunter22', 208 ], 209 ])->assertRedirect('/'); 210 } 211 212 public function testStoreWithCountry() 213 { 214 $country = Country::inRandomOrder()->first() ?? Country::factory()->create(); 215 216 $previousCount = User::count(); 217 218 $this 219 ->json('POST', route('users.store'), [ 220 'user' => [ 221 'username' => 'user1', 222 'user_email' => 'user1@example.com', 223 'password' => 'hunter22', 224 ], 225 ], [ 226 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], 227 'HTTP_CF_IPCOUNTRY' => $country->getKey(), 228 ])->assertJsonFragment([ 229 'username' => 'user1', 230 'country' => [ 231 'code' => $country->getKey(), 232 'name' => $country->name, 233 ], 234 ]); 235 236 $this->assertSame($previousCount + 1, User::count()); 237 } 238 239 /** 240 * Disable registration for logged in user. 241 */ 242 public function testStoreLoggedIn() 243 { 244 $user = User::factory()->create(); 245 246 $previousCount = User::count(); 247 248 $this 249 ->actingAsVerified($user) 250 ->json('POST', route('users.store'), [ 251 'user' => [ 252 'username' => 'user1', 253 'user_email' => 'user1@example.com', 254 'password' => 'hunter22', 255 ], 256 ], [ 257 'HTTP_USER_AGENT' => $GLOBALS['cfg']['osu']['client']['user_agent'], 258 ])->assertStatus(302); 259 260 $this->assertSame($previousCount, User::count()); 261 } 262 263 public function testPreviousUsernameShouldRedirect() 264 { 265 $oldUsername = 'potato'; 266 $newUsername = 'carrot'; 267 268 /** @var User $user */ 269 $user = User::factory()->create([ 270 'osu_subscriptionexpiry' => now()->addDays(), 271 'username' => $oldUsername, 272 'username_clean' => $oldUsername, 273 ]); 274 $user->changeUsername($newUsername, 'paid'); 275 276 $this 277 ->get(route('users.show', ['user' => $oldUsername])) 278 ->assertRedirect(route('users.show', ['user' => $user->getKey(), 'mode' => null])); 279 } 280 281 public function testPreviousUsernameTakenShouldNotRedirect() 282 { 283 $oldUsername = 'potato'; 284 $newUsername = 'carrot'; 285 286 /** @var User $user1 */ 287 $user1 = User::factory()->create([ 288 'osu_subscriptionexpiry' => now()->addDays(), 289 'username' => $oldUsername, 290 'username_clean' => $oldUsername, 291 ]); 292 $user1->changeUsername($newUsername, 'paid'); 293 294 $user2 = User::factory()->create([ 295 'username' => $oldUsername, 296 'username_clean' => $oldUsername, 297 ]); 298 299 $this 300 ->get(route('users.show', ['user' => $oldUsername])) 301 ->assertRedirect(route('users.show', ['user' => $user2->getKey(), 'mode' => null])); 302 } 303 304 public function testUsernameRedirectToId() 305 { 306 $user = User::factory()->create(); 307 308 $this 309 ->get(route('users.show', ['user' => $user->username])) 310 ->assertRedirect(route('users.show', ['user' => $user->getKey()])); 311 } 312 313 public function testUsernameAtPrefixedRedirectToId() 314 { 315 $user = User::factory()->create(); 316 317 $this 318 ->get(route('users.show', ['user' => "@{$user->username}"])) 319 ->assertRedirect(route('users.show', ['user' => $user->getKey()])); 320 } 321 322 public function testUsernameRedirectToIdForApi() 323 { 324 $user = User::factory()->create(); 325 326 $this->actAsScopedUser($user, ['public']); 327 328 $this 329 ->get(route('api.users.show', ['user' => $user->username])) 330 ->assertSuccessful(); 331 } 332 333 public function testUsernameAtPrefixedRedirectToIdForApi() 334 { 335 $user = User::factory()->create(); 336 337 $this->actAsScopedUser($user, ['public']); 338 339 $this 340 ->get(route('api.users.show', ['user' => "@{$user->username}"])) 341 ->assertSuccessful(); 342 } 343 344 public static function dataProviderForStoreWebInvalidParams(): array 345 { 346 return [ 347 ['user1', 'user@email.com', 'user@email.com', 'short', 'short'], 348 ['user1', 'user@email.com', 'user@email.com', '', ''], 349 ['user1', 'user@email.com', 'user@email.com', 'userpassword', 'userpassword1'], 350 ['user1', 'user@email.com', 'user@email.com', 'userpassword', null], 351 ['user1', 'user@email.com', 'user@email.com', null, null], 352 353 ['user1', 'notemail@.com', 'notemail@.com', 'userpassword', 'userpassword'], 354 ['user1', '', '', 'userpassword', 'userpassword'], 355 ['user1', 'user@email.com', 'user1@email.com', 'userpassword', 'userpassword'], 356 ['user1', 'user@email.com', null, 'userpassword', 'userpassword'], 357 ['user1', null, null, 'userpassword', 'userpassword'], 358 359 [null, 'user@email.com', 'user@email.com', 'userpassword', 'userpassword'], 360 ['', 'user@email.com', 'user@email.com', 'userpassword', 'userpassword'], 361 [null, 'user@email.com', 'user@email.com', null, null], 362 [null, null, null, 'userpassword', 'userpassword'], 363 ]; 364 } 365 366 protected function setUp(): void 367 { 368 parent::setUp(); 369 370 Country::factory()->fallback()->create(); 371 } 372}