mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-31 21:12:41 +00:00
Fix whitespace
Also fixed my editor so tabs won't happen again!
This commit is contained in:
parent
b02abec250
commit
a67fe30408
32 changed files with 1402 additions and 1402 deletions
|
@ -362,7 +362,7 @@ class Database {
|
||||||
// if a parent is specified, make sure it exists and belongs to the user; get its root (first-level) folder if it's a nested folder
|
// if a parent is specified, make sure it exists and belongs to the user; get its root (first-level) folder if it's a nested folder
|
||||||
$p = $this->db->prepare(
|
$p = $this->db->prepare(
|
||||||
"WITH RECURSIVE folders(id) as (SELECT id from arsse_folders where owner is ? and id is ? union select arsse_folders.id from arsse_folders join folders on arsse_folders.parent=folders.id) ".
|
"WITH RECURSIVE folders(id) as (SELECT id from arsse_folders where owner is ? and id is ? union select arsse_folders.id from arsse_folders join folders on arsse_folders.parent=folders.id) ".
|
||||||
"SELECT id,(id not in (select id from folders)) as valid from arsse_folders where owner is ? and id is ?",
|
"SELECT id,(id not in (select id from folders)) as valid from arsse_folders where owner is ? and id is ?",
|
||||||
"str", "int", "str", "int")->run($user, $id, $user, $parent)->getRow();
|
"str", "int", "str", "int")->run($user, $id, $user, $parent)->getRow();
|
||||||
if(!$p) {
|
if(!$p) {
|
||||||
throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "parent", 'id' => $parent]);
|
throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "parent", 'id' => $parent]);
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace JKingWeb\Arsse\Db;
|
||||||
abstract class AbstractStatement implements Statement {
|
abstract class AbstractStatement implements Statement {
|
||||||
|
|
||||||
abstract function runArray(array $values): Result;
|
abstract function runArray(array $values): Result;
|
||||||
abstract static function dateFormat(int $part = self::TS_BOTH): string;
|
abstract static function dateFormat(int $part = self::TS_BOTH): string;
|
||||||
|
|
||||||
public function run(...$values): Result {
|
public function run(...$values): Result {
|
||||||
return $this->runArray($values);
|
return $this->runArray($values);
|
||||||
|
@ -30,41 +30,41 @@ abstract class AbstractStatement implements Statement {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function cast($v, string $t) {
|
protected function cast($v, string $t) {
|
||||||
switch($t) {
|
switch($t) {
|
||||||
case "date":
|
case "date":
|
||||||
return $this->formatDate($v, self::TS_DATE);
|
return $this->formatDate($v, self::TS_DATE);
|
||||||
case "time":
|
case "time":
|
||||||
return $this->formatDate($v, self::TS_TIME);
|
return $this->formatDate($v, self::TS_TIME);
|
||||||
case "datetime":
|
case "datetime":
|
||||||
return $this->formatDate($v, self::TS_BOTH);
|
return $this->formatDate($v, self::TS_BOTH);
|
||||||
case "null":
|
case "null":
|
||||||
case "integer":
|
case "integer":
|
||||||
case "float":
|
case "float":
|
||||||
case "binary":
|
case "binary":
|
||||||
case "string":
|
case "string":
|
||||||
case "boolean":
|
case "boolean":
|
||||||
if($t=="binary") $t = "string";
|
if($t=="binary") $t = "string";
|
||||||
$value = $v;
|
$value = $v;
|
||||||
try{
|
try{
|
||||||
settype($value, $t);
|
settype($value, $t);
|
||||||
} catch(\Throwable $e) {
|
} catch(\Throwable $e) {
|
||||||
// handle objects
|
// handle objects
|
||||||
$value = $v;
|
$value = $v;
|
||||||
if($value instanceof \DateTimeInterface) {
|
if($value instanceof \DateTimeInterface) {
|
||||||
$value = $value->getTimestamp();
|
$value = $value->getTimestamp();
|
||||||
if($t=="string") $value = $this->formatDate($value, self::TS_BOTH);
|
if($t=="string") $value = $this->formatDate($value, self::TS_BOTH);
|
||||||
settype($value, $t);
|
settype($value, $t);
|
||||||
} else {
|
} else {
|
||||||
$value = null;
|
$value = null;
|
||||||
settype($value, $t);
|
settype($value, $t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $value;
|
return $value;
|
||||||
default:
|
default:
|
||||||
throw new Exception("paramTypeUnknown", $type);
|
throw new Exception("paramTypeUnknown", $type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function formatDate($date, int $part = self::TS_BOTH) {
|
protected function formatDate($date, int $part = self::TS_BOTH) {
|
||||||
// Force UTC.
|
// Force UTC.
|
||||||
|
@ -82,7 +82,7 @@ abstract class AbstractStatement implements Statement {
|
||||||
$time = strtotime($date);
|
$time = strtotime($date);
|
||||||
if($time===false) return null;
|
if($time===false) return null;
|
||||||
} else if (is_bool($date)) {
|
} else if (is_bool($date)) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
$time = (int) $date;
|
$time = (int) $date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ interface Result extends \Iterator {
|
||||||
function getRow();
|
function getRow();
|
||||||
function getAll(): array;
|
function getAll(): array;
|
||||||
function getValue();
|
function getValue();
|
||||||
|
|
||||||
function changes();
|
function changes();
|
||||||
function lastId();
|
function lastId();
|
||||||
}
|
}
|
|
@ -12,17 +12,17 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
|
||||||
const SQLITE_CONSTRAINT = 19;
|
const SQLITE_CONSTRAINT = 19;
|
||||||
const SQLITE_MISMATCH = 20;
|
const SQLITE_MISMATCH = 20;
|
||||||
const BINDINGS = [
|
const BINDINGS = [
|
||||||
"null" => \SQLITE3_NULL,
|
"null" => \SQLITE3_NULL,
|
||||||
"integer" => \SQLITE3_INTEGER,
|
"integer" => \SQLITE3_INTEGER,
|
||||||
"float" => \SQLITE3_FLOAT,
|
"float" => \SQLITE3_FLOAT,
|
||||||
"date" => \SQLITE3_TEXT,
|
"date" => \SQLITE3_TEXT,
|
||||||
"time" => \SQLITE3_TEXT,
|
"time" => \SQLITE3_TEXT,
|
||||||
"datetime" => \SQLITE3_TEXT,
|
"datetime" => \SQLITE3_TEXT,
|
||||||
"binary" => \SQLITE3_BLOB,
|
"binary" => \SQLITE3_BLOB,
|
||||||
"string" => \SQLITE3_TEXT,
|
"string" => \SQLITE3_TEXT,
|
||||||
"boolean" => \SQLITE3_INTEGER,
|
"boolean" => \SQLITE3_INTEGER,
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $st;
|
protected $st;
|
||||||
protected $types;
|
protected $types;
|
||||||
|
|
|
@ -6,32 +6,32 @@ interface Statement {
|
||||||
const TS_TIME = -1;
|
const TS_TIME = -1;
|
||||||
const TS_DATE = 0;
|
const TS_DATE = 0;
|
||||||
const TS_BOTH = 1;
|
const TS_BOTH = 1;
|
||||||
const TYPES = [
|
const TYPES = [
|
||||||
"null" => "null",
|
"null" => "null",
|
||||||
"nil" => "null",
|
"nil" => "null",
|
||||||
"int" => "integer",
|
"int" => "integer",
|
||||||
"integer" => "integer",
|
"integer" => "integer",
|
||||||
"float" => "float",
|
"float" => "float",
|
||||||
"double" => "float",
|
"double" => "float",
|
||||||
"real" => "float",
|
"real" => "float",
|
||||||
"numeric" => "float",
|
"numeric" => "float",
|
||||||
"date" => "date",
|
"date" => "date",
|
||||||
"time" => "time",
|
"time" => "time",
|
||||||
"datetime" => "datetime",
|
"datetime" => "datetime",
|
||||||
"timestamp" => "datetime",
|
"timestamp" => "datetime",
|
||||||
"blob" => "binary",
|
"blob" => "binary",
|
||||||
"bin" => "binary",
|
"bin" => "binary",
|
||||||
"binary" => "binary",
|
"binary" => "binary",
|
||||||
"text" => "string",
|
"text" => "string",
|
||||||
"string" => "string",
|
"string" => "string",
|
||||||
"str" => "string",
|
"str" => "string",
|
||||||
"bool" => "boolean",
|
"bool" => "boolean",
|
||||||
"boolean" => "boolean",
|
"boolean" => "boolean",
|
||||||
"bit" => "boolean",
|
"bit" => "boolean",
|
||||||
];
|
];
|
||||||
|
|
||||||
static function dateFormat(int $part = self::TS_BOTH): string;
|
static function dateFormat(int $part = self::TS_BOTH): string;
|
||||||
|
|
||||||
function run(...$values): Result;
|
function run(...$values): Result;
|
||||||
function runArray(array $values): Result;
|
function runArray(array $values): Result;
|
||||||
function rebind(...$bindings): bool;
|
function rebind(...$bindings): bool;
|
||||||
|
|
|
@ -24,7 +24,7 @@ class REST {
|
||||||
// Fever https://feedafever.com/api
|
// Fever https://feedafever.com/api
|
||||||
// NewsBlur http://www.newsblur.com/api
|
// NewsBlur http://www.newsblur.com/api
|
||||||
];
|
];
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,6 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST;
|
namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
abstract class AbstractHandler implements Handler {
|
abstract class AbstractHandler implements Handler {
|
||||||
abstract function __construct();
|
abstract function __construct();
|
||||||
abstract function dispatch(Request $req): Response;
|
abstract function dispatch(Request $req): Response;
|
||||||
}
|
}
|
|
@ -4,5 +4,5 @@ namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
interface Handler {
|
interface Handler {
|
||||||
function __construct();
|
function __construct();
|
||||||
function dispatch(Request $req): Response;
|
function dispatch(Request $req): Response;
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$data = [];
|
$data = [];
|
||||||
}
|
}
|
||||||
// FIXME: Do query parameters take precedence in NextCloud? Is there a conflict error when values differ?
|
// FIXME: Do query parameters take precedence in NextCloud? Is there a conflict error when values differ?
|
||||||
$data = array_merge($data, $req->query);
|
$data = array_merge($data, $req->query);
|
||||||
// match the path
|
// match the path
|
||||||
if(preg_match("<^/(items|folders|feeds|cleanup|version|status|user)(?:/([^/]+))?(?:/([^/]+))?(?:/([^/]+))?/?$>", $req->path, $url)) {
|
if(preg_match("<^/(items|folders|feeds|cleanup|version|status|user)(?:/([^/]+))?(?:/([^/]+))?(?:/([^/]+))?/?$>", $req->path, $url)) {
|
||||||
// clean up the path
|
// clean up the path
|
||||||
|
|
|
@ -4,25 +4,25 @@ namespace JKingWeb\Arsse\REST\NextCloudNews;
|
||||||
use JKingWeb\Arsse\REST\Response;
|
use JKingWeb\Arsse\REST\Response;
|
||||||
|
|
||||||
class Versions extends \JKingWeb\Arsse\REST\AbstractHandler {
|
class Versions extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
function __construct() {
|
function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dispatch(\JKingWeb\Arsse\REST\Request $req): \JKingWeb\Arsse\REST\Response {
|
function dispatch(\JKingWeb\Arsse\REST\Request $req): \JKingWeb\Arsse\REST\Response {
|
||||||
// if a method other than GET was used, this is an error
|
// if a method other than GET was used, this is an error
|
||||||
if($req->method != "GET") {
|
if($req->method != "GET") {
|
||||||
return new Response(405);
|
return new Response(405);
|
||||||
}
|
}
|
||||||
if(preg_match("<^/?$>",$req->path)) {
|
if(preg_match("<^/?$>",$req->path)) {
|
||||||
// if the request path is an empty string or just a slash, return the supported versions
|
// if the request path is an empty string or just a slash, return the supported versions
|
||||||
$out = [
|
$out = [
|
||||||
'apiLevels' => [
|
'apiLevels' => [
|
||||||
'v1-2',
|
'v1-2',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
return new Response(200, $out);
|
return new Response(200, $out);
|
||||||
} else {
|
} else {
|
||||||
// if the URL path was anything else, the client is probably trying a version we don't support
|
// if the URL path was anything else, the client is probably trying a version we don't support
|
||||||
return new Response(404);
|
return new Response(404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,59 +3,59 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST;
|
namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
public $method = "GET";
|
public $method = "GET";
|
||||||
public $url = "";
|
public $url = "";
|
||||||
public $path ="";
|
public $path ="";
|
||||||
public $query = "";
|
public $query = "";
|
||||||
public $type ="";
|
public $type ="";
|
||||||
public $body = "";
|
public $body = "";
|
||||||
|
|
||||||
function __construct(string $method = null, string $url = null, string $body = null, string $contentType = null) {
|
function __construct(string $method = null, string $url = null, string $body = null, string $contentType = null) {
|
||||||
if(is_null($method)) $method = $_SERVER['REQUEST_METHOD'];
|
if(is_null($method)) $method = $_SERVER['REQUEST_METHOD'];
|
||||||
if(is_null($url)) $url = $_SERVER['REQUEST_URI'];
|
if(is_null($url)) $url = $_SERVER['REQUEST_URI'];
|
||||||
if(is_null($body)) $body = file_get_contents("php://input");
|
if(is_null($body)) $body = file_get_contents("php://input");
|
||||||
if(is_null($contentType)) {
|
if(is_null($contentType)) {
|
||||||
if(isset($_SERVER['HTTP_CONTENT_TYPE'])) {
|
if(isset($_SERVER['HTTP_CONTENT_TYPE'])) {
|
||||||
$contentType = $_SERVER['HTTP_CONTENT_TYPE'];
|
$contentType = $_SERVER['HTTP_CONTENT_TYPE'];
|
||||||
} else {
|
} else {
|
||||||
$contentType = "";
|
$contentType = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->method = strtoupper($method);
|
$this->method = strtoupper($method);
|
||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
$this->body = $body;
|
$this->body = $body;
|
||||||
$this->type = $contentType;
|
$this->type = $contentType;
|
||||||
$this->refreshURL();
|
$this->refreshURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function refreshURL() {
|
public function refreshURL() {
|
||||||
$url = $this->parseURL($this->url);
|
$url = $this->parseURL($this->url);
|
||||||
$this->path = $url['path'];
|
$this->path = $url['path'];
|
||||||
$this->query = $url['query'];
|
$this->query = $url['query'];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function parseURL(string $url): array {
|
protected function parseURL(string $url): array {
|
||||||
// split the query string from the path
|
// split the query string from the path
|
||||||
$parts = explode("?", $url);
|
$parts = explode("?", $url);
|
||||||
$out = ['path' => $parts[0], 'query' => []];
|
$out = ['path' => $parts[0], 'query' => []];
|
||||||
// if there is a query string, parse it
|
// if there is a query string, parse it
|
||||||
if(isset($parts[1])) {
|
if(isset($parts[1])) {
|
||||||
// split along & to get key-value pairs
|
// split along & to get key-value pairs
|
||||||
$query = explode("&", $parts[1]);
|
$query = explode("&", $parts[1]);
|
||||||
for($a = 0; $a < sizeof($query); $a++) {
|
for($a = 0; $a < sizeof($query); $a++) {
|
||||||
// split each pair, into no more than two parts
|
// split each pair, into no more than two parts
|
||||||
$data = explode("=", $query[$a], 2);
|
$data = explode("=", $query[$a], 2);
|
||||||
// decode the key
|
// decode the key
|
||||||
$key = rawurldecode($data[0]);
|
$key = rawurldecode($data[0]);
|
||||||
// decode the value if there is one
|
// decode the value if there is one
|
||||||
$value = "";
|
$value = "";
|
||||||
if(isset($data[1])) {
|
if(isset($data[1])) {
|
||||||
$value = rawurldecode($data[1]);
|
$value = rawurldecode($data[1]);
|
||||||
}
|
}
|
||||||
// add the pair to the query output, overwriting earlier values for the same key, is present
|
// add the pair to the query output, overwriting earlier values for the same key, is present
|
||||||
$out['query'][$key] = $value;
|
$out['query'][$key] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,20 +3,20 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\REST;
|
namespace JKingWeb\Arsse\REST;
|
||||||
|
|
||||||
class Response {
|
class Response {
|
||||||
const T_JSON = "application/json";
|
const T_JSON = "application/json";
|
||||||
const T_XML = "application/xml";
|
const T_XML = "application/xml";
|
||||||
const T_TEXT = "text/plain";
|
const T_TEXT = "text/plain";
|
||||||
|
|
||||||
public $code;
|
public $code;
|
||||||
public $payload;
|
public $payload;
|
||||||
public $type;
|
public $type;
|
||||||
public $fields;
|
public $fields;
|
||||||
|
|
||||||
|
|
||||||
function __construct(int $code, $payload = null, string $type = self::T_JSON, array $extraFields = []) {
|
function __construct(int $code, $payload = null, string $type = self::T_JSON, array $extraFields = []) {
|
||||||
$this->code = $code;
|
$this->code = $code;
|
||||||
$this->payload = $payload;
|
$this->payload = $payload;
|
||||||
$this->type = $type;
|
$this->type = $type;
|
||||||
$this->fields = $extraFields;
|
$this->fields = $extraFields;
|
||||||
}
|
}
|
||||||
}
|
}
|
12
lib/User.php
12
lib/User.php
|
@ -9,7 +9,7 @@ class User {
|
||||||
protected $authz = true;
|
protected $authz = true;
|
||||||
protected $authzSupported = 0;
|
protected $authzSupported = 0;
|
||||||
protected $actor = [];
|
protected $actor = [];
|
||||||
|
|
||||||
static public function listDrivers(): array {
|
static public function listDrivers(): array {
|
||||||
$sep = \DIRECTORY_SEPARATOR;
|
$sep = \DIRECTORY_SEPARATOR;
|
||||||
$path = __DIR__.$sep."User".$sep;
|
$path = __DIR__.$sep."User".$sep;
|
||||||
|
@ -75,7 +75,7 @@ class User {
|
||||||
if(!in_array($affectedRights,[User\Driver::RIGHTS_NONE,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN])) return false;
|
if(!in_array($affectedRights,[User\Driver::RIGHTS_NONE,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN])) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function credentials(): array {
|
public function credentials(): array {
|
||||||
if(Data::$conf->userAuthPreferHTTP) {
|
if(Data::$conf->userAuthPreferHTTP) {
|
||||||
return $this->credentialsHTTP();
|
return $this->credentialsHTTP();
|
||||||
|
@ -142,7 +142,7 @@ class User {
|
||||||
public function driverFunctions(string $function = null) {
|
public function driverFunctions(string $function = null) {
|
||||||
return $this->u->driverFunctions($function);
|
return $this->u->driverFunctions($function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function list(string $domain = null): array {
|
public function list(string $domain = null): array {
|
||||||
$func = "userList";
|
$func = "userList";
|
||||||
switch($this->u->driverFunctions($func)) {
|
switch($this->u->driverFunctions($func)) {
|
||||||
|
@ -166,7 +166,7 @@ class User {
|
||||||
$this->authz = $setting;
|
$this->authz = $setting;
|
||||||
return $setting;
|
return $setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exists(string $user): bool {
|
public function exists(string $user): bool {
|
||||||
$func = "userExists";
|
$func = "userExists";
|
||||||
switch($this->u->driverFunctions($func)) {
|
switch($this->u->driverFunctions($func)) {
|
||||||
|
@ -321,7 +321,7 @@ class User {
|
||||||
return User\Driver::RIGHTS_NONE;
|
return User\Driver::RIGHTS_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rightsSet(string $user, int $level): bool {
|
public function rightsSet(string $user, int $level): bool {
|
||||||
$func = "userRightsSet";
|
$func = "userRightsSet";
|
||||||
switch($this->u->driverFunctions($func)) {
|
switch($this->u->driverFunctions($func)) {
|
||||||
|
@ -346,7 +346,7 @@ class User {
|
||||||
throw new User\ExceptionNotImplemented("notImplemented", ["action" => $func, "user" => $user]);
|
throw new User\ExceptionNotImplemented("notImplemented", ["action" => $func, "user" => $user]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: stubs
|
// FIXME: stubs
|
||||||
public function challenge(): bool {throw new User\Exception("authFailed");}
|
public function challenge(): bool {throw new User\Exception("authFailed");}
|
||||||
public function challengeForm(): bool {throw new User\Exception("authFailed");}
|
public function challengeForm(): bool {throw new User\Exception("authFailed");}
|
||||||
|
|
|
@ -3,7 +3,7 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse\User\Internal;
|
namespace JKingWeb\Arsse\User\Internal;
|
||||||
use JKingWeb\Arsse\Data;
|
use JKingWeb\Arsse\Data;
|
||||||
|
|
||||||
trait InternalFunctions {
|
trait InternalFunctions {
|
||||||
protected $actor = [];
|
protected $actor = [];
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
@ -32,7 +32,7 @@ trait InternalFunctions {
|
||||||
function userList(string $domain = null): array {
|
function userList(string $domain = null): array {
|
||||||
return $this->db->userList($domain);
|
return $this->db->userList($domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
return $this->db->userPasswordSet($user, $newPassword);
|
return $this->db->userPasswordSet($user, $newPassword);
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,8 @@ trait InternalFunctions {
|
||||||
function userRightsGet(string $user): int {
|
function userRightsGet(string $user): int {
|
||||||
return $this->db->userRightsGet($user);
|
return $this->db->userRightsGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
function userRightsSet(string $user, int $level): bool {
|
||||||
return $this->db->userRightsSet($user, $level);
|
return $this->db->userRightsSet($user, $level);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ use org\bovigo\vfs\vfsStream;
|
||||||
|
|
||||||
class TestConf extends \PHPUnit\Framework\TestCase {
|
class TestConf extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools;
|
use Test\Tools;
|
||||||
|
|
||||||
static $vfs;
|
static $vfs;
|
||||||
static $path;
|
static $path;
|
||||||
|
|
||||||
|
@ -30,11 +30,11 @@ class TestConf extends \PHPUnit\Framework\TestCase {
|
||||||
self::$vfs = null;
|
self::$vfs = null;
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadDefaultValues() {
|
function testLoadDefaultValues() {
|
||||||
$this->assertInstanceOf(Conf::class, new Conf());
|
$this->assertInstanceOf(Conf::class, new Conf());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends testLoadDefaultValues
|
* @depends testLoadDefaultValues
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,279 +7,279 @@ class TestDbDriverSQLite3 extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools;
|
use Test\Tools;
|
||||||
|
|
||||||
protected $data;
|
protected $data;
|
||||||
protected $drv;
|
protected $drv;
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->dbDriver = Db\SQLite3\Driver::class;
|
$conf->dbDriver = Db\SQLite3\Driver::class;
|
||||||
$conf->dbSQLite3File = tempnam(sys_get_temp_dir(), 'ook');
|
$conf->dbSQLite3File = tempnam(sys_get_temp_dir(), 'ook');
|
||||||
Data::$conf = $conf;
|
Data::$conf = $conf;
|
||||||
$this->drv = new Db\SQLite3\Driver(true);
|
$this->drv = new Db\SQLite3\Driver(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
unset($this->drv);
|
unset($this->drv);
|
||||||
unlink(Data::$conf->dbSQLite3File);
|
unlink(Data::$conf->dbSQLite3File);
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchDriverName() {
|
function testFetchDriverName() {
|
||||||
$class = Data::$conf->dbDriver;
|
$class = Data::$conf->dbDriver;
|
||||||
$this->assertTrue(strlen($class::driverName()) > 0);
|
$this->assertTrue(strlen($class::driverName()) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExecAValidStatement() {
|
|
||||||
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testExecAnInvalidStatement() {
|
function testExecAValidStatement() {
|
||||||
$this->assertException("engineErrorGeneral", "Db");
|
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key)"));
|
||||||
$this->drv->exec("And the meek shall inherit the earth...");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testExecMultipleStatements() {
|
function testExecAnInvalidStatement() {
|
||||||
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key); INSERT INTO test(id) values(2112)"));
|
$this->assertException("engineErrorGeneral", "Db");
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$this->drv->exec("And the meek shall inherit the earth...");
|
||||||
$this->assertEquals(2112, $ch->querySingle("SELECT id from test"));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testExecTimeout() {
|
function testExecMultipleStatements() {
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$this->assertTrue($this->drv->exec("CREATE TABLE test(id integer primary key); INSERT INTO test(id) values(2112)"));
|
||||||
$ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->assertException("general", "Db", "ExceptionTimeout");
|
$this->assertEquals(2112, $ch->querySingle("SELECT id from test"));
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testExecConstraintViolation() {
|
function testExecTimeout() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
||||||
$this->drv->exec("INSERT INTO test(id) values(null)");
|
$this->assertException("general", "Db", "ExceptionTimeout");
|
||||||
}
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
|
}
|
||||||
|
|
||||||
function testExecTypeViolation() {
|
function testExecConstraintViolation() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
||||||
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
$this->drv->exec("INSERT INTO test(id) values('ook')");
|
$this->drv->exec("INSERT INTO test(id) values(null)");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMakeAValidQuery() {
|
function testExecTypeViolation() {
|
||||||
$this->assertInstanceOf(Db\SQLite3\Result::class, $this->drv->query("SELECT 1"));
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
}
|
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
||||||
|
$this->drv->exec("INSERT INTO test(id) values('ook')");
|
||||||
|
}
|
||||||
|
|
||||||
function testMakeAnInvalidQuery() {
|
function testMakeAValidQuery() {
|
||||||
$this->assertException("engineErrorGeneral", "Db");
|
$this->assertInstanceOf(Db\SQLite3\Result::class, $this->drv->query("SELECT 1"));
|
||||||
$this->drv->query("Apollo was astonished; Dionysus thought me mad");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testQueryTimeout() {
|
function testMakeAnInvalidQuery() {
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$this->assertException("engineErrorGeneral", "Db");
|
||||||
$ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
$this->drv->query("Apollo was astonished; Dionysus thought me mad");
|
||||||
$this->assertException("general", "Db", "ExceptionTimeout");
|
}
|
||||||
$this->drv->query("CREATE TABLE test(id integer primary key)");
|
|
||||||
}
|
|
||||||
|
|
||||||
function testQueryConstraintViolation() {
|
function testQueryTimeout() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$ch->exec("BEGIN EXCLUSIVE TRANSACTION");
|
||||||
$this->drv->query("INSERT INTO test(id) values(null)");
|
$this->assertException("general", "Db", "ExceptionTimeout");
|
||||||
}
|
$this->drv->query("CREATE TABLE test(id integer primary key)");
|
||||||
|
}
|
||||||
|
|
||||||
function testQueryTypeViolation() {
|
function testQueryConstraintViolation() {
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer not null)");
|
||||||
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
$this->drv->query("INSERT INTO test(id) values('ook')");
|
$this->drv->query("INSERT INTO test(id) values(null)");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPrepareAValidQuery() {
|
function testQueryTypeViolation() {
|
||||||
$s = $this->drv->prepare("SELECT ?, ?", "int", "int");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->assertInstanceOf(Db\SQLite3\Statement::class, $s);
|
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
||||||
}
|
$this->drv->query("INSERT INTO test(id) values('ook')");
|
||||||
|
}
|
||||||
|
|
||||||
function testPrepareAnInvalidQuery() {
|
function testPrepareAValidQuery() {
|
||||||
$this->assertException("engineErrorGeneral", "Db");
|
$s = $this->drv->prepare("SELECT ?, ?", "int", "int");
|
||||||
$s = $this->drv->prepare("This is an invalid query", "int", "int");
|
$this->assertInstanceOf(Db\SQLite3\Statement::class, $s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBeginTransaction() {
|
function testPrepareAnInvalidQuery() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$this->assertException("engineErrorGeneral", "Db");
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$s = $this->drv->prepare("This is an invalid query", "int", "int");
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
}
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
|
||||||
$this->drv->begin();
|
|
||||||
$this->drv->query($insert);
|
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
|
||||||
$this->drv->query($insert);
|
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testCommitTransaction() {
|
function testBeginTransaction() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->commit();
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(1, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRollbackTransaction() {
|
function testCommitTransaction() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->rollback();
|
$this->drv->commit();
|
||||||
$this->assertEquals(0, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(1, $ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBeginChainedTransactions() {
|
function testRollbackTransaction() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->begin();
|
$this->drv->rollback();
|
||||||
$this->drv->query($insert);
|
$this->assertEquals(0, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testCommitChainedTransactions() {
|
function testBeginChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->commit();
|
}
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
|
||||||
$this->drv->commit();
|
|
||||||
$this->assertEquals(2, $ch->querySingle($select));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRollbackChainedTransactions() {
|
function testCommitChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->rollback();
|
$this->drv->commit();
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->drv->commit();
|
||||||
$this->drv->rollback();
|
$this->assertEquals(2, $ch->querySingle($select));
|
||||||
$this->assertEquals(0, $this->drv->query($select)->getValue());
|
}
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPartiallyRollbackChainedTransactions() {
|
function testRollbackChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->rollback();
|
$this->drv->rollback();
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->commit();
|
$this->drv->rollback();
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(0, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(1, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFullyRollbackChainedTransactions() {
|
function testPartiallyRollbackChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->rollback(true);
|
$this->drv->rollback();
|
||||||
$this->assertEquals(0, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
}
|
$this->drv->commit();
|
||||||
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
|
$this->assertEquals(1, $ch->querySingle($select));
|
||||||
|
}
|
||||||
|
|
||||||
function testFullyCommitChainedTransactions() {
|
function testFullyRollbackChainedTransactions() {
|
||||||
$select = "SELECT count(*) FROM test";
|
$select = "SELECT count(*) FROM test";
|
||||||
$insert = "INSERT INTO test(id) values(null)";
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
$this->drv->query($insert);
|
$this->drv->query($insert);
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(0, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
$this->drv->commit(true);
|
$this->drv->rollback(true);
|
||||||
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
$this->assertEquals(0, $this->drv->query($select)->getValue());
|
||||||
$this->assertEquals(2, $ch->querySingle($select));
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchSchemaVersion() {
|
function testFullyCommitChainedTransactions() {
|
||||||
$this->assertSame(0, $this->drv->schemaVersion());
|
$select = "SELECT count(*) FROM test";
|
||||||
$this->drv->exec("PRAGMA user_version=1");
|
$insert = "INSERT INTO test(id) values(null)";
|
||||||
$this->assertSame(1, $this->drv->schemaVersion());
|
$ch = new \SQLite3(Data::$conf->dbSQLite3File);
|
||||||
$this->drv->exec("PRAGMA user_version=2");
|
$this->drv->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$this->assertSame(2, $this->drv->schemaVersion());
|
$this->drv->begin();
|
||||||
|
$this->drv->query($insert);
|
||||||
|
$this->assertEquals(1, $this->drv->query($select)->getValue());
|
||||||
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
|
$this->drv->begin();
|
||||||
|
$this->drv->query($insert);
|
||||||
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
|
$this->assertEquals(0, $ch->querySingle($select));
|
||||||
|
$this->drv->commit(true);
|
||||||
|
$this->assertEquals(2, $this->drv->query($select)->getValue());
|
||||||
|
$this->assertEquals(2, $ch->querySingle($select));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
function testFetchSchemaVersion() {
|
||||||
|
$this->assertSame(0, $this->drv->schemaVersion());
|
||||||
|
$this->drv->exec("PRAGMA user_version=1");
|
||||||
|
$this->assertSame(1, $this->drv->schemaVersion());
|
||||||
|
$this->drv->exec("PRAGMA user_version=2");
|
||||||
|
$this->assertSame(2, $this->drv->schemaVersion());
|
||||||
|
|
||||||
function testManipulateAdvisoryLock() {
|
}
|
||||||
$this->assertTrue($this->drv->unlock());
|
|
||||||
$this->assertFalse($this->drv->isLocked());
|
function testManipulateAdvisoryLock() {
|
||||||
$this->assertTrue($this->drv->lock());
|
$this->assertTrue($this->drv->unlock());
|
||||||
$this->assertFalse($this->drv->isLocked());
|
$this->assertFalse($this->drv->isLocked());
|
||||||
$this->drv->exec("CREATE TABLE arsse_settings(key primary key, value, type) without rowid; PRAGMA user_version=1");
|
$this->assertTrue($this->drv->lock());
|
||||||
$this->assertTrue($this->drv->lock());
|
$this->assertFalse($this->drv->isLocked());
|
||||||
$this->assertTrue($this->drv->isLocked());
|
$this->drv->exec("CREATE TABLE arsse_settings(key primary key, value, type) without rowid; PRAGMA user_version=1");
|
||||||
$this->assertFalse($this->drv->lock());
|
$this->assertTrue($this->drv->lock());
|
||||||
$this->drv->exec("PRAGMA user_version=0");
|
$this->assertTrue($this->drv->isLocked());
|
||||||
$this->assertFalse($this->drv->isLocked());
|
$this->assertFalse($this->drv->lock());
|
||||||
$this->assertTrue($this->drv->lock());
|
$this->drv->exec("PRAGMA user_version=0");
|
||||||
$this->assertFalse($this->drv->isLocked());
|
$this->assertFalse($this->drv->isLocked());
|
||||||
$this->drv->exec("PRAGMA user_version=1");
|
$this->assertTrue($this->drv->lock());
|
||||||
$this->assertTrue($this->drv->isLocked());
|
$this->assertFalse($this->drv->isLocked());
|
||||||
$this->assertTrue($this->drv->unlock());
|
$this->drv->exec("PRAGMA user_version=1");
|
||||||
$this->assertFalse($this->drv->isLocked());
|
$this->assertTrue($this->drv->isLocked());
|
||||||
}
|
$this->assertTrue($this->drv->unlock());
|
||||||
|
$this->assertFalse($this->drv->isLocked());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,88 +8,88 @@ class TestDbStatementSQLite3 extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools, Test\Db\BindingTests;
|
use Test\Tools, Test\Db\BindingTests;
|
||||||
|
|
||||||
protected $c;
|
protected $c;
|
||||||
static protected $imp = Db\SQLite3\Statement::class;
|
static protected $imp = Db\SQLite3\Statement::class;
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
date_default_timezone_set("UTC");
|
date_default_timezone_set("UTC");
|
||||||
$c = new \SQLite3(":memory:");
|
$c = new \SQLite3(":memory:");
|
||||||
$c->enableExceptions(true);
|
$c->enableExceptions(true);
|
||||||
$this->c = $c;
|
$this->c = $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
try {$this->s->close();} catch(\Exception $e) {}
|
try {$this->s->close();} catch(\Exception $e) {}
|
||||||
$this->c->close();
|
$this->c->close();
|
||||||
unset($this->c);
|
unset($this->c);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkBinding($input, array $expectations) {
|
protected function checkBinding($input, array $expectations) {
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
|
||||||
$s = new self::$imp($this->c, $nativeStatement);
|
|
||||||
$types = array_unique(Statement::TYPES);
|
|
||||||
foreach($types as $type) {
|
|
||||||
$s->rebindArray([$type]);
|
|
||||||
$val = $s->runArray([$input])->getRow()['value'];
|
|
||||||
$this->assertSame($expectations[$type], $val, "Type $type failed comparison.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function testConstructStatement() {
|
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
||||||
$this->assertInstanceOf(Statement::class, new Db\SQLite3\Statement($this->c, $nativeStatement));
|
$s = new self::$imp($this->c, $nativeStatement);
|
||||||
}
|
$types = array_unique(Statement::TYPES);
|
||||||
|
foreach($types as $type) {
|
||||||
function testBindMissingValue() {
|
$s->rebindArray([$type]);
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
$val = $s->runArray([$input])->getRow()['value'];
|
||||||
$s = new self::$imp($this->c, $nativeStatement);
|
$this->assertSame($expectations[$type], $val, "Type $type failed comparison.");
|
||||||
$val = $s->runArray()->getRow()['value'];
|
}
|
||||||
$this->assertSame(null, $val);
|
}
|
||||||
}
|
|
||||||
|
function testConstructStatement() {
|
||||||
|
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
||||||
|
$this->assertInstanceOf(Statement::class, new Db\SQLite3\Statement($this->c, $nativeStatement));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testBindMissingValue() {
|
||||||
|
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
||||||
|
$s = new self::$imp($this->c, $nativeStatement);
|
||||||
|
$val = $s->runArray()->getRow()['value'];
|
||||||
|
$this->assertSame(null, $val);
|
||||||
|
}
|
||||||
|
|
||||||
function testBindMultipleValues() {
|
function testBindMultipleValues() {
|
||||||
$exp = [
|
$exp = [
|
||||||
'one' => 1,
|
'one' => 1,
|
||||||
'two' => 2,
|
'two' => 2,
|
||||||
];
|
];
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as one, ? as two");
|
$nativeStatement = $this->c->prepare("SELECT ? as one, ? as two");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, ["int", "int"]);
|
$s = new self::$imp($this->c, $nativeStatement, ["int", "int"]);
|
||||||
$val = $s->runArray([1,2])->getRow();
|
$val = $s->runArray([1,2])->getRow();
|
||||||
$this->assertSame($exp, $val);
|
$this->assertSame($exp, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindRecursively() {
|
function testBindRecursively() {
|
||||||
$exp = [
|
$exp = [
|
||||||
'one' => 1,
|
'one' => 1,
|
||||||
'two' => 2,
|
'two' => 2,
|
||||||
'three' => 3,
|
'three' => 3,
|
||||||
'four' => 4,
|
'four' => 4,
|
||||||
];
|
];
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as one, ? as two, ? as three, ? as four");
|
$nativeStatement = $this->c->prepare("SELECT ? as one, ? as two, ? as three, ? as four");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, ["int", ["int", "int"], "int"]);
|
$s = new self::$imp($this->c, $nativeStatement, ["int", ["int", "int"], "int"]);
|
||||||
$val = $s->runArray([1, [2, 3], 4])->getRow();
|
$val = $s->runArray([1, [2, 3], 4])->getRow();
|
||||||
$this->assertSame($exp, $val);
|
$this->assertSame($exp, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindWithoutType() {
|
function testBindWithoutType() {
|
||||||
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
$nativeStatement = $this->c->prepare("SELECT ? as value");
|
||||||
$this->assertException("paramTypeMissing", "Db");
|
$this->assertException("paramTypeMissing", "Db");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, []);
|
$s = new self::$imp($this->c, $nativeStatement, []);
|
||||||
$s->runArray([1]);
|
$s->runArray([1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testViolateConstraint() {
|
function testViolateConstraint() {
|
||||||
$this->c->exec("CREATE TABLE test(id integer not null)");
|
$this->c->exec("CREATE TABLE test(id integer not null)");
|
||||||
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, ["int"]);
|
$s = new self::$imp($this->c, $nativeStatement, ["int"]);
|
||||||
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
$this->assertException("constraintViolation", "Db", "ExceptionInput");
|
||||||
$s->runArray([null]);
|
$s->runArray([null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMismatchTypes() {
|
function testMismatchTypes() {
|
||||||
$this->c->exec("CREATE TABLE test(id integer primary key)");
|
$this->c->exec("CREATE TABLE test(id integer primary key)");
|
||||||
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)");
|
||||||
$s = new self::$imp($this->c, $nativeStatement, ["str"]);
|
$s = new self::$imp($this->c, $nativeStatement, ["str"]);
|
||||||
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
$this->assertException("typeViolation", "Db", "ExceptionInput");
|
||||||
$s->runArray(['ook']);
|
$s->runArray(['ook']);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,84 +8,84 @@ class TestDbUpdateSQLite3 extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools;
|
use Test\Tools;
|
||||||
|
|
||||||
protected $data;
|
protected $data;
|
||||||
protected $drv;
|
protected $drv;
|
||||||
protected $vfs;
|
protected $vfs;
|
||||||
protected $base;
|
protected $base;
|
||||||
|
|
||||||
const MINIMAL1 = "create table arsse_settings(key text primary key not null, value text, type text not null); pragma user_version=1";
|
const MINIMAL1 = "create table arsse_settings(key text primary key not null, value text, type text not null); pragma user_version=1";
|
||||||
const MINIMAL2 = "pragma user_version=2";
|
const MINIMAL2 = "pragma user_version=2";
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
$this->vfs = vfsStream::setup("schemata", null, ['SQLite3' => []]);
|
$this->vfs = vfsStream::setup("schemata", null, ['SQLite3' => []]);
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->dbDriver = Db\SQLite3\Driver::class;
|
$conf->dbDriver = Db\SQLite3\Driver::class;
|
||||||
$conf->dbSchemaBase = $this->vfs->url();
|
$conf->dbSchemaBase = $this->vfs->url();
|
||||||
$this->base = $this->vfs->url()."/SQLite3/";
|
$this->base = $this->vfs->url()."/SQLite3/";
|
||||||
$conf->dbSQLite3File = ":memory:";
|
$conf->dbSQLite3File = ":memory:";
|
||||||
Data::$conf = $conf;
|
Data::$conf = $conf;
|
||||||
$this->drv = new Db\SQLite3\Driver(true);
|
$this->drv = new Db\SQLite3\Driver(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
unset($this->drv);
|
unset($this->drv);
|
||||||
unset($this->data);
|
unset($this->data);
|
||||||
unset($this->vfs);
|
unset($this->vfs);
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadMissingFile() {
|
function testLoadMissingFile() {
|
||||||
$this->assertException("updateFileMissing", "Db");
|
$this->assertException("updateFileMissing", "Db");
|
||||||
$this->drv->schemaUpdate(1);
|
$this->drv->schemaUpdate(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadUnreadableFile() {
|
function testLoadUnreadableFile() {
|
||||||
touch($this->base."0.sql");
|
touch($this->base."0.sql");
|
||||||
chmod($this->base."0.sql", 0000);
|
chmod($this->base."0.sql", 0000);
|
||||||
$this->assertException("updateFileUnreadable", "Db");
|
$this->assertException("updateFileUnreadable", "Db");
|
||||||
$this->drv->schemaUpdate(1);
|
$this->drv->schemaUpdate(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadCorruptFile() {
|
function testLoadCorruptFile() {
|
||||||
file_put_contents($this->base."0.sql", "This is a corrupt file");
|
file_put_contents($this->base."0.sql", "This is a corrupt file");
|
||||||
$this->assertException("updateFileError", "Db");
|
$this->assertException("updateFileError", "Db");
|
||||||
$this->drv->schemaUpdate(1);
|
$this->drv->schemaUpdate(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadIncompleteFile() {
|
function testLoadIncompleteFile() {
|
||||||
file_put_contents($this->base."0.sql", "create table arsse_settings(key text primary key not null, value text, type text not null);");
|
file_put_contents($this->base."0.sql", "create table arsse_settings(key text primary key not null, value text, type text not null);");
|
||||||
$this->assertException("updateFileIncomplete", "Db");
|
$this->assertException("updateFileIncomplete", "Db");
|
||||||
$this->drv->schemaUpdate(1);
|
$this->drv->schemaUpdate(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadCorrectFile() {
|
function testLoadCorrectFile() {
|
||||||
file_put_contents($this->base."0.sql", self::MINIMAL1);
|
file_put_contents($this->base."0.sql", self::MINIMAL1);
|
||||||
$this->drv->schemaUpdate(1);
|
$this->drv->schemaUpdate(1);
|
||||||
$this->assertEquals(1, $this->drv->schemaVersion());
|
$this->assertEquals(1, $this->drv->schemaVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPerformPartialUpdate() {
|
function testPerformPartialUpdate() {
|
||||||
file_put_contents($this->base."0.sql", self::MINIMAL1);
|
file_put_contents($this->base."0.sql", self::MINIMAL1);
|
||||||
file_put_contents($this->base."1.sql", "");
|
file_put_contents($this->base."1.sql", "");
|
||||||
$this->assertException("updateFileIncomplete", "Db");
|
$this->assertException("updateFileIncomplete", "Db");
|
||||||
try {
|
try {
|
||||||
$this->drv->schemaUpdate(2);
|
$this->drv->schemaUpdate(2);
|
||||||
} catch(Exception $e) {
|
} catch(Exception $e) {
|
||||||
$this->assertEquals(1, $this->drv->schemaVersion());
|
$this->assertEquals(1, $this->drv->schemaVersion());
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPerformSequentialUpdate() {
|
function testPerformSequentialUpdate() {
|
||||||
file_put_contents($this->base."0.sql", self::MINIMAL1);
|
file_put_contents($this->base."0.sql", self::MINIMAL1);
|
||||||
file_put_contents($this->base."1.sql", self::MINIMAL2);
|
file_put_contents($this->base."1.sql", self::MINIMAL2);
|
||||||
$this->drv->schemaUpdate(2);
|
$this->drv->schemaUpdate(2);
|
||||||
$this->assertEquals(2, $this->drv->schemaVersion());
|
$this->assertEquals(2, $this->drv->schemaVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPerformActualUpdate() {
|
function testPerformActualUpdate() {
|
||||||
Data::$conf->dbSchemaBase = (new Conf())->dbSchemaBase;
|
Data::$conf->dbSchemaBase = (new Conf())->dbSchemaBase;
|
||||||
$this->drv->schemaUpdate(Database::SCHEMA_VERSION);
|
$this->drv->schemaUpdate(Database::SCHEMA_VERSION);
|
||||||
$this->assertEquals(Database::SCHEMA_VERSION, $this->drv->schemaVersion());
|
$this->assertEquals(Database::SCHEMA_VERSION, $this->drv->schemaVersion());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ class TestException extends \PHPUnit\Framework\TestCase {
|
||||||
// clean up
|
// clean up
|
||||||
$this->clearData(true);
|
$this->clearData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBaseClass() {
|
function testBaseClass() {
|
||||||
$this->assertException("unknown");
|
$this->assertException("unknown");
|
||||||
throw new Exception("unknown");
|
throw new Exception("unknown");
|
||||||
|
@ -34,7 +34,7 @@ class TestException extends \PHPUnit\Framework\TestCase {
|
||||||
$this->assertException("unknown");
|
$this->assertException("unknown");
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends testBaseClass
|
* @depends testBaseClass
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,7 +19,7 @@ class TestLangComplex extends \PHPUnit\Framework\TestCase {
|
||||||
$this->l->set("ja");
|
$this->l->set("ja");
|
||||||
$this->assertArrayNotHasKey('Test.absentText', $this->l->dump());
|
$this->assertArrayNotHasKey('Test.absentText', $this->l->dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends testLazyLoad
|
* @depends testLazyLoad
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +29,7 @@ class TestLangComplex extends \PHPUnit\Framework\TestCase {
|
||||||
$this->assertEquals("ja", $this->l->get());
|
$this->assertEquals("ja", $this->l->get());
|
||||||
$this->assertEquals("en", $this->l->get(true));
|
$this->assertEquals("en", $this->l->get(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadCascadeOfFiles() {
|
function testLoadCascadeOfFiles() {
|
||||||
$this->l->set("ja", true);
|
$this->l->set("ja", true);
|
||||||
$this->assertEquals("de", $this->l->set("de", true));
|
$this->assertEquals("de", $this->l->set("de", true));
|
||||||
|
@ -44,7 +44,7 @@ class TestLangComplex extends \PHPUnit\Framework\TestCase {
|
||||||
function testLoadSubtag() {
|
function testLoadSubtag() {
|
||||||
$this->assertEquals("en_ca", $this->l->set("en_ca", true));
|
$this->assertEquals("en_ca", $this->l->set("en_ca", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchAMessage() {
|
function testFetchAMessage() {
|
||||||
$this->l->set("de", true);
|
$this->l->set("de", true);
|
||||||
$this->assertEquals('und der Stein der Weisen', $this->l->msg('Test.presentText'));
|
$this->assertEquals('und der Stein der Weisen', $this->l->msg('Test.presentText'));
|
||||||
|
|
|
@ -10,161 +10,161 @@ use Phake;
|
||||||
class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
|
class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools;
|
use Test\Tools;
|
||||||
|
|
||||||
protected $h;
|
protected $h;
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
// create a mock user manager
|
// create a mock user manager
|
||||||
Data::$user = Phake::mock(User::class);
|
Data::$user = Phake::mock(User::class);
|
||||||
Phake::when(Data::$user)->authHTTP->thenReturn(true);
|
Phake::when(Data::$user)->authHTTP->thenReturn(true);
|
||||||
Data::$user->id = "john.doe@example.com";
|
Data::$user->id = "john.doe@example.com";
|
||||||
// create a mock database interface
|
// create a mock database interface
|
||||||
Data::$db = Phake::mock(Database::Class);
|
Data::$db = Phake::mock(Database::Class);
|
||||||
$this->h = new REST\NextCloudNews\V1_2();
|
$this->h = new REST\NextCloudNews\V1_2();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRespondToInvalidPaths() {
|
function testRespondToInvalidPaths() {
|
||||||
$errs = [
|
$errs = [
|
||||||
404 => [
|
404 => [
|
||||||
['GET', "/"],
|
['GET', "/"],
|
||||||
['PUT', "/"],
|
['PUT', "/"],
|
||||||
['POST', "/"],
|
['POST', "/"],
|
||||||
['DELETE', "/"],
|
['DELETE', "/"],
|
||||||
['GET', "/folders/1/invalid"],
|
['GET', "/folders/1/invalid"],
|
||||||
['PUT', "/folders/1/invalid"],
|
['PUT', "/folders/1/invalid"],
|
||||||
['POST', "/folders/1/invalid"],
|
['POST', "/folders/1/invalid"],
|
||||||
['DELETE', "/folders/1/invalid"],
|
['DELETE', "/folders/1/invalid"],
|
||||||
['GET', "/version/invalid"],
|
['GET', "/version/invalid"],
|
||||||
['PUT', "/version/invalid"],
|
['PUT', "/version/invalid"],
|
||||||
['POST', "/version/invalid"],
|
['POST', "/version/invalid"],
|
||||||
['DELETE', "/version/invalid"],
|
['DELETE', "/version/invalid"],
|
||||||
],
|
],
|
||||||
405 => [
|
405 => [
|
||||||
'GET' => [
|
'GET' => [
|
||||||
['PUT', "/version"],
|
['PUT', "/version"],
|
||||||
['POST', "/version"],
|
['POST', "/version"],
|
||||||
['DELETE', "/version"],
|
['DELETE', "/version"],
|
||||||
],
|
],
|
||||||
'GET, POST' => [
|
'GET, POST' => [
|
||||||
['PUT', "/folders"],
|
['PUT', "/folders"],
|
||||||
['DELETE', "/folders"],
|
['DELETE', "/folders"],
|
||||||
],
|
],
|
||||||
'PUT, DELETE' => [
|
'PUT, DELETE' => [
|
||||||
['GET', "/folders/1"],
|
['GET', "/folders/1"],
|
||||||
['POST', "/folders/1"],
|
['POST', "/folders/1"],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
foreach($errs[404] as $req) {
|
foreach($errs[404] as $req) {
|
||||||
$exp = new Response(404);
|
$exp = new Response(404);
|
||||||
list($method, $path) = $req;
|
list($method, $path) = $req;
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 404.");
|
$this->assertEquals($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 404.");
|
||||||
}
|
}
|
||||||
foreach($errs[405] as $allow => $cases) {
|
foreach($errs[405] as $allow => $cases) {
|
||||||
$exp = new Response(405, "", "", ['Allow: '.$allow]);
|
$exp = new Response(405, "", "", ['Allow: '.$allow]);
|
||||||
foreach($cases as $req) {
|
foreach($cases as $req) {
|
||||||
list($method, $path) = $req;
|
list($method, $path) = $req;
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 405.");
|
$this->assertEquals($exp, $this->h->dispatch(new Request($method, $path)), "$method call to $path did not return 405.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListFolders() {
|
function testListFolders() {
|
||||||
$list = [
|
$list = [
|
||||||
['id' => 1, 'name' => "Software", 'parent' => null],
|
['id' => 1, 'name' => "Software", 'parent' => null],
|
||||||
['id' => 12, 'name' => "Hardware", 'parent' => null],
|
['id' => 12, 'name' => "Hardware", 'parent' => null],
|
||||||
];
|
];
|
||||||
Phake::when(Data::$db)->folderList(Data::$user->id, null, false)->thenReturn(new Result($list));
|
Phake::when(Data::$db)->folderList(Data::$user->id, null, false)->thenReturn(new Result($list));
|
||||||
$exp = new Response(200, ['folders' => $list]);
|
$exp = new Response(200, ['folders' => $list]);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/folders")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/folders")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddAFolder() {
|
function testAddAFolder() {
|
||||||
$in = [
|
$in = [
|
||||||
["name" => "Software"],
|
["name" => "Software"],
|
||||||
["name" => "Hardware"],
|
["name" => "Hardware"],
|
||||||
];
|
];
|
||||||
$out = [
|
$out = [
|
||||||
['id' => 1, 'name' => "Software", 'parent' => null],
|
['id' => 1, 'name' => "Software", 'parent' => null],
|
||||||
['id' => 2, 'name' => "Hardware", 'parent' => null],
|
['id' => 2, 'name' => "Hardware", 'parent' => null],
|
||||||
];
|
];
|
||||||
// set of various mocks for testing
|
// set of various mocks for testing
|
||||||
Phake::when(Data::$db)->folderAdd(Data::$user->id, $in[0])->thenReturn(1)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation")); // error on the second call
|
Phake::when(Data::$db)->folderAdd(Data::$user->id, $in[0])->thenReturn(1)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation")); // error on the second call
|
||||||
Phake::when(Data::$db)->folderAdd(Data::$user->id, $in[1])->thenReturn(2)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation")); // error on the second call
|
Phake::when(Data::$db)->folderAdd(Data::$user->id, $in[1])->thenReturn(2)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation")); // error on the second call
|
||||||
Phake::when(Data::$db)->folderPropertiesGet(Data::$user->id, 1)->thenReturn($out[0]);
|
Phake::when(Data::$db)->folderPropertiesGet(Data::$user->id, 1)->thenReturn($out[0]);
|
||||||
Phake::when(Data::$db)->folderPropertiesGet(Data::$user->id, 2)->thenReturn($out[1]);
|
Phake::when(Data::$db)->folderPropertiesGet(Data::$user->id, 2)->thenReturn($out[1]);
|
||||||
// set up mocks that produce errors
|
// set up mocks that produce errors
|
||||||
Phake::when(Data::$db)->folderAdd(Data::$user->id, [])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
|
Phake::when(Data::$db)->folderAdd(Data::$user->id, [])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
|
||||||
Phake::when(Data::$db)->folderAdd(Data::$user->id, ['name' => ""])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
|
Phake::when(Data::$db)->folderAdd(Data::$user->id, ['name' => ""])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
|
||||||
Phake::when(Data::$db)->folderAdd(Data::$user->id, ['name' => " "])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("whitespace"));
|
Phake::when(Data::$db)->folderAdd(Data::$user->id, ['name' => " "])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("whitespace"));
|
||||||
// correctly add two folders, using different means
|
// correctly add two folders, using different means
|
||||||
$exp = new Response(200, ['folders' => [$out[0]]]);
|
$exp = new Response(200, ['folders' => [$out[0]]]);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[0]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[0]), 'application/json')));
|
||||||
$exp = new Response(200, ['folders' => [$out[1]]]);
|
$exp = new Response(200, ['folders' => [$out[1]]]);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders?name=Hardware")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders?name=Hardware")));
|
||||||
Phake::verify(Data::$db)->folderAdd(Data::$user->id, $in[0]);
|
Phake::verify(Data::$db)->folderAdd(Data::$user->id, $in[0]);
|
||||||
Phake::verify(Data::$db)->folderAdd(Data::$user->id, $in[1]);
|
Phake::verify(Data::$db)->folderAdd(Data::$user->id, $in[1]);
|
||||||
Phake::verify(Data::$db)->folderPropertiesGet(Data::$user->id, 1);
|
Phake::verify(Data::$db)->folderPropertiesGet(Data::$user->id, 1);
|
||||||
Phake::verify(Data::$db)->folderPropertiesGet(Data::$user->id, 2);
|
Phake::verify(Data::$db)->folderPropertiesGet(Data::$user->id, 2);
|
||||||
// test bad folder names
|
// test bad folder names
|
||||||
$exp = new Response(422);
|
$exp = new Response(422);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders")));
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", '{"name":""}', 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", '{"name":""}', 'application/json')));
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", '{"name":" "}', 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", '{"name":" "}', 'application/json')));
|
||||||
// try adding the same two folders again
|
// try adding the same two folders again
|
||||||
$exp = new Response(409);
|
$exp = new Response(409);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders?name=Software")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders?name=Software")));
|
||||||
$exp = new Response(409);
|
$exp = new Response(409);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[1]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("POST", "/folders", json_encode($in[1]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAFolder() {
|
function testRemoveAFolder() {
|
||||||
Phake::when(Data::$db)->folderRemove(Data::$user->id, 1)->thenReturn(true)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing"));
|
Phake::when(Data::$db)->folderRemove(Data::$user->id, 1)->thenReturn(true)->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing"));
|
||||||
$exp = new Response(204);
|
$exp = new Response(204);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
||||||
// fail on the second invocation because it no longer exists
|
// fail on the second invocation because it no longer exists
|
||||||
$exp = new Response(404);
|
$exp = new Response(404);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/1")));
|
||||||
Phake::verify(Data::$db, Phake::times(2))->folderRemove(Data::$user->id, 1);
|
Phake::verify(Data::$db, Phake::times(2))->folderRemove(Data::$user->id, 1);
|
||||||
// use a non-integer folder ID
|
// use a non-integer folder ID
|
||||||
$exp = new Response(404);
|
$exp = new Response(404);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/invalid")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("DELETE", "/folders/invalid")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRenameAFolder() {
|
function testRenameAFolder() {
|
||||||
$in = [
|
$in = [
|
||||||
["name" => "Software"],
|
["name" => "Software"],
|
||||||
["name" => "Software"],
|
["name" => "Software"],
|
||||||
["name" => ""],
|
["name" => ""],
|
||||||
["name" => " "],
|
["name" => " "],
|
||||||
[],
|
[],
|
||||||
];
|
];
|
||||||
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[0])->thenReturn(true);
|
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[0])->thenReturn(true);
|
||||||
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 2, $in[1])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation"));
|
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 2, $in[1])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("constraintViolation"));
|
||||||
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[2])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
|
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[2])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("missing"));
|
||||||
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[3])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("whitespace"));
|
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[3])->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("whitespace"));
|
||||||
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[4])->thenReturn(true); // this should be stopped by the handler before the request gets to the database
|
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 1, $in[4])->thenReturn(true); // this should be stopped by the handler before the request gets to the database
|
||||||
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 3, $this->anything())->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing")); // folder ID 3 does not exist
|
Phake::when(Data::$db)->folderPropertiesSet(Data::$user->id, 3, $this->anything())->thenThrow(new \JKingWeb\Arsse\Db\ExceptionInput("idMissing")); // folder ID 3 does not exist
|
||||||
$exp = new Response(204);
|
$exp = new Response(204);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[0]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[0]), 'application/json')));
|
||||||
$exp = new Response(409);
|
$exp = new Response(409);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/2", json_encode($in[1]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/2", json_encode($in[1]), 'application/json')));
|
||||||
$exp = new Response(422);
|
$exp = new Response(422);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[2]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[2]), 'application/json')));
|
||||||
$exp = new Response(422);
|
$exp = new Response(422);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[3]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[3]), 'application/json')));
|
||||||
$exp = new Response(422);
|
$exp = new Response(422);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[4]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1", json_encode($in[4]), 'application/json')));
|
||||||
$exp = new Response(404);
|
$exp = new Response(404);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/3", json_encode($in[0]), 'application/json')));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/3", json_encode($in[0]), 'application/json')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRetrieveServerVersion() {
|
function testRetrieveServerVersion() {
|
||||||
$exp = new Response(200, ['version' => \JKingWeb\Arsse\VERSION]);
|
$exp = new Response(200, ['version' => \JKingWeb\Arsse\VERSION]);
|
||||||
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/version")));
|
$this->assertEquals($exp, $this->h->dispatch(new Request("GET", "/version")));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,37 +8,37 @@ use JKingWeb\Arsse\Rest\Response;
|
||||||
class TestNCNVersionDiscovery extends \PHPUnit\Framework\TestCase {
|
class TestNCNVersionDiscovery extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools;
|
use Test\Tools;
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testFetchVersionList() {
|
function testFetchVersionList() {
|
||||||
$exp = new Response(200, ['apiLevels' => ['v1-2']]);
|
$exp = new Response(200, ['apiLevels' => ['v1-2']]);
|
||||||
$h = new Rest\NextCloudNews\Versions();
|
$h = new Rest\NextCloudNews\Versions();
|
||||||
$req = new Request("GET", "/");
|
$req = new Request("GET", "/");
|
||||||
$res = $h->dispatch($req);
|
$res = $h->dispatch($req);
|
||||||
$this->assertEquals($exp, $res);
|
$this->assertEquals($exp, $res);
|
||||||
$req = new Request("GET", "");
|
$req = new Request("GET", "");
|
||||||
$res = $h->dispatch($req);
|
$res = $h->dispatch($req);
|
||||||
$this->assertEquals($exp, $res);
|
$this->assertEquals($exp, $res);
|
||||||
$req = new Request("GET", "/?id=1827");
|
$req = new Request("GET", "/?id=1827");
|
||||||
$res = $h->dispatch($req);
|
$res = $h->dispatch($req);
|
||||||
$this->assertEquals($exp, $res);
|
$this->assertEquals($exp, $res);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUseIncorrectMethod() {
|
function testUseIncorrectMethod() {
|
||||||
$exp = new Response(405);
|
$exp = new Response(405);
|
||||||
$h = new Rest\NextCloudNews\Versions();
|
$h = new Rest\NextCloudNews\Versions();
|
||||||
$req = new Request("POST", "/");
|
$req = new Request("POST", "/");
|
||||||
$res = $h->dispatch($req);
|
$res = $h->dispatch($req);
|
||||||
$this->assertEquals($exp, $res);
|
$this->assertEquals($exp, $res);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUseIncorrectPath() {
|
function testUseIncorrectPath() {
|
||||||
$exp = new Response(404);
|
$exp = new Response(404);
|
||||||
$h = new Rest\NextCloudNews\Versions();
|
$h = new Rest\NextCloudNews\Versions();
|
||||||
$req = new Request("GET", "/ook");
|
$req = new Request("GET", "/ook");
|
||||||
$res = $h->dispatch($req);
|
$res = $h->dispatch($req);
|
||||||
$this->assertEquals($exp, $res);
|
$this->assertEquals($exp, $res);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,297 +5,297 @@ namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
class TestAuthorization extends \PHPUnit\Framework\TestCase {
|
class TestAuthorization extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools;
|
use Test\Tools;
|
||||||
|
|
||||||
const USERS = [
|
|
||||||
'user@example.com' => User\Driver::RIGHTS_NONE,
|
|
||||||
'user@example.org' => User\Driver::RIGHTS_NONE,
|
|
||||||
'dman@example.com' => User\Driver::RIGHTS_DOMAIN_MANAGER,
|
|
||||||
'dman@example.org' => User\Driver::RIGHTS_DOMAIN_MANAGER,
|
|
||||||
'dadm@example.com' => User\Driver::RIGHTS_DOMAIN_ADMIN,
|
|
||||||
'dadm@example.org' => User\Driver::RIGHTS_DOMAIN_ADMIN,
|
|
||||||
'gman@example.com' => User\Driver::RIGHTS_GLOBAL_MANAGER,
|
|
||||||
'gman@example.org' => User\Driver::RIGHTS_GLOBAL_MANAGER,
|
|
||||||
'gadm@example.com' => User\Driver::RIGHTS_GLOBAL_ADMIN,
|
|
||||||
'gadm@example.org' => User\Driver::RIGHTS_GLOBAL_ADMIN,
|
|
||||||
// invalid rights levels
|
|
||||||
'bad1@example.com' => User\Driver::RIGHTS_NONE+1,
|
|
||||||
'bad1@example.org' => User\Driver::RIGHTS_NONE+1,
|
|
||||||
'bad2@example.com' => User\Driver::RIGHTS_DOMAIN_MANAGER+1,
|
|
||||||
'bad2@example.org' => User\Driver::RIGHTS_DOMAIN_MANAGER+1,
|
|
||||||
'bad3@example.com' => User\Driver::RIGHTS_DOMAIN_ADMIN+1,
|
|
||||||
'bad3@example.org' => User\Driver::RIGHTS_DOMAIN_ADMIN+1,
|
|
||||||
'bad4@example.com' => User\Driver::RIGHTS_GLOBAL_MANAGER+1,
|
|
||||||
'bad4@example.org' => User\Driver::RIGHTS_GLOBAL_MANAGER+1,
|
|
||||||
'bad5@example.com' => User\Driver::RIGHTS_GLOBAL_ADMIN+1,
|
|
||||||
'bad5@example.org' => User\Driver::RIGHTS_GLOBAL_ADMIN+1,
|
|
||||||
|
|
||||||
];
|
const USERS = [
|
||||||
const LEVELS = [
|
'user@example.com' => User\Driver::RIGHTS_NONE,
|
||||||
User\Driver::RIGHTS_NONE,
|
'user@example.org' => User\Driver::RIGHTS_NONE,
|
||||||
User\Driver::RIGHTS_DOMAIN_MANAGER,
|
'dman@example.com' => User\Driver::RIGHTS_DOMAIN_MANAGER,
|
||||||
User\Driver::RIGHTS_DOMAIN_ADMIN,
|
'dman@example.org' => User\Driver::RIGHTS_DOMAIN_MANAGER,
|
||||||
User\Driver::RIGHTS_GLOBAL_MANAGER,
|
'dadm@example.com' => User\Driver::RIGHTS_DOMAIN_ADMIN,
|
||||||
User\Driver::RIGHTS_GLOBAL_ADMIN,
|
'dadm@example.org' => User\Driver::RIGHTS_DOMAIN_ADMIN,
|
||||||
];
|
'gman@example.com' => User\Driver::RIGHTS_GLOBAL_MANAGER,
|
||||||
const DOMAINS = [
|
'gman@example.org' => User\Driver::RIGHTS_GLOBAL_MANAGER,
|
||||||
'@example.com',
|
'gadm@example.com' => User\Driver::RIGHTS_GLOBAL_ADMIN,
|
||||||
'@example.org',
|
'gadm@example.org' => User\Driver::RIGHTS_GLOBAL_ADMIN,
|
||||||
"",
|
// invalid rights levels
|
||||||
];
|
'bad1@example.com' => User\Driver::RIGHTS_NONE+1,
|
||||||
|
'bad1@example.org' => User\Driver::RIGHTS_NONE+1,
|
||||||
|
'bad2@example.com' => User\Driver::RIGHTS_DOMAIN_MANAGER+1,
|
||||||
|
'bad2@example.org' => User\Driver::RIGHTS_DOMAIN_MANAGER+1,
|
||||||
|
'bad3@example.com' => User\Driver::RIGHTS_DOMAIN_ADMIN+1,
|
||||||
|
'bad3@example.org' => User\Driver::RIGHTS_DOMAIN_ADMIN+1,
|
||||||
|
'bad4@example.com' => User\Driver::RIGHTS_GLOBAL_MANAGER+1,
|
||||||
|
'bad4@example.org' => User\Driver::RIGHTS_GLOBAL_MANAGER+1,
|
||||||
|
'bad5@example.com' => User\Driver::RIGHTS_GLOBAL_ADMIN+1,
|
||||||
|
'bad5@example.org' => User\Driver::RIGHTS_GLOBAL_ADMIN+1,
|
||||||
|
|
||||||
protected $data;
|
];
|
||||||
|
const LEVELS = [
|
||||||
|
User\Driver::RIGHTS_NONE,
|
||||||
|
User\Driver::RIGHTS_DOMAIN_MANAGER,
|
||||||
|
User\Driver::RIGHTS_DOMAIN_ADMIN,
|
||||||
|
User\Driver::RIGHTS_GLOBAL_MANAGER,
|
||||||
|
User\Driver::RIGHTS_GLOBAL_ADMIN,
|
||||||
|
];
|
||||||
|
const DOMAINS = [
|
||||||
|
'@example.com',
|
||||||
|
'@example.org',
|
||||||
|
"",
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $data;
|
||||||
|
|
||||||
function setUp(string $drv = Test\User\DriverInternalMock::class, string $db = null) {
|
function setUp(string $drv = Test\User\DriverInternalMock::class, string $db = null) {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->userDriver = $drv;
|
$conf->userDriver = $drv;
|
||||||
$conf->userAuthPreferHTTP = true;
|
$conf->userAuthPreferHTTP = true;
|
||||||
$conf->userComposeNames = true;
|
$conf->userComposeNames = true;
|
||||||
Data::$conf = $conf;
|
Data::$conf = $conf;
|
||||||
if($db !== null) {
|
if($db !== null) {
|
||||||
Data::$db = new $db();
|
Data::$db = new $db();
|
||||||
}
|
}
|
||||||
Data::$user = new User();
|
Data::$user = new User();
|
||||||
Data::$user->authorizationEnabled(false);
|
Data::$user->authorizationEnabled(false);
|
||||||
foreach(self::USERS as $user => $level) {
|
foreach(self::USERS as $user => $level) {
|
||||||
Data::$user->add($user, "");
|
Data::$user->add($user, "");
|
||||||
Data::$user->rightsSet($user, $level);
|
Data::$user->rightsSet($user, $level);
|
||||||
}
|
}
|
||||||
Data::$user->authorizationEnabled(true);
|
Data::$user->authorizationEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSelfActionLogic() {
|
function testSelfActionLogic() {
|
||||||
foreach(array_keys(self::USERS) as $user) {
|
foreach(array_keys(self::USERS) as $user) {
|
||||||
Data::$user->auth($user, "");
|
Data::$user->auth($user, "");
|
||||||
// users should be able to do basic actions for themselves
|
// users should be able to do basic actions for themselves
|
||||||
$this->assertTrue(Data::$user->authorize($user, "userExists"), "User $user could not act for themselves.");
|
$this->assertTrue(Data::$user->authorize($user, "userExists"), "User $user could not act for themselves.");
|
||||||
$this->assertTrue(Data::$user->authorize($user, "userRemove"), "User $user could not act for themselves.");
|
$this->assertTrue(Data::$user->authorize($user, "userRemove"), "User $user could not act for themselves.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRegularUserLogic() {
|
function testRegularUserLogic() {
|
||||||
foreach(self::USERS as $actor => $rights) {
|
foreach(self::USERS as $actor => $rights) {
|
||||||
if($rights != User\Driver::RIGHTS_NONE) continue;
|
if($rights != User\Driver::RIGHTS_NONE) continue;
|
||||||
Data::$user->auth($actor, "");
|
Data::$user->auth($actor, "");
|
||||||
foreach(array_keys(self::USERS) as $affected) {
|
foreach(array_keys(self::USERS) as $affected) {
|
||||||
// regular users should only be able to act for themselves
|
// regular users should only be able to act for themselves
|
||||||
if($actor==$affected) {
|
if($actor==$affected) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
}
|
}
|
||||||
// they should never be able to set rights
|
// they should never be able to set rights
|
||||||
foreach(self::LEVELS as $level) {
|
foreach(self::LEVELS as $level) {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// they should not be able to list users
|
// they should not be able to list users
|
||||||
foreach(self::DOMAINS as $domain) {
|
foreach(self::DOMAINS as $domain) {
|
||||||
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDomainManagerLogic() {
|
function testDomainManagerLogic() {
|
||||||
foreach(self::USERS as $actor => $actorRights) {
|
foreach(self::USERS as $actor => $actorRights) {
|
||||||
if($actorRights != User\Driver::RIGHTS_DOMAIN_MANAGER) continue;
|
if($actorRights != User\Driver::RIGHTS_DOMAIN_MANAGER) continue;
|
||||||
$actorDomain = substr($actor,strrpos($actor,"@")+1);
|
$actorDomain = substr($actor,strrpos($actor,"@")+1);
|
||||||
Data::$user->auth($actor, "");
|
Data::$user->auth($actor, "");
|
||||||
foreach(self::USERS as $affected => $affectedRights) {
|
foreach(self::USERS as $affected => $affectedRights) {
|
||||||
$affectedDomain = substr($affected,strrpos($affected,"@")+1);
|
$affectedDomain = substr($affected,strrpos($affected,"@")+1);
|
||||||
// domain managers should be able to check any user on the same domain
|
// domain managers should be able to check any user on the same domain
|
||||||
if($actorDomain==$affectedDomain) {
|
if($actorDomain==$affectedDomain) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
}
|
}
|
||||||
// they should only be able to act for regular users on the same domain
|
// they should only be able to act for regular users on the same domain
|
||||||
if($actor==$affected || ($actorDomain==$affectedDomain && $affectedRights==User\Driver::RIGHTS_NONE)) {
|
if($actor==$affected || ($actorDomain==$affectedDomain && $affectedRights==User\Driver::RIGHTS_NONE)) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
}
|
}
|
||||||
// and they should only be able to set their own rights to regular user
|
// and they should only be able to set their own rights to regular user
|
||||||
foreach(self::LEVELS as $level) {
|
foreach(self::LEVELS as $level) {
|
||||||
if($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_DOMAIN_MANAGER])) {
|
if($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_DOMAIN_MANAGER])) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// they should also be able to list all users on their own domain
|
// they should also be able to list all users on their own domain
|
||||||
foreach(self::DOMAINS as $domain) {
|
foreach(self::DOMAINS as $domain) {
|
||||||
if($domain=="@".$actorDomain) {
|
if($domain=="@".$actorDomain) {
|
||||||
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDomainAdministratorLogic() {
|
function testDomainAdministratorLogic() {
|
||||||
foreach(self::USERS as $actor => $actorRights) {
|
foreach(self::USERS as $actor => $actorRights) {
|
||||||
if($actorRights != User\Driver::RIGHTS_DOMAIN_ADMIN) continue;
|
if($actorRights != User\Driver::RIGHTS_DOMAIN_ADMIN) continue;
|
||||||
$actorDomain = substr($actor,strrpos($actor,"@")+1);
|
$actorDomain = substr($actor,strrpos($actor,"@")+1);
|
||||||
Data::$user->auth($actor, "");
|
Data::$user->auth($actor, "");
|
||||||
$allowed = [User\Driver::RIGHTS_NONE,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN];
|
$allowed = [User\Driver::RIGHTS_NONE,User\Driver::RIGHTS_DOMAIN_MANAGER,User\Driver::RIGHTS_DOMAIN_ADMIN];
|
||||||
foreach(self::USERS as $affected => $affectedRights) {
|
foreach(self::USERS as $affected => $affectedRights) {
|
||||||
$affectedDomain = substr($affected,strrpos($affected,"@")+1);
|
$affectedDomain = substr($affected,strrpos($affected,"@")+1);
|
||||||
// domain admins should be able to check any user on the same domain
|
// domain admins should be able to check any user on the same domain
|
||||||
if($actorDomain==$affectedDomain) {
|
if($actorDomain==$affectedDomain) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
}
|
}
|
||||||
// they should be able to act for any user on the same domain who is not a global manager or admin
|
// they should be able to act for any user on the same domain who is not a global manager or admin
|
||||||
if($actorDomain==$affectedDomain && in_array($affectedRights, $allowed)) {
|
if($actorDomain==$affectedDomain && in_array($affectedRights, $allowed)) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
}
|
}
|
||||||
// they should be able to set rights for any user on their domain who is not a global manager or admin, up to domain admin level
|
// they should be able to set rights for any user on their domain who is not a global manager or admin, up to domain admin level
|
||||||
foreach(self::LEVELS as $level) {
|
foreach(self::LEVELS as $level) {
|
||||||
if($actorDomain==$affectedDomain && in_array($affectedRights, $allowed) && in_array($level, $allowed)) {
|
if($actorDomain==$affectedDomain && in_array($affectedRights, $allowed) && in_array($level, $allowed)) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// they should also be able to list all users on their own domain
|
// they should also be able to list all users on their own domain
|
||||||
foreach(self::DOMAINS as $domain) {
|
foreach(self::DOMAINS as $domain) {
|
||||||
if($domain=="@".$actorDomain) {
|
if($domain=="@".$actorDomain) {
|
||||||
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGlobalManagerLogic() {
|
function testGlobalManagerLogic() {
|
||||||
foreach(self::USERS as $actor => $actorRights) {
|
foreach(self::USERS as $actor => $actorRights) {
|
||||||
if($actorRights != User\Driver::RIGHTS_GLOBAL_MANAGER) continue;
|
if($actorRights != User\Driver::RIGHTS_GLOBAL_MANAGER) continue;
|
||||||
$actorDomain = substr($actor,strrpos($actor,"@")+1);
|
$actorDomain = substr($actor,strrpos($actor,"@")+1);
|
||||||
Data::$user->auth($actor, "");
|
Data::$user->auth($actor, "");
|
||||||
foreach(self::USERS as $affected => $affectedRights) {
|
foreach(self::USERS as $affected => $affectedRights) {
|
||||||
$affectedDomain = substr($affected,strrpos($affected,"@")+1);
|
$affectedDomain = substr($affected,strrpos($affected,"@")+1);
|
||||||
// global managers should be able to check any user
|
// global managers should be able to check any user
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
// they should only be able to act for regular users
|
// they should only be able to act for regular users
|
||||||
if($actor==$affected || $affectedRights==User\Driver::RIGHTS_NONE) {
|
if($actor==$affected || $affectedRights==User\Driver::RIGHTS_NONE) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
}
|
}
|
||||||
// and they should only be able to set their own rights to regular user
|
// and they should only be able to set their own rights to regular user
|
||||||
foreach(self::LEVELS as $level) {
|
foreach(self::LEVELS as $level) {
|
||||||
if($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_GLOBAL_MANAGER])) {
|
if($actor==$affected && in_array($level, [User\Driver::RIGHTS_NONE, User\Driver::RIGHTS_GLOBAL_MANAGER])) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// they should also be able to list all users
|
// they should also be able to list all users
|
||||||
foreach(self::DOMAINS as $domain) {
|
foreach(self::DOMAINS as $domain) {
|
||||||
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGlobalAdministratorLogic() {
|
function testGlobalAdministratorLogic() {
|
||||||
foreach(self::USERS as $actor => $actorRights) {
|
foreach(self::USERS as $actor => $actorRights) {
|
||||||
if($actorRights != User\Driver::RIGHTS_GLOBAL_ADMIN) continue;
|
if($actorRights != User\Driver::RIGHTS_GLOBAL_ADMIN) continue;
|
||||||
Data::$user->auth($actor, "");
|
Data::$user->auth($actor, "");
|
||||||
// global admins can do anything
|
// global admins can do anything
|
||||||
foreach(self::USERS as $affected => $affectedRights) {
|
foreach(self::USERS as $affected => $affectedRights) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
foreach(self::LEVELS as $level) {
|
foreach(self::LEVELS as $level) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted properly for $affected settings rights level $level, but the action was denied.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach(self::DOMAINS as $domain) {
|
foreach(self::DOMAINS as $domain) {
|
||||||
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($domain, "userList"), "User $actor properly checked user list for domain '$domain', but the action was denied.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInvalidLevelLogic() {
|
function testInvalidLevelLogic() {
|
||||||
foreach(self::USERS as $actor => $rights) {
|
foreach(self::USERS as $actor => $rights) {
|
||||||
if(in_array($rights, self::LEVELS)) continue;
|
if(in_array($rights, self::LEVELS)) continue;
|
||||||
Data::$user->auth($actor, "");
|
Data::$user->auth($actor, "");
|
||||||
foreach(array_keys(self::USERS) as $affected) {
|
foreach(array_keys(self::USERS) as $affected) {
|
||||||
// users with unknown/invalid rights should be treated just like regular users and only be able to act for themselves
|
// users with unknown/invalid rights should be treated just like regular users and only be able to act for themselves
|
||||||
if($actor==$affected) {
|
if($actor==$affected) {
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userExists"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
$this->assertTrue(Data::$user->authorize($affected, "userRemove"), "User $actor acted properly for $affected, but the action was denied.");
|
||||||
} else {
|
} else {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userExists"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRemove"), "User $actor acted improperly for $affected, but the action was allowed.");
|
||||||
}
|
}
|
||||||
// they should never be able to set rights
|
// they should never be able to set rights
|
||||||
foreach(self::LEVELS as $level) {
|
foreach(self::LEVELS as $level) {
|
||||||
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($affected, "userRightsSet", $level), "User $actor acted improperly for $affected settings rights level $level, but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// they should not be able to list users
|
// they should not be able to list users
|
||||||
foreach(self::DOMAINS as $domain) {
|
foreach(self::DOMAINS as $domain) {
|
||||||
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
$this->assertFalse(Data::$user->authorize($domain, "userList"), "User $actor improperly checked user list for domain '$domain', but the action was allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInternalExceptionLogic() {
|
function testInternalExceptionLogic() {
|
||||||
$tests = [
|
$tests = [
|
||||||
// methods of User class to test, with parameters besides affected user
|
// methods of User class to test, with parameters besides affected user
|
||||||
'exists' => [],
|
'exists' => [],
|
||||||
'remove' => [],
|
'remove' => [],
|
||||||
'add' => [''],
|
'add' => [''],
|
||||||
'passwordSet' => [''],
|
'passwordSet' => [''],
|
||||||
'propertiesGet' => [],
|
'propertiesGet' => [],
|
||||||
'propertiesSet' => [[]],
|
'propertiesSet' => [[]],
|
||||||
'rightsGet' => [],
|
'rightsGet' => [],
|
||||||
'rightsSet' => [User\Driver::RIGHTS_GLOBAL_ADMIN],
|
'rightsSet' => [User\Driver::RIGHTS_GLOBAL_ADMIN],
|
||||||
'list' => [],
|
'list' => [],
|
||||||
];
|
];
|
||||||
// try first with a global admin (there should be no exception)
|
// try first with a global admin (there should be no exception)
|
||||||
Data::$user->auth("gadm@example.com", "");
|
Data::$user->auth("gadm@example.com", "");
|
||||||
$this->assertCount(0, $this->checkExceptions("user@example.org", $tests));
|
$this->assertCount(0, $this->checkExceptions("user@example.org", $tests));
|
||||||
// next try with a regular user acting on another user (everything should fail)
|
// next try with a regular user acting on another user (everything should fail)
|
||||||
Data::$user->auth("user@example.com", "");
|
Data::$user->auth("user@example.com", "");
|
||||||
$this->assertCount(sizeof($tests), $this->checkExceptions("user@example.org", $tests));
|
$this->assertCount(sizeof($tests), $this->checkExceptions("user@example.org", $tests));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExternalExceptionLogic() {
|
function testExternalExceptionLogic() {
|
||||||
// set up the test for an external driver
|
// set up the test for an external driver
|
||||||
$this->setUp(Test\User\DriverExternalMock::class, Test\User\Database::class);
|
$this->setUp(Test\User\DriverExternalMock::class, Test\User\Database::class);
|
||||||
// run the previous test with the external driver set up
|
// run the previous test with the external driver set up
|
||||||
$this->testInternalExceptionLogic();
|
$this->testInternalExceptionLogic();
|
||||||
}
|
}
|
||||||
|
|
||||||
// meat of testInternalExceptionLogic and testExternalExceptionLogic
|
// meat of testInternalExceptionLogic and testExternalExceptionLogic
|
||||||
// calls each requested function with supplied arguments, catches authorization exceptions, and returns an array of caught failed calls
|
// calls each requested function with supplied arguments, catches authorization exceptions, and returns an array of caught failed calls
|
||||||
protected function checkExceptions(string $user, $tests): array {
|
protected function checkExceptions(string $user, $tests): array {
|
||||||
$err = [];
|
$err = [];
|
||||||
foreach($tests as $func => $args) {
|
foreach($tests as $func => $args) {
|
||||||
// list method does not take an affected user, so do not unshift for that one
|
// list method does not take an affected user, so do not unshift for that one
|
||||||
if($func != "list") array_unshift($args, $user);
|
if($func != "list") array_unshift($args, $user);
|
||||||
try {
|
try {
|
||||||
call_user_func_array(array(Data::$user, $func), $args);
|
call_user_func_array(array(Data::$user, $func), $args);
|
||||||
} catch(User\ExceptionAuthz $e) {
|
} catch(User\ExceptionAuthz $e) {
|
||||||
$err[] = $func;
|
$err[] = $func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $err;
|
return $err;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,9 +5,9 @@ namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
class TestUserInternalDriver extends \PHPUnit\Framework\TestCase {
|
class TestUserInternalDriver extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools, Test\User\CommonTests;
|
use Test\Tools, Test\User\CommonTests;
|
||||||
|
|
||||||
const USER1 = "john.doe@example.com";
|
|
||||||
const USER2 = "jane.doe@example.com";
|
|
||||||
|
|
||||||
public $drv = User\Internal\Driver::class;
|
const USER1 = "john.doe@example.com";
|
||||||
|
const USER2 = "jane.doe@example.com";
|
||||||
|
|
||||||
|
public $drv = User\Internal\Driver::class;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
class TestUserMockExternal extends \PHPUnit\Framework\TestCase {
|
class TestUserMockExternal extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools, Test\User\CommonTests;
|
use Test\Tools, Test\User\CommonTests;
|
||||||
|
|
||||||
const USER1 = "john.doe@example.com";
|
|
||||||
const USER2 = "jane.doe@example.com";
|
|
||||||
|
|
||||||
public $drv = Test\User\DriverExternalMock::class;
|
const USER1 = "john.doe@example.com";
|
||||||
|
const USER2 = "jane.doe@example.com";
|
||||||
|
|
||||||
|
public $drv = Test\User\DriverExternalMock::class;
|
||||||
}
|
}
|
|
@ -5,13 +5,13 @@ namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
class TestUserMockInternal extends \PHPUnit\Framework\TestCase {
|
class TestUserMockInternal extends \PHPUnit\Framework\TestCase {
|
||||||
use Test\Tools, Test\User\CommonTests;
|
use Test\Tools, Test\User\CommonTests;
|
||||||
|
|
||||||
const USER1 = "john.doe@example.com";
|
|
||||||
const USER2 = "jane.doe@example.com";
|
|
||||||
|
|
||||||
public $drv = Test\User\DriverInternalMock::class;
|
const USER1 = "john.doe@example.com";
|
||||||
|
const USER2 = "jane.doe@example.com";
|
||||||
|
|
||||||
|
public $drv = Test\User\DriverInternalMock::class;
|
||||||
|
|
||||||
function setUpSeries() {
|
function setUpSeries() {
|
||||||
Data::$db = null;
|
Data::$db = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ use JKingWeb\Arsse\Database;
|
||||||
use Phake;
|
use Phake;
|
||||||
|
|
||||||
trait Setup {
|
trait Setup {
|
||||||
protected $drv;
|
protected $drv;
|
||||||
protected $data = [
|
protected $data = [
|
||||||
'arsse_users' => [
|
'arsse_users' => [
|
||||||
'columns' => [
|
'columns' => [
|
||||||
'id' => 'str',
|
'id' => 'str',
|
||||||
|
@ -32,7 +32,7 @@ trait Setup {
|
||||||
// create a default configuration
|
// create a default configuration
|
||||||
Data::$conf = new Conf();
|
Data::$conf = new Conf();
|
||||||
// configure and create the relevant database driver
|
// configure and create the relevant database driver
|
||||||
$this->setUpDriver();
|
$this->setUpDriver();
|
||||||
// create the database interface with the suitable driver
|
// create the database interface with the suitable driver
|
||||||
Data::$db = new Database($this->drv);
|
Data::$db = new Database($this->drv);
|
||||||
Data::$db->schemaUpdate();
|
Data::$db->schemaUpdate();
|
||||||
|
@ -43,77 +43,77 @@ trait Setup {
|
||||||
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
|
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
// call the additional teardiwn method if it exists
|
// call the additional teardiwn method if it exists
|
||||||
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
|
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
|
||||||
// clean up
|
// clean up
|
||||||
$this->drv = null;
|
$this->drv = null;
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function primeDatabase(array $data): bool {
|
function primeDatabase(array $data): bool {
|
||||||
$this->drv->begin();
|
$this->drv->begin();
|
||||||
foreach($data as $table => $info) {
|
foreach($data as $table => $info) {
|
||||||
$cols = implode(",", array_keys($info['columns']));
|
$cols = implode(",", array_keys($info['columns']));
|
||||||
$bindings = array_values($info['columns']);
|
$bindings = array_values($info['columns']);
|
||||||
$params = implode(",", array_fill(0, sizeof($info['columns']), "?"));
|
$params = implode(",", array_fill(0, sizeof($info['columns']), "?"));
|
||||||
$s = $this->drv->prepareArray("INSERT INTO $table($cols) values($params)", $bindings);
|
$s = $this->drv->prepareArray("INSERT INTO $table($cols) values($params)", $bindings);
|
||||||
foreach($info['rows'] as $row) {
|
foreach($info['rows'] as $row) {
|
||||||
$this->assertEquals(1, $s->runArray($row)->changes());
|
$this->assertEquals(1, $s->runArray($row)->changes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->drv->commit();
|
$this->drv->commit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareExpectations(array $expected): bool {
|
function compareExpectations(array $expected): bool {
|
||||||
foreach($expected as $table => $info) {
|
foreach($expected as $table => $info) {
|
||||||
$cols = implode(",", array_keys($info['columns']));
|
$cols = implode(",", array_keys($info['columns']));
|
||||||
$data = $this->drv->prepare("SELECT $cols from $table")->run()->getAll();
|
$data = $this->drv->prepare("SELECT $cols from $table")->run()->getAll();
|
||||||
$cols = array_keys($info['columns']);
|
$cols = array_keys($info['columns']);
|
||||||
foreach($info['rows'] as $index => $values) {
|
foreach($info['rows'] as $index => $values) {
|
||||||
$row = [];
|
$row = [];
|
||||||
foreach($values as $key => $value) {
|
foreach($values as $key => $value) {
|
||||||
$row[$cols[$key]] = $value;
|
$row[$cols[$key]] = $value;
|
||||||
}
|
}
|
||||||
$found = array_search($row, $data);
|
$found = array_search($row, $data);
|
||||||
$this->assertNotSame(false, $found, "Table $table does not contain record at array index $index.");
|
$this->assertNotSame(false, $found, "Table $table does not contain record at array index $index.");
|
||||||
unset($data[$found]);
|
unset($data[$found]);
|
||||||
}
|
}
|
||||||
$this->assertSame([], $data);
|
$this->assertSame([], $data);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function primeExpectations(array $source, array $tableSpecs = null): array {
|
function primeExpectations(array $source, array $tableSpecs = null): array {
|
||||||
$out = [];
|
$out = [];
|
||||||
foreach($tableSpecs as $table => $columns) {
|
foreach($tableSpecs as $table => $columns) {
|
||||||
if(!isset($source[$table])) {
|
if(!isset($source[$table])) {
|
||||||
$this->assertTrue(false, "Source for expectations does not contain requested table $table.");
|
$this->assertTrue(false, "Source for expectations does not contain requested table $table.");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
$out[$table] = [
|
$out[$table] = [
|
||||||
'columns' => [],
|
'columns' => [],
|
||||||
'rows' => [],
|
'rows' => [],
|
||||||
];
|
];
|
||||||
$transformations = [];
|
$transformations = [];
|
||||||
foreach($columns as $target => $col) {
|
foreach($columns as $target => $col) {
|
||||||
if(!isset($source[$table]['columns'][$col])) {
|
if(!isset($source[$table]['columns'][$col])) {
|
||||||
$this->assertTrue(false, "Source for expectations does not contain requested column $col of table $table.");
|
$this->assertTrue(false, "Source for expectations does not contain requested column $col of table $table.");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
$found = array_search($col, array_keys($source[$table]['columns']));
|
$found = array_search($col, array_keys($source[$table]['columns']));
|
||||||
$transformations[$found] = $target;
|
$transformations[$found] = $target;
|
||||||
$out[$table]['columns'][$col] = $source[$table]['columns'][$col];
|
$out[$table]['columns'][$col] = $source[$table]['columns'][$col];
|
||||||
}
|
}
|
||||||
foreach($source[$table]['rows'] as $sourceRow) {
|
foreach($source[$table]['rows'] as $sourceRow) {
|
||||||
$newRow = [];
|
$newRow = [];
|
||||||
foreach($transformations as $from => $to) {
|
foreach($transformations as $from => $to) {
|
||||||
$newRow[$to] = $sourceRow[$from];
|
$newRow[$to] = $sourceRow[$from];
|
||||||
}
|
}
|
||||||
$out[$table]['rows'][] = $newRow;
|
$out[$table]['rows'][] = $newRow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,219 +4,219 @@ namespace JKingWeb\Arsse\Test\Db;
|
||||||
use JKingWeb\Arsse\Db\Statement;
|
use JKingWeb\Arsse\Db\Statement;
|
||||||
|
|
||||||
trait BindingTests {
|
trait BindingTests {
|
||||||
function testBindNull() {
|
function testBindNull() {
|
||||||
$input = null;
|
$input = null;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => null,
|
"integer" => null,
|
||||||
"float" => null,
|
"float" => null,
|
||||||
"date" => null,
|
"date" => null,
|
||||||
"time" => null,
|
"time" => null,
|
||||||
"datetime" => null,
|
"datetime" => null,
|
||||||
"binary" => null,
|
"binary" => null,
|
||||||
"string" => null,
|
"string" => null,
|
||||||
"boolean" => null,
|
"boolean" => null,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindTrue() {
|
function testBindTrue() {
|
||||||
$input = true;
|
$input = true;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 1,
|
"integer" => 1,
|
||||||
"float" => 1.0,
|
"float" => 1.0,
|
||||||
"date" => null,
|
"date" => null,
|
||||||
"time" => null,
|
"time" => null,
|
||||||
"datetime" => null,
|
"datetime" => null,
|
||||||
"binary" => "1",
|
"binary" => "1",
|
||||||
"string" => "1",
|
"string" => "1",
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindFalse() {
|
function testBindFalse() {
|
||||||
$input = false;
|
$input = false;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 0,
|
"integer" => 0,
|
||||||
"float" => 0.0,
|
"float" => 0.0,
|
||||||
"date" => null,
|
"date" => null,
|
||||||
"time" => null,
|
"time" => null,
|
||||||
"datetime" => null,
|
"datetime" => null,
|
||||||
"binary" => "",
|
"binary" => "",
|
||||||
"string" => "",
|
"string" => "",
|
||||||
"boolean" => 0,
|
"boolean" => 0,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindInteger() {
|
function testBindInteger() {
|
||||||
$input = 2112;
|
$input = 2112;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 2112,
|
"integer" => 2112,
|
||||||
"float" => 2112.0,
|
"float" => 2112.0,
|
||||||
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 2112),
|
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 2112),
|
||||||
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 2112),
|
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 2112),
|
||||||
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 2112),
|
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 2112),
|
||||||
"binary" => "2112",
|
"binary" => "2112",
|
||||||
"string" => "2112",
|
"string" => "2112",
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindIntegerZero() {
|
function testBindIntegerZero() {
|
||||||
$input = 0;
|
$input = 0;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 0,
|
"integer" => 0,
|
||||||
"float" => 0.0,
|
"float" => 0.0,
|
||||||
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 0),
|
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 0),
|
||||||
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 0),
|
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 0),
|
||||||
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 0),
|
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 0),
|
||||||
"binary" => "0",
|
"binary" => "0",
|
||||||
"string" => "0",
|
"string" => "0",
|
||||||
"boolean" => 0,
|
"boolean" => 0,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindFloat() {
|
function testBindFloat() {
|
||||||
$input = 2112.0;
|
$input = 2112.0;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 2112,
|
"integer" => 2112,
|
||||||
"float" => 2112.0,
|
"float" => 2112.0,
|
||||||
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 2112),
|
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 2112),
|
||||||
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 2112),
|
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 2112),
|
||||||
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 2112),
|
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 2112),
|
||||||
"binary" => "2112",
|
"binary" => "2112",
|
||||||
"string" => "2112",
|
"string" => "2112",
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindFloatZero() {
|
function testBindFloatZero() {
|
||||||
$input = 0.0;
|
$input = 0.0;
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 0,
|
"integer" => 0,
|
||||||
"float" => 0.0,
|
"float" => 0.0,
|
||||||
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 0),
|
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), 0),
|
||||||
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 0),
|
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), 0),
|
||||||
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 0),
|
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), 0),
|
||||||
"binary" => "0",
|
"binary" => "0",
|
||||||
"string" => "0",
|
"string" => "0",
|
||||||
"boolean" => 0,
|
"boolean" => 0,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindAsciiString() {
|
function testBindAsciiString() {
|
||||||
$input = "Random string";
|
$input = "Random string";
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 0,
|
"integer" => 0,
|
||||||
"float" => 0.0,
|
"float" => 0.0,
|
||||||
"date" => null,
|
"date" => null,
|
||||||
"time" => null,
|
"time" => null,
|
||||||
"datetime" => null,
|
"datetime" => null,
|
||||||
"binary" => $input,
|
"binary" => $input,
|
||||||
"string" => $input,
|
"string" => $input,
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindUtf8String() {
|
function testBindUtf8String() {
|
||||||
$input = "é";
|
$input = "é";
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 0,
|
"integer" => 0,
|
||||||
"float" => 0.0,
|
"float" => 0.0,
|
||||||
"date" => null,
|
"date" => null,
|
||||||
"time" => null,
|
"time" => null,
|
||||||
"datetime" => null,
|
"datetime" => null,
|
||||||
"binary" => $input,
|
"binary" => $input,
|
||||||
"string" => $input,
|
"string" => $input,
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindBinaryString() {
|
function testBindBinaryString() {
|
||||||
// FIXME: This test may be unreliable; SQLite happily stores invalid UTF-8 text as bytes untouched, but other engines probably don't do this
|
// FIXME: This test may be unreliable; SQLite happily stores invalid UTF-8 text as bytes untouched, but other engines probably don't do this
|
||||||
$input = chr(233);
|
$input = chr(233);
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 0,
|
"integer" => 0,
|
||||||
"float" => 0.0,
|
"float" => 0.0,
|
||||||
"date" => null,
|
"date" => null,
|
||||||
"time" => null,
|
"time" => null,
|
||||||
"datetime" => null,
|
"datetime" => null,
|
||||||
"binary" => $input,
|
"binary" => $input,
|
||||||
"string" => $input,
|
"string" => $input,
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindIso8601DateString() {
|
function testBindIso8601DateString() {
|
||||||
$input = "2017-01-09T13:11:17";
|
$input = "2017-01-09T13:11:17";
|
||||||
$time = strtotime($input);
|
$time = strtotime($input);
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 2017,
|
"integer" => 2017,
|
||||||
"float" => 2017.0,
|
"float" => 2017.0,
|
||||||
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), $time),
|
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), $time),
|
||||||
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), $time),
|
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), $time),
|
||||||
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
||||||
"binary" => $input,
|
"binary" => $input,
|
||||||
"string" => $input,
|
"string" => $input,
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindArbitraryDateString() {
|
function testBindArbitraryDateString() {
|
||||||
$input = "Today";
|
$input = "Today";
|
||||||
$time = strtotime($input);
|
$time = strtotime($input);
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => 0,
|
"integer" => 0,
|
||||||
"float" => 0.0,
|
"float" => 0.0,
|
||||||
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), $time),
|
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), $time),
|
||||||
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), $time),
|
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), $time),
|
||||||
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
||||||
"binary" => $input,
|
"binary" => $input,
|
||||||
"string" => $input,
|
"string" => $input,
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindMutableDateObject($class = '\DateTime') {
|
function testBindMutableDateObject($class = '\DateTime') {
|
||||||
$input = new $class("Noon Today");
|
$input = new $class("Noon Today");
|
||||||
$time = $input->getTimestamp();
|
$time = $input->getTimestamp();
|
||||||
$exp = [
|
$exp = [
|
||||||
"null" => null,
|
"null" => null,
|
||||||
"integer" => $time,
|
"integer" => $time,
|
||||||
"float" => (float) $time,
|
"float" => (float) $time,
|
||||||
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), $time),
|
"date" => date(self::$imp::dateFormat(Statement::TS_DATE), $time),
|
||||||
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), $time),
|
"time" => date(self::$imp::dateFormat(Statement::TS_TIME), $time),
|
||||||
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
"datetime" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
||||||
"binary" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
"binary" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
||||||
"string" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
"string" => date(self::$imp::dateFormat(Statement::TS_BOTH), $time),
|
||||||
"boolean" => 1,
|
"boolean" => 1,
|
||||||
];
|
];
|
||||||
$this->checkBinding($input, $exp);
|
$this->checkBinding($input, $exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBindImmutableDateObject() {
|
function testBindImmutableDateObject() {
|
||||||
$this->testBindMutableDateObject('\DateTimeImmutable');
|
$this->testBindMutableDateObject('\DateTimeImmutable');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,135 +9,135 @@ use JKingWeb\Arsse\User\Driver;
|
||||||
trait CommonTests {
|
trait CommonTests {
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
$conf = new Conf();
|
$conf = new Conf();
|
||||||
$conf->userDriver = $this->drv;
|
$conf->userDriver = $this->drv;
|
||||||
$conf->userAuthPreferHTTP = true;
|
$conf->userAuthPreferHTTP = true;
|
||||||
Data::$conf = $conf;
|
Data::$conf = $conf;
|
||||||
Data::$db = new Database();
|
Data::$db = new Database();
|
||||||
Data::$user = new User();
|
Data::$user = new User();
|
||||||
Data::$user->authorizationEnabled(false);
|
Data::$user->authorizationEnabled(false);
|
||||||
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
||||||
$_SERVER['PHP_AUTH_PW'] = "secret";
|
$_SERVER['PHP_AUTH_PW'] = "secret";
|
||||||
// call the additional setup method if it exists
|
// call the additional setup method if it exists
|
||||||
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
|
if(method_exists($this, "setUpSeries")) $this->setUpSeries();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
$this->clearData();
|
$this->clearData();
|
||||||
// call the additional teardiwn method if it exists
|
// call the additional teardiwn method if it exists
|
||||||
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
|
if(method_exists($this, "tearDownSeries")) $this->tearDownSeries();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testListUsers() {
|
function testListUsers() {
|
||||||
$this->assertCount(0,Data::$user->list());
|
$this->assertCount(0,Data::$user->list());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCheckIfAUserDoesNotExist() {
|
|
||||||
$this->assertFalse(Data::$user->exists(self::USER1));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testAddAUser() {
|
function testCheckIfAUserDoesNotExist() {
|
||||||
Data::$user->add(self::USER1, "");
|
$this->assertFalse(Data::$user->exists(self::USER1));
|
||||||
$this->assertCount(1,Data::$user->list());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testCheckIfAUserDoesExist() {
|
function testAddAUser() {
|
||||||
Data::$user->add(self::USER1, "");
|
Data::$user->add(self::USER1, "");
|
||||||
$this->assertTrue(Data::$user->exists(self::USER1));
|
$this->assertCount(1,Data::$user->list());
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAddADuplicateUser() {
|
function testCheckIfAUserDoesExist() {
|
||||||
Data::$user->add(self::USER1, "");
|
Data::$user->add(self::USER1, "");
|
||||||
$this->assertException("alreadyExists", "User");
|
$this->assertTrue(Data::$user->exists(self::USER1));
|
||||||
Data::$user->add(self::USER1, "");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testAddMultipleUsers() {
|
function testAddADuplicateUser() {
|
||||||
Data::$user->add(self::USER1, "");
|
Data::$user->add(self::USER1, "");
|
||||||
Data::$user->add(self::USER2, "");
|
$this->assertException("alreadyExists", "User");
|
||||||
$this->assertCount(2,Data::$user->list());
|
Data::$user->add(self::USER1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRemoveAUser() {
|
|
||||||
Data::$user->add(self::USER1, "");
|
|
||||||
$this->assertCount(1,Data::$user->list());
|
|
||||||
Data::$user->remove(self::USER1);
|
|
||||||
$this->assertCount(0,Data::$user->list());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRemoveAMissingUser() {
|
function testAddMultipleUsers() {
|
||||||
$this->assertException("doesNotExist", "User");
|
Data::$user->add(self::USER1, "");
|
||||||
Data::$user->remove(self::USER1);
|
Data::$user->add(self::USER2, "");
|
||||||
}
|
$this->assertCount(2,Data::$user->list());
|
||||||
|
}
|
||||||
|
|
||||||
function testAuthenticateAUser() {
|
function testRemoveAUser() {
|
||||||
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
Data::$user->add(self::USER1, "");
|
||||||
$_SERVER['PHP_AUTH_PW'] = "secret";
|
$this->assertCount(1,Data::$user->list());
|
||||||
Data::$user->add(self::USER1, "secret");
|
Data::$user->remove(self::USER1);
|
||||||
Data::$user->add(self::USER2, "");
|
$this->assertCount(0,Data::$user->list());
|
||||||
$this->assertTrue(Data::$user->auth());
|
}
|
||||||
$this->assertTrue(Data::$user->auth(self::USER1, "secret"));
|
|
||||||
$this->assertFalse(Data::$user->auth(self::USER1, "superman"));
|
|
||||||
$this->assertTrue(Data::$user->auth(self::USER2, ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testChangeAPassword() {
|
function testRemoveAMissingUser() {
|
||||||
Data::$user->add(self::USER1, "secret");
|
$this->assertException("doesNotExist", "User");
|
||||||
$this->assertEquals("superman", Data::$user->passwordSet(self::USER1, "superman"));
|
Data::$user->remove(self::USER1);
|
||||||
$this->assertTrue(Data::$user->auth(self::USER1, "superman"));
|
}
|
||||||
$this->assertFalse(Data::$user->auth(self::USER1, "secret"));
|
|
||||||
$this->assertEquals("", Data::$user->passwordSet(self::USER1, ""));
|
|
||||||
$this->assertTrue(Data::$user->auth(self::USER1, ""));
|
|
||||||
$this->assertEquals(Data::$conf->userTempPasswordLength, strlen(Data::$user->passwordSet(self::USER1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testChangeAPasswordForAMissingUser() {
|
function testAuthenticateAUser() {
|
||||||
$this->assertException("doesNotExist", "User");
|
$_SERVER['PHP_AUTH_USER'] = self::USER1;
|
||||||
Data::$user->passwordSet(self::USER1, "superman");
|
$_SERVER['PHP_AUTH_PW'] = "secret";
|
||||||
}
|
Data::$user->add(self::USER1, "secret");
|
||||||
|
Data::$user->add(self::USER2, "");
|
||||||
|
$this->assertTrue(Data::$user->auth());
|
||||||
|
$this->assertTrue(Data::$user->auth(self::USER1, "secret"));
|
||||||
|
$this->assertFalse(Data::$user->auth(self::USER1, "superman"));
|
||||||
|
$this->assertTrue(Data::$user->auth(self::USER2, ""));
|
||||||
|
}
|
||||||
|
|
||||||
function testGetThePropertiesOfAUser() {
|
function testChangeAPassword() {
|
||||||
Data::$user->add(self::USER1, "secret");
|
Data::$user->add(self::USER1, "secret");
|
||||||
$p = Data::$user->propertiesGet(self::USER1);
|
$this->assertEquals("superman", Data::$user->passwordSet(self::USER1, "superman"));
|
||||||
$this->assertArrayHasKey('id', $p);
|
$this->assertTrue(Data::$user->auth(self::USER1, "superman"));
|
||||||
$this->assertArrayHasKey('name', $p);
|
$this->assertFalse(Data::$user->auth(self::USER1, "secret"));
|
||||||
$this->assertArrayHasKey('domain', $p);
|
$this->assertEquals("", Data::$user->passwordSet(self::USER1, ""));
|
||||||
$this->assertArrayHasKey('rights', $p);
|
$this->assertTrue(Data::$user->auth(self::USER1, ""));
|
||||||
$this->assertArrayNotHasKey('password', $p);
|
$this->assertEquals(Data::$conf->userTempPasswordLength, strlen(Data::$user->passwordSet(self::USER1)));
|
||||||
$this->assertEquals(self::USER1, $p['name']);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function testSetThePropertiesOfAUser() {
|
function testChangeAPasswordForAMissingUser() {
|
||||||
$pSet = [
|
$this->assertException("doesNotExist", "User");
|
||||||
'name' => 'John Doe',
|
Data::$user->passwordSet(self::USER1, "superman");
|
||||||
'id' => 'invalid',
|
}
|
||||||
'domain' => 'localhost',
|
|
||||||
'rights' => Driver::RIGHTS_GLOBAL_ADMIN,
|
|
||||||
'password' => 'superman',
|
|
||||||
];
|
|
||||||
$pGet = [
|
|
||||||
'name' => 'John Doe',
|
|
||||||
'id' => self::USER1,
|
|
||||||
'domain' => 'example.com',
|
|
||||||
'rights' => Driver::RIGHTS_NONE,
|
|
||||||
];
|
|
||||||
Data::$user->add(self::USER1, "secret");
|
|
||||||
Data::$user->propertiesSet(self::USER1, $pSet);
|
|
||||||
$p = Data::$user->propertiesGet(self::USER1);
|
|
||||||
$this->assertArraySubset($pGet, $p);
|
|
||||||
$this->assertArrayNotHasKey('password', $p);
|
|
||||||
$this->assertFalse(Data::$user->auth(self::USER1, "superman"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function testGetTheRightsOfAUser() {
|
function testGetThePropertiesOfAUser() {
|
||||||
Data::$user->add(self::USER1, "");
|
Data::$user->add(self::USER1, "secret");
|
||||||
$this->assertEquals(Driver::RIGHTS_NONE, Data::$user->rightsGet(self::USER1));
|
$p = Data::$user->propertiesGet(self::USER1);
|
||||||
}
|
$this->assertArrayHasKey('id', $p);
|
||||||
|
$this->assertArrayHasKey('name', $p);
|
||||||
|
$this->assertArrayHasKey('domain', $p);
|
||||||
|
$this->assertArrayHasKey('rights', $p);
|
||||||
|
$this->assertArrayNotHasKey('password', $p);
|
||||||
|
$this->assertEquals(self::USER1, $p['name']);
|
||||||
|
}
|
||||||
|
|
||||||
function testSetTheRightsOfAUser() {
|
function testSetThePropertiesOfAUser() {
|
||||||
Data::$user->add(self::USER1, "");
|
$pSet = [
|
||||||
Data::$user->rightsSet(self::USER1, Driver::RIGHTS_GLOBAL_ADMIN);
|
'name' => 'John Doe',
|
||||||
$this->assertEquals(Driver::RIGHTS_GLOBAL_ADMIN, Data::$user->rightsGet(self::USER1));
|
'id' => 'invalid',
|
||||||
}
|
'domain' => 'localhost',
|
||||||
|
'rights' => Driver::RIGHTS_GLOBAL_ADMIN,
|
||||||
|
'password' => 'superman',
|
||||||
|
];
|
||||||
|
$pGet = [
|
||||||
|
'name' => 'John Doe',
|
||||||
|
'id' => self::USER1,
|
||||||
|
'domain' => 'example.com',
|
||||||
|
'rights' => Driver::RIGHTS_NONE,
|
||||||
|
];
|
||||||
|
Data::$user->add(self::USER1, "secret");
|
||||||
|
Data::$user->propertiesSet(self::USER1, $pSet);
|
||||||
|
$p = Data::$user->propertiesGet(self::USER1);
|
||||||
|
$this->assertArraySubset($pGet, $p);
|
||||||
|
$this->assertArrayNotHasKey('password', $p);
|
||||||
|
$this->assertFalse(Data::$user->auth(self::USER1, "superman"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetTheRightsOfAUser() {
|
||||||
|
Data::$user->add(self::USER1, "");
|
||||||
|
$this->assertEquals(Driver::RIGHTS_NONE, Data::$user->rightsGet(self::USER1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSetTheRightsOfAUser() {
|
||||||
|
Data::$user->add(self::USER1, "");
|
||||||
|
Data::$user->rightsSet(self::USER1, Driver::RIGHTS_GLOBAL_ADMIN);
|
||||||
|
$this->assertEquals(Driver::RIGHTS_GLOBAL_ADMIN, Data::$user->rightsGet(self::USER1));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@ class Database extends DriverSkeleton {
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function userExists(string $user): bool {
|
function userExists(string $user): bool {
|
||||||
if(!Data::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if(!Data::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
return parent::userExists($user);
|
return parent::userExists($user);
|
||||||
|
@ -42,7 +42,7 @@ class Database extends DriverSkeleton {
|
||||||
return parent::userList($domain);
|
return parent::userList($domain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
if(!Data::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if(!Data::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
@ -70,7 +70,7 @@ class Database extends DriverSkeleton {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
return parent::userRightsGet($user);
|
return parent::userRightsGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
function userRightsSet(string $user, int $level): bool {
|
||||||
if(!Data::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if(!Data::$user->authorize($user, __FUNCTION__)) throw new ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
|
|
|
@ -44,7 +44,7 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||||
if(password_verify($password, $this->db[$user]['password'])) return true;
|
if(password_verify($password, $this->db[$user]['password'])) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function userExists(string $user): bool {
|
function userExists(string $user): bool {
|
||||||
return parent::userExists($user);
|
return parent::userExists($user);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||||
return parent::userList($domain);
|
return parent::userList($domain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
if($newPassword===null) $newPassword = (new PassGen)->length(Data::$conf->userTempPasswordLength)->get();
|
if($newPassword===null) $newPassword = (new PassGen)->length(Data::$conf->userTempPasswordLength)->get();
|
||||||
|
@ -89,7 +89,7 @@ class DriverExternalMock extends DriverSkeleton implements Driver {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
return parent::userRightsGet($user);
|
return parent::userRightsGet($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
function userRightsSet(string $user, int $level): bool {
|
||||||
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
if(!$this->userExists($user)) throw new Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
return parent::userRightsSet($user, $level);
|
return parent::userRightsSet($user, $level);
|
||||||
|
|
|
@ -9,9 +9,9 @@ use PasswordGenerator\Generator as PassGen;
|
||||||
|
|
||||||
abstract class DriverSkeleton {
|
abstract class DriverSkeleton {
|
||||||
|
|
||||||
protected $db = [];
|
protected $db = [];
|
||||||
|
|
||||||
function userExists(string $user): bool {
|
function userExists(string $user): bool {
|
||||||
return array_key_exists($user, $this->db);
|
return array_key_exists($user, $this->db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ abstract class DriverSkeleton {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
function userPasswordSet(string $user, string $newPassword = null, string $oldPassword = null): string {
|
||||||
$this->db[$user]['password'] = password_hash($newPassword, \PASSWORD_DEFAULT);
|
$this->db[$user]['password'] = password_hash($newPassword, \PASSWORD_DEFAULT);
|
||||||
return $newPassword;
|
return $newPassword;
|
||||||
|
@ -60,7 +60,7 @@ abstract class DriverSkeleton {
|
||||||
function userRightsGet(string $user): int {
|
function userRightsGet(string $user): int {
|
||||||
return $this->db[$user]['rights'];
|
return $this->db[$user]['rights'];
|
||||||
}
|
}
|
||||||
|
|
||||||
function userRightsSet(string $user, int $level): bool {
|
function userRightsSet(string $user, int $level): bool {
|
||||||
$this->db[$user]['rights'] = $level;
|
$this->db[$user]['rights'] = $level;
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue