develop #28

Merged
blaerf merged 83 commits from develop into main 2025-12-17 14:28:04 +00:00
7 changed files with 0 additions and 426 deletions
Showing only changes of commit 78901adae1 - Show all commits

View File

@ -100,215 +100,4 @@ class UserManagementController
'activeMenu' => 'users',
];
}
/**
* Zeigt das Formular zum Anlegen eines neuen Benutzers (Platzhalter).
* @return array<string, mixed>
*/
public function create(): array
{
// CSRF token sicherstellen
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(16));
}
$viewPath = __DIR__ . '/../../public/views/users_create.php';
return [
'view' => $viewPath,
'data' => [
'loginPage' => false,
'csrf_token' => $_SESSION['csrf_token'],
],
'pageTitle' => 'Benutzer hinzufügen',
'activeMenu' => 'users',
'activeSubMenu' => 'create',
];
}
/**
* Verarbeitet das Absenden des 'Benutzer hinzufügen'-Formulars (Platzhalter,
* führt keine LDAP-Änderung aus, validiert aber Eingaben).
*
* @return array<string, mixed>
*/
public function createSubmit(): array
{
$errors = [];
// CSRF prüfen
$token = $_POST['csrf_token'] ?? '';
if (empty($token) || !isset($_SESSION['csrf_token']) || hash_equals($_SESSION['csrf_token'], $token) === false) {
$errors[] = 'Ungültiger CSRF-Token.';
}
$username = trim((string)($_POST['username'] ?? ''));
$firstname = trim((string)($_POST['givenName'] ?? ''));
$lastname = trim((string)($_POST['sn'] ?? ''));
$email = trim((string)($_POST['mail'] ?? ''));
if ($username === '') {
$errors[] = 'Benutzername wird benötigt.';
}
if ($email !== '' && filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
$errors[] = 'E-Mail-Adresse ist ungültig.';
}
// Für jetzt nur eine Erfolgsmeldung (keine AD-Operation)
$viewPath = __DIR__ . '/../../public/views/users_create.php';
$data = [
'loginPage' => false,
'csrf_token' => $_SESSION['csrf_token'],
];
if (!empty($errors)) {
$data['errors'] = $errors;
$data['form'] = [
'username' => $username,
'givenName' => $firstname,
'sn' => $lastname,
'mail' => $email,
];
return [
'view' => $viewPath,
'data' => $data,
'pageTitle' => 'Benutzer hinzufügen',
'activeMenu' => 'users',
'activeSubMenu' => 'create',
];
}
$data['success'] = 'Benutzer-Formular erfolgreich validiert (Platzhalter, wurde nicht angelegt).';
$data['form'] = ['username' => $username];
return [
'view' => $viewPath,
'data' => $data,
'pageTitle' => 'Benutzer hinzufügen',
'activeMenu' => 'users',
'activeSubMenu' => 'create',
];
}
/**
* Zeigt das CSV-Import-Formular (Platzhalter).
* @return array<string, mixed>
*/
public function import(): array
{
// CSRF token sicherstellen
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(16));
}
$viewPath = __DIR__ . '/../../public/views/users_import.php';
return [
'view' => $viewPath,
'data' => [
'loginPage' => false,
'csrf_token' => $_SESSION['csrf_token'],
],
'pageTitle' => 'Benutzer importieren (CSV)',
'activeMenu' => 'users',
'activeSubMenu' => 'import',
];
}
/**
* Verarbeitet CSV-Upload und zeigt eine Vorschau der ersten Zeilen (Platzhalter).
*
* @return array<string, mixed>
*/
public function importSubmit(): array
{
$errors = [];
// CSRF prüfen
$token = $_POST['csrf_token'] ?? '';
if (empty($token) || !isset($_SESSION['csrf_token']) || hash_equals($_SESSION['csrf_token'], $token) === false) {
$errors[] = 'Ungültiger CSRF-Token.';
}
if (!isset($_FILES['csv_file']) || $_FILES['csv_file']['error'] !== UPLOAD_ERR_OK) {
$errors[] = 'Bitte eine gültige CSV-Datei hochladen.';
}
$preview = [];
if (empty($errors)) {
$tmp = $_FILES['csv_file']['tmp_name'];
if (($handle = fopen($tmp, 'r')) !== false) {
$row = 0;
while (($data = fgetcsv($handle, 0, ',')) !== false && $row < 50) {
$preview[] = $data;
$row++;
}
fclose($handle);
} else {
$errors[] = 'Die hochgeladene Datei konnte nicht gelesen werden.';
}
}
$viewPath = __DIR__ . '/../../public/views/users_import.php';
$data = [
'loginPage' => false,
'csrf_token' => $_SESSION['csrf_token'],
];
if (!empty($errors)) {
$data['errors'] = $errors;
} else {
$data['preview'] = $preview;
$data['success'] = 'CSV-Datei erfolgreich hochgeladen. Vorschau der ersten Zeilen:';
}
return [
'view' => $viewPath,
'data' => $data,
'pageTitle' => 'Benutzer importieren (CSV)',
'activeMenu' => 'users',
'activeSubMenu' => 'import',
];
}
/**
* Zeigt die Benutzersuche (Platzhalter).
* @return array<string, mixed>
*/
public function search(): array
{
$query = trim((string)($_GET['q'] ?? ''));
$users = [];
if ($query !== '') {
try {
$allUsers = $this->directoryService->getUsers();
foreach ($allUsers as $u) {
$hay = strtolower($u['samaccountname'] . ' ' . $u['displayname'] . ' ' . $u['mail']);
if (strpos($hay, strtolower($query)) !== false) {
$users[] = $u;
}
}
} catch (\Throwable $e) {
$this->logger->logException('Fehler bei Benutzersuche.', $e, ['query' => $query]);
}
}
$viewPath = __DIR__ . '/../../public/views/users_search.php';
return [
'view' => $viewPath,
'data' => [
'loginPage' => false,
'query' => $query,
'results' => $users,
],
'pageTitle' => 'Benutzer suchen',
'activeMenu' => 'users',
'activeSubMenu' => 'search',
];
}
}

View File

@ -240,44 +240,6 @@ switch ($route) {
handleResult($result);
break;
case 'users.create':
requireLogin($config);
$result = $userManagementController->create();
handleResult($result);
break;
case 'users.create.submit':
requireLogin($config);
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: index.php?route=users.create');
exit;
}
$result = $userManagementController->createSubmit();
handleResult($result);
break;
case 'users.import':
requireLogin($config);
$result = $userManagementController->import();
handleResult($result);
break;
case 'users.import.submit':
requireLogin($config);
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: index.php?route=users.import');
exit;
}
$result = $userManagementController->importSubmit();
handleResult($result);
break;
case 'users.search':
requireLogin($config);
$result = $userManagementController->search();
handleResult($result);
break;
default:
http_response_code(404);
echo 'Route nicht gefunden.';

View File

@ -49,23 +49,6 @@
<span>Benutzer &amp; Gruppen</span></a>
</li>
<!-- User actions (create/import/search) -->
<li class="nav-item<?= (isset($activeSubMenu) && $activeSubMenu === 'create') ? ' active' : '' ?>">
<a class="nav-link pl-4" href="../../index.php?route=users.create">
<i class="fas fa-fw fa-user-plus"></i>
<span>Benutzer hinzufügen</span></a>
</li>
<li class="nav-item<?= (isset($activeSubMenu) && $activeSubMenu === 'import') ? ' active' : '' ?>">
<a class="nav-link pl-4" href="../../index.php?route=users.import">
<i class="fas fa-fw fa-file-csv"></i>
<span>Benutzer importieren (CSV)</span></a>
</li>
<li class="nav-item<?= (isset($activeSubMenu) && $activeSubMenu === 'search') ? ' active' : '' ?>">
<a class="nav-link pl-4" href="../../index.php?route=users.search">
<i class="fas fa-fw fa-search"></i>
<span>Benutzer suchen</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">

View File

@ -25,11 +25,6 @@ declare(strict_types=1);
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Benutzer &amp; Gruppen</h1>
<div>
<a href="index.php?route=users.create" class="btn btn-sm btn-primary mr-2"><i class="fas fa-user-plus"></i> Benutzer hinzufügen</a>
<a href="index.php?route=users.import" class="btn btn-sm btn-success mr-2"><i class="fas fa-file-csv"></i> CSV importieren</a>
<a href="index.php?route=users.search" class="btn btn-sm btn-info"><i class="fas fa-search"></i> Benutzer suchen</a>
</div>
</div>
<?php if ($error !== null): ?>

View File

@ -1,52 +0,0 @@
<?php
declare(strict_types=1);
/**
* Platzhalter-View: Benutzer hinzufügen
*/
?>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Benutzer hinzufügen</h6>
</div>
<div class="card-body">
<?php if (!empty($errors) && is_array($errors)): ?>
<div class="alert alert-danger">
<ul>
<?php foreach ($errors as $e): ?>
<li><?= htmlspecialchars($e, ENT_QUOTES, 'UTF-8') ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if (!empty($success)): ?>
<div class="alert alert-success"><?= htmlspecialchars($success, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<form method="post" action="index.php?route=users.create.submit" class="user">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf_token ?? '', ENT_QUOTES, 'UTF-8') ?>">
<div class="form-group">
<label for="username">Benutzername</label>
<input id="username" name="username" class="form-control" value="<?= htmlspecialchars($form['username'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
</div>
<div class="form-group">
<label for="givenName">Vorname</label>
<input id="givenName" name="givenName" class="form-control" value="<?= htmlspecialchars($form['givenName'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
</div>
<div class="form-group">
<label for="sn">Nachname</label>
<input id="sn" name="sn" class="form-control" value="<?= htmlspecialchars($form['sn'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
</div>
<div class="form-group">
<label for="mail">E-Mail</label>
<input id="mail" name="mail" class="form-control" value="<?= htmlspecialchars($form['mail'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
</div>
<button type="submit" class="btn btn-primary">Validieren (Platzhalter)</button>
<a href="index.php?route=users" class="btn btn-secondary">Zurück zur Liste</a>
</form>
</div>
</div>

View File

@ -1,55 +0,0 @@
<?php
declare(strict_types=1);
/**
* Platzhalter-View: Benutzer importieren (CSV)
*/
?>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Benutzer importieren (CSV)</h6>
</div>
<div class="card-body">
<?php if (!empty($errors) && is_array($errors)): ?>
<div class="alert alert-danger">
<ul>
<?php foreach ($errors as $e): ?>
<li><?= htmlspecialchars($e, ENT_QUOTES, 'UTF-8') ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if (!empty($success)): ?>
<div class="alert alert-success"><?= htmlspecialchars($success, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<form method="post" action="index.php?route=users.import.submit" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf_token ?? '', ENT_QUOTES, 'UTF-8') ?>">
<div class="form-group">
<label for="csv_file">CSV-Datei</label>
<input type="file" id="csv_file" name="csv_file" accept="text/csv" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Upload & Vorschau</button>
<a href="index.php?route=users" class="btn btn-secondary">Zurück zur Liste</a>
</form>
<?php if (!empty($preview) && is_array($preview)): ?>
<h6 class="mt-4">Vorschau (erste Zeilen)</h6>
<div class="table-responsive">
<table class="table table-sm">
<tbody>
<?php foreach ($preview as $row): ?>
<tr>
<?php foreach ($row as $col): ?>
<td><?= htmlspecialchars((string)$col, ENT_QUOTES, 'UTF-8') ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>

View File

@ -1,48 +0,0 @@
<?php
declare(strict_types=1);
/**
* Platzhalter-View: Benutzer suchen
*/
?>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Benutzer suchen</h6>
</div>
<div class="card-body">
<form method="get" action="index.php">
<input type="hidden" name="route" value="users.search">
<div class="form-group">
<label for="q">Suche</label>
<input id="q" name="q" class="form-control" value="<?= htmlspecialchars($query ?? '', ENT_QUOTES, 'UTF-8') ?>" placeholder="Namen, Benutzername oder E-Mail">
</div>
<button type="submit" class="btn btn-primary">Suchen</button>
<a href="index.php?route=users" class="btn btn-secondary">Zurück zur Liste</a>
</form>
<?php if (!empty($query)): ?>
<h6 class="mt-4">Ergebnisse für "<?= htmlspecialchars($query, ENT_QUOTES, 'UTF-8') ?>"</h6>
<?php if (!empty($results) && is_array($results)): ?>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr><th>Benutzername</th><th>Name</th><th>E-Mail</th></tr>
</thead>
<tbody>
<?php foreach ($results as $r): ?>
<tr>
<td><?= htmlspecialchars($r['samaccountname'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars($r['displayname'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars($r['mail'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="alert alert-info mt-3">Keine Treffer gefunden.</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>