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\OAuth;
7
8use App\Models\OAuth\Client;
9use App\Models\User;
10use Tests\TestCase;
11
12class ClientsControllerTest extends TestCase
13{
14 protected $repository;
15
16 private $client;
17 private $owner;
18
19 public function testGuestCannotDeleteClient()
20 {
21 $this
22 ->json('DELETE', route('oauth.clients.destroy', ['client' => $this->client->getKey()]))
23 ->assertStatus(401);
24
25 $this->assertFalse(Client::find($this->client->getKey())->revoked);
26 }
27
28 public function testCanDeleteOwnClient()
29 {
30 $this
31 ->actingAsVerified($this->owner)
32 ->json('DELETE', route('oauth.clients.destroy', ['client' => $this->client->getKey()]))
33 ->assertSuccessful();
34
35 $this->assertTrue(Client::find($this->client->getKey())->revoked);
36 }
37
38 public function testCannotDeleteOtherUserClient()
39 {
40 $user = User::factory()->create();
41
42 $this
43 ->actingAsVerified($user)
44 ->json('DELETE', route('oauth.clients.destroy', ['client' => $this->client->getKey()]))
45 ->assertStatus(404);
46
47 $this->assertFalse(Client::find($this->client->getKey())->revoked);
48 }
49
50 public function testCreateNewClient()
51 {
52 $data = [
53 'name' => 'best client',
54 'redirect' => 'https://nowhere.local',
55 ];
56
57 $count = Client::count();
58
59 $response = $this
60 ->actingAsVerified($this->owner)
61 ->json('POST', route('oauth.clients.store'), $data)
62 ->assertSuccessful()
63 ->getOriginalContent();
64
65 // because user needs to see this after it's generated.
66 $this->assertArrayHasKey('secret', $response);
67
68 $client = Client::find($response['id']);
69 $this->assertNotNull($client);
70 $this->assertNotEmpty($client->secret);
71 $this->assertSame($this->owner->getKey(), $client->user_id);
72 $this->assertSame('best client', $client->name);
73 $this->assertSame('https://nowhere.local', $client->redirect);
74 $this->assertFalse($client->personal_access_client);
75 $this->assertFalse($client->password_client);
76 $this->assertFalse($client->revoked);
77 $this->assertSame($count + 1, Client::count());
78 }
79
80 /**
81 * @dataProvider emptyStringsTestDataProvider
82 *
83 * @return void
84 */
85 public function testCannotCreateClientWithEmptyStrings($name, $redirect)
86 {
87 $data = [
88 'name' => $name,
89 'redirect' => $redirect,
90 ];
91
92 $count = Client::count();
93
94 $this
95 ->actingAsVerified($this->owner)
96 ->json('POST', route('oauth.clients.store'), $data)
97 ->assertStatus(422);
98
99 $this->assertSame($count, Client::count());
100 }
101
102 public function testOnlyRedirectIsUpdated()
103 {
104 $id = $this->client->getKey();
105 $name = $this->client->name;
106
107 $data = [
108 'id' => $id + 1,
109 'name' => 'new name',
110 'redirect' => 'https://nowhere.local',
111 ];
112
113 $this
114 ->actingAsVerified($this->owner)
115 ->json('PUT', route('oauth.clients.update', ['client' => $id]), $data)
116 ->assertSuccessful();
117
118 $this->client->refresh();
119 // FIXME: assert other values didn't change
120 $this->assertSame($id, $this->client->id);
121 $this->assertSame($name, $this->client->name);
122 $this->assertSame('https://nowhere.local', $this->client->redirect);
123 }
124
125 public static function emptyStringsTestDataProvider()
126 {
127 return [
128 [null, 'https://nowhere.local'],
129 ['', 'https://nowhere.local'],
130 [' ', 'https://nowhere.local'],
131 ];
132 }
133
134 protected function setUp(): void
135 {
136 parent::setUp();
137
138 $this->owner = User::factory()->create();
139 $this->client = Client::factory()->create(['user_id' => $this->owner]);
140 }
141}