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__."/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));
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -1,43 +1,20 @@
|
|||
<?php
|
||||
require(__DIR__."/dbOperations.inc.php");
|
||||
require_once(__DIR__."/dbOperations.inc.php");
|
||||
|
||||
class Authenticator {
|
||||
function isApiKeyAuthenticated($key) {
|
||||
function isApiKeyAuthenticated($api_key, $user_id) {
|
||||
$db = new DbOperations();
|
||||
$db->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'));
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -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;
|
||||
|
|
|
@ -1,34 +1,38 @@
|
|||
<?php
|
||||
require(__DIR__."/configReader.inc.php");
|
||||
require(__DIR__."/basicEnum.inc.php");
|
||||
require_once(__DIR__."/basicEnum.inc.php");
|
||||
|
||||
class DbOperations {
|
||||
function __construct () {
|
||||
function __construct ($tablePrefix = null) {
|
||||
$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() {
|
||||
$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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
session_start();
|
||||
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/responses.inc.php");
|
||||
|
||||
|
@ -9,6 +11,97 @@ class TimeTrackingBranch extends ApiBranch {
|
|||
}
|
||||
|
||||
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