#2857: AdminPage.java
projectforge-wicket/src/main/java/org/projectforge/web/admin/AdminPage.java Apache Wicket-Seite — Systemadministrations-Dashboard. Quelle: projectforge-wicket/src/main/java/org/projectforge/web/admin/AdminPage.java · ~590 Zeilen 590 Zeilen · 502 Code · 43 Kommentare · 45 leer
Die zentrale Administrationsseite, die nur für Benutzer mit Administratorrechten zugänglich ist. Bietet systemweite Operationen, gruppiert in fünf Menükategorien: Konfiguration (Konfigurations-XML erneut einlesen, Konfiguration exportieren, 2FA-Einstellungen exportieren), Caches (alle Caches aktualisieren), Datenbankaktionen (Benutzereinstellungen aktualisieren, fehlende Indizes erstellen, Datenbank dump, Schemaexport, Adressbilder optimieren), Systemprüfung (Integritätsprüfung) und Entwicklung (i18n-Schlüsselvalidierung, UserGroupCache-Debug, Hibernate Search Neuindizierung, Testdatengenerierung, Systemmeldungen). Das Entwicklungsmenü ist nur sichtbar, wenn SystemStatus.isDevelopmentMode() wahr ist.
Architektur
Erweitert AbstractStandardFormPage und implementiert ISelectCallerPage (für kalenderbasierte Datumsauswahl). Die Seite verwendet ProjectForge's Content-Menu-Muster: jede Aktionsgruppe ist ein ContentMenuEntryPanel mit Untermenüeinträgen, die jeweils einen Wicket Link enthalten, dessen onClick() an eine private Methode delegiert.
Die Seite enthält außerdem eine AdminForm-Komponente (den Hauptteil der Seite), die zusätzliche UI-Elemente wie das Systeminformationspanel, den Update-Checker und den Log-Viewer bereitstellt.
Statische Endpunkt-Injektion über set(IProjectForgeEndpoints) — keine Konstruktorinjektion, sondern ein statischer Setter. Dies ist ein Legacy-Muster: Das Feld projectForgeEndpoints bietet Zugriff auf Systeminformationen (Version, Build-Datum, Speicherstatistiken), die im Admin-Formular angezeigt werden. Der statische Setter wird vom Wicket-Anwendungsinitialisierer aufgerufen.
Menügruppen
| Gruppe | Aktionen | Erfordert |
| Konfiguration | Konfigurations-XML von der Festplatte erneut einlesen, Konfiguration als Properties exportieren, 2FA-Konfiguration exportieren | Admin-Zugriff |
| Caches | Alle Caches aktualisieren (Adresse, Benutzer, Gruppe, i18n, Systeminfo usw.) | Admin-Zugriff |
| Datenbankaktionen | Alle Benutzer-XML-Einstellungen aktualisieren, fehlende DB-Indizes erstellen, Datenbank dump, Schemaexport, Adressbilder optimieren (verkleinern + Vorschauen neu erstellen) | Admin-Zugriff |
| Systemprüfung | Integritätsprüfung durchführen (prüft DB-Konsistenz, Fremdschlüssel, verwaiste Datensätze) | Admin-Zugriff |
| Entwicklung | i18n-Schlüsselvalidierung, UserGroupCache JSON-Debug-Export, DatabaseTester, Hibernate Search Neuindizierung, Testdaten erstellen (100 BookDO-Objekte), Systemmeldung, Systemkonfiguration dump, Datenbank-Updates anzeigen | Admin + SystemStatus.isDevelopmentMode() |
Zugriffskontrolle
Die Seite überschreibt onBeforeRender(), um checkAccess() aufzurufen — eine von AbstractStandardFormPage geerbte Methode, die überprüft, ob der aktuelle Benutzer die ADMIN-Rolle hat. Wenn nicht, wird der Benutzer auf eine Seite mit verweigertem Zugriff umgeleitet. Dies ist die einzige Autorisierungsprüfung — es gibt keine feingranulare aktionsspezifische Autorisierung; jeder Administrator kann jede Operation auf dieser Seite ausführen.
Das Entwicklungsmenü hat eine zusätzliche Absicherung: if (SystemStatus.isDevelopmentMode() == false) return; am Ende von addDevelopmentMenu(). Das bedeutet, dass Entwicklungsaktionen nicht nur versteckt sind — ihre Menüeinträge werden der Seite im Nicht-Entwicklungsmodus überhaupt nicht hinzugefügt.
Wichtige Abhängigkeiten
| Import | Rolle |
ConfigXml, Configuration | Systemkonfiguration lesen/schreiben (erneut einlesen, exportieren) |
SystemService | Cache-Aktualisierung, Systemintegritätsprüfung |
DatabaseService | Indizes erstellen, DB dump, Schemaexport |
DatabaseTester | Entwicklung: Datenbankoperationen testen |
AddressImageDao | Datenbank: Adressbilder verkleinern und neu erstellen |
UserXmlPreferencesCache, UserXmlPreferencesMigrationDao | Datenbank: Benutzereinstellungen XML aktualisieren |
HibernateSearchReindexer | Entwicklung: Lucene-Suchindex neu aufbauen |
BookDao, BookDO | Entwicklung: Test-Buchobjekte erstellen |
I18nHelper | Entwicklung: i18n-Schlüsselverwendung validieren |
CronSanityCheckJob | Entwicklung: Nächtlichen Sanity-Check manuell auslösen |
SystemAlertMessage, SystemStatus | Entwicklung: Systemweites Warnbanner setzen/prüfen |
WicketUtils, DownloadUtils | UI: JavaScript-Bestätigungsdialoge, Datei-Download-Trigger |
Entwurfsmuster
Content-Menu-Muster: Anstelle einer flachen Liste von Schaltflächen verwendet die Admin-Seite eine hierarchische Menüstruktur. Jede Gruppe (ContentMenuEntryPanel) enthält Untermenüeinträge, jeweils mit einem Wicket Link. Dies ermöglicht die Organisation von über 20 Admin-Aktionen in logische Kategorien, ohne den Benutzer zu überfordern.
Anonyme innere Klassen für Links: Jede Aktion ist ein new Link<Void>() { onClick() { ... } } — anonyme innere Klassen, die an private Methoden delegieren. Dies ist der Standard-Wicket-Stil vor Java 8. Eine moderne Umschreibung würde Lambda-Ausdrücke verwenden (Link<Void> link = new Link<>(id) { ... } kann kein Lambda sein, da Link eine Klasse und kein funktionales Interface ist).
Statische Endpunkt-Injektion: projectForgeEndpoints ist ein statisches Feld, das über einen statischen Setter gesetzt wird. Dies ist in einer Spring-verwalteten Anwendung ungewöhnlich und existiert, weil AdminPage eine Wicket-Seite (kein Spring-Bean) ist und Zugriff auf systemweite Informationen benötigt, die normalerweise von Spring-Services bereitgestellt werden. Der statische Setter wird im Wicket-Anwendungs-Init aufgerufen.
Git-Verlauf
| Commit | Was hat sich geändert |
868d6abb7 | Copyright 2025→2026. |
eeaafe0df | Menü zur Adressbildoptimierung hinzugefügt. Neue Aktion "Adressbilder optimieren" im Datenbankmenü. Minimiert Dateigrößen von Adressbildern (JPEG-Komprimierung ~100KB) und berechnet Vorschaubilder neu. Enthält JavaScript-Bestätigungsdialog. |
ab200b126 | Automatische Verkleinerung von Adressbildern. Die Optimierungsaktion verkleinert jetzt automatisch zu große Bilder, anstatt nur die Option anzubieten. |
5b042ab5f | UserGroupCache-Debug-Export und DatabaseTester hinzugefügt. Neue Aktion "UserGroupCache debuggen" im Entwicklungsmenü — exportiert Cache-Zustand als JSON zur Offline-Analyse. Neue DatabaseTester-Aktion für Entwicklungs-Stresstests. Jackson Hibernate6-Modulregistrierung für JSON-Serialisierung von Hibernate-Proxys hinzugefügt. |
b309e9be9 | Mail-Anhangsverbesserungen (BirthdayButler, Umfragen). Automatische E-Mail-Benachrichtigung, wenn der nächtliche Sanity-Check Fehler findet. |
092dbf9c5 | SystemService nach Kotlin migriert. Paket umbenannt von systeminfo zu system. |
619985f48 | Release 8.1 Vorbereitungen — PR #247 Merge, verschiedene Stabilisierungen. |
1b50060c3 | BaseDao-Methodenumbenennung: get→find, save→insert, getList→select, load→select. Alle Aufrufer aktualisiert — AdminPage's DAO-Aufrufe verwenden die neuen Namen. |
a72903e36 | StringBuffer→StringBuilder-Migration in allen Java/Kotlin-Dateien. Leistung: StringBuilder ist nicht synchronisiert, StringBuffer schon. |
3aeda5ef5 | Transaktionsbehandlung umgestaltet. *InTrans-Suffix von DAO-Methoden entfernt. PfPersistenceContext wird nicht mehr als Parameter übergeben — verwendet stattdessen ThreadLocal. |
b095e6f7d | Große Änderung der Transaktionsbehandlung. Verwendet PfPersistenceContext wieder. Tests waren zu diesem Zeitpunkt defekt (noch nicht behoben). |
Achtung: Diese Seite hat keine aktionsspezifische Autorisierung. Jeder Benutzer mit Admin-Zugriff kann Datenbank-Dumps, Schemaexporte, Hibernate-Neuindizierung und Testdatenerstellung auslösen — alles auf der Produktionsdatenbank. Das Entwicklungsmenü wird durch SystemStatus.isDevelopmentMode() geschützt, aber das ist ein einzelner Boolean-Flag ohne weitere Granularität.
Migrationspfad: Dies ist eine der ältesten Seiten, die noch auf Wicket läuft. Die REST-API-Äquivalente für diese Admin-Operationen werden in projectforge-rest entwickelt (siehe SystemAdminPageRest). Sobald die REST-Schicht alle Admin-Operationen abdeckt, kann diese Seite durch ein React-basiertes Admin-Dashboard ersetzt werden.