#2857: AdminPage.java
projectforge-wicket/src/main/java/org/projectforge/web/admin/AdminPage.java Страница Apache Wicket — панель администрирования системы. Исходник: projectforge-wicket/src/main/java/org/projectforge/web/admin/AdminPage.java · ~590 строк 590 строк · 502 кода · 43 комментария · 45 пустых
Центральная страница администрирования, доступная только пользователям с правами администратора. Предоставляет системные операции, сгруппированные в пять категорий меню: Конфигурация (перечитать конфигурационный XML, экспортировать конфигурацию, экспортировать настройки 2FA), Кэши (обновить все кэши), Действия с БД (обновить пользовательские настройки, создать недостающие индексы, дамп базы данных, экспорт схемы, оптимизировать изображения адресов), Проверка системы (проверка целостности) и Разработка (валидация ключей i18n, отладка UserGroupCache, переиндексация Hibernate Search, генерация тестовых данных, системные оповещения). Меню «Разработка» отображается только когда SystemStatus.isDevelopmentMode() возвращает true.
Архитектура
Расширяет AbstractStandardFormPage и реализует ISelectCallerPage (для выбора даты на основе календаря). Страница использует шаблон меню контента ProjectForge: каждая группа действий — это ContentMenuEntryPanel с подпунктами меню, каждый из которых содержит Wicket Link, чей onClick() делегирует выполнение приватному методу.
Страница также содержит компонент AdminForm (тело страницы), который предоставляет дополнительные элементы интерфейса, такие как панель информации о системе, проверка обновлений и просмотр логов.
Внедрение статической конечной точки через set(IProjectForgeEndpoints) — не внедрение через конструктор, а статический сеттер. Это устаревший шаблон: поле projectForgeEndpoints предоставляет доступ к системной информации (версия, дата сборки, статистика памяти), которая отображается в административной форме. Статический сеттер вызывается инициализатором приложения Wicket.
Группы меню
| Группа | Действия | Требования |
| Конфигурация | Перечитать конфигурационный XML с диска, экспортировать конфигурацию как свойства, экспортировать конфигурацию 2FA | Права администратора |
| Кэши | Обновить все кэши (адресов, пользователей, групп, i18n, системной информации и т.д.) | Права администратора |
| Действия с БД | Обновить все XML-настройки пользователей, создать недостающие индексы БД, дамп базы данных, экспорт схемы, оптимизировать изображения адресов (сжатие + пересоздание превью) | Права администратора |
| Проверка системы | Запустить проверку целостности (валидация консистентности БД, внешних ключей, потерянных записей) | Права администратора |
| Разработка | Валидация ключей i18n, отладочный экспорт UserGroupCache в JSON, DatabaseTester, переиндексация Hibernate Search, создание тестовых данных (100 объектов BookDO), системное оповещение, дамп системной конфигурации, показать обновления БД | Администратор + SystemStatus.isDevelopmentMode() |
Контроль доступа
Страница переопределяет onBeforeRender() для вызова checkAccess() — метода, унаследованного от AbstractStandardFormPage, который проверяет, имеет ли текущий пользователь роль ADMIN. Если нет, пользователь перенаправляется на страницу отказа в доступе. Это единственная проверка авторизации — нет детальной авторизации по каждому действию; любой администратор может выполнить любую операцию на этой странице.
Меню «Разработка» имеет дополнительную защиту: if (SystemStatus.isDevelopmentMode() == false) return; в конце addDevelopmentMenu(). Это означает, что действия разработки не просто скрыты — их пункты меню вообще не добавляются на страницу, если не включен режим разработки.
Ключевые зависимости
| Импорт | Роль |
ConfigXml, Configuration | Чтение/запись системной конфигурации (перечитывание, экспорт) |
SystemService | Обновление кэша, проверка целостности системы |
DatabaseService | Создание индексов, дамп БД, экспорт схемы |
DatabaseTester | Разработка: тестирование операций с БД |
AddressImageDao | База данных: сжатие и пересоздание изображений адресов |
UserXmlPreferencesCache, UserXmlPreferencesMigrationDao | База данных: обновление XML-настроек пользователей |
HibernateSearchReindexer | Разработка: перестроение поискового индекса Lucene |
BookDao, BookDO | Разработка: создание тестовых объектов книг |
I18nHelper | Разработка: валидация использования ключей i18n |
CronSanityCheckJob | Разработка: ручной запуск ночной проверки целостности |
SystemAlertMessage, SystemStatus | Разработка: установка/проверка общесистемного баннера оповещения |
WicketUtils, DownloadUtils | UI: диалоги подтверждения JavaScript, триггеры загрузки файлов |
Шаблоны проектирования
Шаблон меню контента: Вместо плоского списка кнопок страница администрирования использует иерархическую структуру меню. Каждая группа (ContentMenuEntryPanel) содержит подпункты меню, каждый со ссылкой Wicket. Это позволяет организовать более 20 административных действий в логические категории, не перегружая пользователя.
Анонимные внутренние классы Link: Каждое действие — это new Link<Void>() { onClick() { ... } } — анонимные внутренние классы, делегирующие выполнение приватным методам. Это стандартный стиль Wicket до Java 8. Современный рефакторинг мог бы использовать лямбда-выражения (Link<Void> link = new Link<>(id) { ... } не может быть лямбдой, так как Link — это класс, а не функциональный интерфейс).
Внедрение статической конечной точки: projectForgeEndpoints — это статическое поле, устанавливаемое через статический сеттер. Это необычно для Spring-управляемого приложения и существует потому, что AdminPage является страницей Wicket (не Spring-бином) и нуждается в доступе к системной информации, которая обычно предоставляется сервисами Spring. Статический сеттер вызывается из инициализатора приложения Wicket.
История Git
| Коммит | Что изменилось |
868d6abb7 | Авторские права 2025→2026. |
eeaafe0df | Добавлено меню оптимизации изображений адресов. Новое действие «Оптимизировать изображения адресов» в меню базы данных. Минимизирует размеры файлов изображений адресов (сжатие JPEG ~100 КБ) и пересчитывает миниатюры превью. Включает диалог подтверждения JavaScript. |
ab200b126 | Автоматическое сжатие изображений адресов. Действие оптимизации теперь автоматически сжимает изображения, которые слишком велики, а не просто предлагает опцию. |
5b042ab5f | Добавлен отладочный экспорт UserGroupCache и DatabaseTester. Новое действие «Отладка UserGroupCache» в меню разработки — экспортирует состояние кэша в JSON для офлайн-анализа. Новое действие DatabaseTester для стресс-тестирования разработки. Добавлена регистрация модуля Jackson Hibernate6 для JSON-сериализации прокси Hibernate. |
b309e9be9 | Улучшения вложений почты (BirthdayButler, Polls). Автоматическое уведомление по электронной почте, когда ночная проверка целостности находит ошибки. |
092dbf9c5 | SystemService мигрирован на Kotlin. Пакет переименован с systeminfo на system. |
619985f48 | Подготовка к релизу 8.1 — слияние PR #247, различные стабилизации. |
1b50060c3 | Переименование методов BaseDao: get→find, save→insert, getList→select, load→select. Все вызывающие обновлены — вызовы DAO в AdminPage используют новые имена. |
a72903e36 | Миграция StringBuffer→StringBuilder во всех файлах Java/Kotlin. Производительность: StringBuilder не синхронизирован, StringBuffer — синхронизирован. |
3aeda5ef5 | Рефакторинг обработки транзакций. Суффикс *InTrans удален из методов DAO. PfPersistenceContext больше не передается как параметр — используется ThreadLocal. |
b095e6f7d | Крупное изменение обработки транзакций. Повторно использует PfPersistenceContext. Тесты были сломаны на этом этапе (еще не исправлены). |
Внимание: На этой странице нет авторизации по каждому действию. Любой пользователь с правами администратора может запускать дампы базы данных, экспорт схемы, переиндексацию Hibernate и создание тестовых данных — все это на рабочей базе данных. Меню «Разработка» защищено флагом SystemStatus.isDevelopmentMode(), но это единственный булевый флаг без дальнейшей детализации.
Путь миграции: Это одна из самых старых страниц, все еще работающих на Wicket. Эквиваленты REST API для этих административных операций создаются в projectforge-rest (см. SystemAdminPageRest). Как только REST-уровень покроет все административные операции, эту страницу можно будет заменить на административную панель на основе React.