1
0
mirror of https://github.com/flarum/core.git synced 2025-08-07 00:47:00 +02:00

feat: clear password & email tokens when appropriate (#3567)

* test: password tokens are generated and deleted on password change
* chore: delete all password tokens when the password is changed
* test: email tokens are generated and deleted on email change
* test: email tokens are deleted after password reset
* chore: delete email tokens after password change
* test: password tokens are deleted after email change
* chore: delete password tokens after email change
* chore: syntactic sugar
* chore: unify event listening
This commit is contained in:
Sami Mazouz
2022-07-30 13:02:06 +01:00
committed by GitHub
parent f96f914576
commit 2b31b185e4
6 changed files with 265 additions and 2 deletions

View File

@@ -0,0 +1,202 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Tests\integration\api\users;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Flarum\User\EmailToken;
use Flarum\User\PasswordToken;
class PasswordEmailTokensTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function setUp(): void
{
parent::setUp();
$this->prepareDatabase([
'users' => [
$this->normalUser(),
],
]);
}
/** @test */
public function actor_has_no_tokens_by_default()
{
$this->app();
$this->assertEquals(0, PasswordToken::query()->where('user_id', 2)->count());
$this->assertEquals(0, EmailToken::query()->where('user_id', 2)->count());
}
/** @test */
public function password_tokens_are_generated_when_requesting_password_reset()
{
$response = $this->send(
$this->request('POST', '/api/forgot', [
'authenticatedAs' => 2,
'json' => [
'email' => 'normal@machine.local'
]
])
);
$this->assertEquals(204, $response->getStatusCode());
$this->assertEquals(1, PasswordToken::query()->where('user_id', 2)->count());
}
/** @test */
public function password_tokens_are_deleted_after_password_reset()
{
$this->app();
// Request password change to generate a token.
$response = $this->send(
$this->request('POST', '/api/forgot', [
'authenticatedAs' => 2,
'json' => [
'email' => 'normal@machine.local'
]
])
);
// Additional Tokens
PasswordToken::generate(2)->save();
PasswordToken::generate(2)->save();
$this->assertEquals(204, $response->getStatusCode());
$this->assertEquals(3, PasswordToken::query()->where('user_id', 2)->count());
// Use a token to reset password
$response = $this->send(
$request = $this->requestWithCsrfToken(
$this->request('POST', '/reset', [
'authenticatedAs' => 2,
])->withParsedBody([
'passwordToken' => PasswordToken::query()->latest()->first()->token,
'password' => 'new-password',
'password_confirmation' => 'new-password',
])
)
);
$this->assertEquals(302, $response->getStatusCode());
$this->assertEquals(0, PasswordToken::query()->where('user_id', 2)->count());
}
/** @test */
public function email_tokens_are_generated_when_requesting_email_change()
{
$response = $this->send(
$this->request('PATCH', '/api/users/2', [
'authenticatedAs' => 2,
'json' => [
'data' => [
'attributes' => [
'email' => 'new-normal@machine.local'
]
],
'meta' => [
'password' => 'too-obscure'
]
]
])
);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals(1, EmailToken::query()->where('user_id', 2)->count());
}
/** @test */
public function email_tokens_are_deleted_when_confirming_email()
{
$this->app();
EmailToken::generate('new-normal2@machine.local', 2)->save();
EmailToken::generate('new-normal3@machine.local', 2)->save();
$token = EmailToken::generate('new-normal@machine.local', 2);
$token->save();
$response = $this->send(
$this->requestWithCsrfToken(
$this->request('POST', '/confirm/'.$token->token, [
'authenticatedAs' => 2
])
)
);
$this->assertEquals(302, $response->getStatusCode());
$this->assertEquals(0, EmailToken::query()->where('user_id', 2)->count());
}
/** @test */
public function email_tokens_are_deleted_after_password_reset()
{
$this->app();
// Request password change to generate a token.
$response = $this->send(
$this->request('POST', '/api/forgot', [
'authenticatedAs' => 2,
'json' => [
'email' => 'normal@machine.local'
]
])
);
// Additional Tokens
EmailToken::generate('new-normal@machine.local', 2)->save();
EmailToken::generate('new-normal@machine.local', 2)->save();
$this->assertEquals(204, $response->getStatusCode());
$this->assertEquals(2, EmailToken::query()->where('user_id', 2)->count());
// Use a token to reset password
$response = $this->send(
$request = $this->requestWithCsrfToken(
$this->request('POST', '/reset', [
'authenticatedAs' => 2,
])->withParsedBody([
'passwordToken' => PasswordToken::query()->latest()->first()->token,
'password' => 'new-password',
'password_confirmation' => 'new-password',
])
)
);
$this->assertEquals(302, $response->getStatusCode());
$this->assertEquals(0, EmailToken::query()->where('user_id', 2)->count());
}
/** @test */
public function password_tokens_are_deleted_when_confirming_email()
{
$this->app();
PasswordToken::generate(2)->save();
PasswordToken::generate(2)->save();
$token = EmailToken::generate('new-normal@machine.local', 2);
$token->save();
$response = $this->send(
$this->requestWithCsrfToken(
$this->request('POST', '/confirm/'.$token->token, [
'authenticatedAs' => 2
])
)
);
$this->assertEquals(302, $response->getStatusCode());
$this->assertEquals(0, PasswordToken::query()->where('user_id', 2)->count());
}
}