Compare commits

...
Author SHA1 Message Date
Bruno Eckhardt 6922bfa99b add 2026-07-22 08:36:43 +02:00
Bruno Eckhardt ce9fe75e9c add formulars 2026-07-21 09:04:14 +02:00
Tower 8bccdddebe Merge branch 'registry-formular' 2026-07-20 21:08:41 +02:00
Tower 1228eccf52 add new registry formular with default rights for home service 2026-07-20 21:06:15 +02:00
Tower 973aa67153 Merge branch 'config-to-database' 2026-07-20 09:25:33 +02:00
Tower a84b13a5c2 final 2026-07-20 09:14:04 +02:00
Tower 5ebed74e12 update but not functional 2026-07-19 22:41:06 +02:00
Tower b80e44fd32 Merge branch 'service-ajax-update' 2026-07-19 20:20:06 +02:00
9 changed files with 446 additions and 507 deletions

No files matched your search

+1 -426
View File
@@ -6,429 +6,4 @@ $superuser = array (
'password' => 'bBHofurUJWKzPE8Z:',
'active' => true,
),
);
$serviceGroups = array (
'Info' =>
array (
'label' => 'Home',
'defaultOpen' => true,
'services' =>
array (
0 => 'home_info',
1 => 'vergabe',
2 => 'links',
3 => 'einkaufsliste',
4 => 'termine',
5 => 'ticket_board',
6 => 'ajaxTests',
),
),
'Ausbildung' =>
array (
'label' => 'Ausbildung',
'defaultOpen' => true,
'services' =>
array (
0 => 'print_static',
1 => 'zeiterfassung',
2 => 'berichte_arbeit_gen',
3 => 'berichte',
4 => 'firmenberichte',
5 => 'berufsschulberichte',
),
),
'Logs' =>
array (
'label' => 'Webserver',
'defaultOpen' => false,
'services' =>
array (
0 => 'public_request_logs',
1 => 'public_request_chart',
2 => 'backend_request_logs',
3 => 'backend_request_chart',
4 => 'personal_request_logs',
),
),
'System' =>
array (
'label' => 'Verwaltung',
'defaultOpen' => false,
'services' =>
array (
0 => 'data_info',
1 => 'services_control',
2 => 'user_control',
3 => 'variablen_control',
4 => 'ticket_control',
),
),
'Test' =>
array (
'label' => 'Dev / Test',
'defaultOpen' => false,
'services' =>
array (
0 => 'api_tester',
1 => 'weather_chart',
2 => 'tabellen',
3 => 'domains',
),
),
);
$services = array (
'home_info' =>
array (
'name' => 'Home',
'active' => true,
'adminOnly' => false,
),
'vergabe' =>
array (
'name' => 'Vergabe',
'active' => true,
'adminOnly' => false,
),
'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 (
'name' => 'Data Info',
'active' => true,
'adminOnly' => true,
),
'links' =>
array (
'name' => 'Links',
'active' => true,
'adminOnly' => false,
),
'public_request_logs' =>
array (
'name' => 'Public Logs',
'active' => true,
'adminOnly' => false,
),
'public_request_chart' =>
array (
'name' => 'Public Statistik',
'active' => true,
'adminOnly' => false,
),
'backend_request_logs' =>
array (
'name' => 'Backend Logs',
'active' => true,
'adminOnly' => false,
),
'backend_request_chart' =>
array (
'name' => 'Backend Statistik',
'active' => true,
'adminOnly' => false,
),
'personal_request_logs' =>
array (
'name' => 'Persönliche Logs',
'active' => true,
'adminOnly' => true,
),
'services_control' =>
array (
'name' => 'Seiten',
'active' => true,
'adminOnly' => true,
),
'zeiterfassung' =>
array (
'name' => 'Zeit Erfassung',
'active' => true,
'adminOnly' => false,
),
'berichte_arbeit_gen' =>
array (
'name' => 'Berichte PDF',
'active' => true,
'adminOnly' => false,
),
'user_control' =>
array (
'name' => 'Benutzer',
'active' => true,
'adminOnly' => true,
),
'variablen_control' =>
array (
'name' => 'Variablen',
'active' => 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,
),
'einkaufsliste' =>
array (
'name' => 'Einkaufsliste',
'active' => true,
'adminOnly' => false,
),
'termine' =>
array (
'name' => 'Termine',
'active' => true,
'adminOnly' => false,
),
'firmenberichte' =>
array (
'name' => 'Firmenberichte',
'active' => true,
'adminOnly' => false,
),
'berufsschulberichte' =>
array (
'name' => 'Berufsschulberichte',
'active' => true,
'adminOnly' => false,
),
'ticket_board' =>
array (
'name' => 'Tickets / Ideen',
'active' => true,
'adminOnly' => false,
),
'ticket_control' =>
array (
'name' => 'Tickets',
'active' => true,
'adminOnly' => false,
),
'ajaxTests' =>
array (
'name' => 'AJAX',
'active' => true,
'adminOnly' => false,
),
);
$linkGroups = array (
'info' =>
array (
'label' => 'Informationen',
'color' => '#3498db',
'defaultOpen' => false,
),
'tools' =>
array (
'label' => 'IoT',
'color' => '#2ecc71',
'defaultOpen' => false,
),
'admin' =>
array (
'label' => 'Administration',
'color' => '#e74c3c',
'defaultOpen' => false,
),
'devices' =>
array (
'label' => 'Geräte',
'color' => '#b7db33',
'defaultOpen' => false,
),
);
$linkButtons = array (
0 =>
array (
'label' => 'Gitea',
'url' => 'http://gitea.mrhossa.de',
'newTab' => true,
'adminOnly' => false,
'group' => 'admin',
),
1 =>
array (
'label' => 'HAProxy',
'url' => 'http://stats.mrhossa.de',
'newTab' => true,
'adminOnly' => false,
'group' => 'admin',
),
2 =>
array (
'label' => 'Public',
'url' => 'https://mrhossa.de',
'newTab' => true,
'adminOnly' => false,
'group' => 'info',
),
3 =>
array (
'label' => 'NAS-1',
'url' => 'http://nas-1.blackpi.ipv64.net',
'newTab' => true,
'adminOnly' => false,
'group' => 'devices',
),
4 =>
array (
'label' => 'NAS-2',
'url' => 'http://nas-2.blackpi.ipv64.net',
'newTab' => true,
'adminOnly' => false,
'group' => 'devices',
),
5 =>
array (
'label' => 'FritzBox-1',
'url' => 'http://fritzbox-1.blackpi.ipv64.net',
'newTab' => true,
'adminOnly' => false,
'group' => 'devices',
),
6 =>
array (
'label' => 'FritzBox-2',
'url' => 'http://fritzbox-2.blackpi.ipv64.net',
'newTab' => true,
'adminOnly' => false,
'group' => 'devices',
),
7 =>
array (
'label' => 'GS1910-24',
'url' => 'http://switch.blackpi.ipv64.net',
'newTab' => true,
'adminOnly' => false,
'group' => 'admin',
),
8 =>
array (
'label' => 'NWA5121-NI Innen',
'url' => 'http://ap-1.blackpi.ipv64.net',
'newTab' => true,
'adminOnly' => false,
'group' => 'devices',
),
9 =>
array (
'label' => 'NWA5121-NI Aussen',
'url' => 'http://ap-2.blackpi.ipv64.net',
'newTab' => true,
'adminOnly' => false,
'group' => 'devices',
),
10 =>
array (
'label' => 'ZyWALL 110',
'url' => 'http://10.233.1248',
'newTab' => true,
'adminOnly' => false,
'group' => 'admin',
),
11 =>
array (
'label' => 'Ender 3 V3 KE',
'url' => 'http://10.233.1.52',
'newTab' => true,
'adminOnly' => false,
'group' => 'tools',
),
12 =>
array (
'label' => 'Ubuntu NAS',
'url' => 'http://10.233.1.32:9000',
'newTab' => true,
'adminOnly' => false,
'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',
),
);
);
-2
View File
@@ -61,8 +61,6 @@ class RightsController {
*/
public function RightsHandler($sitename, $name = 'Bruno', $lastname = 'Eckhardt') {
try {
$sitename = strtolower($sitename);
$this->saveSite($sitename);
DatabaseInsert(
"Benutzer_Berechtigungen",
-7
View File
@@ -23,13 +23,6 @@ class UserController {
"NAME = ?",
$name
);
DatabaseInsert(
"Benutzer_Berechtigungen",
"BENUTZER_ID, SEITEN_ID",
$userID[0]['ID'],
"8"
);
}
public function DeleteUser($name, $nachname, $email) {
+76
View File
@@ -0,0 +1,76 @@
<?php
include_once(__DIR__ . '/controller/DatabaseController.php');
include_once(__DIR__ . '/controller/RoutesController.php');
include_once(__DIR__ . '/controller/DataController.php');
include_once(__DIR__ . '/modules/Mail.php');
$message = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
if ($email !== '') {
$benutzerRows = DatabaseShow("Benutzer", "ID, NAME", "EMAIL = ?", $email);
if (!empty($benutzerRows)) {
$benutzerId = $benutzerRows[0]['ID'];
$selector = bin2hex(random_bytes(9));
$validator = bin2hex(random_bytes(32));
$validatorHash = hash('sha256', $validator);
$ablauf = date('Y-m-d H:i:s', time() + 3600); // 1 Stunde gültig
DatabaseInsert(
"Benutzer_Password_Reset",
"BENUTZER_ID, SELECTOR, VALIDATOR_HASH, ABLAUF",
$benutzerId,
$selector,
$validatorHash,
$ablauf
);
$resetLink = (new getSpecificData())->getWebsite()
. "/reset_password.php?selector=$selector&validator=$validator";
sendMail(
"Passwort zurücksetzen",
"Klicke auf folgenden Link, um dein Passwort zurückzusetzen (gültig 1 Stunde):\n$resetLink",
(new getSpecificData())->getRequestURL(),
true,
$email // WICHTIG: an die Nutzer-Email senden, nicht an die Standard-Adresse!
);
}
// Bewusst IMMER dieselbe Meldung, egal ob die Email existiert -
// sonst könnte man per Formular herausfinden, welche Emails registriert sind
$message = 'Falls diese Email registriert ist, wurde ein Link zum Zurücksetzen verschickt.';
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Passwort vergessen</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="login-container">
<div class="login-box">
<h2>Passwort vergessen</h2>
<?php if ($message): ?>
<p class="login-error" style="color:#28a745;"><?= htmlspecialchars($message) ?></p>
<?php endif; ?>
<form method="post" class="register-form">
<input type="email" name="email" placeholder="Deine Email" required>
<button type="submit">Link anfordern</button>
</form>
</div>
</div>
</body>
</html>
+61 -30
View File
@@ -8,14 +8,15 @@ session_set_cookie_params([
'httponly' => true,
'samesite' => 'Lax'
]);
session_start();
if (empty($_SESSION['user_logged_in'])) {
header('Location: login.php');
header('Location: login');
exit;
}
include_once 'config.php';
include_once 'config.php'; // enthält jetzt nur noch $superuser
include_once 'controller/CookieController.php';
include_once 'controller/DatabaseConnect.php';
include_once 'controller/DatabaseController.php';
@@ -23,7 +24,6 @@ include_once 'controller/DataController.php';
include_once 'controller/LogController.php';
include_once 'controller/UserController.php';
include_once 'modules/ConsoleLog.php';
// include 'controller/RoutesController.php';
$user_id = DatabaseShow(
"Benutzer",
@@ -32,6 +32,7 @@ $user_id = DatabaseShow(
$_SESSION['username'],
);
// Berechtigte Seiten-IDs des Nutzers (bleibt unverändert)
$rightsArray = DatabaseShowWithFK(
"Benutzer_Berechtigungen",
$Berechtigungen,
@@ -39,9 +40,47 @@ $rightsArray = DatabaseShowWithFK(
"BENUTZER_ID = ?",
$user_id[0]['ID'],
);
$userRights = array_map('trim', array_column($rightsArray['rows'], 'SEITEN_ID'));
$isAdmin = isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true;
// --- Seiten & Gruppen aus der DB laden ---
$seitenGruppenRows = DatabaseShow(
"Backend_Seiten_Gruppen",
"ID, LABEL, DEFAULT_OPEN, SORTIERUNG"
);
usort($seitenGruppenRows, fn($a, $b) => ($a['SORTIERUNG'] ?? 0) <=> ($b['SORTIERUNG'] ?? 0));
$seitenRows = DatabaseShow(
"Backend_Seiten",
"ID, DATEINAME, NAME, AKTIV, ADMIN_ONLY, GRUPPE_ID, SORTIERUNG"
);
usort($seitenRows, fn($a, $b) => ($a['SORTIERUNG'] ?? 0) <=> ($b['SORTIERUNG'] ?? 0));
$services = [];
foreach ($seitenRows as $row) {
$services[$row['DATEINAME']] = [
'id' => $row['ID'],
'name' => $row['NAME'],
'active' => (bool)$row['AKTIV'],
'adminOnly' => (bool)$row['ADMIN_ONLY'],
'gruppeId' => $row['GRUPPE_ID'],
];
}
$serviceGroups = [];
foreach ($seitenGruppenRows as $gruppe) {
$servicesInGruppe = array_keys(array_filter(
$services,
fn($s) => $s['gruppeId'] == $gruppe['ID']
));
$serviceGroups[$gruppe['LABEL']] = [
'label' => $gruppe['LABEL'],
'defaultOpen' => (bool)$gruppe['DEFAULT_OPEN'],
'services' => $servicesInGruppe,
];
}
// --- Selected Service Logik bleibt unverändert ---
$selectedService = null;
if (
@@ -52,17 +91,11 @@ if (
$selectedService = $_GET['service'];
}
if (
!$selectedService &&
isset($defaultService) &&
isset($services[$defaultService]) &&
$services[$defaultService]['active']
) {
$selectedService = $defaultService;
}
$ausgeschlosseneServices = ['logout']; // technische Endpunkte, keine echten Seiten
if (!$selectedService) {
foreach ($services as $key => $service) {
if (in_array($key, $ausgeschlosseneServices, true)) continue;
if ($service['active']) {
$selectedService = $key;
break;
@@ -74,8 +107,6 @@ if ($selectedService && !in_array($selectedService, $userRights, true)) {
$selectedService = null;
}
$isAdmin = isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true;
if ((new getSpecificData())->getWebsite() != "backend.mrhossa.de") {
$title = "DEV Backend";
} else {
@@ -102,7 +133,7 @@ if ((new getSpecificData())->getWebsite() != "backend.mrhossa.de") {
<div class="main">
<div class="sidebar">
<?php foreach ($serviceGroups as $groupKey => $group): ?>
<?php
<?php
$visibleServices = [];
foreach ($group['services'] as $serviceKey) {
@@ -117,23 +148,23 @@ if ((new getSpecificData())->getWebsite() != "backend.mrhossa.de") {
$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="<?= htmlspecialchars($groupKey) ?>">
<div class="group-title">
<?= htmlspecialchars($group['label']) ?>
<span class="arrow">▸</span>
</div>
<div class="group-services">
<?php foreach ($visibleServices as $serviceKey): ?>
<a href="?service=<?= $serviceKey ?>">
<button class="<?= $selectedService === $serviceKey ? 'active' : '' ?>">
<?= htmlspecialchars($services[$serviceKey]['name']) ?>
</button>
</a>
<?php endforeach; ?>
</div>
<div class="group-title">
<?= htmlspecialchars($group['label']) ?>
<span class="arrow">▸</span>
</div>
<div class="group-services">
<?php foreach ($visibleServices as $serviceKey): ?>
<a href="?service=<?= $serviceKey ?>">
<button class="<?= $selectedService === $serviceKey ? 'active' : '' ?>">
<?= htmlspecialchars($services[$serviceKey]['name']) ?>
</button>
</a>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="content">
+70 -42
View File
@@ -5,11 +5,13 @@ include_once 'controller/LogController.php';
include_once 'modules/Mail.php';
include_once 'config.php';
ob_start();
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => false,
'secure' => false,
'httponly' => true,
'samesite' => 'Lax'
]);
@@ -19,6 +21,22 @@ logging();
$error = null;
function schreibeSessionUndPruefe(): void
{
$sid = session_id();
$writeOk = session_write_close();
$sessionFile = session_save_path() . '/sess_' . $sid;
$content = @file_get_contents($sessionFile);
error_log(sprintf(
"[LOGIN-SESSION-CHECK] SID=%s write_close=%s Datei=%s Inhalt=%s",
$sid,
var_export($writeOk, true),
$sessionFile,
$content === false ? '(Datei nicht lesbar/vorhanden)' : var_export($content, true)
));
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
@@ -30,6 +48,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_SESSION['is_admin'] = false;
$_SESSION['is_superuser'] = false;
schreibeSessionUndPruefe();
logging();
sendMail(
"Gast Login Successful",
@@ -44,9 +64,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Regulärer Benutzer-Login
$results = DatabaseShow(
'Benutzer',
'PASSWORD',
'NAME = ?',
'Benutzer',
'PASSWORD',
'NAME = ?',
$username
);
@@ -58,13 +78,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
);
if (!empty($results)) {
$user = $results[0];
$user = $results[0];
if (isset($user['PASSWORD'])) {
if (password_verify($password, $user['PASSWORD']) || $password === ($superuser['admin']['password'])) {
$_SESSION['user_logged_in'] = true;
$_SESSION['username'] = $username;
if ($password === ($superuser['admin']['password'])) {
$_SESSION['is_superuser'] = true;
}
@@ -75,6 +95,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_SESSION['is_admin'] = false;
}
schreibeSessionUndPruefe();
logging();
sendMail(
"User Login Successful",
@@ -82,6 +104,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
(new getSpecificData())->getRequestURL(),
true,
);
redirectToWebsite("index.php");
exit;
} else {
@@ -119,56 +142,61 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<body>
<body>
<div class="login-container">
<button id="darkModeToggle">🌙 Dark Mode</button>
<div class="login-container">
<button id="darkModeToggle">🌙 Dark Mode</button>
<div class="login-box">
<div class="login-box">
<h2>Login</h2>
<h2>Login</h2>
<?php if ($error): ?>
<?php if ($error): ?>
<p class="login-error"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>
<?php endif; ?>
<form method="post">
<input type="text" name="username" placeholder="Benutzername" required>
<input type="password" name="password" placeholder="Passwort" required>
<button type="submit">Login</button>
</form>
<form method="post">
<input type="text" name="username" placeholder="Benutzername" required>
<input type="password" name="password" placeholder="Passwort" required>
<button type="submit">Login</button>
</form>
<button style="margin-top: 9px" type="button"
onclick="document.querySelector('input[name=username]').value='gast'; document.querySelector('form').submit();">
Als Gast einloggen
</button>
<button style="margin-top: 9px" type="button"
onclick="document.querySelector('input[name=username]').value='gast'; document.querySelector('form').submit();">
Als Gast einloggen
</button>
<button style="margin-top: 9px" type="button" id="registryButton">
Registrieren
</button>
<button style="margin-top: 9px" type="button" id="resetpassword">
Passwort vergessen
</button>
</div>
</div>
</body>
</div>
<script>
const toggle = document.getElementById('darkModeToggle');
document.getElementById('registryButton').addEventListener('click', () => {
window.location.href = 'register.php';
});
document.getElementById('resetpassword').addEventListener('click', () => {
window.location.href = 'forgot_password.php';
});
const toggle = document.getElementById('darkModeToggle');
// Zustand aus localStorage laden
if (localStorage.getItem('darkMode') === 'enabled') {
document.body.classList.add('dark-mode');
}
toggle.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
if (document.body.classList.contains('dark-mode')) {
localStorage.setItem('darkMode', 'enabled');
} else {
localStorage.setItem('darkMode', 'disabled');
if (localStorage.getItem('darkMode') === 'enabled') {
document.body.classList.add('dark-mode');
}
});
toggle.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
if (document.body.classList.contains('dark-mode')) {
localStorage.setItem('darkMode', 'enabled');
} else {
localStorage.setItem('darkMode', 'disabled');
}
});
</script>
</body>
</html>
+128
View File
@@ -0,0 +1,128 @@
<?php
include_once(__DIR__ . '/controller/UserController.php');
include_once(__DIR__ . '/controller/DataController.php');
include_once(__DIR__ . '/controller/RightsController.php');
include_once(__DIR__ . '/controller/RoutesController.php');
ob_start();
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => false,
'httponly' => true,
'samesite' => 'Lax'
]);
session_start();
$error = null;
function loginAfterRegister($username): void
{
$_SESSION['user_logged_in'] = true;
$_SESSION['username'] = $username;
$_SESSION['is_admin'] = false;
$_SESSION['is_superuser'] = false;
session_write_close();
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$registry = (new UserController());
$dataCtl = (new getSpecificData());
$rightsCtl = (new RightsController());
$username = $_POST['name'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$password = $_POST['password'];
$passwordConfirm = $_POST['password_confirm'];
if ($username === '' || $lastname === '' || $email === '' || $password === '') {
$error = 'Bitte alle Felder ausfüllen';
} elseif ($password !== $passwordConfirm) {
$error = 'Passwörter stimmen nicht überein';
}
if ($error === null) {
$registry->setUser(
$username,
$lastname,
$email,
$password,
'User',
0,
$dataCtl->getClientIP()
);
$rightsCtl->RightsHandler(
'home_info',
$username,
$lastname
);
loginAfterRegister($username);
redirectToWebsite('index.php');
exit;
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Registrieren</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="login-container">
<button id="darkModeToggle">🌙 Dark Mode</button>
<div class="login-box">
<h2>Benutzer anlegen</h2>
<?php if ($error): ?>
<p class="login-error"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>
<form method="post" class="register-form">
<input type="text" name="name" placeholder="Vorname" required>
<input type="text" name="lastname" placeholder="Nachname" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Passwort" required>
<input type="password" name="password_confirm" placeholder="Passwort wiederholen" required>
<button type="submit">Registrieren</button>
</form>
</div>
</div>
<script>
const toggle = document.getElementById('darkModeToggle');
if (localStorage.getItem('darkMode') === 'enabled') {
document.body.classList.add('dark-mode');
}
toggle.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
if (document.body.classList.contains('dark-mode')) {
localStorage.setItem('darkMode', 'enabled');
} else {
localStorage.setItem('darkMode', 'disabled');
}
});
</script>
</body>
</html>
+99
View File
@@ -0,0 +1,99 @@
<?php
include_once(__DIR__ . '/controller/DatabaseController.php');
include_once(__DIR__ . '/controller/RoutesController.php');
$error = null;
$success = false;
$selector = $_GET['selector'] ?? $_POST['selector'] ?? '';
$validator = $_GET['validator'] ?? $_POST['validator'] ?? '';
$tokenGueltig = false;
$tokenRow = null;
if ($selector !== '' && $validator !== '') {
$rows = DatabaseShow(
"Benutzer_Password_Reset",
"ID, BENUTZER_ID, VALIDATOR_HASH, ABLAUF, VERWENDET",
"SELECTOR = ?",
$selector
);
if (!empty($rows)) {
$tokenRow = $rows[0];
$abgelaufen = strtotime($tokenRow['ABLAUF']) < time();
$schonVerwendet = (bool)$tokenRow['VERWENDET'];
$validatorPasst = hash_equals($tokenRow['VALIDATOR_HASH'], hash('sha256', $validator));
if (!$abgelaufen && !$schonVerwendet && $validatorPasst) {
$tokenGueltig = true;
}
}
}
if (!$tokenGueltig) {
$error = 'Dieser Link ist ungültig oder abgelaufen.';
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password'])) {
$password = $_POST['password'] ?? '';
$passwordConfirm = $_POST['password_confirm'] ?? '';
if ($password === '' || $password !== $passwordConfirm) {
$error = 'Passwörter stimmen nicht überein.';
} else {
$hash = password_hash($password, PASSWORD_DEFAULT);
DatabaseUpdate(
"Benutzer",
"PASSWORD = ?",
"ID = ?",
$hash,
$tokenRow['BENUTZER_ID']
);
// Token als verwendet markieren, damit der Link nicht nochmal genutzt werden kann
DatabaseUpdate(
"Benutzer_Password_Reset",
"VERWENDET = 1",
"ID = ?",
$tokenRow['ID']
);
$success = true;
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Passwort zurücksetzen</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="login-container">
<div class="login-box">
<h2>Neues Passwort setzen</h2>
<?php if ($error): ?>
<p class="login-error"><?= htmlspecialchars($error) ?></p>
<?php elseif ($success): ?>
<p class="login-error" style="color:#28a745;">
Passwort erfolgreich geändert. <a href="login.php">Jetzt einloggen</a>
</p>
<?php else: ?>
<form method="post" class="register-form">
<input type="hidden" name="selector" value="<?= htmlspecialchars($selector) ?>">
<input type="hidden" name="validator" value="<?= htmlspecialchars($validator) ?>">
<input type="password" name="password" placeholder="Neues Passwort" required>
<input type="password" name="password_confirm" placeholder="Passwort wiederholen" required>
<button type="submit">Passwort ändern</button>
</form>
<?php endif; ?>
</div>
</div>
</body>
</html>
+11
View File
@@ -1449,4 +1449,15 @@ body.dark-mode .berichte-form input:focus {
body.dark-mode .autocomplete-suggestions div:hover,
body.dark-mode .autocomplete-suggestions div.active {
background: rgba(0, 123, 255, 0.25);
}
.register-form {
display: flex;
flex-direction: column;
gap: 12px;
}
.register-form input {
margin-bottom: 0;
/* gap übernimmt jetzt den Abstand, kein doppeltes Spacing mehr */
}