Added first draft

This commit is contained in:
Maximilian Giller 2020-01-10 22:33:46 +01:00
parent cae31b68fd
commit f58e976373
13 changed files with 495 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
juggl/config/config.txt
juggl/config/config.path

View file

@ -0,0 +1 @@
relativepath=config/config.txt

View file

@ -0,0 +1,4 @@
host=HOST
dbname=DBNAME
username=USERNAME
password=PASSWORD

View file

@ -0,0 +1,38 @@
<?php
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 {
function get (ParamCleaner $params) {}
function post (ParamCleaner $params) {}
function authenticationMissing (ParamCleaner $params) {
respondStatus(403);
}
function execute ($authenticationRequired = true) {
if ($authenticationRequired) {
$auth = new Authenticator();
if (!$auth->isAuthenticated($_SESSION, $_REQUEST)) {
$this->authenticationMissing($this->getParams());
return;
}
}
$currentType = currentRequestType();
if($currentType === RequestType::GET) {
$this->get($this->getParams());
} else if ($currentType === RequestType::POST) {
$this->post($this->getParams());
}
}
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));
}
}
?>

View file

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

View file

@ -0,0 +1,33 @@
<?php
abstract class BasicEnum {
private static $constCacheArray = NULL;
private static function getConstants() {
if (self::$constCacheArray == NULL) {
self::$constCacheArray = [];
}
$calledClass = get_called_class();
if (!array_key_exists($calledClass, self::$constCacheArray)) {
$reflect = new ReflectionClass($calledClass);
self::$constCacheArray[$calledClass] = $reflect->getConstants();
}
return self::$constCacheArray[$calledClass];
}
public static function isValidName($name, $strict = false) {
$constants = self::getConstants();
if ($strict) {
return array_key_exists($name, $constants);
}
$keys = array_map('strtolower', array_keys($constants));
return in_array(strtolower($name), $keys);
}
public static function isValidValue($value, $strict = true) {
$values = array_values(self::getConstants());
return in_array($value, $values, $strict);
}
}
?>

View file

@ -0,0 +1,45 @@
<?php
class ConfigReader {
private const VALUE_SEPARATOR = '=';
function readFile ($path) {
if (file_exists($path) == false)
return;
$this->configuration = array();
foreach (file($path) as $line) {
$valuePair = $this->convertLine(trim($line));
if ($valuePair === false)
continue;
$this->configuration[$valuePair['key']] = $valuePair['value'];
}
}
function getSetting ($key) {
if (array_key_exists($key, $this->configuration) == false)
return NULL;
return $this->configuration[$key];
}
private function convertLine($line) {
if ($line == "")
return False;
$splitted = explode (self::VALUE_SEPARATOR, $line, 2);
$key = $splitted[0];
$value = "";
for ($i = 1; $i < sizeof($splitted); $i++) {
if ($i > 1) {
$value .= "=";
}
$value .= $splitted[$i];
}
return ['key' => $key, 'value' => $value];
}
}
?>

View file

@ -0,0 +1,190 @@
<?php
require(__DIR__."/configReader.inc.php");
require(__DIR__."/basicEnum.inc.php");
class DbOperations {
function __construct () {
$this->resetQuery();
}
function resetQuery() {
$this->query = "";
$this->data = array();
$this->table = "";
}
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');
$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);
}
function select (string $table, array $attributes = array()) {
$this->table = $table;
if (count($attributes) == 0)
$formattedAttributes = "*";
else {
for($i = 0; $i < count($attributes); $i++){
$a = $attributes[$i];
if (strpos($a, ".") === false) {
$attributes[$i] = "$this->table.$a";
}
}
$formattedAttributes = implode(', ', $attributes);
}
$this->addToQuery("SELECT $formattedAttributes FROM $table");
return $this;
}
function orderBy (string $attribute, string $order = Order::ASC) {
$this->addToQuery("ORDER BY $attribute $order");
return $this;
}
static function getLatestIdInTable (string $table, string $attribute = "id") {
$db = new DbOperations();
$db->select($table, array($attribute));
$db->orderBy($attribute, Order::DESC);
return $db->execute()[0][$attribute];
}
function insert (string $table, array $data) {
$this->table = $table;
$attributes = implode(", ", array_keys($data));
$valuesIds = array();
foreach($data as $attribute => $value) {
$valuesIds[] = $this->addData($value, $attribute);
}
$values = implode(" , ", $valuesIds);
$this->addToQuery("INSERT INTO $table ( $attributes ) VALUES ( $values )");
return $this;
}
function update (string $table, array $data) {
$this->table = $table;
$sets = array();
foreach($data as $attribute => $value) {
$valueId = $this->addData($value, $attribute);
$sets[] = "$attribute = $valueId";
}
$setString = implode(", ", $sets);
$this->addToQuery("UPDATE $table SET $setString");
return $this;
}
function delete (string $table) {
$this->table = $table;
$this->addToQuery("DELETE FROM $table");
return $this;
}
private function addToQuery (string $phrase) {
$delimeter = " ";
$this->query = implode($delimeter, array($this->query, $phrase));
}
function where (string $attribute, string $comparison, $value, string $connector = Combination::AND) {
if (Comparison::isValidValue($comparison) == false)
return;
$keyWord = "WHERE";
if (!(strpos($this->query, $keyWord) === false))
$keyWord = $connector;
$valueId = $this->addData($value, $attribute);
$this->addToQuery("$keyWord $attribute $comparison $valueId");
return $this;
}
function innerJoin (string $table, string $externAttribute, string $internAttribute, string $internTable = "") {
if ($internTable === "") {
$internTable = $this->table;
}
$innerJoin = "INNER JOIN $table ON $table.$externAttribute = $internTable.$internAttribute";
$this->addToQuery($innerJoin);
return $this;
}
private function addData($data, $attribute) {
$name = str_replace(".", "", $attribute);
$this->data[$name] = $data;
return ":".$name;
}
function execute() {
try{
$this->openConnection();
$pdoQuery = $this->pdo->prepare($this->query);
$pdoQuery->execute($this->data);
$results = array();
while($row = $pdoQuery->fetch()) {
$results[] = $row;
}
$this->resetQuery();
return $results;
} catch (PDOException $e) {
// TODO: Hide errors from user and log them
print($e);
return array();
}
}
function sql(string $sqlStatement, array $data) {
$this->query = $sqlStatement;
foreach($data as $attribute => $value) {
$this->addData($value, $attribute);
}
}
}
abstract class Comparison extends BasicEnum {
const EQUAL = "=";
const GREATER_THAN = ">";
const GREATER_THAN_OR_EQUAL = ">=";
const LESS_THAN = "<";
const LESS_THAN_OR_EQUAL = "<=";
const UNEQUAL = "!=";
const LIKE = "LIKE";
}
abstract class Combination extends BasicEnum {
const AND = "AND";
const OR = "OR";
}
abstract class Order extends BasicEnum {
const ASC = "ASC";
const DESC = "DESC";
}
?>

View file

@ -0,0 +1,37 @@
<?php
class JsonBuilder {
function __construct () {
$this->jsonData = array();
}
function getJson () {
return json_encode($this->jsonData, JSON_FORCE_OBJECT);
}
function getArray () {
return $this->jsonData;
}
function addCategories (array $categories) {
$columns = array("id" => "",
"name" => "");
foreach ($categories as $category) {
$this->jsonData['categories'] = array();
$this->jsonData['categories'][] = $this->createJsonArray($category, $columns);
}
return $this;
}
private function createJsonArray (array $data, array $columns) {
$jsonArray = array();
foreach ($columns as $key => $column) {
if ($column === "") {
$column = $key;
}
$jsonArray[$key] = $data[$column];
}
return $jsonArray;
}
}
?>

View file

@ -0,0 +1,41 @@
<?php
class ParamCleaner {
function __construct (array $params) {
$this->sourceParams = $params;
$this->selectedParams = $params;
$this->errorCount = 0;
$this->errorMessage = "";
}
function select (string $prop = "") {
if ($prop == "") {
$this->selectedParams = $this->sourceParams;
} else {
$this->selectedParams = $this->selectedParams[$prop];
}
}
function get (string $prop) {
if(isset($this->selectedParams[$prop])) {
return $this->selectedParams[$prop];
} else {
$this->errorCount += 1;
$this->errorMessage .= "Property \"{$prop}\" missing. ";
return null;
}
}
function hasErrorOccurred () {
return $this->errorCount > 0;
}
function getErrorMessage () {
return $this->errorMessage;
}
function resetErrors () {
$this->errorMessage = "";
$this->errorCount = 0;
}
}
?>

View file

@ -0,0 +1,19 @@
<?php
require_once(__DIR__.'/basicEnum.inc.php');
abstract class RequestType extends BasicEnum {
const GET = "GET";
const POST = "POST";
const PUT = "PUT";
const DELETE = "DELETE";
}
function currentRequestType () {
$requestType = $_SERVER['REQUEST_METHOD'];
if (RequestType::isValidValue($requestType)) {
return $requestType;
} else {
return null;
}
}
?>

View file

@ -0,0 +1,25 @@
<?php
require_once(__DIR__."/jsonBuilder.inc.php");
function respondJson(JsonBuilder $builder) {
header('Content-type: application/json');
echo($builder->getJson());
}
function respondHtml(string $html) {
print($html);
}
function respondStatus(int $statusCode, string $message = "") {
http_response_code($statusCode);
die($message);
}
function redirectBack() {
header("Location: {$_SERVER['HTTP_REFERER']}");
}
function redirectTo($url) {
header("Location: {$url}");
}
?>

17
juggl/timetracking.php Normal file
View file

@ -0,0 +1,17 @@
<?php
require_once(__DIR__."/services/apiBranch.inc.php");
require_once(__DIR__."/services/jsonBuilder.inc.php");
require_once(__DIR__."/services/responses.inc.php");
class TimeTrackingBranch extends ApiBranch {
function get (ParamCleaner $params) {
respondStatus(404);
}
function post (ParamCleaner $params) {
}
}
$branch = new TimeTrackingBranch();
$branch->execute();
?>