This repository has been archived on 2023-01-06. You can view files and clone it, but cannot push or open issues or pull requests.
web/app/lib/App/Core/AccessControl.php

116 lines
3.2 KiB
PHP

<?php
namespace App\Core;
use \Exception;
/**
* Decides what is allowed and what not
* TODO: ...
*/
class AccessControl
{
public App $app;
private array $acl;
private string $currentPage;
public function __construct(App $app)
{
$this->app = $app;
/**
* WARNING WARNING WARNING:
*
* Never use an asterisk without putting anything before it like this "*".
* An attacker could leverage this by putting a forward slash behind a
* protected page like this "protected-page.php/pwned!" to gain access.
*/
$this->acl = [
// routes that need power level 1 and up
[
"routes" => [
"race/simulator.php*",
"race/configure/*"
],
"catcher" => [
"name" => "page",
"args" => 1,
],
],
// routes that dont need any auth
[
"routes" => [
"*"
],
"catcher" => [
"name" => "nothing",
],
]
];
$this->currentPage = substr(
$_SERVER["PHP_SELF"],
strlen($this->app->config["root_url"])
);
// TODO: add error handling
foreach ($this->acl as $key => $value)
{
$routes = $value["routes"];
$catcher = $value["catcher"];
foreach ($routes as $key => $value)
{
// if the end of the route is an asterisk we match everything after it
if ($value[-1] == '*')
{
// remove asterisk
$value = substr($value, 0, -1);
// check if string starts with
if (strncmp($this->currentPage, $value, strlen($value)) !== 0)
{
continue;
}
} else {
// end is not an asterisk, match full string
if ($value !== $this->currentPage)
{
continue;
}
}
if (isset($catcher["args"]))
{
call_user_func([$this, $catcher["name"]], $catcher["args"]);
} else {
call_user_func([$this, $catcher["name"]]);
}
return;
}
}
throw new Exception("Could not find current page in access control list, did you add it?");
}
private function page(int $powerLevel): void
{
if (!$this->app->user->loggedIn || !($this->app->user->powerLevel >= $powerLevel))
{
http_response_code(401);
$this->app->view("template/header", ["title" => "Ingen tilgang!"]);
$this->app->view("App/Core/AccessControl/unauthorized");
$this->app->view("template/footer");
die();
}
}
/**
* Does... nothing! For when the page does not need any access control.
*/
private function nothing(): void
{
return;
}
}