From e6feb8de8dc9b0c2f4357e9a60920e1de9b6b0b2 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sun, 19 Feb 2017 00:22:16 -0500 Subject: [PATCH] First basic test for User class As the User class depends on the database and this has yet to be tested (though I'm fairly certain it works), the mock driver also acts as a mock of the required database functions, with both instances sharing a common storage structure. Later test series should separate the two. --- lib/Database.php | 6 ++-- lib/User.php | 2 +- tests/User/TestUser.php | 16 ++++++++- tests/lib/User/DriverInternalMock.php | 49 +++++++++++++++++++++------ 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/lib/Database.php b/lib/Database.php index ef924aa6..c835e58d 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -175,7 +175,7 @@ class Database { if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); if($this->userExists($user)) return false; if(strlen($password) > 0) $password = password_hash($password, \PASSWORD_DEFAULT); - $this->db->prepare("INSERT INTO newssync_users(id,password) values(?,?)", "str", "str", "str")->run($user,$password,$admin); + $this->db->prepare("INSERT INTO newssync_users(id,password) values(?,?)", "str", "str")->run($user,$password); return true; } @@ -211,7 +211,7 @@ class Database { public function userPasswordSet(string $user, string $password = null): bool { if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); if(!$this->userExists($user)) return false; - if(strlen($password > 0)) $password = password_hash($password); + if(strlen($password > 0)) $password = password_hash($password, \PASSWORD_DEFAULT); $this->db->prepare("UPDATE newssync_users set password = ? where id is ?", "str", "str")->run($password, $user); return true; } @@ -244,7 +244,7 @@ class Database { } public function userRightsSet(string $user, int $rights): bool { - if(!$this->data->user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); + if(!$this->data->user->authorize($user, __FUNCTION__, $rights)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); if(!$this->userExists($user)) return false; $this->db->prepare("UPDATE newssync_users set rights = ? where id is ?", "int", "str")->run($rights, $user); return true; diff --git a/lib/User.php b/lib/User.php index 5360981b..bdea2f19 100644 --- a/lib/User.php +++ b/lib/User.php @@ -144,7 +144,7 @@ class User { if($this->u->driverFunctions("userAdd") != User\Driver::FUNC_INTERNAL) { if(!$this->data->user->authorize($user, "userAdd")) throw new User\ExceptionAuthz("notAuthorized", ["action" => "userAdd", "user" => $user]); } - if($this->exists($user)) return false; + if($this->exists($user)) throw new User\Exception("alreadyExists", ["action" => "userAdd", "user" => $user]); $out = $this->u->userAdd($user, $password); if($out && $this->u->driverFunctions("userAdd") != User\Driver::FUNC_INTERNAL) { try { diff --git a/tests/User/TestUser.php b/tests/User/TestUser.php index aef45757..2f7f5f80 100644 --- a/tests/User/TestUser.php +++ b/tests/User/TestUser.php @@ -9,9 +9,23 @@ class TestUser extends \PHPUnit\Framework\TestCase { protected $data; function setUp() { + $drv = Test\User\DriverInternalMock::class; $conf = new Conf(); - $conf->userDriver = Test\User\DriverInternalMock::class; + $conf->userDriver = $drv; + $conf->userAuthPreferHTTP = true; $this->data = new Test\RuntimeData($conf); $this->data->user = new User($this->data); + $this->data->db = new $drv($this->data); + Test\User\DriverInternalMock::$db = []; + $_SERVER['PHP_AUTH_USER'] = "john.doe@example.com"; + $_SERVER['PHP_AUTH_PW'] = "secret"; + } + + function testAddingAUser() { + $this->assertCount(0,$this->data->user->list()); + $this->data->user->add($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); + $this->assertCount(1,$this->data->user->list()); + $this->assertException("alreadyExists", "User"); + $this->data->user->add($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); } } diff --git a/tests/lib/User/DriverInternalMock.php b/tests/lib/User/DriverInternalMock.php index 2403a7f2..8d0ad852 100644 --- a/tests/lib/User/DriverInternalMock.php +++ b/tests/lib/User/DriverInternalMock.php @@ -5,8 +5,8 @@ use JKingWeb\NewsSync\Lang, JKingWeb\NewsSync\User\Driver; final class DriverInternalMock implements Driver { + public static $db = []; protected $data; - protected $db; protected $functions = [ "auth" => Driver::FUNC_INTERNAL, "authorize" => Driver::FUNC_INTERNAL, @@ -43,47 +43,74 @@ final class DriverInternalMock implements Driver { } function auth(string $user, string $password): bool { - return true; + if(!$this->userExists($user)) return false; + if(password_verify($password, static::$db[$user]['password'])) return true; + return false; } function authorize(string $affectedUser, string $action, int $newRightsLevel = 0): bool { - if($affectedUser==$this->data->user->id) return true; - return false; - } - - function userExists(string $user): bool { return true; } + function userExists(string $user): bool { + return array_key_exists($user, static::$db); + } + function userAdd(string $user, string $password = null): bool { + if($this->userExists($user)) return false; + $u = [ + 'password' => $password ? password_hash($password, \PASSWORD_DEFAULT) : null, + 'rights' => Driver::RIGHTS_NONE, + ]; + static::$db[$user] = $u; return true; } function userRemove(string $user): bool { + if(!$this->userExists($user)) return false; + unset(static::$db[$user]); return true; } function userList(string $domain = null): array { - return []; + $list = array_keys(static::$db); + if($domain===null) { + return $list; + } else { + $suffix = '@'.$domain; + $len = -1 * strlen($suffix); + return array_filter($list, function($user) use($suffix, $len) { + return substr_compare($user, $suffix, $len); + }); + } } function userPasswordSet(string $user, string $newPassword, string $oldPassword): bool { + if(!$this->userExists($user)) return false; + if(!$this->auth($user, $oldPassword)) return false; + static::$db[$user]['password'] = password_hash($newPassword, \PASSWORD_DEFAULT); return true; } function userPropertiesGet(string $user): array { - return []; + if(!$this->userExists($user)) return []; + return static::$db[$user]; } function userPropertiesSet(string $user, array $properties): array { - return []; + if(!$this->userExists($user)) return []; + static::$db[$user] = array_merge(static::$db[$user], $properties); + return $this->userPropertiesGet($user); } function userRightsGet(string $user): int { - return 0; + if(!$this->userExists($user)) return Driver::RIGHTS_NONE; + return static::$db[$user]['rights']; } function userRightsSet(string $user, int $level): bool { + if(!$this->userExists($user)) return false; + static::$db[$user]['rights'] = $level; return true; } } \ No newline at end of file