diff --git a/juggl/config/config.inc.php b/juggl/config/config.inc.php new file mode 100644 index 0000000..c9eda41 --- /dev/null +++ b/juggl/config/config.inc.php @@ -0,0 +1,6 @@ +readPathFile(__DIR__."/config.path"); +?> \ No newline at end of file diff --git a/juggl/services/apiBranch.inc.php b/juggl/services/apiBranch.inc.php index 62601e9..a84618e 100644 --- a/juggl/services/apiBranch.inc.php +++ b/juggl/services/apiBranch.inc.php @@ -2,7 +2,6 @@ require_once(__DIR__."/authenticator.inc.php"); require_once(__DIR__."/responses.inc.php"); require_once(__DIR__."/requestTypes.inc.php"); -require_once(__DIR__."/dbOperations.inc.php"); require_once(__DIR__."/paramCleaner.inc.php"); abstract class ApiBranch { @@ -13,26 +12,27 @@ abstract class ApiBranch { } function execute ($authenticationRequired = true) { + $params = $this->getParams(); + if ($authenticationRequired) { $auth = new Authenticator(); - if (!$auth->isAuthenticated($_SESSION, $_REQUEST)) { - $this->authenticationMissing($this->getParams()); + if (!$auth->isAuthenticated($params)) { + $this->authenticationMissing($params); return; } } $currentType = currentRequestType(); if($currentType === RequestType::GET) { - $this->get($this->getParams()); + $this->get($params); } else if ($currentType === RequestType::POST) { - $this->post($this->getParams()); + $this->post($params); } } private function getParams() { $content = json_decode(file_get_contents('php://input'), true); - $contentArray = array("json" => $content); - return new ParamCleaner(array_merge($contentArray, $_REQUEST, $_SESSION, $_FILES)); + return new ParamCleaner(array_merge($content, $_REQUEST, $_SESSION, $_FILES)); } } ?> \ No newline at end of file diff --git a/juggl/services/authenticator.inc.php b/juggl/services/authenticator.inc.php index 8cb07d9..39b94e5 100644 --- a/juggl/services/authenticator.inc.php +++ b/juggl/services/authenticator.inc.php @@ -1,43 +1,20 @@ select("api_keys", array("quota_max", "client_key")); - $db->where("client_key", Comparison::EQUAL, $key); - + $db->select("api_keys", ["enabled"]); + $db->where("api_key", Comparison::EQUAL, $api_key); + $db->where("user_id", Comparison::EQUAL, $user_id); + $result = $db->execute(); - if (count($result) == 1 && $result[0]['quota_max'] > 0) - return true; - else - return false; + return count($result) == 1 && $result[0]['enabled']; } - function isSessionAuthenticated($session) { - if (isset($session['stayloggedin'])) { - if($session["stayloggedin"]) { - return true; - } - } - - if (!isset($session['until'])) { - return false; - } - - if ($session['until'] > time() || $session['until'] == 0) - return true; - else - return false; - } - - function isAuthenticated($session, $request) { - if (isset($request['key'])) { - return $this->isApiKeyAuthenticated($request['key']); - } else { - return $this->isSessionAuthenticated($session); - } + function isAuthenticated($params) { + return $this->isApiKeyAuthenticated($params->get('api_key'), $params->get('user_id')); } } ?> \ No newline at end of file diff --git a/juggl/services/configReader.inc.php b/juggl/services/configReader.inc.php index c9bcd69..cbe36ab 100644 --- a/juggl/services/configReader.inc.php +++ b/juggl/services/configReader.inc.php @@ -3,6 +3,10 @@ class ConfigReader { private const VALUE_SEPARATOR = '='; + function __construct () { + $this->configuration = array(); + } + function readFile ($path) { if (file_exists($path) == false) return; @@ -17,6 +21,11 @@ class ConfigReader { } } + function readPathFile ($pathToPathFile) { + $this->readFile($pathToPathFile); + $this->readFile(__DIR__."/../".$this->getSetting("relativepath")); + } + function getSetting ($key) { if (array_key_exists($key, $this->configuration) == false) return NULL; diff --git a/juggl/services/dbOperations.inc.php b/juggl/services/dbOperations.inc.php index e73ecb9..f074ec8 100644 --- a/juggl/services/dbOperations.inc.php +++ b/juggl/services/dbOperations.inc.php @@ -1,34 +1,38 @@ resetQuery(); + $this->tablePrefix = $tablePrefix; + + require(__DIR__."/../config/config.inc.php"); + $this->config = $config; + + if ($this->tablePrefix == null) { + $this->tablePrefix = $this->config->getSetting("table_prefix"); + } } function resetQuery() { $this->query = ""; $this->data = array(); $this->table = ""; + $this->tablePrefix = ""; } private function openConnection () { - $config = new ConfigReader(); - $config->readFile(__DIR__."/../config/config.path"); - $config->readFile(__DIR__."/../".$config->getSetting("relativepath")); - - $host = $config->getSetting('host'); - $dbname = $config->getSetting('dbname'); + $host = $this->config->getSetting('host'); + $dbname = $this->config->getSetting('dbname'); $dsn = "mysql:host=$host;dbname=$dbname"; $options = array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC); - $this->pdo = new PDO($dsn, $config->getSetting('username'), $config->getSetting('password'), $options); + $this->pdo = new PDO($dsn, $this->config->getSetting('username'), $this->config->getSetting('password'), $options); } function select (string $table, array $attributes = array()) { - $this->table = $table; + $this->table = $this->tablePrefix.$table; if (count($attributes) == 0) $formattedAttributes = "*"; else { @@ -41,7 +45,7 @@ class DbOperations { $formattedAttributes = implode(', ', $attributes); } - $this->addToQuery("SELECT $formattedAttributes FROM $table"); + $this->addToQuery("SELECT $formattedAttributes FROM $this->tablePrefix$table"); return $this; } @@ -62,7 +66,7 @@ class DbOperations { } function insert (string $table, array $data) { - $this->table = $table; + $this->table = $this->tablePrefix.$table; $attributes = implode(", ", array_keys($data)); $valuesIds = array(); @@ -71,13 +75,40 @@ class DbOperations { } $values = implode(" , ", $valuesIds); - $this->addToQuery("INSERT INTO $table ( $attributes ) VALUES ( $values )"); + $this->addToQuery("INSERT INTO $this->tablePrefix$table ( $attributes ) VALUES ( $values )"); + + return $this; + } + + function insertMultiple (string $table, array $attributes, array $data) { + $this->table = $this->tablePrefix.$table; + + $attributesString = implode(", ", $attributes); + $valueGroups = array(); + $groupIndex = 0; // To avoid same value ids + foreach($data as $dataGroup) { + if (sizeof($attributes) != sizeof($dataGroup)) { + continue; + } + + $valueIds = array(); + // Indexed for used, so that attributes can easily be assigned to the according values + for ($i = 0; $i < sizeof($dataGroup); $i++) { + $valueIds[] = $this->addData($dataGroup[$i], $attributes[$i] . "_" . (string) $groupIndex); + } + + $valueGroups[] = "(" . implode(", " ,$valueIds) . ")"; + $groupIndex++; + } + $values = implode(", ", $valueGroups); + + $this->addToQuery("INSERT INTO $this->tablePrefix$table ( $attributesString ) VALUES $values"); return $this; } function update (string $table, array $data) { - $this->table = $table; + $this->table = $this->tablePrefix.$table; $sets = array(); foreach($data as $attribute => $value) { @@ -86,15 +117,15 @@ class DbOperations { } $setString = implode(", ", $sets); - $this->addToQuery("UPDATE $table SET $setString"); + $this->addToQuery("UPDATE $this->tablePrefix$table SET $setString"); return $this; } function delete (string $table) { - $this->table = $table; + $this->table = $this->tablePrefix.$table; - $this->addToQuery("DELETE FROM $table"); + $this->addToQuery("DELETE FROM $this->tablePrefix$table"); return $this; } @@ -118,12 +149,15 @@ class DbOperations { return $this; } - function innerJoin (string $table, string $externAttribute, string $internAttribute, string $internTable = "") { + function innerJoin (string $table, string $externAttribute, string $internAttribute = "", string $internTable = "") { if ($internTable === "") { - $internTable = $this->table; + $internTable = substr($this->table, sizeof($this->tablePrefix)); + } + if ($internAttribute === "") { + $internAttribute = $externAttribute; } - $innerJoin = "INNER JOIN $table ON $table.$externAttribute = $internTable.$internAttribute"; + $innerJoin = "INNER JOIN $this->tablePrefix$table ON $this->tablePrefix$table.$externAttribute = $this->tablePrefix$internTable.$internAttribute"; $this->addToQuery($innerJoin); diff --git a/juggl/services/paramCleaner.inc.php b/juggl/services/paramCleaner.inc.php index e6ef868..d9ba0bc 100644 --- a/juggl/services/paramCleaner.inc.php +++ b/juggl/services/paramCleaner.inc.php @@ -24,6 +24,15 @@ class ParamCleaner { return null; } } + + function exists (array $props) { + foreach ($props as $prop) { + if(isset($this->selectedParams[$prop]) == false) { + return false; + } + } + return true; + } function hasErrorOccurred () { return $this->errorCount > 0; diff --git a/juggl/timetracking.php b/juggl/timetracking.php index 246799e..3ce3e77 100644 --- a/juggl/timetracking.php +++ b/juggl/timetracking.php @@ -1,5 +1,7 @@ get("user_id"); + $params->select("request"); + + // Is id given, should update? + if ($params->exists(["record_id"])) { + $this->updateTimeRecord($user_id, $params); + } else { + if ($params->exists(["start_time", "end_time", "duration"]) == false) { + respondStatus(400, "Missing parameter"); + } + + $project_id = $params->get("project_id"); + if ($this->isProjectValid($project_id, $user_id) == false) { + $project_id = null; + } + + $device_id = $params->get("device_id"); + if ($this->isDeviceValid($device_id, $user_id) == false) { + $device_id = null; + } + + $this->addTimeRecord($user_id, $params, $project_id, $device_id); + } + } + + private function isProjectValid ($project_id, $user_id) { + $db = new DbOperations(); + $db->select("projects"); + $db->where("project_id", Comparison::EQUAL, $project_id); + $db->where("user_id", Comparison::EQUAL, $user_id); + + return count($db->execute()) == 1; + } + + private function isDeviceValid ($device_id, $user_id) { + $db = new DbOperations(); + $db->select("devices"); + $db->where("device_id", Comparison::EQUAL, $device_id); + $db->where("user_id", Comparison::EQUAL, $user_id); + + return count($db->execute()) == 1; + } + + private function addTimeRecord ($user_id, $params, $project_id = null, $device_id = null) { + $data = ["user_id" => $user_id, + "start_time" => $params->get("start_time"), + "end_time" => $params->get("end_time"), + "duration" => $params->get("duration"), + "project_id" => $project_id, + "device_id" => $device_id]; + + $db = new DbOperations(); + $db->insert("time_records", $data); + $db->execute(); + } + + private function updateTimeRecord ($user_id, $params) { + $data = ["user_id" => $user_id, + "record_id" => $params->get("record_id") + ]; + + $anythingUpdated = false; + + if ($params->exists(["start_time"])) { + $data["start_time"] = $params->get("start_time"); + $anythingUpdated = true; + } + if ($params->exists(["end_time"])) { + $data["end_time"] = $params->get("end_time"); + $anythingUpdated = true; + } + if ($params->exists(["duration"])) { + $data["duration"] = $params->get("duration"); + $anythingUpdated = true; + } + if ($params->exists(["project_id"])) { + $data["project_id"] = $params->get("project_id"); + $anythingUpdated = true; + } + if ($params->exists(["device_id"])) { + $data["device_id"] = $params->get("device_id"); + $anythingUpdated = true; + } + + if ($anythingUpdated == false) { + return; + } + + $db = new DbOperations(); + $db->update("time_records", $data); + $db->execute(); } } diff --git a/juggl_documentation.txt b/juggl_documentation.txt index e69de29..0d6f550 100644 --- a/juggl_documentation.txt +++ b/juggl_documentation.txt @@ -0,0 +1,40 @@ +Juggl Documentation + + Goal + Hold information about projects + Timetracking + Invoice generation + Shared files + ToDo + Progress + Shared Workspace for client + Deadlines + API interface + Ticket system + + ToDo + High Priority + Time tracking + API interface + Web interface + Low Priority + Timetracking API + Setting null does not work + Web interface + + Datbase + Table prefix + ju_ + + API + timetracking + POST + api_key + user_id + request + start_time (required for insert) + end_time (required for insert) + duration (required for insert) + project_id (optional) + device_id (optional) + record_id (optional, update when given) \ No newline at end of file