Database abstraction

This commit is contained in:
2020-04-02 00:02:51 +02:00
parent 26d28377be
commit 81995b06b8
51 changed files with 1660 additions and 641 deletions

View File

@@ -17,13 +17,20 @@ class CreateApiKey extends Request {
}
$apiKey = generateRandomString(64);
$query = "INSERT INTO ApiKey (user_id, api_key, valid_until) VALUES (?,?,(SELECT DATE_ADD(now(), INTERVAL 30 DAY)))";
$request = new ExecuteStatement($this->user);
$this->success = $request->execute(array("query" => $query, $this->user->getId(), $apiKey));
$this->lastError = $request->getLastError();
$this->result["api_key"] = $apiKey;
$this->result["valid_until"] = "TODO";
$this->result["uid"] = $this->user->getSQL()->getLastInsertId();
$sql = $this->user->getSQL();
$validUntil = (new \DateTime())->modify("+30 DAY");
$this->success = $sql->insert("ApiKey", array("user_id", "api_key", "valid_until"))
->addRow($this->user->getId(), $apiKey, $validUntil)
->execute();
$this->lastError = $sql->getLastError();
if ($this->success) {
$this->result["api_key"] = $apiKey;
$this->result["valid_until"] = $validUntil->getTimestamp();
$this->result["uid"] = $sql->getLastInsertId();
}
return $this->success;
}
};

View File

@@ -1,109 +0,0 @@
<?php
namespace Api;
use Api\Parameter\Parameter;
use Api\Parameter\StringType;
class ExecuteSelect extends Request {
public function __construct($user, $externCall = false) {
parent::__construct($user, $externCall, array(
'query' => new StringType('query')
));
$this->isPublic = false;
$this->variableParamCount = true;
}
public function execute($values = array()) {
if(!parent::execute($values)) {
return false;
}
$sql = $this->user->getSQL();
$this->success = false;
$this->result['rows'] = array();
if(count($this->params) === 1) {
$res = $sql->query($this->getParam('query'));
if(!$res) {
$this->lastError = 'Database Error: query() failed with ' . $sql->getLastError();
return false;
}
while($row = $res->fetch_assoc()) {
array_push($this->result['rows'], $row);
}
$this->success = true;
$res->close();
} else {
$aSqlParams = array('');
foreach($this->params as $param) {
if($param->name === 'query') continue;
$value = $param->value;
switch($param->type) {
case Parameter::TYPE_BOOLEAN:
$value = $param->value ? 1 : 0;
case Parameter::TYPE_INT:
$aSqlParams[0] .= 'i';
break;
case Parameter::TYPE_FLOAT:
$aSqlParams[0] .= 'd';
break;
case Parameter::TYPE_DATE:
$value = $value->format('Y-m-d');
$aSqlParams[0] .= 's';
break;
case Parameter::TYPE_TIME:
$value = $value->format('H:i:s');
$aSqlParams[0] .= 's';
break;
case Parameter::TYPE_DATE_TIME:
$value = $value->format('Y-m-d H:i:s');
$aSqlParams[0] .= 's';
break;
case Parameter::TYPE_EMAIL:
default:
$aSqlParams[0] .= 's';
}
$aSqlParams[] = $value;
}
$tmp = array();
foreach($aSqlParams as $key => $value) $tmp[$key] = &$aSqlParams[$key];
if($stmt = $sql->connection->prepare($this->getParam('query'))) {
if(call_user_func_array(array($stmt, "bind_param"), $tmp))
{
if($stmt->execute()) {
$res = $stmt->get_result();
if($res) {
while($row = $res->fetch_assoc()) {
array_push($this->result['rows'], $row);
}
$res->close();
$this->success = true;
} else {
$this->lastError = 'Database Error: execute() failed with ' . $sql->getLastError();
}
} else {
$this->lastError = 'Database Error: get_result() failed with ' . $sql->getLastError();
}
} else {
$this->lastError = 'Database Error: bind_param() failed with ' . $sql->getLastError();
}
$stmt->close();
} else {
$this->lastError = 'Database Error: prepare failed with() ' . $sql->getLastError();
}
}
return $this->success;
}
};
?>

View File

@@ -1,97 +0,0 @@
<?php
namespace Api;
use Api\Parameter\Parameter;
use Api\Parameter\StringType;
class ExecuteStatement extends Request {
public function __construct($user, $externCall = false) {
parent::__construct($user, $externCall, array(
'query' => new StringType('query')
));
$this->isPublic = false;
$this->variableParamCount = true;
}
public function execute($values = array()) {
if(!parent::execute($values)) {
return false;
}
$this->success = false;
$this->result['rows'] = array();
if(count($this->params) == 1) {
$this->success = $this->user->getSQL()->execute($this->getParam('query'));
if(!$this->success) {
$this->lastError = $this->user->getSQL()->getLastError();
}
} else {
$aSqlParams = array('');
foreach($this->params as $param) {
if($param->name === 'query') continue;
$value = $param->value;
if(is_null($value)) {
$aSqlParams[0] .= 's';
} else {
switch($param->type) {
case Parameter::TYPE_BOOLEAN:
$value = $param->value ? 1 : 0;
$aSqlParams[0] .= 'i';
break;
case Parameter::TYPE_INT:
$aSqlParams[0] .= 'i';
break;
case Parameter::TYPE_FLOAT:
$aSqlParams[0] .= 'd';
break;
case Parameter::TYPE_DATE:
$value = $value->format('Y-m-d');
$aSqlParams[0] .= 's';
break;
case Parameter::TYPE_TIME:
$value = $value->format('H:i:s');
$aSqlParams[0] .= 's';
break;
case Parameter::TYPE_DATE_TIME:
$value = $value->format('Y-m-d H:i:s');
$aSqlParams[0] .= 's';
break;
case Parameter::TYPE_EMAIL:
default:
$aSqlParams[0] .= 's';
}
}
$aSqlParams[] = $value;
}
$tmp = array();
foreach($aSqlParams as $key => $value) $tmp[$key] = &$aSqlParams[$key];
if($stmt = $this->user->getSQL()->connection->prepare($this->getParam('query'))) {
if(call_user_func_array(array($stmt, "bind_param"), $tmp)) {
if($stmt->execute()) {
$this->result['rows'] = $stmt->affected_rows;
$this->success = true;
} else {
$this->lastError = 'Database Error: execute() failed with ' . $this->user->getSQL()->getLastError();
}
} else {
$this->lastError = 'Database Error: bind_param() failed with ' . $this->user->getSQL()->getLastError();
}
$stmt->close();
} else {
$this->lastError = 'Database Error: prepare() failed with ' . $this->user->getSQL()->getLastError();
}
}
return $this->success;
}
};
?>

View File

@@ -1,82 +0,0 @@
<?php
namespace Api\External;
use \Api\Parameter\Parameter;
use \Api\Parameter\StringType;
class RequestData extends \Api\Request {
public function __construct($user, $externCall = false) {
parent::__construct($user, $externCall, array(
"url" => new StringType("url", 256)
));
$this->isPublic = false;
}
private function requestURL() {
$url = $this->getParam("url");
$ckfile = tempnam("/tmp", 'cookiename');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
$data = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$success = false;
if(curl_errno($ch)) {
$this->lastError = curl_error($ch);
} else if($statusCode != 200) {
$this->lastError = "External Site returned status code: " . $statusCode;
} else {
$this->result["data"] = $data;
$this->result["cached"] = false;
$success = true;
}
unlink($ckfile);
curl_close ($ch);
return $success;
}
public function execute($values = array()) {
if(!parent::execute($values)) {
return false;
}
$url = $this->getParam("url");
$expires = $this->getParam("expires");
$query = "SELECT data, expires FROM ExternalSiteCache WHERE url=?";
$req = new \Api\ExecuteSelect($this->user);
$this->success = $req->execute(array("query" => $query, $url));
$this->lastError = $req->getLastError();
if($this->success) {
$mustRevalidate = true;
if(!empty($req->getResult()['rows'])) {
$row = $req->getResult()['rows'][0];
if($row["expires"] == null || !isinPast($row["expires"])) {
$mustRevalidate = false;
$this->result["data"] = $row["data"];
$this->result["expires"] = $row["expires"];
$this->result["cached"] = true;
}
}
if($mustRevalidate) {
$this->success = $this->requestURL();
}
}
return $this->success;
}
};
?>

View File

@@ -1,44 +0,0 @@
<?php
namespace Api\External;
use Api\Parameter\Parameter;
use Api\Parameter\StringType;
class WriteData extends \Api\Request {
public function __construct($user, $externCall = false) {
parent::__construct($user, $externCall, array(
"url" => new StringType("url", 256),
"data" => new StringType("data", -1),
"expires" => new Parameter("expires", Parameter::TYPE_INT, false, 0),
));
$this->isPublic = false;
}
public function execute($values = array()) {
if(!parent::execute($values)) {
return false;
}
$url = $this->getParam("url");
$data = $this->getParam("data");
$expires = $this->getParam("expires");
if($expires > 0) {
$expires = getDateTime(new \DateTime("+${expires} seconds"));
} else {
$expires = null;
}
$query = "INSERT INTO ExternalSiteCache (url, data, expires) VALUES(?,?,?)
ON DUPLICATE KEY UPDATE data=?, expires=?";
$request = new \Api\ExecuteStatement($this->user);
$this->success = $request->execute(array("query" => $query, $url, $data, $expires, $data, $expires));
$this->lastError = $request->getLastError();
return $this->lastError;
}
}
?>

View File

@@ -2,6 +2,9 @@
namespace Api;
use \Driver\SQL\Keyword;
use \Driver\SQL\Condition\Compare;
class GetApiKeys extends Request {
public function __construct($user, $externCall = false) {
@@ -14,16 +17,19 @@ class GetApiKeys extends Request {
return false;
}
$query = "SELECT ApiKey.uid, ApiKey.api_key, ApiKey.valid_until
FROM ApiKey
WHERE ApiKey.user_id = ?
AND ApiKey.valid_until > now()";
$request = new ExecuteSelect($this->user);
$this->success = $request->execute(array("query" => $query, $this->user->getId()));
$this->lastError = $request->getLastError();
$sql = $this->user->getSQL();
$res = $sql->select("uid", "api_key", "valid_until")
->from("ApiKey")
->where(new Compare("user_id", $this->user->getId()))
->where(new Compare("valid_until", new Keyword($sql->currentTimestamp()), ">"))
->where(new Compare("active", true))
->execute();
$this->success = ($res !== FALSE);
$this->lastError = $sql->getLastError();
if($this->success) {
$this->result["api_keys"] = $request->getResult()['rows'];
$this->result["api_keys"] = $res;
}
return $this->success;

View File

@@ -13,17 +13,20 @@ class GetLanguages extends Request {
return false;
}
$query = 'SELECT uid, code, name FROM Language';
$request = new ExecuteSelect($this->user);
$this->success = $request->execute(array('query' => $query));
$this->lastError = $request->getLastError();
$sql = $this->user->getSQL();
$res = $sql->select("uid", "code", "name")
->from("Language")
->execute();
$this->success = ($res !== FALSE);
$this->lastError = $sql->getLastError();
if($this->success) {
$this->result['languages'] = array();
if(count($request->getResult()['rows']) === 0) {
if(empty($res) === 0) {
$this->lastError = L("No languages found");
} else {
foreach($request->getResult()['rows'] as $row) {
foreach($res as $row) {
$this->result['languages'][$row['uid']] = $row;
}
}

View File

@@ -4,6 +4,7 @@ namespace Api;
use Api\Parameter\Parameter;
use Api\Parameter\StringType;
use Driver\SQL\Condition\Compare;
class Login extends Request {
@@ -42,27 +43,30 @@ class Login extends Request {
$password = $this->getParam('password');
$stayLoggedIn = $this->getParam('stayLoggedIn');
$query = 'SELECT User.uid, User.password, User.salt FROM User WHERE User.name=?';
$request = new ExecuteSelect($this->user);
$this->success = $request->execute(array('query' => $query, $username));
$this->lastError = $request->getLastError();
$sql = $this->user->getSQL();
$res = $sql->select("User.uid", "User.password", "User.salt")
->from("User")
->where(new Compare("User.name", $username))
->execute();
$this->success = ($res !== FALSE);
$this->lastError = $sql->getLastError();
if($this->success) {
$this->success = false;
if(count($request->getResult()['rows']) === 0) {
if(count($res) === 0) {
return $this->wrongCredentials();
$this->lastError = L('Wrong username or password');
} else {
$row = $request->getResult()['rows'][0];
$row = $res[0];
$salt = $row['salt'];
$uid = $row['uid'];
$hash = hash('sha256', $password . $salt);
if($hash === $row['password']) {
if(!($this->success = $this->user->createSession($uid, $stayLoggedIn))) {
return $this->createError("Error creating Session");
} else {
$this->result['logoutIn'] = $this->user->getSession()->getExpiresSeconds();
}
if(!($this->success = $this->user->createSession($uid, $stayLoggedIn))) {
return $this->createError("Error creating Session: " . $sql->getLastError());
} else {
$this->result['logoutIn'] = $this->user->getSession()->getExpiresSeconds();
$this->success = true;
}
}
else {
return $this->wrongCredentials();

View File

@@ -15,9 +15,9 @@ class Logout extends Request {
return false;
}
$this->success = true;
$this->user->logout();
return true;
$this->success = $this->user->logout();
$this->lastError = $this->user->getSQL()->getLastError();
return $this->success;
}
};

View File

@@ -1,7 +1,10 @@
<?php
namespace Api;
use \Api\Parameter\Parameter;
use \Driver\SQL\Keyword;
use \Driver\SQL\Condition\Compare;
class RefreshApiKey extends Request {
@@ -14,12 +17,20 @@ class RefreshApiKey extends Request {
private function apiKeyExists() {
$id = $this->getParam("id");
$query = "SELECT * FROM ApiKey WHERE uid = ? AND user_id = ? AND valid_until > now()";
$request = new ExecuteSelect($this->user);
$this->success = $request->execute(array("query" => $query, $id, $this->user->getId()));
$this->lastError = $request->getLastError();
if($this->success && count($request->getResult()['rows']) == 0) {
$sql = $this->user->getSQL();
$res = $sql->select("COUNT(*)")
->from("ApiKey")
->where(new Compare("uid", $id))
->where(new Compare("user_id", $this->user->getId()))
->where(new Compare("valid_until", new Keyword($sql->currentTimestamp()), ">"))
->where(new Compare("active", 1))
->execute();
$this->success = ($res !== FALSE);
$this->lastError = $sql->getLastError();
if($this->success && $res[0]["COUNT(*)"] === 0) {
$this->success = false;
$this->lastError = "This API-Key does not exist.";
}
@@ -36,10 +47,18 @@ class RefreshApiKey extends Request {
if(!$this->apiKeyExists())
return false;
$query = "UPDATE ApiKey SET valid_until = (SELECT DATE_ADD(now(), INTERVAL 30 DAY)) WHERE uid = ? AND user_id = ? AND valid_until > now()";
$request = new ExecuteStatement($this->user);
$this->success = $request->execute(array("query" => $query, $id, $this->user->getId()));
$this->lastError = $request->getLastError();
$validUntil = (new \DateTime)->modify("+30 DAY");
$sql = $this->user->getSQL();
$this->success = $sql->update("ApiKey")
->set("valid_until", $validUntil)
->where(new Compare("uid", $id))
->where(new Compare("user_id", $this->user->getId()))
->execute();
$this->lastError = $sql->getLastError();
if ($this->success) {
$this->result["valid_until"] = $validUntil->getTimestamp();
}
return $this->success;
}

View File

@@ -1,7 +1,10 @@
<?php
namespace Api;
use \Api\Parameter\Parameter;
use \Driver\SQL\Keyword;
use \Driver\SQL\Condition\Compare;
class RevokeApiKey extends Request {
@@ -14,12 +17,20 @@ class RevokeApiKey extends Request {
private function apiKeyExists() {
$id = $this->getParam("id");
$query = "SELECT * FROM ApiKey WHERE uid = ? AND user_id = ? AND valid_until > now()";
$request = new ExecuteSelect($this->user);
$this->success = $request->execute(array("query" => $query, $id, $this->user->getId()));
$this->lastError = $request->getLastError();
if($this->success && count($request->getResult()['rows']) == 0) {
$sql = $this->user->getSQL();
$res = $sql->select("COUNT(*)")
->from("ApiKey")
->where(new Compare("uid", $id))
->where(new Compare("user_id", $this->user->getId()))
->where(new Compare("valid_until", new Keyword($sql->currentTimestamp()), ">"))
->where(new Compare("active", 1))
->execute();
$this->success = ($res !== FALSE);
$this->lastError = $sql->getLastError();
if($this->success && $res[0]["COUNT(*)"] === 0) {
$this->success = false;
$this->lastError = "This API-Key does not exist.";
}
@@ -36,10 +47,13 @@ class RevokeApiKey extends Request {
if(!$this->apiKeyExists())
return false;
$query = "DELETE FROM ApiKey WHERE valid_until < now() OR (uid = ? AND user_id = ?)";
$request = new ExecuteStatement($this->user);
$this->success = $request->execute(array("query" => $query, $id, $this->user->getId()));
$this->lastError = $request->getLastError();
$sql = $this->user->getSQL();
$this->success = $sql->update("ApiKey")
->set("active", false)
->where(new Compare("uid", $id))
->where(new Compare("user_id", $this->user->getId()))
->execute();
$this->lastError = $sql->getLastError();
return $this->success;
}

View File

@@ -4,6 +4,8 @@ namespace Api;
use Api\Parameter\Parameter;
use Api\Parameter\StringType;
use Driver\SQL\Condition\CondOr;
use Driver\SQL\Condition\Compare;
class SetLanguage extends Request {
@@ -24,16 +26,20 @@ class SetLanguage extends Request {
return $this->createError(L("Either langId or langCode must be given"));
}
$query = "SELECT uid, code, name FROM Language WHERE uid=? OR code=?";
$request = new ExecuteSelect($this->user);
$this->success = $request->execute(array("query" => $query, $langId, $langCode));
$this->lastError = $request->getLastError();
$res = $this->user->getSQL()
->select("uid", "code", "name")
->from("Language")
->where(new CondOr(new Compare("uid", $langId), new Compare("code", $langCode)))
->execute();
if($this->success) {
if(count($request->getResult()['rows']) == 0) {
$this->success = ($res !== FALSE);
$this->lastError = $this->user->getSQL()->getLastError();
if ($this->success) {
if(count($res) == 0) {
return $this->createError(L("This Language does not exist"));
} else {
$row = $request->getResult()['rows'][0];
$row = $res[0];
$this->language = \Objects\Language::newInstance($row['uid'], $row['code'], $row['name']);
if(!$this->language) {
return $this->createError(L("Error while loading language"));
@@ -47,11 +53,13 @@ class SetLanguage extends Request {
private function updateLanguage() {
$languageId = $this->language->getId();
$userId = $this->user->getId();
$sql = $this->user->getSQL();
$query = "UPDATE User SET language_id = ? WHERE uid = ?";
$request = new ExecuteStatement($this->user);
$this->success = $request->execute(array("query" => $query, $languageId, $userId));
$this->lastError = $request->getLastError();
$this->success = $sql->update("User")
->set("language_id", $languageId)
->where(new Compare("uid", $userId))
->execute();
$this->lastError = $sql->getLastError();
return $this->success;
}