X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/90b4257889a5f9a63ee5d9934e90557e67ebca56..refs/pull/5676/head:/tests/Auth/RegistrationTest.php diff --git a/tests/Auth/RegistrationTest.php b/tests/Auth/RegistrationTest.php index 45d265b72..2666fa3b4 100644 --- a/tests/Auth/RegistrationTest.php +++ b/tests/Auth/RegistrationTest.php @@ -2,9 +2,9 @@ namespace Tests\Auth; -use BookStack\Auth\Role; -use BookStack\Auth\User; -use BookStack\Notifications\ConfirmEmail; +use BookStack\Access\Notifications\ConfirmEmailNotification; +use BookStack\Users\Models\Role; +use BookStack\Users\Models\User; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Notification; use Tests\TestCase; @@ -25,10 +25,13 @@ class RegistrationTest extends TestCase $resp->assertRedirect('/register/confirm'); $this->assertDatabaseHas('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); + $resp = $this->get('/register/confirm'); + $resp->assertSee('Thanks for registering!'); + // Ensure notification sent /** @var User $dbUser */ $dbUser = User::query()->where('email', '=', $user->email)->first(); - Notification::assertSentTo($dbUser, ConfirmEmail::class); + Notification::assertSentTo($dbUser, ConfirmEmailNotification::class); // Test access and resend confirmation email $resp = $this->post('/login', ['email' => $user->email, 'password' => $user->password]); @@ -42,12 +45,22 @@ class RegistrationTest extends TestCase // Get confirmation and confirm notification matches $emailConfirmation = DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first(); - Notification::assertSentTo($dbUser, ConfirmEmail::class, function ($notification, $channels) use ($emailConfirmation) { + Notification::assertSentTo($dbUser, ConfirmEmailNotification::class, function ($notification, $channels) use ($emailConfirmation) { return $notification->token === $emailConfirmation->token; }); - // Check confirmation email confirmation activation. - $this->get('/register/confirm/' . $emailConfirmation->token)->assertRedirect('/login'); + // Check confirmation email confirmation accept page. + $resp = $this->get('/register/confirm/' . $emailConfirmation->token); + $acceptPage = $this->withHtml($resp); + $resp->assertOk(); + $resp->assertSee('Thanks for confirming!'); + $acceptPage->assertElementExists('form[method="post"][action$="/register/confirm/accept"][component="auto-submit"] button'); + $acceptPage->assertFieldHasValue('token', $emailConfirmation->token); + + // Check acceptance confirm + $this->post('/register/confirm/accept', ['token' => $emailConfirmation->token])->assertRedirect('/login'); + + // Check state on login redirect $this->get('/login')->assertSee('Your email has been confirmed! You should now be able to login using this email address.'); $this->assertDatabaseMissing('email_confirmations', ['token' => $emailConfirmation->token]); $this->assertDatabaseHas('users', ['name' => $dbUser->name, 'email' => $dbUser->email, 'email_confirmed' => true]); @@ -174,4 +187,107 @@ class RegistrationTest extends TestCase $resp->assertSee('The email must be a valid email address.'); $resp->assertSee('The password must be at least 8 characters.'); } + + public function test_registration_simple_honeypot_active() + { + $this->setSettings(['registration-enabled' => 'true']); + + $resp = $this->get('/register'); + $this->withHtml($resp)->assertElementExists('form input[name="username"]'); + + $resp = $this->post('/register', [ + 'name' => 'Barry', + 'email' => 'barrybot@example.com', + 'password' => 'barryIsTheBestBot', + 'username' => 'MyUsername' + ]); + $resp->assertRedirect('/register'); + + $resp = $this->followRedirects($resp); + $this->withHtml($resp)->assertElementExists('form input[name="username"].text-neg'); + } + + public function test_registration_endpoint_throttled() + { + $this->setSettings(['registration-enabled' => 'true']); + + for ($i = 0; $i < 11; $i++) { + $response = $this->post('/register/', [ + 'name' => "Barry{$i}", + 'email' => "barry{$i}@example.com", + 'password' => "barryIsTheBest{$i}", + ]); + auth()->logout(); + } + + $response->assertStatus(429); + } + + public function test_registration_confirmation_throttled() + { + $this->setSettings(['registration-enabled' => 'true']); + + for ($i = 0; $i < 11; $i++) { + $response = $this->post('/register/confirm/accept', [ + 'token' => "token{$i}", + ]); + } + + $response->assertStatus(429); + } + + public function test_registration_confirmation_resend() + { + Notification::fake(); + $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); + $user = User::factory()->make(); + + $resp = $this->post('/register', $user->only('name', 'email', 'password')); + $resp->assertRedirect('/register/confirm'); + $dbUser = User::query()->where('email', '=', $user->email)->first(); + + $resp = $this->post('/login', ['email' => $user->email, 'password' => $user->password]); + $resp->assertRedirect('/register/confirm/awaiting'); + + $resp = $this->post('/register/confirm/resend'); + $resp->assertRedirect('/register/confirm'); + Notification::assertSentToTimes($dbUser, ConfirmEmailNotification::class, 2); + } + + public function test_registration_confirmation_expired_resend() + { + Notification::fake(); + $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); + $user = User::factory()->make(); + + $resp = $this->post('/register', $user->only('name', 'email', 'password')); + $resp->assertRedirect('/register/confirm'); + $dbUser = User::query()->where('email', '=', $user->email)->first(); + + $resp = $this->post('/login', ['email' => $user->email, 'password' => $user->password]); + $resp->assertRedirect('/register/confirm/awaiting'); + + $emailConfirmation = DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first(); + $this->travel(2)->days(); + + $resp = $this->post("/register/confirm/accept", [ + 'token' => $emailConfirmation->token, + ]); + $resp->assertRedirect('/register/confirm'); + $this->assertSessionError('The confirmation token has expired, A new confirmation email has been sent.'); + + Notification::assertSentToTimes($dbUser, ConfirmEmailNotification::class, 2); + } + + public function test_registration_confirmation_awaiting_and_resend_returns_to_log_if_no_login_attempt_user_found() + { + $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); + + $this->get('/register/confirm/awaiting')->assertRedirect('/login'); + $this->assertSessionError('A user for this action could not be found.'); + $this->flushSession(); + + $this->post('/register/confirm/resend')->assertRedirect('/login'); + $this->assertSessionError('A user for this action could not be found.'); + } }