Added basic time record api interface for posting

This commit is contained in:
Maximilian Giller 2020-01-11 17:56:21 +01:00
parent f58e976373
commit 6e3ff52607
8 changed files with 228 additions and 60 deletions

View file

@ -0,0 +1,6 @@
<?php
require_once(__DIR__."/../services/configReader.inc.php");
$config = new ConfigReader();
$config->readPathFile(__DIR__."/config.path");
?>

View file

@ -2,7 +2,6 @@
require_once(__DIR__."/authenticator.inc.php"); require_once(__DIR__."/authenticator.inc.php");
require_once(__DIR__."/responses.inc.php"); require_once(__DIR__."/responses.inc.php");
require_once(__DIR__."/requestTypes.inc.php"); require_once(__DIR__."/requestTypes.inc.php");
require_once(__DIR__."/dbOperations.inc.php");
require_once(__DIR__."/paramCleaner.inc.php"); require_once(__DIR__."/paramCleaner.inc.php");
abstract class ApiBranch { abstract class ApiBranch {
@ -13,26 +12,27 @@ abstract class ApiBranch {
} }
function execute ($authenticationRequired = true) { function execute ($authenticationRequired = true) {
$params = $this->getParams();
if ($authenticationRequired) { if ($authenticationRequired) {
$auth = new Authenticator(); $auth = new Authenticator();
if (!$auth->isAuthenticated($_SESSION, $_REQUEST)) { if (!$auth->isAuthenticated($params)) {
$this->authenticationMissing($this->getParams()); $this->authenticationMissing($params);
return; return;
} }
} }
$currentType = currentRequestType(); $currentType = currentRequestType();
if($currentType === RequestType::GET) { if($currentType === RequestType::GET) {
$this->get($this->getParams()); $this->get($params);
} else if ($currentType === RequestType::POST) { } else if ($currentType === RequestType::POST) {
$this->post($this->getParams()); $this->post($params);
} }
} }
private function getParams() { private function getParams() {
$content = json_decode(file_get_contents('php://input'), true); $content = json_decode(file_get_contents('php://input'), true);
$contentArray = array("json" => $content); return new ParamCleaner(array_merge($content, $_REQUEST, $_SESSION, $_FILES));
return new ParamCleaner(array_merge($contentArray, $_REQUEST, $_SESSION, $_FILES));
} }
} }
?> ?>

View file

@ -1,43 +1,20 @@
<?php <?php
require(__DIR__."/dbOperations.inc.php"); require_once(__DIR__."/dbOperations.inc.php");
class Authenticator { class Authenticator {
function isApiKeyAuthenticated($key) { function isApiKeyAuthenticated($api_key, $user_id) {
$db = new DbOperations(); $db = new DbOperations();
$db->select("api_keys", array("quota_max", "client_key")); $db->select("api_keys", ["enabled"]);
$db->where("client_key", Comparison::EQUAL, $key); $db->where("api_key", Comparison::EQUAL, $api_key);
$db->where("user_id", Comparison::EQUAL, $user_id);
$result = $db->execute(); $result = $db->execute();
if (count($result) == 1 && $result[0]['quota_max'] > 0) return count($result) == 1 && $result[0]['enabled'];
return true;
else
return false;
} }
function isSessionAuthenticated($session) { function isAuthenticated($params) {
if (isset($session['stayloggedin'])) { return $this->isApiKeyAuthenticated($params->get('api_key'), $params->get('user_id'));
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);
}
} }
} }
?> ?>

View file

@ -3,6 +3,10 @@
class ConfigReader { class ConfigReader {
private const VALUE_SEPARATOR = '='; private const VALUE_SEPARATOR = '=';
function __construct () {
$this->configuration = array();
}
function readFile ($path) { function readFile ($path) {
if (file_exists($path) == false) if (file_exists($path) == false)
return; return;
@ -17,6 +21,11 @@ class ConfigReader {
} }
} }
function readPathFile ($pathToPathFile) {
$this->readFile($pathToPathFile);
$this->readFile(__DIR__."/../".$this->getSetting("relativepath"));
}
function getSetting ($key) { function getSetting ($key) {
if (array_key_exists($key, $this->configuration) == false) if (array_key_exists($key, $this->configuration) == false)
return NULL; return NULL;

View file

@ -1,34 +1,38 @@
<?php <?php
require(__DIR__."/configReader.inc.php"); require_once(__DIR__."/basicEnum.inc.php");
require(__DIR__."/basicEnum.inc.php");
class DbOperations { class DbOperations {
function __construct () { function __construct ($tablePrefix = null) {
$this->resetQuery(); $this->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() { function resetQuery() {
$this->query = ""; $this->query = "";
$this->data = array(); $this->data = array();
$this->table = ""; $this->table = "";
$this->tablePrefix = "";
} }
private function openConnection () { private function openConnection () {
$config = new ConfigReader(); $host = $this->config->getSetting('host');
$config->readFile(__DIR__."/../config/config.path"); $dbname = $this->config->getSetting('dbname');
$config->readFile(__DIR__."/../".$config->getSetting("relativepath"));
$host = $config->getSetting('host');
$dbname = $config->getSetting('dbname');
$dsn = "mysql:host=$host;dbname=$dbname"; $dsn = "mysql:host=$host;dbname=$dbname";
$options = array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC); $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()) { function select (string $table, array $attributes = array()) {
$this->table = $table; $this->table = $this->tablePrefix.$table;
if (count($attributes) == 0) if (count($attributes) == 0)
$formattedAttributes = "*"; $formattedAttributes = "*";
else { else {
@ -41,7 +45,7 @@ class DbOperations {
$formattedAttributes = implode(', ', $attributes); $formattedAttributes = implode(', ', $attributes);
} }
$this->addToQuery("SELECT $formattedAttributes FROM $table"); $this->addToQuery("SELECT $formattedAttributes FROM $this->tablePrefix$table");
return $this; return $this;
} }
@ -62,7 +66,7 @@ class DbOperations {
} }
function insert (string $table, array $data) { function insert (string $table, array $data) {
$this->table = $table; $this->table = $this->tablePrefix.$table;
$attributes = implode(", ", array_keys($data)); $attributes = implode(", ", array_keys($data));
$valuesIds = array(); $valuesIds = array();
@ -71,13 +75,40 @@ class DbOperations {
} }
$values = implode(" , ", $valuesIds); $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; return $this;
} }
function update (string $table, array $data) { function update (string $table, array $data) {
$this->table = $table; $this->table = $this->tablePrefix.$table;
$sets = array(); $sets = array();
foreach($data as $attribute => $value) { foreach($data as $attribute => $value) {
@ -86,15 +117,15 @@ class DbOperations {
} }
$setString = implode(", ", $sets); $setString = implode(", ", $sets);
$this->addToQuery("UPDATE $table SET $setString"); $this->addToQuery("UPDATE $this->tablePrefix$table SET $setString");
return $this; return $this;
} }
function delete (string $table) { 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; return $this;
} }
@ -118,12 +149,15 @@ class DbOperations {
return $this; return $this;
} }
function innerJoin (string $table, string $externAttribute, string $internAttribute, string $internTable = "") { function innerJoin (string $table, string $externAttribute, string $internAttribute = "", string $internTable = "") {
if ($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); $this->addToQuery($innerJoin);

View file

@ -25,6 +25,15 @@ class ParamCleaner {
} }
} }
function exists (array $props) {
foreach ($props as $prop) {
if(isset($this->selectedParams[$prop]) == false) {
return false;
}
}
return true;
}
function hasErrorOccurred () { function hasErrorOccurred () {
return $this->errorCount > 0; return $this->errorCount > 0;
} }

View file

@ -1,5 +1,7 @@
<?php <?php
session_start();
require_once(__DIR__."/services/apiBranch.inc.php"); require_once(__DIR__."/services/apiBranch.inc.php");
require_once(__DIR__."/services/dbOperations.inc.php");
require_once(__DIR__."/services/jsonBuilder.inc.php"); require_once(__DIR__."/services/jsonBuilder.inc.php");
require_once(__DIR__."/services/responses.inc.php"); require_once(__DIR__."/services/responses.inc.php");
@ -9,6 +11,97 @@ class TimeTrackingBranch extends ApiBranch {
} }
function post (ParamCleaner $params) { function post (ParamCleaner $params) {
$user_id = $params->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();
} }
} }

View file

@ -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)