]> BookStack Code Mirror - bookstack/blob - tests/Api/UsersApiTest.php
Create additional test helper classes
[bookstack] / tests / Api / UsersApiTest.php
1 <?php
2
3 namespace Tests\Api;
4
5 use BookStack\Actions\ActivityType;
6 use BookStack\Auth\Role;
7 use BookStack\Auth\User;
8 use BookStack\Entities\Models\Entity;
9 use BookStack\Notifications\UserInvite;
10 use Illuminate\Support\Facades\Hash;
11 use Illuminate\Support\Facades\Notification;
12 use Tests\TestCase;
13
14 class UsersApiTest extends TestCase
15 {
16     use TestsApi;
17
18     protected $baseEndpoint = '/api/users';
19
20     protected $endpointMap = [
21         ['get', '/api/users'],
22         ['post', '/api/users'],
23         ['get', '/api/users/1'],
24         ['put', '/api/users/1'],
25         ['delete', '/api/users/1'],
26     ];
27
28     public function test_users_manage_permission_needed_for_all_endpoints()
29     {
30         $this->actingAsApiEditor();
31         foreach ($this->endpointMap as [$method, $uri]) {
32             $resp = $this->json($method, $uri);
33             $resp->assertStatus(403);
34             $resp->assertJson($this->permissionErrorResponse());
35         }
36     }
37
38     public function test_no_endpoints_accessible_in_demo_mode()
39     {
40         config()->set('app.env', 'demo');
41         $this->actingAsApiAdmin();
42
43         foreach ($this->endpointMap as [$method, $uri]) {
44             $resp = $this->json($method, $uri);
45             $resp->assertStatus(403);
46             $resp->assertJson($this->permissionErrorResponse());
47         }
48     }
49
50     public function test_index_endpoint_returns_expected_shelf()
51     {
52         $this->actingAsApiAdmin();
53         /** @var User $firstUser */
54         $firstUser = User::query()->orderBy('id', 'asc')->first();
55
56         $resp = $this->getJson($this->baseEndpoint . '?count=1&sort=+id');
57         $resp->assertJson(['data' => [
58             [
59                 'id'          => $firstUser->id,
60                 'name'        => $firstUser->name,
61                 'slug'        => $firstUser->slug,
62                 'email'       => $firstUser->email,
63                 'profile_url' => $firstUser->getProfileUrl(),
64                 'edit_url'    => $firstUser->getEditUrl(),
65                 'avatar_url'  => $firstUser->getAvatar(),
66             ],
67         ]]);
68     }
69
70     public function test_create_endpoint()
71     {
72         $this->actingAsApiAdmin();
73         /** @var Role $role */
74         $role = Role::query()->first();
75
76         $resp = $this->postJson($this->baseEndpoint, [
77             'name'        => 'Benny Boris',
78             'email'       => '[email protected]',
79             'password'    => 'mysuperpass',
80             'language'    => 'it',
81             'roles'       => [$role->id],
82             'send_invite' => false,
83         ]);
84
85         $resp->assertStatus(200);
86         $resp->assertJson([
87             'name'             => 'Benny Boris',
88             'email'            => '[email protected]',
89             'external_auth_id' => '',
90             'roles'            => [
91                 [
92                     'id'           => $role->id,
93                     'display_name' => $role->display_name,
94                 ],
95             ],
96         ]);
97         $this->assertDatabaseHas('users', ['email' => '[email protected]']);
98
99         /** @var User $user */
100         $user = User::query()->where('email', '=', '[email protected]')->first();
101         $this->assertActivityExists(ActivityType::USER_CREATE, null, $user->logDescriptor());
102         $this->assertEquals(1, $user->roles()->count());
103         $this->assertEquals('it', setting()->getUser($user, 'language'));
104     }
105
106     public function test_create_with_send_invite()
107     {
108         $this->actingAsApiAdmin();
109         Notification::fake();
110
111         $resp = $this->postJson($this->baseEndpoint, [
112             'name'        => 'Benny Boris',
113             'email'       => '[email protected]',
114             'send_invite' => true,
115         ]);
116
117         $resp->assertStatus(200);
118         /** @var User $user */
119         $user = User::query()->where('email', '=', '[email protected]')->first();
120         Notification::assertSentTo($user, UserInvite::class);
121     }
122
123     public function test_create_name_and_email_validation()
124     {
125         $this->actingAsApiAdmin();
126         /** @var User $existingUser */
127         $existingUser = User::query()->first();
128
129         $resp = $this->postJson($this->baseEndpoint, [
130             'email' => '[email protected]',
131         ]);
132         $resp->assertStatus(422);
133         $resp->assertJson($this->validationResponse(['name' => ['The name field is required.']]));
134
135         $resp = $this->postJson($this->baseEndpoint, [
136             'name' => 'Benny Boris',
137         ]);
138         $resp->assertStatus(422);
139         $resp->assertJson($this->validationResponse(['email' => ['The email field is required.']]));
140
141         $resp = $this->postJson($this->baseEndpoint, [
142             'email' => $existingUser->email,
143             'name'  => 'Benny Boris',
144         ]);
145         $resp->assertStatus(422);
146         $resp->assertJson($this->validationResponse(['email' => ['The email has already been taken.']]));
147     }
148
149     public function test_read_endpoint()
150     {
151         $this->actingAsApiAdmin();
152         /** @var User $user */
153         $user = User::query()->first();
154         /** @var Role $userRole */
155         $userRole = $user->roles()->first();
156
157         $resp = $this->getJson($this->baseEndpoint . "/{$user->id}");
158
159         $resp->assertStatus(200);
160         $resp->assertJson([
161             'id'               => $user->id,
162             'slug'             => $user->slug,
163             'email'            => $user->email,
164             'external_auth_id' => $user->external_auth_id,
165             'roles'            => [
166                 [
167                     'id'           => $userRole->id,
168                     'display_name' => $userRole->display_name,
169                 ],
170             ],
171         ]);
172     }
173
174     public function test_update_endpoint()
175     {
176         $this->actingAsApiAdmin();
177         /** @var User $user */
178         $user = $this->users->admin();
179         $roles = Role::query()->pluck('id');
180         $resp = $this->putJson($this->baseEndpoint . "/{$user->id}", [
181             'name'             => 'My updated user',
182             'email'            => '[email protected]',
183             'roles'            => $roles,
184             'external_auth_id' => 'btest',
185             'password'         => 'barrytester',
186             'language'         => 'fr',
187         ]);
188
189         $resp->assertStatus(200);
190         $resp->assertJson([
191             'id'               => $user->id,
192             'name'             => 'My updated user',
193             'email'            => '[email protected]',
194             'external_auth_id' => 'btest',
195         ]);
196         $user->refresh();
197         $this->assertEquals('fr', setting()->getUser($user, 'language'));
198         $this->assertEquals(count($roles), $user->roles()->count());
199         $this->assertNotEquals('barrytester', $user->password);
200         $this->assertTrue(Hash::check('barrytester', $user->password));
201     }
202
203     public function test_update_endpoint_does_not_remove_info_if_not_provided()
204     {
205         $this->actingAsApiAdmin();
206         /** @var User $user */
207         $user = $this->users->admin();
208         $roleCount = $user->roles()->count();
209         $resp = $this->putJson($this->baseEndpoint . "/{$user->id}", []);
210
211         $resp->assertStatus(200);
212         $this->assertDatabaseHas('users', [
213             'id'       => $user->id,
214             'name'     => $user->name,
215             'email'    => $user->email,
216             'password' => $user->password,
217         ]);
218         $this->assertEquals($roleCount, $user->roles()->count());
219     }
220
221     public function test_delete_endpoint()
222     {
223         $this->actingAsApiAdmin();
224         /** @var User $user */
225         $user = User::query()->where('id', '!=', $this->users->admin()->id)
226             ->whereNull('system_name')
227             ->first();
228
229         $resp = $this->deleteJson($this->baseEndpoint . "/{$user->id}");
230
231         $resp->assertStatus(204);
232         $this->assertActivityExists('user_delete', null, $user->logDescriptor());
233     }
234
235     public function test_delete_endpoint_with_ownership_migration_user()
236     {
237         $this->actingAsApiAdmin();
238         /** @var User $user */
239         $user = User::query()->where('id', '!=', $this->users->admin()->id)
240             ->whereNull('system_name')
241             ->first();
242         $entityChain = $this->entities->createChainBelongingToUser($user);
243         /** @var User $newOwner */
244         $newOwner = User::query()->where('id', '!=', $user->id)->first();
245
246         /** @var Entity $entity */
247         foreach ($entityChain as $entity) {
248             $this->assertEquals($user->id, $entity->owned_by);
249         }
250
251         $resp = $this->deleteJson($this->baseEndpoint . "/{$user->id}", [
252             'migrate_ownership_id' => $newOwner->id,
253         ]);
254
255         $resp->assertStatus(204);
256         /** @var Entity $entity */
257         foreach ($entityChain as $entity) {
258             $this->assertEquals($newOwner->id, $entity->refresh()->owned_by);
259         }
260     }
261
262     public function test_delete_endpoint_fails_deleting_only_admin()
263     {
264         $this->actingAsApiAdmin();
265         $adminRole = Role::getSystemRole('admin');
266         $adminToDelete = $adminRole->users()->first();
267         $adminRole->users()->where('id', '!=', $adminToDelete->id)->delete();
268
269         $resp = $this->deleteJson($this->baseEndpoint . "/{$adminToDelete->id}");
270
271         $resp->assertStatus(500);
272         $resp->assertJson($this->errorResponse('You cannot delete the only admin', 500));
273     }
274
275     public function test_delete_endpoint_fails_deleting_public_user()
276     {
277         $this->actingAsApiAdmin();
278         /** @var User $publicUser */
279         $publicUser = User::query()->where('system_name', '=', 'public')->first();
280
281         $resp = $this->deleteJson($this->baseEndpoint . "/{$publicUser->id}");
282
283         $resp->assertStatus(500);
284         $resp->assertJson($this->errorResponse('You cannot delete the guest user', 500));
285     }
286 }