diff --git a/lib/REST/Fever/API.php b/lib/REST/Fever/API.php
index b80fe8d..c4ad36b 100644
--- a/lib/REST/Fever/API.php
+++ b/lib/REST/Fever/API.php
@@ -97,26 +97,4 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
Arsse::$user->id = $s['user'];
return true;
}
-
- public static function userRegister(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;
- }
-
- public static function userUnregister(string $user): bool {
- return (bool) Arsse::$db->tokenRevoke($user, "fever.login");
- }
-
- public static function userAuthenticate(string $user, string $password): bool {
- try {
- return (bool) Arsse::$db->tokenLookup("fever.login", md5("$user:$password"));
- } catch (ExceptionInput $e) {
- return false;
- }
- }
}
diff --git a/lib/REST/Fever/User.php b/lib/REST/Fever/User.php
new file mode 100644
index 0000000..ac3cf69
--- /dev/null
+++ b/lib/REST/Fever/User.php
@@ -0,0 +1,34 @@
+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;
+ }
+
+ public static function unregister(string $user): bool {
+ return (bool) Arsse::$db->tokenRevoke($user, "fever.login");
+ }
+
+ public static function authenticate(string $user, string $password): bool {
+ try {
+ return (bool) Arsse::$db->tokenLookup("fever.login", md5("$user:$password"));
+ } catch (ExceptionInput $e) {
+ return false;
+ }
+ }
+}
diff --git a/tests/cases/REST/Fever/TestAPI.php b/tests/cases/REST/Fever/TestAPI.php
index b1c6901..c76d567 100644
--- a/tests/cases/REST/Fever/TestAPI.php
+++ b/tests/cases/REST/Fever/TestAPI.php
@@ -144,61 +144,4 @@ 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"));
- try {
- if ($exp instanceof \JKingWeb\Arsse\AbstractException) {
- $this->assertException($exp);
- API::userRegister($user, $password);
- } else {
- $this->assertSame($exp, API::userRegister($user, $password));
- }
- } finally {
- \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::userUnregister("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::userUnregister("john.doe@example.com"));
- \Phake::verify(Arsse::$db)->tokenRevoke("john.doe@example.com", "fever.login");
- }
-
- /** @dataProvider provideUserAuthenticationRequests */
- public function testAuthenticateAUserName(string $user, string $password, bool $exp) {
- \Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("constraintViolation"));
- \Phake::when(Arsse::$db)->tokenLookup("fever.login", md5("jane.doe@example.com:secret"))->thenReturn(['user' => "jane.doe@example.com"]);
- \Phake::when(Arsse::$db)->tokenLookup("fever.login", md5("john.doe@example.com:superman"))->thenReturn(['user' => "john.doe@example.com"]);
- $this->assertSame($exp, API::userAuthenticate($user, $password));
- }
-
- public function provideUserAuthenticationRequests() {
- return [
- ["jane.doe@example.com", "secret", true],
- ["jane.doe@example.com", "superman", false],
- ["john.doe@example.com", "secret", false],
- ["john.doe@example.com", "superman", true],
- ];
- }
}
diff --git a/tests/cases/REST/Fever/TestUser.php b/tests/cases/REST/Fever/TestUser.php
new file mode 100644
index 0000000..c185647
--- /dev/null
+++ b/tests/cases/REST/Fever/TestUser.php
@@ -0,0 +1,94 @@
+ */
+class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
+ protected $u;
+
+ public function setUp() {
+ self::clearData();
+ self::setConf();
+ // create a mock user manager
+ Arsse::$user = \Phake::mock(User::class);
+ \Phake::when(Arsse::$user)->auth->thenReturn(true);
+ // create a mock database interface
+ Arsse::$db = \Phake::mock(Database::class);
+ \Phake::when(Arsse::$db)->begin->thenReturn(\Phake::mock(Transaction::class));
+ // instantiate the handler
+ $this->u = new FeverUser();
+ }
+
+ public function tearDown() {
+ self::clearData();
+ }
+
+ /** @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"));
+ try {
+ if ($exp instanceof \JKingWeb\Arsse\AbstractException) {
+ $this->assertException($exp);
+ $this->u->register($user, $password);
+ } else {
+ $this->assertSame($exp, $this->u->register($user, $password));
+ }
+ } finally {
+ \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($this->u->unregister("jane.doe@example.com"));
+ \Phake::verify(Arsse::$db)->tokenRevoke("jane.doe@example.com", "fever.login");
+ \Phake::when(Arsse::$db)->tokenRevoke->thenReturn(0);
+ $this->assertFalse($this->u->unregister("john.doe@example.com"));
+ \Phake::verify(Arsse::$db)->tokenRevoke("john.doe@example.com", "fever.login");
+ }
+
+ /** @dataProvider provideUserAuthenticationRequests */
+ public function testAuthenticateAUserName(string $user, string $password, bool $exp) {
+ \Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("constraintViolation"));
+ \Phake::when(Arsse::$db)->tokenLookup("fever.login", md5("jane.doe@example.com:secret"))->thenReturn(['user' => "jane.doe@example.com"]);
+ \Phake::when(Arsse::$db)->tokenLookup("fever.login", md5("john.doe@example.com:superman"))->thenReturn(['user' => "john.doe@example.com"]);
+ $this->assertSame($exp, $this->u->authenticate($user, $password));
+ }
+
+ public function provideUserAuthenticationRequests() {
+ return [
+ ["jane.doe@example.com", "secret", true],
+ ["jane.doe@example.com", "superman", false],
+ ["john.doe@example.com", "secret", false],
+ ["john.doe@example.com", "superman", true],
+ ];
+ }
+}
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
index 9200dd8..7c698ab 100644
--- a/tests/phpunit.xml
+++ b/tests/phpunit.xml
@@ -105,6 +105,7 @@
cases/REST/TinyTinyRSS/PDO/TestAPI.php
+ cases/REST/Fever/TestUser.php
cases/REST/Fever/TestAPI.php
cases/REST/Fever/PDO/TestAPI.php