web-base/core/Api/Request.class.php

183 lines
5.7 KiB
PHP
Raw Normal View History

2020-02-09 23:02:19 +01:00
<?php
namespace Api;
2020-04-03 15:56:04 +02:00
use Objects\User;
2020-02-09 23:02:19 +01:00
class Request {
2020-04-03 15:56:04 +02:00
protected User $user;
protected array $params;
protected string $lastError;
protected array $result;
protected bool $success;
protected bool $isPublic;
protected bool $loginRequired;
protected bool $variableParamCount;
protected bool $isDisabled;
protected bool $apiKeyAllowed;
2020-04-03 18:09:01 +02:00
protected int $requiredGroup;
2020-06-14 19:39:52 +02:00
protected bool $csrfTokenRequired;
2020-04-03 15:56:04 +02:00
private array $aDefaultParams;
private array $allowedMethods;
2020-04-03 18:09:01 +02:00
private bool $externalCall;
2020-04-03 15:56:04 +02:00
public function __construct(User $user, bool $externalCall = false, array $params = array()) {
2020-02-09 23:02:19 +01:00
$this->user = $user;
$this->aDefaultParams = $params;
2020-04-03 18:09:01 +02:00
2020-02-09 23:02:19 +01:00
$this->success = false;
$this->result = array();
2020-04-03 18:09:01 +02:00
$this->externalCall = $externalCall;
2020-02-09 23:02:19 +01:00
$this->isPublic = true;
$this->isDisabled = false;
$this->loginRequired = false;
$this->variableParamCount = false;
$this->apiKeyAllowed = true;
$this->allowedMethods = array("GET", "POST");
2020-04-03 18:09:01 +02:00
$this->requiredGroup = 0;
$this->lastError = "";
2020-06-14 19:39:52 +02:00
$this->csrfTokenRequired = false;
2020-02-09 23:02:19 +01:00
}
protected function forbidMethod($method) {
if (($key = array_search($method, $this->allowedMethods)) !== false) {
unset($this->allowedMethods[$key]);
}
}
2020-02-10 00:52:25 +01:00
public function parseParams($values) {
2020-02-09 23:02:19 +01:00
foreach($this->params as $name => $param) {
2020-02-10 00:52:25 +01:00
$value = (isset($values[$name]) ? $values[$name] : NULL);
2020-02-09 23:02:19 +01:00
if(!$param->optional && is_null($value)) {
$this->lastError = 'Missing parameter: ' . $name;
return false;
}
if(!is_null($value)) {
if(!$param->parseParam($value)) {
$value = print_r($value, true);
$this->lastError = "Invalid Type for parameter: $name '$value' (Required: " . $param->getTypeName() . ")";
return false;
}
}
}
return true;
}
2020-02-10 00:52:25 +01:00
public function parseVariableParams($values) {
foreach($values as $name => $value) {
2020-02-09 23:02:19 +01:00
if(isset($this->params[$name])) continue;
$type = Parameter\Parameter::parseType($value);
$param = new Parameter\Parameter($name, $type, true);
$param->parseParam($value);
$this->params[$name] = $param;
}
}
2020-02-10 00:52:25 +01:00
public function execute($values = array()) {
2020-02-09 23:02:19 +01:00
$this->params = $this->aDefaultParams;
$this->success = false;
$this->result = array();
$this->lastError = '';
if($this->user->isLoggedIn()) {
$this->result['logoutIn'] = $this->user->getSession()->getExpiresSeconds();
}
2020-04-03 18:09:01 +02:00
if($this->externalCall) {
2020-02-10 00:52:25 +01:00
$values = $_REQUEST;
2020-02-09 23:02:19 +01:00
if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER["CONTENT_TYPE"]) && in_array("application/json", explode(";", $_SERVER["CONTENT_TYPE"]))) {
$jsonData = json_decode(file_get_contents('php://input'), true);
2020-06-14 22:35:01 +02:00
if ($jsonData) {
$values = array_merge($values, $jsonData);
} else {
$this->lastError = 'Invalid request body.';
header('HTTP 1.1 400 Bad Request');
return false;
}
2020-02-09 23:02:19 +01:00
}
}
if($this->isDisabled) {
$this->lastError = "This function is currently disabled.";
return false;
}
2020-04-03 18:09:01 +02:00
if($this->externalCall && !$this->isPublic) {
2020-02-09 23:02:19 +01:00
$this->lastError = 'This function is private.';
header('HTTP 1.1 403 Forbidden');
return false;
}
if(!in_array($_SERVER['REQUEST_METHOD'], $this->allowedMethods)) {
$this->lastError = 'This method is not allowed';
header('HTTP 1.1 405 Method Not Allowed');
return false;
}
2020-04-03 18:09:01 +02:00
if($this->loginRequired || $this->requiredGroup > 0) {
2020-06-14 19:39:52 +02:00
$apiKeyAuthorized = false;
2020-02-10 00:52:25 +01:00
if(isset($values['api_key']) && $this->apiKeyAllowed) {
$apiKey = $values['api_key'];
2020-06-14 19:39:52 +02:00
$apiKeyAuthorized = $this->user->authorize($apiKey);
2020-02-09 23:02:19 +01:00
}
2020-06-14 19:39:52 +02:00
if(!$this->user->isLoggedIn() && !$apiKeyAuthorized) {
2020-02-09 23:02:19 +01:00
$this->lastError = 'You are not logged in.';
header('HTTP 1.1 401 Unauthorized');
return false;
2020-04-03 18:09:01 +02:00
} else if($this->requiredGroup > 0 && !$this->user->hasGroup($this->requiredGroup)) {
$this->lastError = "Insufficient permissions. Required group: ". GroupName($this->requiredGroup);
header('HTTP 1.1 401 Unauthorized');
return false;
2020-06-14 19:39:52 +02:00
} else if($this->csrfTokenRequired && !$apiKeyAuthorized && $this->externalCall) {
// csrf token required + external call
// if it's not a call with API_KEY, check for csrf_token
if (!isset($values["csrf_token"]) || strcmp($values["csrf_token"], $this->user->getSession()->getCsrfToken()) !== 0) {
$this->lastError = "CSRF-Token mismatch";
header('HTTP 1.1 403 Forbidden');
return false;
}
2020-02-09 23:02:19 +01:00
}
}
2020-02-10 00:52:25 +01:00
if(!$this->parseParams($values))
2020-02-09 23:02:19 +01:00
return false;
if($this->variableParamCount)
2020-02-10 00:52:25 +01:00
$this->parseVariableParams($values);
2020-02-09 23:02:19 +01:00
if(!$this->user->getSQL()->isConnected()) {
$this->lastError = $this->user->getSQL()->getLastError();
return false;
}
$this->user->getSQL()->setLastError('');
$this->success = true;
return true;
}
protected function createError($err) {
$this->success = false;
$this->lastError = $err;
return false;
}
protected function getParam($name) { return isset($this->params[$name]) ? $this->params[$name]->value : NULL; }
2020-04-03 15:56:04 +02:00
2020-02-09 23:02:19 +01:00
public function isPublic() { return $this->isPublic; }
public function getLastError() { return $this->lastError; }
public function getResult() { return $this->result; }
public function success() { return $this->success; }
public function loginRequired() { return $this->loginRequired; }
2020-04-03 18:09:01 +02:00
public function isExternalCall() { return $this->externalCall; }
2020-02-09 23:02:19 +01:00
public function getJsonResult() {
$this->result['success'] = $this->success;
$this->result['msg'] = $this->lastError;
return json_encode($this->result);
}
2020-04-03 15:56:04 +02:00
}