Enhance API error handling, add lastError tracking, and implement admin home template

This commit is contained in:
marc-go committed 2026-10-11 14:37:56 +02:00
1 parent ce0777bb33
commit 205f2e2f73
9 files changed
+257 -33

No files matched your search

+42 -10
View File
@@ -16,6 +16,7 @@ class gbAPI {
private $config;
private $internal;
private $response;
private $lastError;
private function b64url_encode($data) {
return rtrim(strtr(base64_encode($data), "+/", "-_"), "=");
@@ -40,6 +41,8 @@ class gbAPI {
"error_text" => "Authentication failed."
];
$this->lastError = $data;
$this->answer($status, $data, true);
}
}
@@ -52,17 +55,25 @@ class gbAPI {
try {
$input = json_decode(file_get_contents("php://input"), true);
} catch (JsonException $error) {
$this->answer(400, [
$error_payload = [
"error" => "invalid_body",
"error_text" => "Can not read request body: " . $error
]);
];
$this->lastError = $error_payload;
$this->answer(400, $error_payload, true);
}
return $input;
}else{
$this->answer(400, [
$error_payload = [
"error" => "false_request_method",
"error_text" => "Only POST allowed"
], true);
];
$this->lastError = $error_payload;
$this->answer(400, $error_payload, true);
}
}
@@ -191,6 +202,14 @@ class gbAPI {
}
}
function returnLastError() {
if (isset($this->lastError)) {
return $this->lastError;
}else{
return NULL;
}
}
function getAnswer() {
if (!isset($this->response)) {
$error = [
@@ -199,6 +218,8 @@ class gbAPI {
"error_text" => "API Returned nothing."
];
$this->lastError = $error;
return $error;
}
@@ -218,17 +239,25 @@ class gbAPI {
$db_path = APP_PATH . $db_name;
if (!is_file($db_path)) {
$api->answer(500, [
$error_payload = [
"error" => "database_not_found",
"error_text" => "The Database was not found."
], true);
];
$this->lastError = $error_payload;
$api->answer(500, $error_payload, true);
}
if (!is_writeable($db_path)) {
$this->answer(500, [
$error_payload = [
"error" => "database_not_writeable",
"error_text" => "The Database is not writeable."
]);
];
$this->lastError = $error_payload;
$this->answer(500, $error_payload, true);
return;
}
@@ -250,11 +279,14 @@ class gbAPI {
$command = "SELECT name, value FROM settings WHERE name = :name";
$value = $this->dbCommand($command, true, true, [":name" => $key]);
if (isset($value[0]["value"])) {
return $value[0]["value"];
}else{
return;
$this->answer(500, [
"error" => "query_returned_nothing",
"error_text" => "The SQL Query Returned nothing usable. Check Database Permissions."
]);
}
}
}
+17 -4
View File
@@ -9,7 +9,20 @@ if (!isset($internal)) {
require_once API_DIR . "api.php";
$api = new gbAPI(true, $internal);
$api->answer(200, [
"login" => true,
"username" => $api->username
]);
$auth = $api->checkAuth();
$lastError = $api->returnLastError();
if ($lastError == NULL) {
if ($auth) {
$api->answer(200, [
"login" => true,
"username" => $api->username
]);
}else{
$api->answer(401, [
"login" => false,
"username" => ""
]);
}
}
+5 -4
View File
@@ -10,7 +10,8 @@ $api = new gbAPI(false, $internal);
// Get Template
$template = $api->getSetting("template");
$api->answer(200, [
"template_name" => $template
]);
if ($template !== NULL) {
$api->answer(200, [
"template_name" => $template
]);
}
BIN
View File
Binary file not shown.
+5 -2
View File
@@ -16,7 +16,10 @@ $htmlloader = new HTMLLoader();
$call = new APICall("auth/isauth.php");
$response = $call->response;
if (!isset($response["data"]["login"])) {
if (!$response["data"]["login"]) {
$htmlloader->setPage("login");
$htmlloader->show();
$htmlloader->show([], true);
}else{
$htmlloader->setPage("admin_home");
$htmlloader->show([], true);
}
+16 -11
View File
@@ -4,7 +4,7 @@ class HTMLLoader {
private $page;
private $templates;
private $tempalte_conf;
private $template_conf;
function __construct() {
// Check if Paths variables exists
@@ -13,6 +13,7 @@ class HTMLLoader {
}
$this->templates = json_decode(file_get_contents(TEMPLATE_CONF), true);
$this->getTemplate();
}
function setTemplate($template) {
@@ -26,6 +27,7 @@ class HTMLLoader {
}
$this->template = $template;
$this->template_conf = file_get_contents(TEMPLATE_PATH . $this->templates[$template]["dir_name"] . "/template.json");
}
function getTemplate() {
@@ -38,19 +40,26 @@ class HTMLLoader {
$this->showError("Template API Returned an error: " . $response["error_text"]);
}
$this->template = $response["data"]["template_name"];
$template = $response["data"]["template_name"];
$this->template_conf = json_decode(file_get_contents(TEMPLATE_PATH . $this->templates[$template]["dir_name"] . "/template.json"), true);
$this->template = $template;
}
function setPage($page) {
$this->page = $page;
if (!array_key_exists($page, $this->template_conf)) {
$this->showError("Page " . $page . " for template " . $this->template . " not found.");
}else{
$this->page = $page;
}
}
function showError($error) {
$template_dir = $this->templates[$this->template]["dir_name"];
$template_conf = json_decode(file_get_contents(TEMPLATE_DIR . $template_dir));
$template_conf = json_decode(file_get_contents(TEMPLATE_PATH . $template_dir . "/template.json"), true);
$page = $tempalte_conf["error"];
$html = file_get_contents(TEMPLATE_PATH . $page["dir_name"] . "/" . $page["html_file"]);
$page = $template_conf["error"];
$html = file_get_contents(TEMPLATE_PATH . $template_dir . "/" . $page["dir_name"] . "/" . $page["html_file"]);
$css = "";
@@ -79,12 +88,8 @@ class HTMLLoader {
}
$template = $this->template;
$tempalte_conf = $this->template_conf;
$template_dir = $this->templates[$template]["dir_name"];
$template_conf = TEMPLATE_PATH . $template_dir . "/template.json";
$file = file_get_contents($template_conf);
$tempalte_conf = json_decode($file, true);
$page = $tempalte_conf[$this->page];
@@ -0,0 +1,150 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
<script type="importmap">
{
"imports": {
"@material/web/": "https://esm.run/@material/web/"
}
}
</script>
<script type="module">
import '@material/web/all.js';
import { styles as typescaleStyles } from '@material/web/typography/md-typescale-styles.js';
document.adoptedStyleSheets.push(typescaleStyles.styleSheet);
</script>
<style>
:root {
--md-sys-color-primary: rgb(58, 58, 255);
--active-menu-point-color: rgb(116, 148, 250);
--md-sys-color-surface-container: rgb(223, 228, 255);
}
body {
margin: 0;
}
.layout {
display: flex;
height: 100vh;
overflow: hidden;
}
.sidebar {
flex: 0 0 280px;
width: 280px;
overflow: hidden;
background: var(--md-sys-color-surface-container);
border-right: 1px solid var(--md-sys-color-outline-variant);
transition: flex-basis .2s ease, width .2s ease;
padding: 10px;
overflow-y: auto;
}
.sidebar-header {
display: flex;
align-items: center;
gap: 8px;
padding: 12px;
white-space: nowrap;
}
.sidebar md-list {
background: transparent;
}
md-list-item.active {
background-color: var(--active-menu-point-color);
border-radius: 28px;
margin-bottom: 10px;
}
md-list-item {
border-radius: 28px;
margin-bottom: 10px;
}
.sidebar.collapsed {
flex-basis: 58px;
width: 58x;
}
.sidebar.collapsed .title,
.sidebar.collapsed .label {
display: none;
}
.content {
flex: 1;
padding: 24px;
overflow-y: auto;
}
@media (max-width: 720px) {
body {
overflow-x: hidden;
}
}
</style>
</head>
<body>
<div class="layout">
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<md-icon-button id="toggle" aria-label="Menü ein-/ausklappen">
<md-icon>menu</md-icon>
</md-icon-button>
<span class="title">Dashboard</span>
</div>
<md-list>
<md-list-item type="link" href="/admin/" class="active">
<md-icon slot="start">dashboard</md-icon>
<span class="label">Overview</span>
</md-list-item>
<md-list-item type="link" href="/admin/settings.php">
<md-icon slot="start">settings</md-icon>
<span class="label">Settings</span>
</md-list-item>
</md-list>
</aside>
<main class="content">
<h1>Dashboard</h1>
</main>
</div>
<script type="module">
const sidebar = document.getElementById('sidebar');
const items = sidebar.querySelectorAll('md-list-item');
const mq = window.matchMedia('(max-width: 720px)');
const applyBreakpoint = () => {
sidebar.classList.toggle('collapsed', mq.matches);
};
applyBreakpoint();
mq.addEventListener('change', applyBreakpoint);
document.getElementById('toggle').addEventListener('click', () => {
sidebar.classList.toggle('collapsed');
});
items.forEach(item => {
item.addEventListener('click', () => {
items.forEach(i => i.classList.remove('active'));
item.classList.add('active');
});
});
</script>
</body>
</html>
+10
View File
@@ -7,22 +7,32 @@
"error.css"
]
},
"setup":{
"name":"setup",
"dir_name":"setup",
"html_file":"setup.html",
"css_files":[]
},
"entrys_frontend":{
"name":"entrys_frontend",
"dir_name":"entrys_frontend",
"html_file":"entrys_frontend.html",
"css_files":[]
},
"login":{
"name":"login",
"dir_name":"login",
"html_file":"login.html",
"css_files":[]
},
"admin_home":{
"name":"admin_home",
"dir_name":"admin_home",
"html_file":"home.html",
"css_files":[]
}
}
+12 -2
View File
@@ -19,5 +19,15 @@
//print_r(explode(".", "jakob.stinkt"));
var_dump(extension_loaded("pdo_sqlite"));
var_dump(extension_loaded("sqlite3"));
//var_dump(extension_loaded("pdo_sqlite"));
//var_dump(extension_loaded("sqlite3"));
class test {
private $test;
function __construct() {
var_dump(isset($this->test));
}
}
new test();