Compare commits
No commits in common. "a8e304270721306c453ed71681e46e96c570688c" and "717aca3617bfd04b1809f19fd48b64d4fe2196ca" have entirely different histories.
a8e3042707
...
717aca3617
@ -1,153 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
use App\Services\Ldap\LdapDirectoryService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller für die Benutzer- und Gruppenanzeige.
|
|
||||||
*
|
|
||||||
* Aufgaben:
|
|
||||||
* - holt über den LdapDirectoryService die Listen von Benutzern und Gruppen
|
|
||||||
* - behandelt technische Fehler und bereitet eine Fehlermeldung für die View auf
|
|
||||||
* - gibt die Daten an eine View-Datei (public/views/users.php) weiter
|
|
||||||
*
|
|
||||||
* WICHTIG:
|
|
||||||
* - Es werden aktuell nur Daten angezeigt (Read-only).
|
|
||||||
* - Es findet keine Änderung im Active Directory statt.
|
|
||||||
*/
|
|
||||||
class UserManagementController
|
|
||||||
{
|
|
||||||
/** @var array<string, mixed> Vollständige Anwendungskonfiguration (aus config.php) */
|
|
||||||
private array $config;
|
|
||||||
|
|
||||||
/** @var LdapDirectoryService Service für das Lesen von Benutzern und Gruppen aus dem LDAP/AD */
|
|
||||||
private LdapDirectoryService $directoryService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<string, mixed> $config Vollständige Konfiguration aus config.php
|
|
||||||
*/
|
|
||||||
public function __construct(array $config)
|
|
||||||
{
|
|
||||||
// Komplette Konfiguration speichern (falls später weitere Werte benötigt werden).
|
|
||||||
$this->config = $config;
|
|
||||||
|
|
||||||
// LDAP-Konfiguration aus der Gesamt-Konfiguration herausziehen.
|
|
||||||
$ldapConfig = $config['ldap'] ?? [];
|
|
||||||
|
|
||||||
// Directory-Service initialisieren, der die eigentliche LDAP-Arbeit übernimmt.
|
|
||||||
$this->directoryService = new LdapDirectoryService($ldapConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zeigt Benutzer- und Gruppenliste an.
|
|
||||||
* Wird typischerweise über die Route "users" (index.php?route=users) aufgerufen.
|
|
||||||
*/
|
|
||||||
public function show(): void
|
|
||||||
{
|
|
||||||
// Standardwerte für die View-Variablen vorbereiten.
|
|
||||||
$error = null;
|
|
||||||
$users = [];
|
|
||||||
$groups = [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Benutzer- und Gruppenlisten aus dem AD laden.
|
|
||||||
$users = $this->directoryService->getUsers();
|
|
||||||
$groups = $this->directoryService->getGroups();
|
|
||||||
} catch (\Throwable $exception) {
|
|
||||||
// Sämtliche technischen Fehler (z. B. Verbindungs- oder Konfigurationsprobleme)
|
|
||||||
// werden hier in eine für den Benutzer lesbare Fehlermeldung übersetzt.
|
|
||||||
$error = 'Fehler beim Laden von Benutzern/Gruppen: ' . $exception->getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pfad zur eigentlichen View-Datei bestimmen.
|
|
||||||
$viewPath = __DIR__ . '/../../public/views/users.php';
|
|
||||||
|
|
||||||
// Falls die View-Datei (noch) nicht existiert, Fallback-Ausgabe verwenden.
|
|
||||||
if (file_exists($viewPath) === false) {
|
|
||||||
$this->renderInline($users, $groups, $error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variablen $users, $groups, $error stehen in der View zur Verfügung,
|
|
||||||
// weil sie im aktuellen Scope definiert sind.
|
|
||||||
require $viewPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fallback-Ausgabe, falls noch keine View-Datei existiert.
|
|
||||||
*
|
|
||||||
* @param array<int, array<string, string>> $users Liste der Benutzer-Datensätze
|
|
||||||
* @param array<int, array<string, string>> $groups Liste der Gruppen-Datensätze
|
|
||||||
* @param string|null $error Fehlermeldung (falls vorhanden)
|
|
||||||
*/
|
|
||||||
private function renderInline(array $users, array $groups, ?string $error): void
|
|
||||||
{
|
|
||||||
?>
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="de">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>AD Admin Tool – Benutzer & Gruppen</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Benutzer & Gruppen</h1>
|
|
||||||
|
|
||||||
<?php if ($error !== null): ?>
|
|
||||||
<!-- Fehlermeldung ausgeben, HTML-sicher maskiert -->
|
|
||||||
<p style="color: red;"><?php echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></p>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<h2>Benutzer</h2>
|
|
||||||
<table border="1" cellpadding="4" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Benutzername (sAMAccountName)</th>
|
|
||||||
<th>Anzeigename</th>
|
|
||||||
<th>E-Mail</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($users as $user): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($user['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($user['displayname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($user['mail'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h2>Gruppen</h2>
|
|
||||||
<table border="1" cellpadding="4" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Gruppenname (sAMAccountName)</th>
|
|
||||||
<th>CN</th>
|
|
||||||
<th>Beschreibung</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($groups as $group): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($group['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($group['cn'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($group['description'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="index.php?route=dashboard">Zurück zum Dashboard</a> |
|
|
||||||
<a href="index.php?route=logout">Logout</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,37 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Services\Ldap;
|
namespace App\Services\Ldap;
|
||||||
|
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Hilfsklasse zum Aufbau einer LDAP/LDAPS-Verbindung.
|
|
||||||
*
|
|
||||||
* Aufgaben:
|
|
||||||
* - liest Server, Port und Timeout aus der LDAP-Konfiguration
|
|
||||||
* - erstellt eine LDAP-Verbindung
|
|
||||||
* - setzt die notwendigen Optionen (Protokollversion, Netzwerk-Timeout)
|
|
||||||
*
|
|
||||||
* Wichtig:
|
|
||||||
* - Diese Klasse führt KEIN ldap_bind durch.
|
|
||||||
* - Das Bind (mit Benutzer- oder Service-Konto) erfolgt in den Fach-Services
|
|
||||||
* wie LdapAuthService oder LdapDirectoryService.
|
|
||||||
*/
|
|
||||||
class LdapConnectionHelper
|
class LdapConnectionHelper
|
||||||
{
|
{
|
||||||
/** @var array<string, mixed> LDAP-spezifische Konfiguration (server, port, timeout, etc.) */
|
/** @var array<string, mixed> */
|
||||||
private array $config;
|
private array $config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $ldapConfig Teilbereich "ldap" aus der config.php
|
* @param array<string, mixed> $ldapConfig
|
||||||
*/
|
*/
|
||||||
public function __construct(array $ldapConfig)
|
public function __construct(array $ldapConfig)
|
||||||
{
|
{
|
||||||
// LDAP-Konfiguration in der Instanz speichern.
|
|
||||||
// Dadurch steht sie in allen Methoden dieser Klasse zur Verfügung.
|
|
||||||
$this->config = $ldapConfig;
|
$this->config = $ldapConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,43 +24,26 @@ class LdapConnectionHelper
|
|||||||
* aber ohne Bind. Den Bind führen die aufrufenden Services durch.
|
* aber ohne Bind. Den Bind führen die aufrufenden Services durch.
|
||||||
*
|
*
|
||||||
* @return resource LDAP-Verbindungs-Handle
|
* @return resource LDAP-Verbindungs-Handle
|
||||||
*
|
|
||||||
* @throws RuntimeException wenn der Server nicht konfiguriert ist oder die Verbindung scheitert
|
|
||||||
*/
|
*/
|
||||||
public function createConnection()
|
public function createConnection()
|
||||||
{
|
{
|
||||||
// Server, Port und Timeout aus der Konfiguration lesen.
|
|
||||||
// Die Null-Koaleszenz-Operatoren (??) setzen Standardwerte, falls Keys fehlen.
|
|
||||||
$server = (string)($this->config['server'] ?? '');
|
$server = (string)($this->config['server'] ?? '');
|
||||||
$port = (int)($this->config['port'] ?? 636);
|
$port = (int)($this->config['port'] ?? 636);
|
||||||
$timeout = (int)($this->config['timeout'] ?? 5);
|
$timeout = (int)($this->config['timeout'] ?? 5);
|
||||||
|
|
||||||
// Ohne Server-Adresse kann keine Verbindung aufgebaut werden.
|
|
||||||
if ($server === '') {
|
if ($server === '') {
|
||||||
throw new RuntimeException('LDAP-Konfiguration ist unvollständig (server fehlt).');
|
throw new RuntimeException('LDAP-Konfiguration ist unvollständig (server fehlt).');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verbindung zum LDAP/AD-Server herstellen.
|
|
||||||
// ldap_connect liefert entweder ein Verbindungs-Handle (Resource) oder false.
|
|
||||||
$connection = ldap_connect($server, $port);
|
$connection = ldap_connect($server, $port);
|
||||||
|
|
||||||
// Wenn keine Verbindung aufgebaut werden konnte, Exception werfen.
|
|
||||||
if ($connection === false) {
|
if ($connection === false) {
|
||||||
throw new RuntimeException('LDAP-Verbindung konnte nicht aufgebaut werden.');
|
throw new RuntimeException('LDAP-Verbindung konnte nicht aufgebaut werden.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// LDAP-Version auf 3 setzen, dies ist die gängige Standardversion.
|
|
||||||
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||||
|
|
||||||
// Netzwerk-Timeout setzen, damit Anfragen nicht ewig hängen bleiben.
|
|
||||||
ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, $timeout);
|
ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, $timeout);
|
||||||
|
|
||||||
// Referral-Following deaktivieren (0 = aus).
|
|
||||||
// Das verhindert, dass der Client automatisch zu anderen LDAP-Servern weitergeleitet wird.
|
|
||||||
ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);
|
|
||||||
|
|
||||||
// Verbindungs-Handle an aufrufende Services zurückgeben.
|
|
||||||
// Dort wird dann der eigentliche ldap_bind durchgeführt.
|
|
||||||
return $connection;
|
return $connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,203 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Services\Ldap;
|
|
||||||
|
|
||||||
use RuntimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service zum Lesen von Objekten aus dem Active Directory.
|
|
||||||
*
|
|
||||||
* Aktueller Umfang:
|
|
||||||
* - Liste von Benutzern (sAMAccountName, displayName, mail)
|
|
||||||
* - Liste von Gruppen (sAMAccountName, cn, description)
|
|
||||||
*
|
|
||||||
* Technische Details:
|
|
||||||
* - Verwendet ein technisches Konto (bind_dn + bind_password) für Lesezugriffe
|
|
||||||
* - Nutzt LdapConnectionHelper zum Aufbau der Verbindung
|
|
||||||
*/
|
|
||||||
class LdapDirectoryService
|
|
||||||
{
|
|
||||||
/** @var array<string, mixed> LDAP-Konfiguration (inkl. base_dn, bind_dn, bind_password) */
|
|
||||||
private array $config;
|
|
||||||
|
|
||||||
/** @var LdapConnectionHelper Zentrale Hilfsklasse für den Aufbau von LDAP-Verbindungen */
|
|
||||||
private LdapConnectionHelper $connectionHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<string, mixed> $ldapConfig Teilbereich "ldap" aus der config.php
|
|
||||||
*/
|
|
||||||
public function __construct(array $ldapConfig)
|
|
||||||
{
|
|
||||||
// Vollständige LDAP-Konfiguration speichern.
|
|
||||||
$this->config = $ldapConfig;
|
|
||||||
|
|
||||||
// Gemeinsamen Verbindungs-Helper initialisieren.
|
|
||||||
// Dieser kümmert sich um ldap_connect und die grundlegenden Optionen.
|
|
||||||
$this->connectionHelper = new LdapConnectionHelper($ldapConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stellt eine LDAP-Verbindung her und bindet sich mit dem technischen Konto.
|
|
||||||
*
|
|
||||||
* @return resource LDAP-Verbindungs-Handle
|
|
||||||
*
|
|
||||||
* @throws RuntimeException wenn Bind-Daten fehlen oder der Bind fehlschlägt
|
|
||||||
*/
|
|
||||||
private function connect()
|
|
||||||
{
|
|
||||||
// Technischen Bind-DN (Service-Account) aus der Konfiguration lesen.
|
|
||||||
$bindDn = (string)($this->config['bind_dn'] ?? '');
|
|
||||||
$bindPassword = (string)($this->config['bind_password'] ?? '');
|
|
||||||
|
|
||||||
// Ohne Bind-DN oder Passwort kann kein technischer Bind durchgeführt werden.
|
|
||||||
if ($bindDn === '' || $bindPassword === '') {
|
|
||||||
throw new RuntimeException('LDAP-Binddaten für technisches Konto sind nicht konfiguriert.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verbindung über den zentralen Helper erstellen (Server, Port, Optionen).
|
|
||||||
$connection = $this->connectionHelper->createConnection();
|
|
||||||
|
|
||||||
// Mit dem technischen Konto binden, um Lesezugriffe durchführen zu können.
|
|
||||||
// Das @-Zeichen unterdrückt PHP-Warnings bei Fehlversuchen.
|
|
||||||
if (@ldap_bind($connection, $bindDn, $bindPassword) !== true) {
|
|
||||||
// Bei fehlgeschlagenem Bind Verbindung wieder schließen.
|
|
||||||
ldap_unbind($connection);
|
|
||||||
throw new RuntimeException('LDAP-Bind mit technischem Konto ist fehlgeschlagen.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Erfolgreich gebundene Verbindung zurückgeben.
|
|
||||||
return $connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Liefert eine Liste von Benutzern aus dem AD.
|
|
||||||
*
|
|
||||||
* @return array<int, array<string, string>> Liste von Benutzer-Datensätzen
|
|
||||||
* [
|
|
||||||
* [
|
|
||||||
* 'samaccountname' => 'user1',
|
|
||||||
* 'displayname' => 'User Eins',
|
|
||||||
* 'mail' => 'user1@example.local',
|
|
||||||
* ],
|
|
||||||
* ...
|
|
||||||
* ]
|
|
||||||
*
|
|
||||||
* @throws RuntimeException bei Konfigurations- oder Verbindungsproblemen
|
|
||||||
*/
|
|
||||||
public function getUsers(): array
|
|
||||||
{
|
|
||||||
// Base-DN ist der Startpunkt der Suche im Verzeichnisbaum (z. B. DC=...,DC=...).
|
|
||||||
$baseDn = (string)($this->config['base_dn'] ?? '');
|
|
||||||
if ($baseDn === '') {
|
|
||||||
throw new RuntimeException('LDAP base_dn für Benutzersuche ist nicht konfiguriert.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verbindung mit technischem Bind herstellen.
|
|
||||||
$connection = $this->connect();
|
|
||||||
|
|
||||||
// Standard-Filter für Benutzer in AD:
|
|
||||||
// - objectClass=user
|
|
||||||
// - objectCategory=person
|
|
||||||
$filter = '(&(objectClass=user)(objectCategory=person))';
|
|
||||||
|
|
||||||
// Nur relevante Attribute auslesen, um Datenmenge klein zu halten.
|
|
||||||
$attributes = ['sAMAccountName', 'displayName', 'mail'];
|
|
||||||
|
|
||||||
// LDAP-Suche unterhalb des Base-DN durchführen.
|
|
||||||
$search = @ldap_search($connection, $baseDn, $filter, $attributes);
|
|
||||||
if ($search === false) {
|
|
||||||
// Bei einem Fehler die Verbindung schließen und Exception werfen.
|
|
||||||
ldap_unbind($connection);
|
|
||||||
throw new RuntimeException('LDAP-Suche nach Benutzern ist fehlgeschlagen.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Suchergebnisse in ein PHP-Array umwandeln.
|
|
||||||
$entries = ldap_get_entries($connection, $search);
|
|
||||||
|
|
||||||
// Verbindung wieder schließen, da sie nicht mehr benötigt wird.
|
|
||||||
ldap_unbind($connection);
|
|
||||||
|
|
||||||
// Ergebnisliste für die View vorbereiten.
|
|
||||||
$users = [];
|
|
||||||
|
|
||||||
// Wenn die Struktur unerwartet ist, leere Liste zurückgeben.
|
|
||||||
if (!is_array($entries) || !isset($entries['count'])) {
|
|
||||||
return $users;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jeden einzelnen Eintrag aus dem Ergebnis verarbeiten.
|
|
||||||
for ($i = 0; $i < $entries['count']; $i++) {
|
|
||||||
$entry = $entries[$i];
|
|
||||||
|
|
||||||
// Attribute sind im Ergebnis verschachtelt, daher Zugriff über [...][0].
|
|
||||||
$users[] = [
|
|
||||||
'samaccountname' => isset($entry['samaccountname'][0]) ? (string)$entry['samaccountname'][0] : '',
|
|
||||||
'displayname' => isset($entry['displayname'][0]) ? (string)$entry['displayname'][0] : '',
|
|
||||||
'mail' => isset($entry['mail'][0]) ? (string)$entry['mail'][0] : '',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $users;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Liefert eine Liste von Gruppen aus dem AD.
|
|
||||||
*
|
|
||||||
* @return array<int, array<string, string>> Liste von Gruppen-Datensätzen
|
|
||||||
*
|
|
||||||
* @throws RuntimeException bei Konfigurations- oder Verbindungsproblemen
|
|
||||||
*/
|
|
||||||
public function getGroups(): array
|
|
||||||
{
|
|
||||||
// Base-DN für die Gruppensuche aus der Konfiguration lesen.
|
|
||||||
$baseDn = (string)($this->config['base_dn'] ?? '');
|
|
||||||
if ($baseDn === '') {
|
|
||||||
throw new RuntimeException('LDAP base_dn für Gruppensuche ist nicht konfiguriert.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verbindung mit technischem Bind herstellen.
|
|
||||||
$connection = $this->connect();
|
|
||||||
|
|
||||||
// Filter für Gruppenobjekte im AD.
|
|
||||||
$filter = '(objectClass=group)';
|
|
||||||
|
|
||||||
// Attribute, die für die Darstellung relevant sind.
|
|
||||||
$attributes = ['sAMAccountName', 'cn', 'description'];
|
|
||||||
|
|
||||||
// LDAP-Suche ausführen.
|
|
||||||
$search = @ldap_search($connection, $baseDn, $filter, $attributes);
|
|
||||||
if ($search === false) {
|
|
||||||
ldap_unbind($connection);
|
|
||||||
throw new RuntimeException('LDAP-Suche nach Gruppen ist fehlgeschlagen.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ergebnisse holen.
|
|
||||||
$entries = ldap_get_entries($connection, $search);
|
|
||||||
|
|
||||||
// Verbindung schließen.
|
|
||||||
ldap_unbind($connection);
|
|
||||||
|
|
||||||
$groups = [];
|
|
||||||
|
|
||||||
// Struktur prüfen, leere Liste zurückgeben, falls unerwartet.
|
|
||||||
if (!is_array($entries) || !isset($entries['count'])) {
|
|
||||||
return $groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alle Einträge in ein flacheres Array-Format transformieren.
|
|
||||||
for ($i = 0; $i < $entries['count']; $i++) {
|
|
||||||
$entry = $entries[$i];
|
|
||||||
|
|
||||||
$groups[] = [
|
|
||||||
'samaccountname' => isset($entry['samaccountname'][0]) ? (string)$entry['samaccountname'][0] : '',
|
|
||||||
'cn' => isset($entry['cn'][0]) ? (string)$entry['cn'][0] : '',
|
|
||||||
'description' => isset($entry['description'][0]) ? (string)$entry['description'][0] : '',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $groups;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -18,9 +18,6 @@ return [
|
|||||||
|
|
||||||
// Optional: Timeout in Sekunden
|
// Optional: Timeout in Sekunden
|
||||||
'timeout' => 5,
|
'timeout' => 5,
|
||||||
|
|
||||||
'bind_dn' => 'CN=Service IIS,OU=WebAppUsers,DC=ITFA-PROJ-DOM,DC=local',
|
|
||||||
'bind_password' => '$7aE!R$l$D!p1Q9l458K8@O6&',
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'security' => [
|
'security' => [
|
||||||
|
|||||||
@ -47,7 +47,6 @@ $config = require $configPath;
|
|||||||
|
|
||||||
use App\Controllers\AuthController;
|
use App\Controllers\AuthController;
|
||||||
use App\Controllers\DashboardController;
|
use App\Controllers\DashboardController;
|
||||||
use App\Controllers\UserManagementController;
|
|
||||||
|
|
||||||
// Hilfsfunktion für geschützte Routen
|
// Hilfsfunktion für geschützte Routen
|
||||||
function requireLogin(array $config): void
|
function requireLogin(array $config): void
|
||||||
@ -72,9 +71,6 @@ $authController = new AuthController($config);
|
|||||||
// Neue Instanz der Klasse DashboardController erstellen (wird bei Bedarf über den Autoloader geladen).
|
// Neue Instanz der Klasse DashboardController erstellen (wird bei Bedarf über den Autoloader geladen).
|
||||||
$dashboardController = new DashboardController($config);
|
$dashboardController = new DashboardController($config);
|
||||||
|
|
||||||
// Neue Instanz der Klasse UserManagmentController erstellen (wird bei Bedarf über den Autoloader geladen).
|
|
||||||
$userManagementController = new UserManagementController($config);
|
|
||||||
|
|
||||||
// Anhand des Routing-Ziels (route) entscheiden, welcher Code ausgeführt wird.
|
// Anhand des Routing-Ziels (route) entscheiden, welcher Code ausgeführt wird.
|
||||||
switch ($route) {
|
switch ($route) {
|
||||||
case 'login':
|
case 'login':
|
||||||
@ -98,11 +94,6 @@ switch ($route) {
|
|||||||
$dashboardController->show();
|
$dashboardController->show();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'users':
|
|
||||||
requireLogin($config);
|
|
||||||
$userManagementController->show();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
http_response_code(404);
|
http_response_code(404);
|
||||||
echo 'Route nicht gefunden.';
|
echo 'Route nicht gefunden.';
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
// Call the dataTables jQuery plugin
|
// Call the dataTables jQuery plugin
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#dataTable').DataTable();
|
$('#dataTable').DataTable();
|
||||||
$('#usersTable').DataTable();
|
|
||||||
$('#groupsTable').DataTable();
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,520 +0,0 @@
|
|||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/** @var array<int, array<string, string>> $users */
|
|
||||||
/** @var array<int, array<string, string>> $groups */
|
|
||||||
/** @var string|null $error */
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Tables</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template -->
|
|
||||||
<link href="../vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template -->
|
|
||||||
<link href="../css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this page -->
|
|
||||||
<link href="../vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="../views/dashboard.php">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="../views/dashboard.php">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
|
|
||||||
aria-expanded="true" aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="../buttons.php">Buttons</a>
|
|
||||||
<a class="collapse-item" href="../cards.php">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="../utilities-color.php">Colors</a>
|
|
||||||
<a class="collapse-item" href="../utilities-border.php">Borders</a>
|
|
||||||
<a class="collapse-item" href="../utilities-animation.php">Animations</a>
|
|
||||||
<a class="collapse-item" href="../utilities-other.php">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.php">Login</a>
|
|
||||||
<a class="collapse-item" href="../register.php">Register</a>
|
|
||||||
<a class="collapse-item" href="../forgot-password.php">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="../404.php">404 Page</a>
|
|
||||||
<a class="collapse-item" href="../blank.php">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="../charts.php">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="../tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<form class="form-inline">
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="../images/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="../images/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="../images/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="../images/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-2 text-gray-800">Benutzer & Gruppen</h1>
|
|
||||||
<?php if ($error !== null): ?>
|
|
||||||
<p class="error">
|
|
||||||
<?php echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
<p class="mb-4">DataTables is a third party plugin that is used to generate the demo table below.
|
|
||||||
For more information about DataTables, please visit the <a target="_blank"
|
|
||||||
href="https://datatables.net">official DataTables documentation</a>.</p>
|
|
||||||
|
|
||||||
<!-- DataTales Example -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Benutzer</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-bordered" id="usersTable" width="100%" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Anmeldename</th>
|
|
||||||
<th>Anzeigename</th>
|
|
||||||
<th>E-Mail</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th>Anmeldename</th>
|
|
||||||
<th>Anzeigename</th>
|
|
||||||
<th>E-Mail</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($users as $user): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($user['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($user['displayname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($user['mail'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Gruppen</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-bordered" id="groupsTable" width="100%" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Gruppenname</th>
|
|
||||||
<th>CN</th>
|
|
||||||
<th>Beschreibung</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th>Gruppenname</th>
|
|
||||||
<th>CN</th>
|
|
||||||
<th>Beschreibung</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($groups as $group): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($group['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($group['cn'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($group['description'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.php">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="../vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="../vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="../vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="../js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Page level plugins -->
|
|
||||||
<script src="../vendor/datatables/jquery.dataTables.min.js"></script>
|
|
||||||
<script src="../vendor/datatables/dataTables.bootstrap4.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Page level custom scripts -->
|
|
||||||
<script src="../js/demo/datatables-demo.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
Loading…
Reference in New Issue
Block a user