3 use BookStack\Entities\Page;
4 use BookStack\Notifications\ConfirmEmail;
5 use BookStack\Auth\User;
6 use BookStack\Settings\SettingService;
7 use Illuminate\Support\Facades\Notification;
9 class AuthTest extends BrowserKitTest
12 public function test_auth_working()
15 ->seePageIs('/login');
18 public function test_login()
20 $this->login('admin@admin.com', 'password')
24 public function test_public_viewing()
26 $settings = app(SettingService::class);
27 $settings->put('app-public', 'true');
33 public function test_registration_showing()
35 // Ensure registration form is showing
36 $this->setSettings(['registration-enabled' => 'true']);
37 $this->visit('/login')
40 ->seePageIs('/register');
43 public function test_normal_registration()
45 // Set settings and get user instance
46 $this->setSettings(['registration-enabled' => 'true']);
47 $user = factory(User::class)->make();
49 // Test form and ensure user is created
50 $this->visit('/register')
52 ->type($user->name, '#name')
53 ->type($user->email, '#email')
54 ->type($user->password, '#password')
55 ->press('Create Account')
58 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email]);
61 public function test_empty_registration_redirects_back_with_errors()
63 // Set settings and get user instance
64 $this->setSettings(['registration-enabled' => 'true']);
66 // Test form and ensure user is created
67 $this->visit('/register')
68 ->press('Create Account')
69 ->see('The name field is required')
70 ->seePageIs('/register');
73 public function test_registration_validation()
75 $this->setSettings(['registration-enabled' => 'true']);
77 $this->visit('/register')
80 ->type('1', '#password')
81 ->press('Create Account')
82 ->see('The name must be at least 2 characters.')
83 ->see('The email must be a valid email address.')
84 ->see('The password must be at least 6 characters.')
85 ->seePageIs('/register');
88 public function test_sign_up_link_on_login()
90 $this->visit('/login')
93 $this->setSettings(['registration-enabled' => 'true']);
95 $this->visit('/login')
99 public function test_confirmed_registration()
101 // Fake notifications
102 Notification::fake();
104 // Set settings and get user instance
105 $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']);
106 $user = factory(User::class)->make();
108 // Go through registration process
109 $this->visit('/register')
111 ->type($user->name, '#name')
112 ->type($user->email, '#email')
113 ->type($user->password, '#password')
114 ->press('Create Account')
115 ->seePageIs('/register/confirm')
116 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]);
118 // Ensure notification sent
119 $dbUser = User::where('email', '=', $user->email)->first();
120 Notification::assertSentTo($dbUser, ConfirmEmail::class);
122 // Test access and resend confirmation email
123 $this->login($user->email, $user->password)
124 ->seePageIs('/register/confirm/awaiting')
127 ->seePageIs('/register/confirm/awaiting')
128 ->press('Resend Confirmation Email');
130 // Get confirmation and confirm notification matches
131 $emailConfirmation = \DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first();
132 Notification::assertSentTo($dbUser, ConfirmEmail::class, function($notification, $channels) use ($emailConfirmation) {
133 return $notification->token === $emailConfirmation->token;
136 // Check confirmation email confirmation activation.
137 $this->visit('/register/confirm/' . $emailConfirmation->token)
140 ->notSeeInDatabase('email_confirmations', ['token' => $emailConfirmation->token])
141 ->seeInDatabase('users', ['name' => $dbUser->name, 'email' => $dbUser->email, 'email_confirmed' => true]);
144 public function test_restricted_registration()
146 $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true', 'registration-restrict' => 'example.com']);
147 $user = factory(User::class)->make();
148 // Go through registration process
149 $this->visit('/register')
150 ->type($user->name, '#name')
151 ->type($user->email, '#email')
152 ->type($user->password, '#password')
153 ->press('Create Account')
154 ->seePageIs('/register')
155 ->dontSeeInDatabase('users', ['email' => $user->email])
156 ->see('That email domain does not have access to this application');
158 $user->email = 'barry@example.com';
160 $this->visit('/register')
161 ->type($user->name, '#name')
162 ->type($user->email, '#email')
163 ->type($user->password, '#password')
164 ->press('Create Account')
165 ->seePageIs('/register/confirm')
166 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]);
168 $this->visit('/')->seePageIs('/login')
169 ->type($user->email, '#email')
170 ->type($user->password, '#password')
172 ->seePageIs('/register/confirm/awaiting')
173 ->seeText('Email Address Not Confirmed');
176 public function test_restricted_registration_with_confirmation_disabled()
178 $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'false', 'registration-restrict' => 'example.com']);
179 $user = factory(User::class)->make();
180 // Go through registration process
181 $this->visit('/register')
182 ->type($user->name, '#name')
183 ->type($user->email, '#email')
184 ->type($user->password, '#password')
185 ->press('Create Account')
186 ->seePageIs('/register')
187 ->dontSeeInDatabase('users', ['email' => $user->email])
188 ->see('That email domain does not have access to this application');
190 $user->email = 'barry@example.com';
192 $this->visit('/register')
193 ->type($user->name, '#name')
194 ->type($user->email, '#email')
195 ->type($user->password, '#password')
196 ->press('Create Account')
197 ->seePageIs('/register/confirm')
198 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]);
200 $this->visit('/')->seePageIs('/login')
201 ->type($user->email, '#email')
202 ->type($user->password, '#password')
204 ->seePageIs('/register/confirm/awaiting')
205 ->seeText('Email Address Not Confirmed');
208 public function test_user_creation()
210 $user = factory(User::class)->make();
213 ->visit('/settings/users')
214 ->click('Add New User')
215 ->type($user->name, '#name')
216 ->type($user->email, '#email')
217 ->check('roles[admin]')
218 ->type($user->password, '#password')
219 ->type($user->password, '#password-confirm')
221 ->seePageIs('/settings/users')
222 ->seeInDatabase('users', $user->toArray())
226 public function test_user_updating()
228 $user = $this->getNormalUser();
229 $password = $user->password;
231 ->visit('/settings/users')
233 ->seePageIs('/settings/users/' . $user->id)
235 ->type('Barry Scott', '#name')
237 ->seePageIs('/settings/users')
238 ->seeInDatabase('users', ['id' => $user->id, 'name' => 'Barry Scott', 'password' => $password])
239 ->notSeeInDatabase('users', ['name' => $user->name]);
242 public function test_user_password_update()
244 $user = $this->getNormalUser();
245 $userProfilePage = '/settings/users/' . $user->id;
247 ->visit($userProfilePage)
248 ->type('newpassword', '#password')
250 ->seePageIs($userProfilePage)
251 ->see('Password confirmation required')
253 ->type('newpassword', '#password')
254 ->type('newpassword', '#password-confirm')
256 ->seePageIs('/settings/users');
258 $userPassword = User::find($user->id)->password;
259 $this->assertTrue(\Hash::check('newpassword', $userPassword));
262 public function test_user_deletion()
264 $userDetails = factory(User::class)->make();
265 $user = $this->getEditor($userDetails->toArray());
268 ->visit('/settings/users/' . $user->id)
269 ->click('Delete User')
272 ->seePageIs('/settings/users')
273 ->notSeeInDatabase('users', ['name' => $user->name]);
276 public function test_user_cannot_be_deleted_if_last_admin()
278 $adminRole = \BookStack\Auth\Role::getRole('admin');
279 // Ensure we currently only have 1 admin user
280 $this->assertEquals(1, $adminRole->users()->count());
281 $user = $adminRole->users->first();
283 $this->asAdmin()->visit('/settings/users/' . $user->id)
284 ->click('Delete User')
286 ->seePageIs('/settings/users/' . $user->id)
287 ->see('You cannot delete the only admin');
290 public function test_logout()
297 ->seePageIs('/login');
300 public function test_reset_password_flow()
303 Notification::fake();
305 $this->visit('/login')->click('Forgot Password?')
306 ->seePageIs('/password/email')
307 ->type('admin@admin.com', 'email')
308 ->press('Send Reset Link')
309 ->see('A password reset link has been sent to admin@admin.com');
311 $this->seeInDatabase('password_resets', [
312 'email' => 'admin@admin.com'
315 $user = User::where('email', '=', 'admin@admin.com')->first();
317 Notification::assertSentTo($user, \BookStack\Notifications\ResetPassword::class);
318 $n = Notification::sent($user, \BookStack\Notifications\ResetPassword::class);
320 $this->visit('/password/reset/' . $n->first()->token)
321 ->see('Reset Password')
322 ->submitForm('Reset Password', [
323 'email' => 'admin@admin.com',
324 'password' => 'randompass',
325 'password_confirmation' => 'randompass'
327 ->see('Your password has been successfully reset');
330 public function test_reset_password_page_shows_sign_links()
332 $this->setSettings(['registration-enabled' => 'true']);
333 $this->visit('/password/email')
335 ->seeLink('Sign up');
338 public function test_login_redirects_to_initially_requested_url_correctly()
340 config()->set('app.url', 'http://localhost');
341 $page = Page::query()->first();
343 $this->visit($page->getUrl())
344 ->seePageUrlIs(baseUrl('/login'));
345 $this->login('admin@admin.com', 'password')
346 ->seePageUrlIs($page->getUrl());
351 * @param string $email
352 * @param string $password
355 protected function login($email, $password)
357 return $this->visit('/login')
358 ->type($email, '#email')
359 ->type($password, '#password')