Compare commits
62
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af8dea2e7f | ||
|
|
3d8c4291be | ||
|
|
a0afeabb27 | ||
|
|
96c27a8722 | ||
|
|
4478f7e82f | ||
|
|
c1f3c3ea4e | ||
|
|
2a8564d3bf | ||
|
|
14f4143207 | ||
|
|
53b4bd3423 | ||
|
|
386bef9094 | ||
|
|
4e52aa468f | ||
|
|
f4b65903f7 | ||
|
|
29a1be5d22 | ||
|
|
51bc1f7876 | ||
|
|
4e0fcfea3f | ||
|
|
63373ac90c | ||
|
|
966ed2690c | ||
|
|
51ce63b0f0 | ||
|
|
d9f98176c5 | ||
|
|
2aa48a2601 | ||
|
|
2bd315efcd | ||
|
|
d862ed1102 | ||
|
|
5cc4fd0d10 | ||
|
|
24cb1be31f | ||
|
|
955744ee7e | ||
|
|
88f01fe156 | ||
|
|
0c189487c6 | ||
|
|
50934501ab | ||
|
|
54c77e4651 | ||
|
|
351ec88131 | ||
|
|
7ac6a3cd49 | ||
|
|
236fe1fd7f | ||
|
|
4b30f00872 | ||
|
|
e0a4f9ff77 | ||
|
|
ae5beb7ff3 | ||
|
|
614531394d | ||
|
|
773d48f6dd | ||
|
|
b98c8f39d7 | ||
|
|
c286ec3aa2 | ||
|
|
05086a12f5 | ||
|
|
9f76387eec | ||
|
|
d2e076e683 | ||
|
|
80184ed2f0 | ||
|
|
8e2270c674 | ||
|
|
53eb3d4bc2 | ||
|
|
527e783c75 | ||
|
|
6bcdf3f9e3 | ||
|
|
e58bfb6bb1 | ||
|
|
fc665213b3 | ||
|
|
d9ae978837 | ||
|
|
0559317875 | ||
|
|
865320a75c | ||
|
|
35dcb96e5d | ||
|
|
037396fec0 | ||
|
|
d916632d1b | ||
|
|
182997b3fb | ||
|
|
306e3b9c28 | ||
|
|
24a36b020d | ||
|
|
e3dae4c853 | ||
|
|
66fd469c3a | ||
|
|
0846dea367 | ||
|
|
2511b94616 |
No files matched your search
+2
-1
@@ -1,2 +1,3 @@
|
|||||||
WEBROOT/config_backups/*
|
WEBROOT/config_backups/*
|
||||||
WEBROOT/static/*
|
WEBROOT/static/*
|
||||||
|
WEBROOT/sitemap.xml
|
||||||
-73
@@ -1,73 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "============================="
|
|
||||||
echo " Git Management Script"
|
|
||||||
echo "============================="
|
|
||||||
echo ""
|
|
||||||
echo "1) Geänderte Dateien anzeigen"
|
|
||||||
echo "2) Einzelne Dateien zum Commit auswählen"
|
|
||||||
echo "3) Alles stagen"
|
|
||||||
echo "4) Commit & Push"
|
|
||||||
echo "5) Alte Stände anzeigen"
|
|
||||||
echo "6) Aktueller Branch"
|
|
||||||
echo "7) Änderungen"
|
|
||||||
echo "99) Programm beenden"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Auswahl: " auswahl
|
|
||||||
|
|
||||||
case $auswahl in
|
|
||||||
|
|
||||||
1)
|
|
||||||
echo "Geänderte Dateien:"
|
|
||||||
git status -s
|
|
||||||
;;
|
|
||||||
|
|
||||||
2)
|
|
||||||
echo "Geänderte Dateien:"
|
|
||||||
git status -s
|
|
||||||
echo ""
|
|
||||||
read -p "Welche Datei soll gestaged werden? (Pfad eingeben): " file
|
|
||||||
git add "$file"
|
|
||||||
echo ">> Datei '$file' wurde gestaged."
|
|
||||||
;;
|
|
||||||
|
|
||||||
3)
|
|
||||||
echo ">> Alle Dateien werden gestaged..."
|
|
||||||
git add -A
|
|
||||||
;;
|
|
||||||
|
|
||||||
4)
|
|
||||||
read -p "Commit Nachricht: " commitmsg
|
|
||||||
git commit -m "$commitmsg"
|
|
||||||
echo ">> Pushen..."
|
|
||||||
git push
|
|
||||||
;;
|
|
||||||
|
|
||||||
5)
|
|
||||||
echo ">> Alte Commits:"
|
|
||||||
git log --oneline --graph --decorate --all
|
|
||||||
;;
|
|
||||||
6)
|
|
||||||
echo "Aktueller Branch"
|
|
||||||
git branch
|
|
||||||
;;
|
|
||||||
7)
|
|
||||||
echo "Änderungen"
|
|
||||||
git status
|
|
||||||
;;
|
|
||||||
|
|
||||||
99)
|
|
||||||
echo "Beendet."
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo "Ungültige Auswahl!"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
RewriteEngine On
|
||||||
|
|
||||||
|
RewriteRule ^(Commands|config_backups|controller|modules)($|/.*) - [F,L,NC]
|
||||||
|
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||||
|
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
// loginTest.php
|
||||||
|
|
||||||
|
$loginUrl = "https://backend.blackpi.ipv64.net/login.php"; // URL zu deinem Login-Script
|
||||||
|
|
||||||
|
// Testfälle
|
||||||
|
$tests = [
|
||||||
|
[
|
||||||
|
'username' => 'Bruno', // korrektes Testkonto
|
||||||
|
'password' => 'bBHofurUJWKzPE8Z', // korrektes Passwort
|
||||||
|
'expected' => true,
|
||||||
|
'description' => 'Erfolgreiches Login'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'username' => 'admin',
|
||||||
|
'password' => 'falschespasswort',
|
||||||
|
'expected' => false,
|
||||||
|
'description' => 'Fehlerhaftes Login'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($tests as $test) {
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $loginUrl);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
|
||||||
|
'username' => $test['username'],
|
||||||
|
'password' => $test['password']
|
||||||
|
]));
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // Wichtige Info: redirect erkennen
|
||||||
|
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||||
|
$body = substr($response, $headerSize);
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
// Prüfen, ob Login erfolgreich war: Redirect auf index.php oder Session gesetzt
|
||||||
|
if (strpos($response, "Location: index.php") !== false || strpos($body, "Login fehlgeschlagen") === false) {
|
||||||
|
$success = true;
|
||||||
|
} else {
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($success === $test['expected']) {
|
||||||
|
echo "[PASS] {$test['description']}\n";
|
||||||
|
} else {
|
||||||
|
echo "[FAIL] {$test['description']}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
include_once '../controller/DatabaseController.php';
|
||||||
|
include_once '../controller/DataController.php';
|
||||||
|
include_once __DIR__ . '/../modules/Mail.php';
|
||||||
|
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
header("Access-Control-Allow-Origin: *");
|
||||||
|
header("Access-Control-Allow-Headers: Authorization, Function, Content-Type");
|
||||||
|
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||||
|
http_response_code(200);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// $validTokens = [
|
||||||
|
// "15a437d128c918633e57dc7d18118a073b807644f21731ed5a7ebcf3eca9e242",
|
||||||
|
// ];
|
||||||
|
$validTokens = DatabaseShow(
|
||||||
|
"API_Credentials",
|
||||||
|
"TOKEN"
|
||||||
|
);
|
||||||
|
|
||||||
|
$validTokens = array_column($validTokens, 'TOKEN');
|
||||||
|
|
||||||
|
$headers = getallheaders();
|
||||||
|
$token = $headers['Authorization'] ?? $headers['authorization'] ?? $_SERVER['HTTP_AUTHORIZATION'] ?? '';
|
||||||
|
$function = $headers['Function'] ?? $headers['function'] ?? '';
|
||||||
|
|
||||||
|
if (!in_array($token, $validTokens)) {
|
||||||
|
http_response_code(401);
|
||||||
|
$error = json_encode([
|
||||||
|
"error" => "Unauthorized",
|
||||||
|
"debug_received_token" => $token,
|
||||||
|
"debug_all_headers" => $headers
|
||||||
|
]);
|
||||||
|
|
||||||
|
DatabaseInsert(
|
||||||
|
"API_LOGS",
|
||||||
|
"CLIENT_IP, TOKEN, API, FUNKTION, JSON",
|
||||||
|
(new getSpecificData())->getClientIP(),
|
||||||
|
$token,
|
||||||
|
(new getSpecificData())->getRequestURL(),
|
||||||
|
$function,
|
||||||
|
$error
|
||||||
|
);
|
||||||
|
|
||||||
|
errorMail(
|
||||||
|
"API Login failed",
|
||||||
|
$error,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
echo json_encode(
|
||||||
|
[
|
||||||
|
"error" => "Unauthorized",
|
||||||
|
"Contact" => "bruno.eckhardt07@gmail.com",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($token, $validTokens)) {
|
||||||
|
DatabaseInsert(
|
||||||
|
"API_LOGS",
|
||||||
|
"CLIENT_IP, TOKEN, API, FUNKTION",
|
||||||
|
(new getSpecificData())->getClientIP(),
|
||||||
|
$token,
|
||||||
|
(new getSpecificData())->getRequestURL(),
|
||||||
|
$function
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($function === "IPs") {
|
||||||
|
$data = DatabaseShow(
|
||||||
|
"logs",
|
||||||
|
"CLIENT_IP"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function === "Ueberstunden") {
|
||||||
|
$data = DatabaseShow(
|
||||||
|
"Ueberstunden",
|
||||||
|
"MINUTEN"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($function === "Berichte") {
|
||||||
|
$data = DatabaseShowWithFK(
|
||||||
|
"Berufsschulberichte",
|
||||||
|
$Berufsschulberichte,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode(
|
||||||
|
[
|
||||||
|
"success" => true,
|
||||||
|
"data" => $data,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
include_once(__DIR__ . '/../controller/DatabaseController.php');
|
||||||
|
include_once(__DIR__ . '/../controller/DataController.php');
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$data = DatabaseShowWithFK(
|
||||||
|
"Berufsschulberichte",
|
||||||
|
$Berufsschulberichte,
|
||||||
|
);
|
||||||
|
|
||||||
|
echo json_encode(
|
||||||
|
[
|
||||||
|
'status' => 'success',
|
||||||
|
'data' => $data,
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
|
||||||
|
);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo json_encode(
|
||||||
|
[
|
||||||
|
'status' => 'failed',
|
||||||
|
'data' => 'none',
|
||||||
|
'error' => $e,
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
include_once '../controller/DatabaseController.php';
|
||||||
|
include_once '../controller/DataController.php';
|
||||||
|
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
header("Access-Control-Allow-Origin: *");
|
||||||
|
header("Access-Control-Allow-Headers: Authorization, Function, Content-Type");
|
||||||
|
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
|
||||||
|
|
||||||
|
$validTokens = [
|
||||||
|
"15a437d128c918633e57dc7d18118a073b807644f21731ed5a7ebcf3eca9e242",
|
||||||
|
];
|
||||||
|
$baseUploadDir = __DIR__ . "/../services/uploads/";
|
||||||
|
|
||||||
|
$headers = getallheaders();
|
||||||
|
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
|
||||||
|
|
||||||
|
$token = trim($token);
|
||||||
|
|
||||||
|
if (!in_array($token, $validTokens, true)) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo json_encode([
|
||||||
|
"error" => "Unauthorized",
|
||||||
|
"received_token" => $token
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_FILES['files'])) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(["error" => "No files uploaded"]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$folderName = null;
|
||||||
|
$readmeContent = null;
|
||||||
|
|
||||||
|
// Prüfen ob readme.md hochgeladen wurde
|
||||||
|
foreach ($_FILES['files']['name'] as $key => $name) {
|
||||||
|
if (strtolower($name) === "readme.md") {
|
||||||
|
$tmpName = $_FILES['files']['tmp_name'][$key];
|
||||||
|
$readmeContent = file_get_contents($tmpName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($readmeContent) {
|
||||||
|
// Erste Markdown-Überschrift extrahieren (# Titel)
|
||||||
|
if (preg_match('/^#\s*(.+)$/m', $readmeContent, $matches)) {
|
||||||
|
$rawName = $matches[1];
|
||||||
|
|
||||||
|
// Slug erzeugen (ordner-tauglich machen)
|
||||||
|
$folderName = strtolower($rawName);
|
||||||
|
$folderName = preg_replace("/[^a-z0-9]+/", "-", $folderName);
|
||||||
|
$folderName = trim($folderName, "-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback falls keine readme oder kein Titel
|
||||||
|
if (!$folderName) {
|
||||||
|
$folderName = uniqid("upload_", true);
|
||||||
|
}
|
||||||
|
$uploadDir = $baseUploadDir . $folderName . "/";
|
||||||
|
|
||||||
|
if (!mkdir($uploadDir, 0755, true)) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(["error" => "Failed to create directory"]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploadedFiles = [];
|
||||||
|
|
||||||
|
foreach ($_FILES['files']['tmp_name'] as $key => $tmpName) {
|
||||||
|
|
||||||
|
if ($_FILES['files']['error'][$key] !== UPLOAD_ERR_OK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$originalName = basename($_FILES['files']['name'][$key]);
|
||||||
|
|
||||||
|
$safeName = preg_replace("/[^a-zA-Z0-9._-]/", "", $originalName);
|
||||||
|
|
||||||
|
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||||
|
$mime = $finfo->file($tmpName);
|
||||||
|
|
||||||
|
if ($_FILES['files']['size'][$key] > 25 * 1024 * 1024) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetPath = $uploadDir . $safeName;
|
||||||
|
|
||||||
|
if (move_uploaded_file($tmpName, $targetPath)) {
|
||||||
|
$uploadedFiles[] = $safeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$json = json_encode([
|
||||||
|
"success" => true,
|
||||||
|
"folder" => $folderName,
|
||||||
|
"uploaded_files" => $uploadedFiles
|
||||||
|
]);
|
||||||
|
|
||||||
|
DatabaseInsert(
|
||||||
|
"API",
|
||||||
|
"CLIENT_IP, TOKEN, API, FUNKTION, JSON",
|
||||||
|
(new getSpecificData())->getClientIP(),
|
||||||
|
$token,
|
||||||
|
(new getSpecificData())->getRequestURL(),
|
||||||
|
"Upload",
|
||||||
|
$json
|
||||||
|
);
|
||||||
|
|
||||||
|
echo $json;
|
||||||
+128
-14
@@ -17,8 +17,18 @@ $serviceGroups = array (
|
|||||||
array (
|
array (
|
||||||
0 => 'home_info',
|
0 => 'home_info',
|
||||||
1 => 'links',
|
1 => 'links',
|
||||||
2 => 'berichte_arbeit',
|
),
|
||||||
3 => 'berichte_arbeit_gen',
|
),
|
||||||
|
'Ausbildung' =>
|
||||||
|
array (
|
||||||
|
'label' => 'Ausbildung',
|
||||||
|
'defaultOpen' => true,
|
||||||
|
'services' =>
|
||||||
|
array (
|
||||||
|
0 => 'print_static',
|
||||||
|
1 => 'zeiterfassung',
|
||||||
|
2 => 'berichte_arbeit_gen',
|
||||||
|
3 => 'berichte',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'Logs' =>
|
'Logs' =>
|
||||||
@@ -37,13 +47,25 @@ $serviceGroups = array (
|
|||||||
'System' =>
|
'System' =>
|
||||||
array (
|
array (
|
||||||
'label' => 'Verwaltung',
|
'label' => 'Verwaltung',
|
||||||
'defaultOpen' => true,
|
'defaultOpen' => false,
|
||||||
'services' =>
|
'services' =>
|
||||||
array (
|
array (
|
||||||
0 => 'services_control',
|
0 => 'data_info',
|
||||||
1 => 'user_control',
|
1 => 'services_control',
|
||||||
2 => 'variablen_control',
|
2 => 'user_control',
|
||||||
3 => 'data_info',
|
3 => 'variablen_control',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'Test' =>
|
||||||
|
array (
|
||||||
|
'label' => 'Dev / Test',
|
||||||
|
'defaultOpen' => false,
|
||||||
|
'services' =>
|
||||||
|
array (
|
||||||
|
0 => 'api_tester',
|
||||||
|
1 => 'weather_chart',
|
||||||
|
2 => 'tabellen',
|
||||||
|
3 => 'domains',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -55,7 +77,25 @@ $services = array (
|
|||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => false,
|
'adminOnly' => false,
|
||||||
),
|
),
|
||||||
'data_info' =>
|
'print_static' =>
|
||||||
|
array (
|
||||||
|
'name' => 'Berichte Drucken',
|
||||||
|
'active' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
),
|
||||||
|
'api_tester' =>
|
||||||
|
array (
|
||||||
|
'name' => 'API Testing',
|
||||||
|
'active' => true,
|
||||||
|
'adminOnly' => true,
|
||||||
|
),
|
||||||
|
'weather_chart' =>
|
||||||
|
array (
|
||||||
|
'name' => 'Wetter Statistik',
|
||||||
|
'active' => true,
|
||||||
|
'adminOnly' => true,
|
||||||
|
),
|
||||||
|
'data_info' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'Data Info',
|
'name' => 'Data Info',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
@@ -63,7 +103,7 @@ $services = array (
|
|||||||
),
|
),
|
||||||
'links' =>
|
'links' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'Externe Links',
|
'name' => 'Links',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => false,
|
'adminOnly' => false,
|
||||||
),
|
),
|
||||||
@@ -95,7 +135,7 @@ $services = array (
|
|||||||
array (
|
array (
|
||||||
'name' => 'Persönliche Logs',
|
'name' => 'Persönliche Logs',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => false,
|
'adminOnly' => true,
|
||||||
),
|
),
|
||||||
'services_control' =>
|
'services_control' =>
|
||||||
array (
|
array (
|
||||||
@@ -103,15 +143,15 @@ $services = array (
|
|||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => true,
|
'adminOnly' => true,
|
||||||
),
|
),
|
||||||
'berichte_arbeit' =>
|
'zeiterfassung' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'Arbeitsberichte',
|
'name' => 'Zeit Erfassung',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => false,
|
'adminOnly' => false,
|
||||||
),
|
),
|
||||||
'berichte_arbeit_gen' =>
|
'berichte_arbeit_gen' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'Arbeitsberichte PDF',
|
'name' => 'Berichte PDF',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => false,
|
'adminOnly' => false,
|
||||||
),
|
),
|
||||||
@@ -119,7 +159,7 @@ $services = array (
|
|||||||
array (
|
array (
|
||||||
'name' => 'Benutzer',
|
'name' => 'Benutzer',
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => false,
|
'adminOnly' => true,
|
||||||
),
|
),
|
||||||
'variablen_control' =>
|
'variablen_control' =>
|
||||||
array (
|
array (
|
||||||
@@ -127,6 +167,24 @@ $services = array (
|
|||||||
'active' => true,
|
'active' => true,
|
||||||
'adminOnly' => true,
|
'adminOnly' => true,
|
||||||
),
|
),
|
||||||
|
'tabellen' =>
|
||||||
|
array (
|
||||||
|
'name' => 'Tabellen',
|
||||||
|
'active' => true,
|
||||||
|
'adminOnly' => true,
|
||||||
|
),
|
||||||
|
'berichte' =>
|
||||||
|
array (
|
||||||
|
'name' => 'Berichte Einsehen',
|
||||||
|
'active' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
),
|
||||||
|
'domains' =>
|
||||||
|
array (
|
||||||
|
'name' => 'Domains',
|
||||||
|
'active' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
$linkGroups = array (
|
$linkGroups = array (
|
||||||
@@ -261,4 +319,60 @@ $linkButtons = array (
|
|||||||
'adminOnly' => false,
|
'adminOnly' => false,
|
||||||
'group' => 'tools',
|
'group' => 'tools',
|
||||||
),
|
),
|
||||||
|
13 =>
|
||||||
|
array (
|
||||||
|
'label' => 'Backend',
|
||||||
|
'url' => 'https://backend.blackpi.ipv64.net',
|
||||||
|
'newTab' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
'group' => 'info',
|
||||||
|
),
|
||||||
|
14 =>
|
||||||
|
array (
|
||||||
|
'label' => 'Dev Backend',
|
||||||
|
'url' => 'https://dev-backend.blackpi.ipv64.net',
|
||||||
|
'newTab' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
'group' => 'info',
|
||||||
|
),
|
||||||
|
15 =>
|
||||||
|
array (
|
||||||
|
'label' => 'Dev Pubic',
|
||||||
|
'url' => 'https://dev-public.blackpi.ipv64.net',
|
||||||
|
'newTab' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
'group' => 'info',
|
||||||
|
),
|
||||||
|
16 =>
|
||||||
|
array (
|
||||||
|
'label' => 'Local Backend',
|
||||||
|
'url' => 'http://backend.local.ipv64.net',
|
||||||
|
'newTab' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
'group' => 'info',
|
||||||
|
),
|
||||||
|
17 =>
|
||||||
|
array (
|
||||||
|
'label' => 'Local Pubic',
|
||||||
|
'url' => 'http://public.local.ipv64.net',
|
||||||
|
'newTab' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
'group' => 'info',
|
||||||
|
),
|
||||||
|
18 =>
|
||||||
|
array (
|
||||||
|
'label' => 'Proxmox',
|
||||||
|
'url' => 'https://100.88.208.86:8006',
|
||||||
|
'newTab' => true,
|
||||||
|
'adminOnly' => true,
|
||||||
|
'group' => 'devices',
|
||||||
|
),
|
||||||
|
19 =>
|
||||||
|
array (
|
||||||
|
'label' => 'Flatnotes',
|
||||||
|
'url' => 'http://10.233.1.130:8080',
|
||||||
|
'newTab' => true,
|
||||||
|
'adminOnly' => false,
|
||||||
|
'group' => 'tools',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
class getSpecificData {
|
class getSpecificData {
|
||||||
|
|
||||||
public function getWeather() {
|
public function getWeather() {
|
||||||
$url = "https://api.openweathermap.org/data/2.5/weather?q=Berlin,DE&APPID=5bc3e1a438c58fca444c4370ac0517b2&units=metric";
|
$url = "https://api.openweathermap.org/data/2.5/weather?q=Jena,DE&APPID=5bc3e1a438c58fca444c4370ac0517b2&units=metric";
|
||||||
|
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
curl_setopt($ch, CURLOPT_URL, $url);
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
include_once __DIR__ . '/../modules/Mail.php';
|
||||||
|
include_once __DIR__ . '/../controller/RoutesController.php';
|
||||||
|
include_once 'DataController.php';
|
||||||
|
|
||||||
function db_connect() {
|
function db_connect() {
|
||||||
$servers = [
|
$servers = [
|
||||||
'dev' => [
|
'local' => [
|
||||||
'hostaddr' => '10.233.1.29',
|
'hostaddr' => '127.0.0.1',
|
||||||
'username' => 'worker',
|
'username' => 'worker',
|
||||||
'password' => 'bBHofurUJWKzPE8Z',
|
'password' => 'bBHofurUJWKzPE8Z',
|
||||||
'database' => 'DEV',
|
'database' => 'DEV',
|
||||||
@@ -14,35 +18,58 @@ function db_connect() {
|
|||||||
'password' => 'bBHofurUJWKzPE8Z',
|
'password' => 'bBHofurUJWKzPE8Z',
|
||||||
'database' => 'DEV',
|
'database' => 'DEV',
|
||||||
],
|
],
|
||||||
|
'backup' => [
|
||||||
|
'hostaddr' => '10.233.1.241',
|
||||||
|
'username' => 'worker',
|
||||||
|
'password' => 'bBHofurUJWKzPE8Z',
|
||||||
|
'database' => 'DEV',
|
||||||
|
],
|
||||||
|
'dev' => [
|
||||||
|
'hostaddr' => '10.233.1.243',
|
||||||
|
'username' => 'worker',
|
||||||
|
'password' => 'bBHofurUJWKzPE8Z',
|
||||||
|
'database' => 'DEV',
|
||||||
|
],
|
||||||
'live' => [
|
'live' => [
|
||||||
'hostaddr' => '10.233.1.244',
|
'hostaddr' => '10.233.1.244',
|
||||||
'username' => 'worker',
|
'username' => 'worker',
|
||||||
'password' => 'bBHofurUJWKzPE8Z',
|
'password' => 'bBHofurUJWKzPE8Z',
|
||||||
'database' => 'DEV',
|
'database' => 'DEV',
|
||||||
],
|
],
|
||||||
'backup' => [
|
'error' => [
|
||||||
'hostaddr' => '10.233.1.243',
|
'hostaddr' => '10.233.1.244',
|
||||||
'username' => 'worker',
|
'username' => 'error',
|
||||||
'password' => 'bBHofurUJWKzPE8Z',
|
'password' => 'bBHofurUJWKzPE8Z',
|
||||||
'database' => 'DEV',
|
'database' => 'DEV',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
$enviroment = 'live';
|
$enviroment = 'vpn';
|
||||||
|
|
||||||
$conn = new mysqli(
|
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||||
$servers[$enviroment]['hostaddr'],
|
|
||||||
$servers[$enviroment]['username'],
|
|
||||||
$servers[$enviroment]['password'],
|
|
||||||
$servers[$enviroment]['database'],
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($conn->connect_error) {
|
try {
|
||||||
throw new Exception('Connection Error: ' . $conn->connect_error);
|
|
||||||
|
$conn = new mysqli(
|
||||||
|
$servers[$enviroment]['hostaddr'],
|
||||||
|
$servers[$enviroment]['username'],
|
||||||
|
$servers[$enviroment]['password'],
|
||||||
|
$servers[$enviroment]['database'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$conn->set_charset("utf8mb4");
|
||||||
|
return $conn;
|
||||||
|
|
||||||
|
} catch (mysqli_sql_exception $e) {
|
||||||
|
|
||||||
|
errorMail(
|
||||||
|
"Database Connection failed",
|
||||||
|
$e->getMessage(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
redirectToWebsite("https://blackpi.ipv64.net");
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
$conn->set_charset("utf8mb4");
|
|
||||||
return $conn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -1,5 +1,72 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
function DatabaseCreateTable($table, $columnsDefinition) {
|
||||||
|
include_once 'DatabaseConnect.php';
|
||||||
|
$conn = db_connect();
|
||||||
|
|
||||||
|
$sql = "CREATE TABLE IF NOT EXISTS `$table` ($columnsDefinition)";
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
|
||||||
|
if (!$stmt) {
|
||||||
|
die("Fehler beim Prepare: " . $conn->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$stmt->execute()) {
|
||||||
|
die("Fehler beim Execute: " . $stmt->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DatabaseShowTables() {
|
||||||
|
include_once 'DatabaseConnect.php';
|
||||||
|
$conn = db_connect();
|
||||||
|
|
||||||
|
$tablesResult = $conn->query("SHOW TABLES");
|
||||||
|
if (!$tablesResult) {
|
||||||
|
die("Fehler beim Laden der Tabellen: " . $conn->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tables = [];
|
||||||
|
|
||||||
|
while ($tableRow = $tablesResult->fetch_array()) {
|
||||||
|
$tables[] = $tableRow[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DatabaseShowTableStructure($table) {
|
||||||
|
include_once 'DatabaseConnect.php';
|
||||||
|
$conn = db_connect();
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("SHOW COLUMNS FROM `$table`");
|
||||||
|
if (!$stmt) {
|
||||||
|
die("Fehler beim Prepare: " . $conn->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$stmt->execute()) {
|
||||||
|
die("Fehler beim Execute: " . $stmt->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
|
||||||
|
$columns = [];
|
||||||
|
|
||||||
|
while ($column = $result->fetch_assoc()) {
|
||||||
|
$columns[] = [
|
||||||
|
"Field" => $column["Field"],
|
||||||
|
"Type" => $column["Type"],
|
||||||
|
"Null" => $column["Null"],
|
||||||
|
"Key" => $column["Key"],
|
||||||
|
"Default" => $column["Default"],
|
||||||
|
"Extra" => $column["Extra"]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $columns;
|
||||||
|
}
|
||||||
|
|
||||||
function DatabaseShow($table, $columns = "*", $where = "", ...$values) {
|
function DatabaseShow($table, $columns = "*", $where = "", ...$values) {
|
||||||
include_once 'DatabaseConnect.php';
|
include_once 'DatabaseConnect.php';
|
||||||
$conn = db_connect();
|
$conn = db_connect();
|
||||||
@@ -80,10 +147,37 @@ function DatabaseUpdate($table, $set, $where, ...$values) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFKValue($conn, $table, $key, $value, $id, &$cache) {
|
||||||
|
if ($id === null) return null;
|
||||||
|
|
||||||
|
$cacheKey = $table . "_" . $id;
|
||||||
|
|
||||||
|
if (isset($cache[$cacheKey])) {
|
||||||
|
return $cache[$cacheKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("SELECT `$value` FROM `$table` WHERE `$key` = ? LIMIT 1");
|
||||||
|
if (!$stmt) {
|
||||||
|
die("FK Prepare Fehler: " . $conn->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->bind_param("i", $id);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$result = $stmt->get_result()->fetch_assoc();
|
||||||
|
$valueResult = $result[$value] ?? null;
|
||||||
|
|
||||||
|
$cache[$cacheKey] = $valueResult;
|
||||||
|
|
||||||
|
return $valueResult;
|
||||||
|
}
|
||||||
|
|
||||||
function DatabaseShowWithFK($table, $fkMap = [], $columns = "*", $where = "", ...$values) {
|
function DatabaseShowWithFK($table, $fkMap = [], $columns = "*", $where = "", ...$values) {
|
||||||
include_once 'DatabaseConnect.php';
|
include_once 'DatabaseConnect.php';
|
||||||
$conn = db_connect();
|
$conn = db_connect();
|
||||||
|
|
||||||
|
$cache = [];
|
||||||
|
|
||||||
$select = is_array($columns) ? implode(", ", $columns) : $columns;
|
$select = is_array($columns) ? implode(", ", $columns) : $columns;
|
||||||
|
|
||||||
$sql = "SELECT $select FROM `$table`";
|
$sql = "SELECT $select FROM `$table`";
|
||||||
@@ -94,33 +188,32 @@ function DatabaseShowWithFK($table, $fkMap = [], $columns = "*", $where = "", ..
|
|||||||
$stmt = $conn->prepare($sql);
|
$stmt = $conn->prepare($sql);
|
||||||
if (!$stmt) die("Fehler beim Prepare: " . $conn->error);
|
if (!$stmt) die("Fehler beim Prepare: " . $conn->error);
|
||||||
|
|
||||||
if (!$stmt->execute($values)) die("Fehler beim Execute: " . $stmt->error);
|
if (!empty($values)) {
|
||||||
|
$stmt->execute($values);
|
||||||
|
} else {
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
$result = $stmt->get_result();
|
$result = $stmt->get_result();
|
||||||
if (!$result) die("Fehler beim get_result: " . $stmt->error);
|
if (!$result) die("Fehler beim get_result: " . $conn->error);
|
||||||
|
|
||||||
$columnsResult = [];
|
|
||||||
while ($fieldinfo = $result->fetch_field()) {
|
|
||||||
$columnsResult[] = $fieldinfo->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||||
|
|
||||||
foreach ($rows as &$row) {
|
foreach ($rows as &$row) {
|
||||||
foreach ($fkMap as $fkColumn => $fkInfo) {
|
foreach ($fkMap as $fkColumn => $fkInfo) {
|
||||||
if (isset($row[$fkColumn]) && $row[$fkColumn] !== null) {
|
|
||||||
$fkStmt = $conn->prepare(
|
|
||||||
"SELECT {$fkInfo['value']} FROM `{$fkInfo['table']}` WHERE {$fkInfo['key']} = ?"
|
|
||||||
);
|
|
||||||
if (!$fkStmt) die("Fehler beim Prepare FK: " . $conn->error);
|
|
||||||
|
|
||||||
$fkStmt->bind_param("i", $row[$fkColumn]);
|
if (!isset($row[$fkColumn]) || $row[$fkColumn] === null) {
|
||||||
$fkStmt->execute();
|
continue;
|
||||||
$fkResult = $fkStmt->get_result();
|
|
||||||
$fkRow = $fkResult->fetch_assoc();
|
|
||||||
|
|
||||||
$row[$fkColumn] = $fkRow ? $fkRow[$fkInfo['value']] : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$row[$fkColumn] = getFKValue(
|
||||||
|
$conn,
|
||||||
|
$fkInfo['table'],
|
||||||
|
$fkInfo['key'],
|
||||||
|
$fkInfo['value'],
|
||||||
|
$row[$fkColumn],
|
||||||
|
$cache
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +257,7 @@ $Berufsschulberichte = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
$Stundenplan = [
|
$Stundenplan = [
|
||||||
"MO" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
"MO" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
||||||
"DI" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
"DI" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
||||||
"MI" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
"MI" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
||||||
"DO" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
"DO" => ["table" => "Fach", "key" => "ID", "value" => "Fach"],
|
||||||
@@ -172,6 +265,6 @@ $Stundenplan = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
$Berechtigungen = [
|
$Berechtigungen = [
|
||||||
"BENUTZER_ID" => ["table" => "Benutzer", "key" => "ID", "value" => "ID"],
|
"BENUTZER_ID" => ["table" => "Benutzer", "key" => "ID", "value" => "NAME"],
|
||||||
"BERECHTIGUNGEN_ID" => ["table" => "Berechtigungen", "key" => "ID", "value" => "ID"]
|
"SEITEN_ID" => ["table" => "Backend_Seiten", "key" => "ID", "value" => "DATEINAME"]
|
||||||
];
|
];
|
||||||
@@ -3,10 +3,15 @@
|
|||||||
|
|
||||||
function logging() {
|
function logging() {
|
||||||
include_once 'DataController.php';
|
include_once 'DataController.php';
|
||||||
|
include_once 'DatabaseConnect.php';
|
||||||
|
include_once 'DatabaseController.php';
|
||||||
|
include_once __DIR__ . '/../modules/Mail.php';
|
||||||
|
|
||||||
if ((new getSpecificData())->getLoggingStatus("GENERAL_BACKEND_LOGGING")[0]['WERT'] == 'ON') {
|
if ((new getSpecificData())->getLoggingStatus("GENERAL_BACKEND_LOGGING")[0]['WERT'] == 'ON') {
|
||||||
include_once 'DatabaseConnect.php';
|
|
||||||
include_once 'DatabaseController.php';
|
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||||
include_once 'DataController.php';
|
|
||||||
|
try {
|
||||||
|
|
||||||
$ClientIP = (new getSpecificData())->getClientIP();
|
$ClientIP = (new getSpecificData())->getClientIP();
|
||||||
$UserAgent = (new getSpecificData())->getUserAgent();
|
$UserAgent = (new getSpecificData())->getUserAgent();
|
||||||
@@ -39,52 +44,59 @@ function logging() {
|
|||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$stmt->store_result();
|
$stmt->store_result();
|
||||||
|
|
||||||
if ($RequestURL !== '/favicon.ico') {
|
if ($RequestURL !== '/favicon.ico') {
|
||||||
if ($stmt->num_rows > 0) { //wenn mindestens eine zeile vorhanden ist für die client ip dann führe updates durch, wenn nicht mache neue zeile
|
if ($stmt->num_rows > 0) { //wenn mindestens eine zeile vorhanden ist für die client ip dann führe updates durch, wenn nicht mache neue zeile
|
||||||
$updateCounter = $db_conn->prepare("
|
$updateCounter = $db_conn->prepare("
|
||||||
UPDATE logs
|
UPDATE logs
|
||||||
SET COUNTER = COUNTER + 1
|
SET COUNTER = COUNTER + 1
|
||||||
WHERE `CLIENT_IP` = ?
|
WHERE `CLIENT_IP` = ?
|
||||||
AND `REQUEST_URL` = ?
|
AND `REQUEST_URL` = ?
|
||||||
");
|
");
|
||||||
$updateCounter->bind_param("ss", $ClientIP, $RequestURL);
|
$updateCounter->bind_param("ss", $ClientIP, $RequestURL);
|
||||||
$updateCounter->execute();
|
$updateCounter->execute();
|
||||||
|
|
||||||
$updateLastRequest = $db_conn->prepare("
|
$updateLastRequest = $db_conn->prepare("
|
||||||
UPDATE logs
|
UPDATE logs
|
||||||
SET `LAST_REQUEST` = ?
|
SET `LAST_REQUEST` = ?
|
||||||
WHERE `CLIENT_IP` = ?
|
WHERE `CLIENT_IP` = ?
|
||||||
AND `REQUEST_URL` = ?
|
AND `REQUEST_URL` = ?
|
||||||
");
|
");
|
||||||
$updateLastRequest->bind_param("sss", $REQUESTTIME, $ClientIP, $RequestURL);
|
$updateLastRequest->bind_param("sss", $REQUESTTIME, $ClientIP, $RequestURL);
|
||||||
$updateLastRequest->execute();
|
$updateLastRequest->execute();
|
||||||
|
|
||||||
$updateCookieValue = $db_conn->prepare("
|
$updateCookieValue = $db_conn->prepare("
|
||||||
UPDATE logs
|
UPDATE logs
|
||||||
SET `USER_COOKIE_VALUE` = ?
|
SET `USER_COOKIE_VALUE` = ?
|
||||||
WHERE `CLIENT_IP` = ?
|
WHERE `CLIENT_IP` = ?
|
||||||
AND `REQUEST_URL` = ?
|
AND `REQUEST_URL` = ?
|
||||||
");
|
");
|
||||||
$updateCookieValue->bind_param("sss", $USERCOOKIE, $ClientIP, $RequestURL);
|
$updateCookieValue->bind_param("sss", $USERCOOKIE, $ClientIP, $RequestURL);
|
||||||
$updateCookieValue->execute();
|
$updateCookieValue->execute();
|
||||||
} else {
|
} else {
|
||||||
DatabaseInsert(
|
DatabaseInsert(
|
||||||
"logs",
|
"logs",
|
||||||
"CLIENT_IP, LAND, SERVER_IP, USER_AGENT, REQUEST_URL, USER_COOKIE_VALUE, USER_SESSION_VALUE, FIRST_REQUEST, QUERY, WEBSITE, USER",
|
"CLIENT_IP, LAND, SERVER_IP, USER_AGENT, REQUEST_URL, USER_COOKIE_VALUE, USER_SESSION_VALUE, FIRST_REQUEST, QUERY, WEBSITE, USER",
|
||||||
$ClientIP,
|
$ClientIP,
|
||||||
$LAND,
|
$LAND,
|
||||||
$node,
|
$node,
|
||||||
$UserAgent,
|
$UserAgent,
|
||||||
$RequestURL,
|
$RequestURL,
|
||||||
$USERCOOKIE,
|
$USERCOOKIE,
|
||||||
$SessionID,
|
$SessionID,
|
||||||
$REQUESTTIME,
|
$REQUESTTIME,
|
||||||
$QUERY,
|
$QUERY,
|
||||||
$website,
|
$website,
|
||||||
$username
|
$username
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ConsoleLog("Client IP: $ClientIP | User Agent: $UserAgent | Request URL: $RequestURL | User Cookie: $USERCOOKIE | Session ID: $SessionID | Request Time: $REQUESTTIME | GeoIP: $LAND | Server Node: $node | Website: $website");
|
} catch (mysqli_sql_exception $e) {
|
||||||
|
errorMail(
|
||||||
|
"Logging failed",
|
||||||
|
$e->getMessage(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,20 @@ class UserController {
|
|||||||
$admin,
|
$admin,
|
||||||
$home_ip,
|
$home_ip,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$userID = DatabaseShow(
|
||||||
|
"Benutzer",
|
||||||
|
"ID",
|
||||||
|
"NAME = ?",
|
||||||
|
$name
|
||||||
|
);
|
||||||
|
|
||||||
|
DatabaseInsert(
|
||||||
|
"Benutzer_Berechtigungen",
|
||||||
|
"BENUTZER_ID, SEITEN_ID",
|
||||||
|
$userID[0]['ID'],
|
||||||
|
"8"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DeleteUser($name, $nachname, $email) {
|
public function DeleteUser($name, $nachname, $email) {
|
||||||
|
|||||||
+46
-33
@@ -1,11 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
ob_start();
|
ob_start();
|
||||||
// Vor allen includes, vor jeglicher Ausgabe
|
|
||||||
session_set_cookie_params([
|
session_set_cookie_params([
|
||||||
'lifetime' => 0, // bis Browser geschlossen
|
'lifetime' => 0,
|
||||||
'path' => '/', // Gültig für ganze Domain
|
'path' => '/',
|
||||||
'domain' => '', // aktuelle Domain
|
'domain' => '',
|
||||||
'secure' => false, // true nur für HTTPS
|
'secure' => false,
|
||||||
'httponly' => true,
|
'httponly' => true,
|
||||||
'samesite' => 'Lax'
|
'samesite' => 'Lax'
|
||||||
]);
|
]);
|
||||||
@@ -16,20 +15,35 @@ if (empty($_SESSION['user_logged_in'])) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
include 'config.php';
|
include_once 'config.php';
|
||||||
include 'controller/CookieController.php';
|
include_once 'controller/CookieController.php';
|
||||||
include 'controller/DatabaseConnect.php';
|
include_once 'controller/DatabaseConnect.php';
|
||||||
include 'controller/DatabaseController.php';
|
include_once 'controller/DatabaseController.php';
|
||||||
include 'controller/DataController.php';
|
include_once 'controller/DataController.php';
|
||||||
include 'controller/LogController.php';
|
include_once 'controller/LogController.php';
|
||||||
include 'controller/UserController.php';
|
include_once 'controller/UserController.php';
|
||||||
include 'modules/ConsoleLog.php';
|
include_once 'modules/ConsoleLog.php';
|
||||||
// include 'controller/RoutesController.php';
|
// include 'controller/RoutesController.php';
|
||||||
|
|
||||||
|
$user_id = DatabaseShow(
|
||||||
|
"Benutzer",
|
||||||
|
"ID",
|
||||||
|
"NAME = ?",
|
||||||
|
$_SESSION['username'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$rightsArray = DatabaseShowWithFK(
|
||||||
|
"Benutzer_Berechtigungen",
|
||||||
|
$Berechtigungen,
|
||||||
|
"SEITEN_ID",
|
||||||
|
"BENUTZER_ID = ?",
|
||||||
|
$user_id[0]['ID'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$userRights = array_map('trim', array_column($rightsArray['rows'], 'SEITEN_ID'));
|
||||||
|
|
||||||
$selectedService = null;
|
$selectedService = null;
|
||||||
|
|
||||||
// 1. Service aus URL, wenn erlaubt & aktiv
|
|
||||||
if (
|
if (
|
||||||
isset($_GET['service']) &&
|
isset($_GET['service']) &&
|
||||||
isset($services[$_GET['service']]) &&
|
isset($services[$_GET['service']]) &&
|
||||||
@@ -38,7 +52,6 @@ if (
|
|||||||
$selectedService = $_GET['service'];
|
$selectedService = $_GET['service'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Default-Service
|
|
||||||
if (!$selectedService &&
|
if (!$selectedService &&
|
||||||
isset($defaultService) &&
|
isset($defaultService) &&
|
||||||
isset($services[$defaultService]) &&
|
isset($services[$defaultService]) &&
|
||||||
@@ -47,7 +60,6 @@ if (!$selectedService &&
|
|||||||
$selectedService = $defaultService;
|
$selectedService = $defaultService;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Fallback: erster aktiver Service
|
|
||||||
if (!$selectedService) {
|
if (!$selectedService) {
|
||||||
foreach ($services as $key => $service) {
|
foreach ($services as $key => $service) {
|
||||||
if ($service['active']) {
|
if ($service['active']) {
|
||||||
@@ -56,6 +68,11 @@ if (!$selectedService) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($selectedService && !in_array($selectedService, $userRights, true)) {
|
||||||
|
$selectedService = null;
|
||||||
|
}
|
||||||
|
|
||||||
$isAdmin = isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true;
|
$isAdmin = isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true;
|
||||||
|
|
||||||
if ((new getSpecificData())->getWebsite() != "backend.blackpi.ipv64.net") {
|
if ((new getSpecificData())->getWebsite() != "backend.blackpi.ipv64.net") {
|
||||||
@@ -76,7 +93,7 @@ if ((new getSpecificData())->getWebsite() != "backend.blackpi.ipv64.net") {
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header class="main-header">
|
||||||
Backend
|
Backend
|
||||||
<button id="darkModeToggle">Dark Mode</button>
|
<button id="darkModeToggle">Dark Mode</button>
|
||||||
<button id="logoutButton">Logout</button>
|
<button id="logoutButton">Logout</button>
|
||||||
@@ -85,33 +102,29 @@ if ((new getSpecificData())->getWebsite() != "backend.blackpi.ipv64.net") {
|
|||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<?php foreach ($serviceGroups as $groupKey => $group): ?>
|
<?php foreach ($serviceGroups as $groupKey => $group): ?>
|
||||||
<?php
|
<?php
|
||||||
$isOpen = false;
|
$visibleServices = [];
|
||||||
|
|
||||||
if (!empty($group['defaultOpen'])) {
|
foreach ($group['services'] as $serviceKey) {
|
||||||
$isOpen = true;
|
if (!isset($services[$serviceKey])) continue;
|
||||||
|
if (!$services[$serviceKey]['active']) continue;
|
||||||
|
if (!empty($services[$serviceKey]['adminOnly']) && !$isAdmin) continue;
|
||||||
|
if (!in_array($serviceKey, $userRights, true)) continue;
|
||||||
|
$visibleServices[] = $serviceKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($selectedService, $group['services'], true)) {
|
if (empty($visibleServices)) continue;
|
||||||
$isOpen = true;
|
|
||||||
}
|
$isOpen = !empty($group['defaultOpen']) || in_array($selectedService, $visibleServices, true);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="service-group <?= $isOpen ? 'open' : '' ?>" data-group="<?= $groupKey ?>">
|
<div class="service-group <?= $isOpen ? 'open' : '' ?>" data-group="<?= $groupKey ?>">
|
||||||
|
|
||||||
<div class="group-title">
|
<div class="group-title">
|
||||||
<?= htmlspecialchars($group['label']) ?>
|
<?= htmlspecialchars($group['label']) ?>
|
||||||
<span class="arrow">▸</span>
|
<span class="arrow">▸</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="group-services">
|
<div class="group-services">
|
||||||
<?php foreach ($group['services'] as $serviceKey): ?>
|
<?php foreach ($visibleServices as $serviceKey): ?>
|
||||||
<?php
|
|
||||||
if (!isset($services[$serviceKey])) continue;
|
|
||||||
if (!$services[$serviceKey]['active']) continue;
|
|
||||||
|
|
||||||
if (!empty($services[$serviceKey]['adminOnly']) && !$isAdmin) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<a href="?service=<?= $serviceKey ?>">
|
<a href="?service=<?= $serviceKey ?>">
|
||||||
<button class="<?= $selectedService === $serviceKey ? 'active' : '' ?>">
|
<button class="<?= $selectedService === $serviceKey ? 'active' : '' ?>">
|
||||||
<?= htmlspecialchars($services[$serviceKey]['name']) ?>
|
<?= htmlspecialchars($services[$serviceKey]['name']) ?>
|
||||||
|
|||||||
+49
-6
@@ -2,6 +2,7 @@
|
|||||||
include_once 'controller/DatabaseController.php';
|
include_once 'controller/DatabaseController.php';
|
||||||
include_once 'controller/RoutesController.php';
|
include_once 'controller/RoutesController.php';
|
||||||
include_once 'controller/LogController.php';
|
include_once 'controller/LogController.php';
|
||||||
|
include_once 'modules/Mail.php';
|
||||||
include_once 'config.php';
|
include_once 'config.php';
|
||||||
|
|
||||||
session_set_cookie_params([
|
session_set_cookie_params([
|
||||||
@@ -22,20 +23,40 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$username = $_POST['username'] ?? '';
|
$username = $_POST['username'] ?? '';
|
||||||
$password = $_POST['password'] ?? '';
|
$password = $_POST['password'] ?? '';
|
||||||
|
|
||||||
|
// Gast-Login direkt prüfen
|
||||||
|
if ($username === 'gast') {
|
||||||
|
$_SESSION['user_logged_in'] = true;
|
||||||
|
$_SESSION['username'] = 'gast';
|
||||||
|
$_SESSION['is_admin'] = false;
|
||||||
|
$_SESSION['is_superuser'] = false;
|
||||||
|
|
||||||
|
logging();
|
||||||
|
sendMail(
|
||||||
|
"Gast Login erfolgreich",
|
||||||
|
"Benutzer: gast",
|
||||||
|
(new getSpecificData())->getRequestURL(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
redirectToWebsite("index.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regulärer Benutzer-Login
|
||||||
$results = DatabaseShow(
|
$results = DatabaseShow(
|
||||||
'Benutzer',
|
'Benutzer',
|
||||||
'PASSWORD',
|
'PASSWORD',
|
||||||
'NAME = ?',
|
'NAME = ?',
|
||||||
$username
|
$username
|
||||||
);
|
);
|
||||||
|
|
||||||
$isAdmin = DatabaseShow(
|
$isAdmin = DatabaseShow(
|
||||||
"Benutzer",
|
"Benutzer",
|
||||||
"ADMIN",
|
"ADMIN",
|
||||||
"NAME = ?",
|
"NAME = ?",
|
||||||
$username
|
$username
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($results)) {
|
if (!empty($results)) {
|
||||||
$user = $results[0];
|
$user = $results[0];
|
||||||
|
|
||||||
@@ -54,18 +75,35 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$_SESSION['is_admin'] = false;
|
$_SESSION['is_admin'] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// header("Location: index.php");
|
|
||||||
logging();
|
logging();
|
||||||
|
sendMail(
|
||||||
|
"User Login Successful",
|
||||||
|
"$username, $password",
|
||||||
|
(new getSpecificData())->getRequestURL(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
redirectToWebsite("index.php");
|
redirectToWebsite("index.php");
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
$error = 'Login fehlgeschlagen: Passwort inkorrekt';
|
$error = 'Login fehlgeschlagen';
|
||||||
|
sendMail(
|
||||||
|
"User Login failed",
|
||||||
|
"$username, $password",
|
||||||
|
(new getSpecificData())->getRequestURL(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$error = 'Systemfehler: Spalte "password" nicht in der Datenbank gefunden.';
|
$error = 'Systemfehler: Spalte "password" nicht in der Datenbank gefunden.';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$error = 'Login fehlgeschlagen: Benutzer nicht gefunden';
|
$error = 'Login fehlgeschlagen';
|
||||||
|
sendMail(
|
||||||
|
"User Login failed",
|
||||||
|
"$username, $password",
|
||||||
|
(new getSpecificData())->getRequestURL(),
|
||||||
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -100,6 +138,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
<button type="submit">Login</button>
|
<button type="submit">Login</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<button style="margin-top: 9px" type="button"
|
||||||
|
onclick="document.querySelector('input[name=username]').value='gast'; document.querySelector('form').submit();">
|
||||||
|
Als Gast einloggen
|
||||||
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
include_once __DIR__ . '/../controller/DatabaseController.php';
|
||||||
|
include_once __DIR__ . '/../controller/DataController.php';
|
||||||
|
|
||||||
|
function sendMail($subject, $message, $url, bool $log) {
|
||||||
|
$headers = "From: bruno.eckhardt07@gmail.com\r\n";
|
||||||
|
mail(
|
||||||
|
"bruno.eckhardt07@gmail.com",
|
||||||
|
$subject,
|
||||||
|
$message,
|
||||||
|
$headers
|
||||||
|
);
|
||||||
|
if ($log == true) {
|
||||||
|
DatabaseInsert(
|
||||||
|
"Mailing",
|
||||||
|
"DATUM, SUBJECT, MESSAGE, URL, CLIENT_IP",
|
||||||
|
(new getSpecificData())->getRequestTime(),
|
||||||
|
$subject,
|
||||||
|
$message,
|
||||||
|
$url,
|
||||||
|
(new getSpecificData())->getClientIP(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorMail($title, $error, bool $log) {
|
||||||
|
$headers = "From: bruno.eckhardt07@gmail.com\r\n";
|
||||||
|
mail(
|
||||||
|
"bruno.eckhardt07@gmail.com",
|
||||||
|
"ERROR: $title",
|
||||||
|
$error,
|
||||||
|
$headers,
|
||||||
|
);
|
||||||
|
if ($log == true) {
|
||||||
|
DatabaseInsert(
|
||||||
|
"Mailing",
|
||||||
|
"DATUM, SUBJECT, MESSAGE, URL, CLIENT_IP",
|
||||||
|
(new getSpecificData())->getRequestTime(),
|
||||||
|
"ERROR: $title",
|
||||||
|
$error,
|
||||||
|
(new getSpecificData())->getClientIP(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
<?php
|
||||||
|
// API Tester Service - Als Modul für index.php
|
||||||
|
// Dieser Service dient zum manuellen Testen der API-Endpunkte.
|
||||||
|
|
||||||
|
// Basis-Verzeichnisse scannen (Pfad relativ zur index.php)
|
||||||
|
$apiDir = __DIR__ . '/../api/';
|
||||||
|
$apiFiles = glob($apiDir . '*.php');
|
||||||
|
$apiOptions = [];
|
||||||
|
foreach ($apiFiles as $file) {
|
||||||
|
$apiOptions[] = 'api/' . basename($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Token aus deiner get.php entnommen
|
||||||
|
$defaultToken = "15a437d128c918633e57dc7d18118a073b807644f21731ed5a7ebcf3eca9e242";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Spezifische Styles für den API Tester innerhalb des Content-Bereichs */
|
||||||
|
.api-tester-container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: var(--card-bg);
|
||||||
|
padding: 25px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid var(--card-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-tester-container h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: var(--btn-bg);
|
||||||
|
border-bottom: 1px solid var(--card-border);
|
||||||
|
padding-bottom: 10px;
|
||||||
|
display: block;
|
||||||
|
/* style.css h2 hat flex, wir wollen hier einfaches block */
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-form-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: var(--input-bg);
|
||||||
|
border: 1px solid var(--input-border);
|
||||||
|
color: var(--input-text);
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-btn-send {
|
||||||
|
background-color: var(--btn-bg);
|
||||||
|
color: white;
|
||||||
|
padding: 12px 20px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-btn-send:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tester-response-container {
|
||||||
|
margin-top: 25px;
|
||||||
|
background-color: var(--input-bg);
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--card-border);
|
||||||
|
min-height: 80px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tester-output-content {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
margin: 0;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-status-200 {
|
||||||
|
background-color: var(--status-bg);
|
||||||
|
color: var(--status-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-status-error {
|
||||||
|
background-color: #dc3545;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tester-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.tester-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="api-tester-container">
|
||||||
|
<h2>🛠️ API Tester</h2>
|
||||||
|
|
||||||
|
<div class="tester-form-group">
|
||||||
|
<label for="endpoint">API Endpunkt</label>
|
||||||
|
<select id="endpoint" class="tester-input" onchange="checkEndpoint()">
|
||||||
|
<?php foreach ($apiOptions as $opt): ?>
|
||||||
|
<option value="<?= $opt ?>"><?= $opt ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tester-grid">
|
||||||
|
<div class="tester-form-group">
|
||||||
|
<label for="method">HTTP Methode</label>
|
||||||
|
<select id="method" class="tester-input">
|
||||||
|
<option value="GET">GET</option>
|
||||||
|
<option value="POST">POST</option>
|
||||||
|
<option value="OPTIONS">OPTIONS</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tester-form-group" id="function-group">
|
||||||
|
<label for="function-header">Function Header</label>
|
||||||
|
<input type="text" id="function-header" class="tester-input" placeholder="z.B. IPs, Ueberstunden">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tester-form-group">
|
||||||
|
<label for="token">Authorization Token</label>
|
||||||
|
<input type="text" id="token" class="tester-input" value="<?= $defaultToken ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tester-form-group hidden" id="file-group">
|
||||||
|
<label for="files">Dateien (files)</label>
|
||||||
|
<input type="file" id="files" class="tester-input" multiple>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="tester-btn-send" onclick="sendApiRequest()">Anfrage senden 🚀</button>
|
||||||
|
|
||||||
|
<div id="tester-response-container">
|
||||||
|
<div style="text-align: center; color: #888; padding: 10px;">Bereit für Anfragen.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function checkEndpoint() {
|
||||||
|
const endpoint = document.getElementById('endpoint').value;
|
||||||
|
const fileGroup = document.getElementById('file-group');
|
||||||
|
const functionGroup = document.getElementById('function-group');
|
||||||
|
const methodSelect = document.getElementById('method');
|
||||||
|
|
||||||
|
// Standard: alles ausblenden
|
||||||
|
fileGroup.classList.add('hidden');
|
||||||
|
functionGroup.classList.remove('hidden');
|
||||||
|
|
||||||
|
if (endpoint === 'api/upload.php') {
|
||||||
|
// Nur bei exakt api/upload.php Dateien anzeigen
|
||||||
|
fileGroup.classList.remove('hidden');
|
||||||
|
functionGroup.classList.add('hidden');
|
||||||
|
methodSelect.value = 'POST';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endpoint === 'api/get.php') {
|
||||||
|
methodSelect.value = 'GET';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendApiRequest() {
|
||||||
|
const endpoint = document.getElementById('endpoint').value;
|
||||||
|
const method = document.getElementById('method').value;
|
||||||
|
const token = document.getElementById('token').value;
|
||||||
|
const functionHeader = document.getElementById('function-header').value;
|
||||||
|
const fileInput = document.getElementById('files');
|
||||||
|
const responseContainer = document.getElementById('tester-response-container');
|
||||||
|
|
||||||
|
responseContainer.innerHTML = '<div style="text-align: center; padding: 10px;">Lade...</div>';
|
||||||
|
|
||||||
|
let headers = {
|
||||||
|
'Authorization': token
|
||||||
|
};
|
||||||
|
|
||||||
|
if (endpoint.includes('get.php') && functionHeader) {
|
||||||
|
headers['Function'] = functionHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
let options = {
|
||||||
|
method: method,
|
||||||
|
headers: headers
|
||||||
|
};
|
||||||
|
|
||||||
|
if (endpoint.includes('upload.php') && fileInput.files.length > 0) {
|
||||||
|
const formData = new FormData();
|
||||||
|
for (let i = 0; i < fileInput.files.length; i++) {
|
||||||
|
formData.append('files[]', fileInput.files[i]);
|
||||||
|
}
|
||||||
|
options.body = formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(endpoint, options);
|
||||||
|
const status = response.status;
|
||||||
|
const rawText = await response.text();
|
||||||
|
let resultText = rawText;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(rawText);
|
||||||
|
resultText = JSON.stringify(json, null, 2);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
const badgeClass = status >= 200 && status < 300 ? 'tester-status-200' : 'tester-status-error';
|
||||||
|
|
||||||
|
responseContainer.innerHTML = `
|
||||||
|
<div class="tester-badge ${badgeClass}">Status: ${status}</div>
|
||||||
|
<pre id="tester-output-content"></pre>
|
||||||
|
`;
|
||||||
|
document.getElementById('tester-output-content').textContent = resultText;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
responseContainer.innerHTML = `<div style="color:#dc3545; padding: 10px;">Fehler: ${error.message}</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial check
|
||||||
|
checkEndpoint();
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$mode = $_GET['mode'] ?? 'fk';
|
||||||
|
|
||||||
|
if ($mode === 'normal') {
|
||||||
|
$data = Databaseshow("Firmenberichte");
|
||||||
|
} else {
|
||||||
|
$data = DatabaseShowWithFK(
|
||||||
|
"Berufsschulberichte",
|
||||||
|
$Berufsschulberichte,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_reverse($data);
|
||||||
|
|
||||||
|
$displayData = (is_array($data) && isset($data['rows'])) ? $data['rows'] : $data;
|
||||||
|
$count = is_array($displayData) ? count($displayData) : 0;
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="stylesheet" href="../style.css">
|
||||||
|
<style>
|
||||||
|
.debug-table-container {
|
||||||
|
background: #252525;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0;
|
||||||
|
margin-top: 20px;
|
||||||
|
overflow-x: auto;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
color: #ccc;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background: #333;
|
||||||
|
text-align: left;
|
||||||
|
padding: 15px 12px;
|
||||||
|
border-bottom: 2px solid #3498db;
|
||||||
|
color: #3498db;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background: rgba(255, 255, 255, 0.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:hover {
|
||||||
|
background: rgba(52, 152, 219, 0.1);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Highlight für DATUM Spalte */
|
||||||
|
td:first-child,
|
||||||
|
th:first-child {
|
||||||
|
position: sticky;
|
||||||
|
left: 0;
|
||||||
|
background: #252525;
|
||||||
|
z-index: 5;
|
||||||
|
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
th:first-child {
|
||||||
|
z-index: 11;
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.debug-raw {
|
||||||
|
background: #1a1a1a;
|
||||||
|
color: #00ff00;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-family: 'Fira Code', monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
overflow: auto;
|
||||||
|
border-left: 4px solid #3498db;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-count {
|
||||||
|
background: #3498db;
|
||||||
|
color: white;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-note {
|
||||||
|
padding: 40px;
|
||||||
|
text-align: center;
|
||||||
|
color: #777;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="<?= ($_SESSION['dark_mode'] ?? true) ? 'dark-mode' : '' ?>">
|
||||||
|
<div class="main">
|
||||||
|
<div class="content">
|
||||||
|
<h2 style="display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<span>📊 Berichtte-Vorschau:</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a href="?service=<?= $selectedService ?>&mode=fk">
|
||||||
|
<button <?= $mode === 'fk' ? 'style="background:#3498db;color:white;"' : '' ?>>
|
||||||
|
Berufsschulberichte
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="?service=<?= $selectedService ?>&mode=normal">
|
||||||
|
<button <?= $mode === 'normal' ? 'style="background:#3498db;color:white;"' : '' ?>>
|
||||||
|
Arbeitsberichte
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<?php if ($count > 0 && is_array($displayData[0])): ?>
|
||||||
|
<div class="debug-table-container">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<?php foreach (array_keys($displayData[0]) as $column): ?>
|
||||||
|
<th><?= htmlspecialchars($column) ?></th>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($displayData as $row): ?>
|
||||||
|
<tr>
|
||||||
|
<?php foreach ($row as $key => $cell): ?>
|
||||||
|
<td><?= htmlspecialchars($cell ?? '-') ?></td>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="debug-table-container">
|
||||||
|
<div class="empty-note">
|
||||||
|
Keine tabellarischen Daten gefunden.<br>
|
||||||
|
<small>Struktur: <?= is_array($data) ? 'Array ('.count($data).' Keys)' : gettype($data) ?></small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
<?php
|
|
||||||
$conn = db_connect();
|
|
||||||
$view = $_GET['view'] ?? 'show';
|
|
||||||
$selectedService = $_GET['service'];
|
|
||||||
|
|
||||||
// --- LOGIK: Überstunden-Eintrag (Abbau) speichern ---
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_overtime'])) {
|
|
||||||
$datum = $_POST['ot_date'];
|
|
||||||
$minuten = intval($_POST['ot_minutes']);
|
|
||||||
$grund = $conn->real_escape_string($_POST['ot_reason']);
|
|
||||||
$insert_sql = "INSERT INTO Ueberstunden (DATUM, MINUTEN, GRUND) VALUES ('$datum', $minuten, '$grund')";
|
|
||||||
$conn->query($insert_sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Daten laden ---
|
|
||||||
$daten = [];
|
|
||||||
$sql = "SELECT `DATUM`, `PROZESS_1`, `PROZESS_2`, `PROZESS_3`, `PROZESS_4`, `BEGINN`, `ENDE_REAL`, `OVERTIME` FROM Firmenberichte ORDER BY `DATUM` DESC";
|
|
||||||
if ($erg = $conn->query($sql)) {
|
|
||||||
while ($datensatz = $erg->fetch_object()) { $daten[] = $datensatz; }
|
|
||||||
$erg->free();
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Gesamtsumme berechnen ---
|
|
||||||
$minuten_berichte = 0;
|
|
||||||
$res1 = $conn->query("SELECT SUM(OVERTIME) AS summe FROM Firmenberichte");
|
|
||||||
if ($row = $res1->fetch_object()) { $minuten_berichte = intval($row->summe); }
|
|
||||||
|
|
||||||
$minuten_extra = 0;
|
|
||||||
$res2 = $conn->query("SELECT SUM(MINUTEN) AS summe FROM Ueberstunden");
|
|
||||||
if ($row = $res2->fetch_object()) { $minuten_extra = intval($row->summe); }
|
|
||||||
|
|
||||||
$gesamt_minuten = $minuten_berichte - $minuten_extra;
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="arbeitsberichte-wrapper">
|
|
||||||
<div style="display: flex; gap: 10px; margin-bottom: 25px;">
|
|
||||||
<a href="?service=<?= $selectedService ?>&view=rechner" style="text-decoration:none;">
|
|
||||||
<button class="nav-btn <?= $view == 'rechner' ? 'active' : '' ?>" style="padding: 10px 20px; cursor: pointer; border: none; border-radius: 4px; font-weight: bold;
|
|
||||||
background: <?= $view == 'rechner' ? '#007bff' : 'rgba(150,150,150,0.2)' ?>;
|
|
||||||
color: <?= $view == 'rechner' ? '#fff' : '#fff' ?>;">
|
|
||||||
Live-Timer
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
<a href="?service=<?= $selectedService ?>&view=show" style="text-decoration:none;">
|
|
||||||
<button class="nav-btn <?= $view == 'show' ? 'active' : '' ?>" style="padding: 10px 20px; cursor: pointer; border: none; border-radius: 4px; font-weight: bold;
|
|
||||||
background: <?= $view == 'show' ? '#007bff' : 'rgba(150,150,150,0.2)' ?>;
|
|
||||||
color: <?= $view == 'show' ? '#fff' : '#fff' ?>;">
|
|
||||||
Übersicht
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if ($view === 'rechner'): ?>
|
|
||||||
<div class="overtime-container" style="color: inherit;">
|
|
||||||
<h2 style="color: inherit;">Überstunden Rechner</h2>
|
|
||||||
<label for="startTime">Arbeitsstartzeit:</label>
|
|
||||||
<input type="time" id="startTime" step="60"
|
|
||||||
style="background: rgba(150,150,150,0.1); color: inherit; border: 1px solid #555;">
|
|
||||||
<button id="startBtn">Timer starten</button>
|
|
||||||
|
|
||||||
<div id="resultBox" class="overtime-result">
|
|
||||||
<p style="margin:0; font-size: 0.9rem;">Überstunden / Restzeit:</p>
|
|
||||||
<div id="result">0:00</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<div
|
|
||||||
style="background: rgba(150,150,150,0.05); padding: 25px; border-radius: 10px; margin-bottom: 25px; border: 1px solid rgba(150,150,150,0.2); border-left: 6px solid #007bff;">
|
|
||||||
<div style="margin-bottom: 20px;">
|
|
||||||
<span style="color: #888; font-size: 0.8rem; font-weight: bold; text-transform: uppercase;">Aktueller
|
|
||||||
Stand</span>
|
|
||||||
<h2 style="margin: 5px 0 0 0; font-size: 2rem; color: <?= $gesamt_minuten >= 0 ? '#28a745' : '#dc3545' ?>;">
|
|
||||||
<?= intdiv($gesamt_minuten, 60) ?>h <?= abs($gesamt_minuten % 60) ?>min
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="POST" style="display: flex; gap: 15px; flex-wrap: wrap; align-items: flex-end;">
|
|
||||||
<input type="hidden" name="add_overtime" value="1">
|
|
||||||
<div style="display: flex; flex-direction: column; gap: 5px;">
|
|
||||||
<label style="font-size: 0.85rem; font-weight: 600; color: inherit;">Datum</label>
|
|
||||||
<input type="date" name="ot_date" value="<?= date('Y-m-d') ?>" required
|
|
||||||
style="padding: 8px; border: 1px solid rgba(150,150,150,0.3); border-radius: 4px; background: rgba(150,150,150,0.1); color: inherit;">
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; flex-direction: column; gap: 5px;">
|
|
||||||
<label style="font-size: 0.85rem; font-weight: 600; color: inherit;">Minuten Abbau</label>
|
|
||||||
<input type="number" name="ot_minutes" placeholder="480" required
|
|
||||||
style="width: 100px; padding: 8px; border: 1px solid rgba(150,150,150,0.3); border-radius: 4px; background: rgba(150,150,150,0.1); color: inherit;">
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; flex-direction: column; gap: 5px; flex-grow: 1;">
|
|
||||||
<label style="font-size: 0.85rem; font-weight: 600; color: inherit;">Grund</label>
|
|
||||||
<input type="text" name="ot_reason" placeholder="z.B. Abbau" required
|
|
||||||
style="padding: 8px; border: 1px solid rgba(150,150,150,0.3); border-radius: 4px; background: rgba(150,150,150,0.1); color: inherit;">
|
|
||||||
</div>
|
|
||||||
<button type="submit"
|
|
||||||
style="background: #007bff; color: white; border: none; padding: 10px 20px; border-radius: 4px; font-weight: bold; cursor: pointer;">
|
|
||||||
Eintrag speichern
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table style="width: 100%; border-collapse: collapse; color: inherit;">
|
|
||||||
<thead>
|
|
||||||
<tr style="background: rgba(0,123,255,0.15); text-align: left;">
|
|
||||||
<th style="padding: 12px; border-bottom: 2px solid #007bff;">Datum</th>
|
|
||||||
<th style="padding: 12px; border-bottom: 2px solid #007bff;">Prozesse</th>
|
|
||||||
<th style="padding: 12px; border-bottom: 2px solid #007bff;">Zeitraum</th>
|
|
||||||
<th style="padding: 12px; border-bottom: 2px solid #007bff;">Overtime</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($daten as $b): ?>
|
|
||||||
<tr style="border-bottom: 1px solid rgba(150,150,150,0.2); vertical-align: top;">
|
|
||||||
<td style="padding: 12px; white-space: nowrap;"><?= htmlspecialchars($b->DATUM) ?></td>
|
|
||||||
<td style="padding: 12px;">
|
|
||||||
<div style="display: flex; flex-direction: column; gap: 3px; font-size: 0.85rem; opacity: 0.8;">
|
|
||||||
<?php for($i=1; $i<=4; $i++): $p = "PROZESS_$i"; ?>
|
|
||||||
<?php if(!empty($b->$p)): ?> <span>• <?= htmlspecialchars($b->$p) ?></span> <?php endif; ?>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td style="padding: 12px; font-size: 0.9rem; white-space: nowrap;"><?= $b->BEGINN ?> -
|
|
||||||
<?= $b->ENDE_REAL ?></td>
|
|
||||||
<td style="padding: 12px; font-weight: bold; color: <?= $b->OVERTIME >= 0 ? '#28a745' : '#dc3545' ?>;">
|
|
||||||
<?= $b->OVERTIME ?> min
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Live-Rechner Logik
|
|
||||||
if (document.getElementById('startBtn')) {
|
|
||||||
document.getElementById('startBtn').addEventListener('click', function() {
|
|
||||||
const startTimeInput = document.getElementById('startTime').value;
|
|
||||||
if (!startTimeInput) return;
|
|
||||||
const [hours, minutes] = startTimeInput.split(':').map(Number);
|
|
||||||
let startDate = new Date();
|
|
||||||
startDate.setHours(hours, minutes, 0);
|
|
||||||
const targetWorkMs = 8.5 * 60 * 60 * 1000;
|
|
||||||
const resultEl = document.getElementById('result');
|
|
||||||
const resultBox = document.getElementById('resultBox');
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
const diffMs = (new Date() - startDate) - targetWorkMs;
|
|
||||||
const negative = diffMs < 0;
|
|
||||||
const absMs = Math.abs(diffMs);
|
|
||||||
const h = Math.floor(absMs / 3600000);
|
|
||||||
const m = Math.floor((absMs % 3600000) / 60000);
|
|
||||||
resultEl.innerText = (negative ? '-' : '+') + h + ":" + (m < 10 ? '0' : '') + m;
|
|
||||||
if (negative) {
|
|
||||||
resultBox.classList.add('negative');
|
|
||||||
} else {
|
|
||||||
resultBox.classList.remove('negative');
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$statusMsg = "";
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
Neue Domain hinzufügen
|
||||||
|
========================= */
|
||||||
|
if (isset($_POST["add_domain"])) {
|
||||||
|
|
||||||
|
$subdomain = trim($_POST["subdomain"]);
|
||||||
|
|
||||||
|
if ($subdomain != "") {
|
||||||
|
DatabaseInsert("Domains", "SUBDOMAIN", $subdomain);
|
||||||
|
$statusMsg = "Domain wurde hinzugefügt.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
Domain löschen
|
||||||
|
========================= */
|
||||||
|
if (isset($_POST["delete_domain"])) {
|
||||||
|
|
||||||
|
$id = intval($_POST["id"]);
|
||||||
|
|
||||||
|
DatabaseDelete("Domains", "ID = ?", $id);
|
||||||
|
|
||||||
|
$statusMsg = "Domain wurde gelöscht.";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
Domain bearbeiten
|
||||||
|
========================= */
|
||||||
|
if (isset($_POST["save_domain"])) {
|
||||||
|
|
||||||
|
$id = intval($_POST["id"]);
|
||||||
|
$subdomain = trim($_POST["subdomain"]);
|
||||||
|
|
||||||
|
DatabaseUpdate("Domains", "SUBDOMAIN = ?", "ID = ?", $subdomain, $id);
|
||||||
|
|
||||||
|
$statusMsg = "Domain wurde gespeichert.";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =========================
|
||||||
|
Domains laden
|
||||||
|
========================= */
|
||||||
|
|
||||||
|
$domains = DatabaseShow("Domains", "*");
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Domain Verwaltung
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<?php if ($statusMsg): ?>
|
||||||
|
<div class="status-msg">
|
||||||
|
<?= htmlspecialchars($statusMsg) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="admin-grid">
|
||||||
|
|
||||||
|
<?php foreach ($domains as $domain): ?>
|
||||||
|
|
||||||
|
<form method="post" class="admin-card">
|
||||||
|
|
||||||
|
<input type="hidden" name="id" value="<?= $domain["ID"] ?>">
|
||||||
|
|
||||||
|
<label>Subdomain</label>
|
||||||
|
|
||||||
|
<input type="text" name="subdomain" value="<?= htmlspecialchars($domain["SUBDOMAIN"]) ?>">
|
||||||
|
|
||||||
|
<div style="margin-top:10px; display:flex; gap:10px;">
|
||||||
|
|
||||||
|
<button type="submit" name="save_domain" class="btn-save">
|
||||||
|
Speichern
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="submit" name="delete_domain" class="btn-delete">
|
||||||
|
Löschen
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Neue Domain -->
|
||||||
|
|
||||||
|
<form method="post" class="admin-card new-item">
|
||||||
|
|
||||||
|
<h3>Neu</h3>
|
||||||
|
|
||||||
|
<label>Subdomain</label>
|
||||||
|
|
||||||
|
<input type="text" name="subdomain" placeholder="z.B. kleinerpenis.blackpi.ipv64.net">
|
||||||
|
|
||||||
|
<button type="submit" name="add_domain" class="btn-add">
|
||||||
|
Domain hinzufügen
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -19,6 +19,7 @@ $db_res = DatabaseShow(
|
|||||||
<h3 style="background-color: #007bff;">👤 Benutzerprofil</h3>
|
<h3 style="background-color: #007bff;">👤 Benutzerprofil</h3>
|
||||||
<div class="group-links" style="padding: 10px; color: inherit;">
|
<div class="group-links" style="padding: 10px; color: inherit;">
|
||||||
<p style="margin: 5px 0;"><strong>Name:</strong> <code><?= htmlspecialchars($username) ?></code></p>
|
<p style="margin: 5px 0;"><strong>Name:</strong> <code><?= htmlspecialchars($username) ?></code></p>
|
||||||
|
<?php if ($username != 'gast'): ?>
|
||||||
<p style="margin: 5px 0;"><strong>Nachname:</strong>
|
<p style="margin: 5px 0;"><strong>Nachname:</strong>
|
||||||
<code><?= htmlspecialchars($db_res[0]['NACHNAME']) ?></code>
|
<code><?= htmlspecialchars($db_res[0]['NACHNAME']) ?></code>
|
||||||
</p>
|
</p>
|
||||||
@@ -31,6 +32,7 @@ $db_res = DatabaseShow(
|
|||||||
<p style="margin: 5px 0;"><strong>Home IP:</strong>
|
<p style="margin: 5px 0;"><strong>Home IP:</strong>
|
||||||
<code><?= htmlspecialchars($db_res[0]['HOME_IP']) ?></code>
|
<code><?= htmlspecialchars($db_res[0]['HOME_IP']) ?></code>
|
||||||
</p>
|
</p>
|
||||||
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$dir = __DIR__ . "/../static";
|
||||||
|
$files = array_diff(scandir($dir), ['.', '..']);
|
||||||
|
|
||||||
|
echo '<button onclick="printFiles()">Alle Dateien drucken</button>';
|
||||||
|
|
||||||
|
echo '<div class="print-container">';
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
|
||||||
|
$url = "static/" . rawurlencode($file);
|
||||||
|
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
||||||
|
|
||||||
|
echo '<div class="print-page">';
|
||||||
|
|
||||||
|
if (in_array($ext, ['png','jpg','jpeg','webp'])) {
|
||||||
|
echo "<img src='$url'>";
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif ($ext === "pdf") {
|
||||||
|
echo "<embed src='$url' type='application/pdf'>";
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
echo "<p>$file kann nicht direkt gedruckt werden.</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</div>';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function printFiles() {
|
||||||
|
console.log("Ich wurde gedrückt");
|
||||||
|
window.print();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.print-page {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
page-break-after: always;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-page img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-page embed {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
|
||||||
|
body * {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-container,
|
||||||
|
.print-container * {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.print-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -118,7 +118,7 @@ unset($_SESSION['status_message']);
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="<?= ($_SESSION['dark_mode'] ?? false) ? 'dark-mode' : '' ?>">
|
<body class="<?= ($_SESSION['dark_mode'] ?? false) ? 'dark-mode' : '' ?>">
|
||||||
<div class="main">
|
<div class="content">
|
||||||
<?php if (!($_SESSION['logged_in'] ?? false)): ?>
|
<?php if (!($_SESSION['logged_in'] ?? false)): ?>
|
||||||
<div class="login-container">
|
<div class="login-container">
|
||||||
<div class="login-box">
|
<div class="login-box">
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
$tables = DatabaseShowTables();
|
||||||
|
$selectedTable = $_GET['table'] ?? null;
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<h2>Datenbank Struktur</h2>
|
||||||
|
|
||||||
|
<form method="GET">
|
||||||
|
<input type="hidden" name="service" value="tabellen">
|
||||||
|
|
||||||
|
<label for="table">Tabelle auswählen:</label>
|
||||||
|
<select name="table" id="table" onchange="this.form.submit()">
|
||||||
|
<option value="">-- Bitte wählen --</option>
|
||||||
|
<?php foreach ($tables as $table): ?>
|
||||||
|
<option value="<?= htmlspecialchars($table) ?>" <?= ($selectedTable === $table) ? 'selected' : '' ?>>
|
||||||
|
<?= htmlspecialchars($table) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if ($selectedTable && in_array($selectedTable, $tables)) {
|
||||||
|
|
||||||
|
$structure = DatabaseShowTableStructure($selectedTable);
|
||||||
|
|
||||||
|
echo "<div class='table-container'>";
|
||||||
|
echo "<table class='db-table'>";
|
||||||
|
echo "<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Null</th>
|
||||||
|
<th>Key</th>
|
||||||
|
<th>Default</th>
|
||||||
|
<th>Extra</th>
|
||||||
|
</tr>";
|
||||||
|
|
||||||
|
foreach ($structure as $column) {
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<td>" . ($column['Field']) . "</td>";
|
||||||
|
echo "<td>" . ($column['Type']) . "</td>";
|
||||||
|
echo "<td>" . ($column['Null']) . "</td>";
|
||||||
|
echo "<td>" . ($column['Key']) . "</td>";
|
||||||
|
echo "<td>" . ($column['Default']) . "</td>";
|
||||||
|
echo "<td>" . ($column['Extra']) . "</td>";
|
||||||
|
echo "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "</table>";
|
||||||
|
echo "</div>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
$conn = db_connect();
|
||||||
|
|
||||||
|
$sql = "SELECT ZEIT, AKTUELL FROM Wetter";
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
$labels = [];
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
while($row = $result->fetch_assoc()) {
|
||||||
|
$labels[] = $row['ZEIT'];
|
||||||
|
$data[] = (float)$row['AKTUELL'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<canvas id="logChart" width="600" height="400"></canvas>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const ctx = document.getElementById('logChart').getContext('2d');
|
||||||
|
const logChart = new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: <?php echo json_encode($labels); ?>,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Wetter',
|
||||||
|
data: <?php echo json_encode($data); ?>,
|
||||||
|
borderColor: 'rgba(75, 192, 192, 1)',
|
||||||
|
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||||
|
fill: false,
|
||||||
|
tension: 0
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
position: 'top'
|
||||||
|
},
|
||||||
|
zoom: {
|
||||||
|
pan: {
|
||||||
|
enabled: true,
|
||||||
|
mode: 'x',
|
||||||
|
},
|
||||||
|
zoom: {
|
||||||
|
wheel: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
mode: 'x',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
interaction: {
|
||||||
|
mode: 'index',
|
||||||
|
intersect: false
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Zeitraum'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
min: -10,
|
||||||
|
max: 40,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Temperatur in °C'
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
stepSize: 1
|
||||||
|
},
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
include_once __DIR__ . '/../controller/DatabaseController.php';
|
||||||
|
include_once __DIR__ . '/../controller/RoutesController.php';
|
||||||
|
|
||||||
|
$conn = db_connect();
|
||||||
|
$view = $_GET['view'] ?? 'show';
|
||||||
|
$selectedService = $_GET['service'];
|
||||||
|
|
||||||
|
// --- LOGIK: Überstunden-Eintrag (Abbau) speichern ---
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_overtime'])) {
|
||||||
|
$datum = $_POST['ot_date'];
|
||||||
|
$minuten = intval($_POST['ot_minutes']);
|
||||||
|
$grund = $conn->real_escape_string($_POST['ot_reason']);
|
||||||
|
|
||||||
|
DatabaseInsert(
|
||||||
|
"Ueberstunden",
|
||||||
|
"DATUM, MINUTEN, GRUND",
|
||||||
|
$datum,
|
||||||
|
$minuten,
|
||||||
|
$grund
|
||||||
|
);
|
||||||
|
|
||||||
|
redirectToWebsite((new getSpecificData())->getReferer());
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Gesamtsumme berechnen ---
|
||||||
|
$minuten_berichte = 0;
|
||||||
|
$res1 = $conn->query("SELECT SUM(OVERTIME) AS summe FROM Firmenberichte");
|
||||||
|
if ($row = $res1->fetch_object()) { $minuten_berichte = intval($row->summe); }
|
||||||
|
|
||||||
|
$minuten_abbau = 0;
|
||||||
|
$res2 = $conn->query("SELECT SUM(MINUTEN) AS summe FROM Ueberstunden WHERE GRUND = 'Abbau'");
|
||||||
|
if ($row = $res2->fetch_object()) { $minuten_abbau = intval($row->summe); }
|
||||||
|
|
||||||
|
$minuten_aufbau = 0;
|
||||||
|
$res2 = $conn->query("SELECT SUM(MINUTEN) AS summe FROM Ueberstunden WHERE GRUND = 'Aufbau'");
|
||||||
|
if ($row = $res2->fetch_object()) { $minuten_aufbau = intval($row->summe); }
|
||||||
|
|
||||||
|
$gesamt_minuten = $minuten_berichte - $minuten_abbau + $minuten_aufbau;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="arbeitsberichte-wrapper">
|
||||||
|
<div
|
||||||
|
style="background: rgba(150,150,150,0.05); padding: 25px; border-radius: 10px; margin-bottom: 25px; border: 1px solid rgba(150,150,150,0.2); border-left: 6px solid #007bff;">
|
||||||
|
<div style="margin-bottom: 20px;">
|
||||||
|
<span style="color: #888; font-size: 0.8rem; font-weight: bold; text-transform: uppercase;">Aktueller
|
||||||
|
Stand</span>
|
||||||
|
<h2 style="margin: 5px 0 0 0; font-size: 2rem; color: <?= $gesamt_minuten >= 0 ? '#28a745' : '#dc3545' ?>;">
|
||||||
|
<?= intdiv($gesamt_minuten, 60) ?>h <?= abs($gesamt_minuten % 60) ?>min
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<?php if ($_SESSION['username'] == "bruno" || $_SESSION['username'] == "Bruno"): ?>
|
||||||
|
<form method="POST" style="display: flex; gap: 15px; flex-wrap: wrap; align-items: flex-end;">
|
||||||
|
<input type="hidden" name="add_overtime" value="1">
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 5px;">
|
||||||
|
<label style="font-size: 0.85rem; font-weight: 600; color: inherit;">Datum</label>
|
||||||
|
<input type="date" name="ot_date" value="<?= date('Y-m-d') ?>" required
|
||||||
|
style="padding: 8px; border: 1px solid rgba(150,150,150,0.3); border-radius: 4px; background: rgba(150,150,150,0.1); color: inherit;">
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 5px;">
|
||||||
|
<label style="font-size: 0.85rem; font-weight: 600; color: inherit;">Minuten Abbau</label>
|
||||||
|
<input type="number" name="ot_minutes" placeholder="480" required
|
||||||
|
style="width: 100px; padding: 8px; border: 1px solid rgba(150,150,150,0.3); border-radius: 4px; background: rgba(150,150,150,0.1); color: inherit;">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label style="font-size: 0.85rem; font-weight: 600; color: inherit;">Grund</label>
|
||||||
|
|
||||||
|
<select name="ot_reason" required>
|
||||||
|
|
||||||
|
<option value="">Bitte wählen</option>
|
||||||
|
<option value="Abbau">Abbau</option>
|
||||||
|
<option value="Aufbau">Aufbau</option>
|
||||||
|
<option value="Anderes">Anderes</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit"
|
||||||
|
style="background: #007bff; color: white; border: none; padding: 10px 20px; border-radius: 4px; font-weight: bold; cursor: pointer;">
|
||||||
|
Eintrag speichern
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<?php endif ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/.htaccess</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/api/get.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/api/upload.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/favicon.ico</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/index.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/modules/ConsoleLog.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/api_tester.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/backend_request_chart.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/backend_request_logs.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/berichte_arbeit.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/berichte_arbeit_gen.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/data_info.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/home_info.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/links.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/logout.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/personal_request_logs.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/public_request_chart.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/public_request_logs.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/services_control.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/tabellen.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/user_control.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/variablen_control.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/services/weather_chart.php</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/sitemap.xml</loc>
|
||||||
|
<lastmod>2026-03-03</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>http://backend.blackpi.ipv64.net/style.css</loc>
|
||||||
|
<lastmod>2026-03-02</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>1.0</priority>
|
||||||
|
</url>
|
||||||
|
</urlset>
|
||||||
+119
-3
@@ -4,6 +4,7 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
@@ -17,14 +18,29 @@ header {
|
|||||||
.main {
|
.main {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
height: calc(100vh - 60px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-header {
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
padding: 15px 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 200px;
|
width: 240px;
|
||||||
background-color: #f4f4f4;
|
background-color: #f4f4f4;
|
||||||
border-right: 1px solid #ccc;
|
border-right: 1px solid #ccc;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar button {
|
.sidebar button {
|
||||||
@@ -46,7 +62,10 @@ header {
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
padding: 15px;
|
||||||
|
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark Mode Styles */
|
/* Dark Mode Styles */
|
||||||
@@ -954,4 +973,101 @@ body.dark-mode .info-key {
|
|||||||
|
|
||||||
body.dark-mode .info-value {
|
body.dark-mode .info-value {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== Datenbank Struktur Tabelle ===== */
|
||||||
|
|
||||||
|
.db-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
table-layout: fixed;
|
||||||
|
/* sorgt für feste Spaltenbreite */
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-table thead {
|
||||||
|
background-color: var(--btn-bg);
|
||||||
|
color: var(--btn-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-table th,
|
||||||
|
.db-table td {
|
||||||
|
padding: 12px 15px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid var(--card-border);
|
||||||
|
|
||||||
|
/* Wichtig für gleiche Größe */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.db-table tr:hover {
|
||||||
|
background-color: rgba(0, 123, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alternierende Zeilen */
|
||||||
|
.db-table tr:nth-child(even) {
|
||||||
|
background-color: var(--card-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark Mode */
|
||||||
|
body.dark-mode .db-table thead {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .db-table tr:hover {
|
||||||
|
background-color: rgba(0, 123, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .db-table tr:nth-child(even) {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar::-webkit-scrollbar,
|
||||||
|
.content::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar::-webkit-scrollbar-thumb,
|
||||||
|
.content::-webkit-scrollbar-thumb {
|
||||||
|
background: #888;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar::-webkit-scrollbar-thumb:hover,
|
||||||
|
.content::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .sidebar::-webkit-scrollbar-thumb,
|
||||||
|
body.dark-mode .content::-webkit-scrollbar-thumb {
|
||||||
|
background: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Optional: schöner Dropdown Pfeil */
|
||||||
|
select {
|
||||||
|
appearance: none;
|
||||||
|
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg fill='%23666' height='20' viewBox='0 0 20 20' width='20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 7l5 5 5-5z'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right 10px center;
|
||||||
|
background-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark Mode Pfeil */
|
||||||
|
body.dark-mode select {
|
||||||
|
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg fill='%23ccc' height='20' viewBox='0 0 20 20' width='20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 7l5 5 5-5z'/%3E%3C/svg%3E");
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user