diff --git a/lib/REST/Fever/API.php b/lib/REST/Fever/API.php index 65854380..b5b91ab3 100644 --- a/lib/REST/Fever/API.php +++ b/lib/REST/Fever/API.php @@ -101,7 +101,10 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { public static function registerUser(string $user, string $password = null): string { $password = $password ?? Arsse::$user->generatePassword(); $hash = md5("$user:$password"); + $tr = Arsse::$db->begin(); + Arsse::$db->tokenRevoke($user, "fever.login"); Arsse::$db->tokenCreate($user, "fever.login", $hash); + $tr->commit(); return $password; } diff --git a/tests/cases/REST/Fever/TestAPI.php b/tests/cases/REST/Fever/TestAPI.php index ccf45641..0d974d18 100644 --- a/tests/cases/REST/Fever/TestAPI.php +++ b/tests/cases/REST/Fever/TestAPI.php @@ -16,6 +16,7 @@ use JKingWeb\Arsse\Test\Result; use JKingWeb\Arsse\Misc\Date; use JKingWeb\Arsse\Context\Context; use JKingWeb\Arsse\Db\ExceptionInput; +use JKingWeb\Arsse\User\Exception as UserException; use JKingWeb\Arsse\Db\Transaction; use JKingWeb\Arsse\REST\Fever\API; use Psr\Http\Message\ResponseInterface; @@ -48,7 +49,7 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { $req = $req->withParsedBody($dataPost); } else { $body = $req->getBody(); - $body->write($strData); + $body->write($dataPost); $req = $req->withBody($body); } if (isset($user)) { @@ -135,4 +136,41 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { [true, false, "validUser", ['api_key' => "invalidToken"], ['api' => null], $success], ]; } + + /** @dataProvider providePasswordCreations */ + public function testRegisterAUserPassword(string $user, string $password = null, $exp) { + \Phake::when(Arsse::$user)->generatePassword->thenReturn("RANDOM_PASSWORD"); + \Phake::when(Arsse::$db)->tokenCreate->thenReturnCallback(function($user, $class, $id = null) { + return $id ?? "RANDOM_TOKEN"; + }); + \Phake::when(Arsse::$db)->tokenCreate("john.doe@example.org", $this->anything(), $this->anything())->thenThrow(new UserException("doesNotExist")); + if ($exp instanceof \JKingWeb\Arsse\AbstractException) { + $this->assertException($exp); + API::registerUser($user, $password); + } else { + $this->assertSame($exp, API::registerUser($user, $password)); + } + \Phake::verify(Arsse::$db)->tokenRevoke($user, "fever.login"); + \Phake::verify(Arsse::$db)->tokenCreate($user, "fever.login", md5($user.":".($password ?? "RANDOM_PASSWORD"))); + } + + public function providePasswordCreations() { + return [ + ["jane.doe@example.com", "secret", "secret"], + ["jane.doe@example.com", "superman", "superman"], + ["jane.doe@example.com", null, "RANDOM_PASSWORD"], + ["john.doe@example.org", null, new UserException("doesNotExist")], + ["john.doe@example.net", null, "RANDOM_PASSWORD"], + ["john.doe@example.net", "secret", "secret"], + ]; + } + + public function testUnregisterAUser() { + \Phake::when(Arsse::$db)->tokenRevoke->thenReturn(3); + $this->assertTrue(API::unregisterUser("jane.doe@example.com")); + \Phake::verify(Arsse::$db)->tokenRevoke("jane.doe@example.com", "fever.login"); + \Phake::when(Arsse::$db)->tokenRevoke->thenReturn(0); + $this->assertFalse(API::unregisterUser("john.doe@example.com")); + \Phake::verify(Arsse::$db)->tokenRevoke("john.doe@example.com", "fever.login"); + } } diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index 38142210..f55ca9b5 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -55,17 +55,22 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { Arsse::$conf = (($force ? null : Arsse::$conf) ?? (new Conf))->import($defaults)->import($conf); } - public function assertException(string $msg = "", string $prefix = "", string $type = "Exception") { + public function assertException($msg = "", string $prefix = "", string $type = "Exception") { if (func_num_args()) { - $class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type; - $msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg"; - if (array_key_exists($msgID, Exception::CODES)) { - $code = Exception::CODES[$msgID]; + if ($msg instanceof \JKingWeb\Arsse\AbstractException) { + $this->expectException(get_class($msg)); + $this->expectExceptionCode($msg->getCode()); } else { - $code = 0; + $class = \JKingWeb\Arsse\NS_BASE . ($prefix !== "" ? str_replace("/", "\\", $prefix) . "\\" : "") . $type; + $msgID = ($prefix !== "" ? $prefix . "/" : "") . $type. ".$msg"; + if (array_key_exists($msgID, Exception::CODES)) { + $code = Exception::CODES[$msgID]; + } else { + $code = 0; + } + $this->expectException($class); + $this->expectExceptionCode($code); } - $this->expectException($class); - $this->expectExceptionCode($code); } else { // expecting a standard PHP exception $this->expectException(\Throwable::class);