304 lines
7.8 KiB
PHP
304 lines
7.8 KiB
PHP
<?php #lib/20_routes.php
|
|
|
|
/**************************************************/
|
|
/********************* Route **********************/
|
|
/**************************************************/
|
|
|
|
class Condition
|
|
{
|
|
protected $mode = "and";
|
|
protected $list = [];
|
|
protected $subs = [];
|
|
|
|
|
|
public function __construct($mode = "and") {$this->mode = $mode;}
|
|
|
|
public function Add($field, $value, $table = null) {
|
|
$this->list[] = ["field" => $field, "value" => $value, "table" => $table];
|
|
return $this;
|
|
}
|
|
|
|
public function Sub(Condition $condition) {
|
|
$this->subs[] = $condition;
|
|
return $this;
|
|
}
|
|
|
|
private function checkValue($is, $should) {
|
|
if (is_array($is)) {
|
|
if (array_key_exists("ID", $is)) {
|
|
return $should==$is["ID"];
|
|
} else {
|
|
foreach ($is as $entry) {
|
|
if ($this->checkValue($entry, $should)) {
|
|
return true;
|
|
} }
|
|
return false;
|
|
}
|
|
return in_array($should, $is);
|
|
} else {
|
|
return $should==$is;
|
|
} }
|
|
|
|
public function CheckInput($json) {
|
|
if ($this->mode=="and") {
|
|
foreach ($this->list as $cond) {
|
|
if (!$this->checkValue($json[$cond["field"]], $cond["value"])) {
|
|
return false;
|
|
} }
|
|
foreach ($this->subs as $sub) {
|
|
if (!$sub->CheckInput($json)) {
|
|
return false;
|
|
} }
|
|
return true;
|
|
} else if ($this->mode=="or") {
|
|
foreach ($this->list as $cond) {
|
|
if ($this->checkValue($json[$cond["field"]], $cond["value"])) {
|
|
return true;
|
|
} }
|
|
foreach ($this->subs as $sub) {
|
|
if ($sub->CheckInput($json)) {
|
|
return true;
|
|
} }
|
|
return false;
|
|
}
|
|
return false; // Failsafe if mode was misconfigured
|
|
}
|
|
|
|
public function GetFilterCondition() {
|
|
$conditionList = new \Filter\ConditionList($this->mode);
|
|
foreach ($this->list as $cond) {
|
|
$conditionList->Add(new \Filter\Condition($cond["field"], "=", $cond["value"], $cond["table"]));
|
|
}
|
|
foreach ($this->subs as $sub) {
|
|
$conditionList->Add($sub->GetFilterCondition());
|
|
}
|
|
return $conditionList;
|
|
}
|
|
|
|
public function Export() {
|
|
if (sizeof($this->list) + sizeof($this->subs) == 1) {
|
|
return empty($this->list) ? $this->subs[0]->Export() : $this->list[0];
|
|
}
|
|
$ret = [
|
|
"mode" => $this->mode,
|
|
"conditions" => $this->list
|
|
];
|
|
foreach ($this->subs as &$condition) {
|
|
$ret["conditions"][] = $condition->Export();
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
public static function Make($mode = "and") {
|
|
return (new self($mode));
|
|
}
|
|
}
|
|
|
|
class Restriction
|
|
{
|
|
protected $condition = null;
|
|
protected $limits = [];
|
|
|
|
public function AddCondition(\Condition $condition) {
|
|
if (is_null($this->condition)) {
|
|
$this->condition = \Condition::Make("or");
|
|
}
|
|
$this->condition->Sub($condition);
|
|
return $this;
|
|
}
|
|
|
|
public function AddLimits($fields) {
|
|
if (is_array($fields)) {
|
|
foreach ($fields as $field) {
|
|
$this->limits[] = $field;
|
|
}
|
|
} else {
|
|
$this->limits[] = $fields;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function CheckInput($id = null, $json = []) {
|
|
// Check limits
|
|
if (!empty($json) && !empty($this->limits)) {
|
|
foreach ($json as $field => $value) {
|
|
if (!in_array($field, $this->limits)) {
|
|
return false;
|
|
} } }
|
|
|
|
// Check condition
|
|
return is_null($this->condition) || $this->condition->CheckInput(array_merge(["ID" => $id], $json));
|
|
}
|
|
|
|
public function GetFilterCondition() {
|
|
return is_null($this->condition) ? null : $this->condition->GetFilterCondition();
|
|
}
|
|
|
|
public function Export() {
|
|
return [
|
|
"limits" => $this->limits,
|
|
"condition" => is_null($this->condition) ? null : $this->condition->Export()
|
|
];
|
|
}
|
|
}
|
|
|
|
class Right
|
|
{
|
|
protected $requiredRight = null;
|
|
protected $restriction = null;
|
|
protected $allow = [];
|
|
|
|
public function __construct($requiredRight = null) {
|
|
$this->requiredRight = $requiredRight;
|
|
}
|
|
|
|
public function IsApplicable() {
|
|
return is_null($this->requiredRight) || \Login::HasRight($this->requiredRight);
|
|
}
|
|
|
|
public function IsAdmin() {
|
|
return sizeof($this->allow)==6 && is_null($this->restriction);
|
|
}
|
|
|
|
public function Allow($allow = "readonly") {
|
|
switch ($allow) {
|
|
case "admin":
|
|
$this->allow = ["get", "update", "insert", "remove", "upload", "erase"];
|
|
break;
|
|
case "nodelete":
|
|
$this->allow = ["get", "update", "insert", "upload"];
|
|
break;
|
|
case "justdata":
|
|
$this->allow = ["get", "update", "insert", "remove"];
|
|
break;
|
|
case "update":
|
|
$this->allow = ["get", "update"];
|
|
break;
|
|
case "readonly":
|
|
$this->allow = ["get"];
|
|
break;
|
|
default:
|
|
$this->allow = [];
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function Require(\Condition $condition) {
|
|
if (is_null($this->restriction)) {
|
|
$this->restriction = new \Restriction();
|
|
}
|
|
$this->restriction->AddCondition($condition);
|
|
return $this;
|
|
}
|
|
|
|
public function Limit($fields) {
|
|
if (is_null($this->restriction)) {
|
|
$this->restriction = new \Restriction();
|
|
}
|
|
$this->restriction->AddLimits($fields);
|
|
return $this;
|
|
}
|
|
|
|
public function GetAllowed() {
|
|
return $this->allow;
|
|
}
|
|
|
|
public function GetRestriction() {
|
|
return $this->restriction;
|
|
}
|
|
|
|
public static function Make($requiredRight = null) {
|
|
return (new self($requiredRight));
|
|
}
|
|
|
|
public static function AllowSelf() {
|
|
return self::Make()->Allow("readonly")->Require(\Condition::Make()->Add("ID", \Login::ID()));
|
|
}
|
|
|
|
public static function AllowUpdateSelf() {
|
|
return self::Make()->Allow("update")->Require(\Condition::Make()->Add("ID", \Login::ID()));
|
|
}
|
|
}
|
|
|
|
class Rights {
|
|
// false == not allowed
|
|
// array with refs to restrictions [a ... n] == restrictions apply
|
|
// true == allowed without restrictions
|
|
protected $actions = [
|
|
"get" => false,
|
|
"update" => false,
|
|
"insert" => false,
|
|
"remove" => false,
|
|
"upload" => false,
|
|
"erase" => false
|
|
];
|
|
|
|
public function __construct() {}
|
|
|
|
public function Add($right) {
|
|
// If user already has admin rights or does not posess this right, skip
|
|
if ($right->IsApplicable()) {
|
|
$restriction = $right->GetRestriction();
|
|
// Parse the right for every action
|
|
foreach ($right->GetAllowed() as $action) {
|
|
if (is_null($restriction)) {
|
|
// No restriction in the added right, so just overwrite current restrictions
|
|
$this->actions[$action] = true;
|
|
} else if (is_array($this->actions[$action])) {
|
|
// Restrictions applied before (or nothing was allowed) and in the new one, so add new restrictions
|
|
$this->actions[$action][] = $restriction;
|
|
} else if ($this->actions[$action]===false) {
|
|
// Not allowed before, but now restrictions apply
|
|
$this->actions[$action] = [$restriction];
|
|
} } }
|
|
return $this;
|
|
}
|
|
|
|
public function CheckInput($action, $id = null, $json = []) {
|
|
if (!is_array($this->actions[$action])) {
|
|
return $this->actions[$action];
|
|
}
|
|
|
|
// At this point, some but not everything is allowed for this user and this action, so check more carefully
|
|
foreach ($this->actions[$action] as $restriction) {
|
|
if ($restriction->CheckInput($id, $json)) {
|
|
return true;
|
|
} }
|
|
return false;
|
|
}
|
|
|
|
public function RestrictFilter() {
|
|
if (is_array($this->actions["get"])) {
|
|
$restrictions = new \Filter\ConditionList("or");
|
|
foreach ($this->actions["get"] as $restriction) {
|
|
$filterCondition = $restriction->GetFilterCondition();
|
|
if (!is_null($filterCondition)) {
|
|
$restrictions->Add($filterCondition);
|
|
}
|
|
|
|
}
|
|
\Filter\Filter::Restrict($restrictions);
|
|
return true;
|
|
} else {
|
|
return $this->actions["get"];
|
|
} }
|
|
|
|
public function Export() {
|
|
$ret = [];
|
|
foreach ($this->actions as $action => $restrictions) {
|
|
if (is_array($restrictions)) {
|
|
$ret[$action] = [];
|
|
foreach ($restrictions as $restriction) {
|
|
$ret[$action][] = $restriction->Export();
|
|
}
|
|
} else {
|
|
$ret[$action] = $restrictions;
|
|
} }
|
|
return $ret;
|
|
}
|
|
|
|
public static function Make() {
|
|
return (new self())->Add(\Right::Make("ADMIN")->Allow("admin"));
|
|
}
|
|
}
|