A new editor needs a username and a password of at least 12 characters. A persistent login needs an unexpired key and an existing account. Removing an account revokes its persistent logins, and its sessions end.
100 lines
4.9 KiB
PHP
100 lines
4.9 KiB
PHP
<?php
|
|
namespace Xxx\Tests\Pages;
|
|
|
|
use PHPUnit\Framework\Attributes\DataProvider;
|
|
use Xxx\Tests\Support\PageTestCase;
|
|
|
|
// publish/addeditor.php
|
|
class AddEditorTest extends PageTestCase {
|
|
private string $token;
|
|
|
|
protected function setUp(): void {
|
|
parent::setUp();
|
|
$this->setTables(array('editors' => array(array('username' => 'ed', 'password' => 'x', 'email' => ''))));
|
|
$this->token = $this->loginAs();
|
|
}
|
|
|
|
private function add(array $fields = array()): array {
|
|
return $this->post('/publish/addeditor', $fields + array('adduser' => '1', 'username' => 'newbie', 'password' => 'a long pass phrase',
|
|
'email' => 'new@example.org', 'csrf_token' => $this->token));
|
|
}
|
|
|
|
public function testVisitorsAreSentToTheLogin(): void {
|
|
$this->cookies = array();
|
|
$this->assertRedirect('/publish/login', $this->get('/publish/addeditor'));
|
|
$this->assertRedirect('/publish/login', $this->add(array('csrf_token' => '')));
|
|
$this->assertCount(1, $this->tables()['editors']);
|
|
}
|
|
|
|
public function testPlainHttpIsSentToHttps(): void {
|
|
$this->assertRedirect('https://site.test/publish/addeditor', $this->get('/publish/addeditor', array('X-Test-Plain' => '1')));
|
|
}
|
|
|
|
public function testTheFormHasTheToken(): void {
|
|
$this->assertSame($this->token, $this->csrfToken($this->get('/publish/addeditor')['body']));
|
|
}
|
|
|
|
public function testAnEditorIsAddedWithAPasswordHash(): void {
|
|
$answer = $this->add();
|
|
$this->assertStringContainsString('<p>Added editor newbie</p>', $answer['body']);
|
|
$row = $this->tables()['editors'][1];
|
|
$this->assertSame(array('newbie', 'new@example.org'), array($row['username'], $row['email']));
|
|
$this->assertTrue(password_verify('a long pass phrase', $row['password']));
|
|
}
|
|
|
|
public function testTheTokenIsChecked(): void {
|
|
$answer = $this->add(array('csrf_token' => 'wrong'));
|
|
$this->assertStringContainsString('Your session has expired. Please try again.', $answer['body']);
|
|
$this->assertCount(1, $this->tables()['editors']);
|
|
}
|
|
|
|
public function testAnExistingUsernameIsRefused(): void {
|
|
$answer = $this->add(array('username' => 'ed'));
|
|
$this->assertStringContainsString('An editor with that username already exists.', $answer['body']);
|
|
$this->assertSame('x', $this->tables()['editors'][0]['password']);
|
|
}
|
|
|
|
public function testAHashThatDoesNotFitIsNotKept(): void {
|
|
$this->setTables(array('editors' => array(array('username' => 'ed', 'password' => 'x', 'email' => ''))), 40);
|
|
$answer = $this->add();
|
|
$this->assertStringContainsString('the editors.password column is too short', $answer['body']);
|
|
$this->assertSame(array('ed'), array_column($this->tables()['editors'], 'username'));
|
|
$this->assertCount(1, $this->queries('/^DELETE FROM persistent_sessions WHERE username = \?$/'));
|
|
}
|
|
|
|
public static function badAccounts(): array {
|
|
return array(
|
|
'no username' => array(array('username' => ''), 'Please enter a username.'),
|
|
'a blank username' => array(array('username' => ' '), 'Please enter a username.'),
|
|
'an array username' => array(array('username' => array('x')), 'Please enter a username.'),
|
|
'spaces at the ends' => array(array('username' => ' newbie'), 'no spaces at the ends'),
|
|
'a bar' => array(array('username' => 'new|bie'), 'no spaces at the ends'),
|
|
'a long username' => array(array('username' => str_repeat('n', 65)), 'at most 64 characters'),
|
|
'no password' => array(array('password' => ''), 'A password needs at least 12 characters.'),
|
|
'a short password' => array(array('password' => 'eleven char'), 'A password needs at least 12 characters.'),
|
|
'an array password' => array(array('password' => array('a long pass phrase')), 'A password needs at least 12 characters.'),
|
|
'a huge password' => array(array('password' => str_repeat('p', 1025)), 'A password has at most 1024 characters.'),
|
|
'the username' => array(array('username' => 'newbie-editor', 'password' => 'NEWBIE-EDITOR'), 'The password cannot be the username.'),
|
|
);
|
|
}
|
|
|
|
#[DataProvider('badAccounts')]
|
|
public function testABadAccountIsRefused(array $fields, string $message): void {
|
|
$answer = $this->add($fields);
|
|
$this->assertSame(200, $answer['status']);
|
|
$this->assertStringContainsString(htmlspecialchars($message, ENT_QUOTES), $answer['body']);
|
|
$this->assertStringNotContainsString('Added editor', $answer['body']);
|
|
$this->assertCount(1, $this->tables()['editors']);
|
|
$this->assertCount(0, $this->queries('/^INSERT INTO editors/'));
|
|
}
|
|
|
|
public function testTwelveCharactersAreEnough(): void {
|
|
$this->assertStringContainsString('Added editor newbie', $this->add(array('password' => 'twelve chars'))['body']);
|
|
}
|
|
|
|
public function testTheUsernameIsEscaped(): void {
|
|
$body = $this->add(array('username' => '<b>x</b>'))['body'];
|
|
$this->assertStringContainsString('Added editor <b>x</b>', $body);
|
|
}
|
|
}
|