Added basic time record api interface for posting
This commit is contained in:
parent
f58e976373
commit
6e3ff52607
8 changed files with 228 additions and 60 deletions
6
juggl/config/config.inc.php
Normal file
6
juggl/config/config.inc.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
require_once(__DIR__."/../services/configReader.inc.php");
|
||||||
|
|
||||||
|
$config = new ConfigReader();
|
||||||
|
$config->readPathFile(__DIR__."/config.path");
|
||||||
|
?>
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
Loading…
Reference in a new issue