EN · DE · RU · FR · ES

#2857: AdminPage.java

projectforge-wicket/src/main/java/org/projectforge/web/admin/AdminPage.java Página Apache Wicket — panel de administración del sistema. Fuente: projectforge-wicket/src/main/java/org/projectforge/web/admin/AdminPage.java · ~590 líneas 590 líneas · 502 código · 43 comentarios · 45 en blanco
La página de administración central accesible solo para usuarios con privilegios de administrador. Proporciona operaciones a nivel de sistema agrupadas en cinco categorías de menú: Configuración (releer config XML, exportar config, exportar ajustes 2FA), Cachés (refrescar todas las cachés), Acciones de Base de Datos (actualizar preferencias de usuario, crear índices faltantes, volcar base de datos, exportar esquema, optimizar imágenes de direcciones), Verificación del Sistema (verificación de integridad) y Desarrollo (validación de claves i18n, depuración de UserGroupCache, reindexación de Hibernate Search, generación de datos de prueba, alertas del sistema). El menú de Desarrollo solo es visible cuando SystemStatus.isDevelopmentMode() es verdadero.

Arquitectura

Extiende AbstractStandardFormPage e implementa ISelectCallerPage (para selección de fechas basada en calendario). La página utiliza el patrón de menú de contenido de ProjectForge: cada grupo de acciones es un ContentMenuEntryPanel con entradas de submenú, cada una contiene un Link de Wicket cuyo onClick() delega a un método privado.

La página también contiene un componente AdminForm (el cuerpo de la página) que proporciona elementos de UI adicionales como el panel de información del sistema, el verificador de actualizaciones y el visor de registros.

Inyección de endpoint estático mediante set(IProjectForgeEndpoints) — no es inyección por constructor sino un setter estático. Este es un patrón heredado: el campo projectForgeEndpoints proporciona acceso a información del sistema (versión, fecha de compilación, estadísticas de memoria) que se muestra en el formulario de administración. El setter estático es llamado por el inicializador de la aplicación Wicket.

Grupos de Menú

GrupoAccionesRequiere
ConfiguraciónReleer config XML desde disco, exportar config como propiedades, exportar configuración 2FAAcceso admin
CachésRefrescar todas las cachés (direcciones, usuario, grupo, i18n, información del sistema, etc.)Acceso admin
Acciones de Base de DatosActualizar todas las preferencias XML de usuario, crear índices de BD faltantes, volcar base de datos, exportar esquema, optimizar imágenes de direcciones (reducir + recrear vistas previas)Acceso admin
Verificación del SistemaEjecutar verificación de integridad (valida consistencia de BD, claves foráneas, registros huérfanos)Acceso admin
DesarrolloValidación de claves i18n, exportación de depuración JSON de UserGroupCache, DatabaseTester, reindexación de Hibernate Search, crear datos de prueba (100 objetos BookDO), mensaje de alerta del sistema, volcar configuración del sistema, mostrar actualizaciones de BDAdmin + SystemStatus.isDevelopmentMode()

Control de Acceso

La página sobrescribe onBeforeRender() para llamar a checkAccess() — un método heredado de AbstractStandardFormPage que verifica que el usuario actual tenga el rol ADMIN. Si no, el usuario es redirigido a una página de acceso denegado. Esta es la única verificación de autorización — no hay autorización detallada por acción; cualquier administrador puede realizar cualquier operación en esta página.

El menú de Desarrollo tiene una protección adicional: if (SystemStatus.isDevelopmentMode() == false) return; al final de addDevelopmentMenu(). Esto significa que las acciones de desarrollo no solo están ocultas — sus entradas de menú nunca se agregan a la página cuando no está en modo de desarrollo.

Dependencias Clave

ImportaciónRol
ConfigXml, ConfigurationLeer/escribir configuración del sistema (releer, exportar)
SystemServiceRefresco de caché, verificación de integridad del sistema
DatabaseServiceCrear índices, volcar BD, exportar esquema
DatabaseTesterDesarrollo: probar operaciones de base de datos
AddressImageDaoBase de datos: reducir y recrear imágenes de direcciones
UserXmlPreferencesCache, UserXmlPreferencesMigrationDaoBase de datos: actualizar XML de preferencias de usuario
HibernateSearchReindexerDesarrollo: reconstruir índice de búsqueda Lucene
BookDao, BookDODesarrollo: crear objetos de libro de prueba
I18nHelperDesarrollo: validar uso de claves i18n
CronSanityCheckJobDesarrollo: activar verificación nocturna manualmente
SystemAlertMessage, SystemStatusDesarrollo: establecer/verificar banner de alerta del sistema
WicketUtils, DownloadUtilsUI: diálogos de confirmación JavaScript, disparadores de descarga de archivos

Patrones de Diseño

Patrón de Menú de Contenido: En lugar de una lista plana de botones, la página de administración utiliza una estructura de menú jerárquica. Cada grupo (ContentMenuEntryPanel) contiene entradas de submenú, cada una con un Link de Wicket. Esto permite organizar más de 20 acciones de administración en categorías lógicas sin abrumar al usuario.

Links con clases internas anónimas: Cada acción es un new Link<Void>() { onClick() { ... } } — clases internas anónimas que delegan a métodos privados. Este es el estilo estándar de Wicket anterior a Java 8. Una reescritura moderna usaría expresiones lambda (Link<Void> link = new Link<>(id) { ... } no puede ser lambda porque Link es una clase, no una interfaz funcional).

Inyección de endpoint estático: projectForgeEndpoints es un campo estático establecido mediante un setter estático. Esto es inusual en una aplicación gestionada por Spring y existe porque AdminPage es una página de Wicket (no un bean de Spring) y necesita acceso a información a nivel de sistema que normalmente proporcionan los servicios de Spring. El setter estático se llama desde el init de la aplicación Wicket.

Historial Git

CommitQué cambió
868d6abb7Copyright 2025→2026.
eeaafe0dfSe agregó menú de optimización de imágenes de direcciones. Nueva acción "Optimizar imágenes de direcciones" en el menú de Base de Datos. Minimiza el tamaño de archivo de las imágenes de direcciones (compresión JPEG ~100KB) y recalcula las miniaturas de vista previa. Incluye diálogo de confirmación JavaScript.
ab200b126Reducción automática de imágenes de direcciones. La acción de optimización ahora reduce automáticamente las imágenes que son demasiado grandes, no solo ofrece la opción.
5b042ab5fSe agregaron exportación de depuración de UserGroupCache y DatabaseTester. Nueva acción "Depurar UserGroupCache" en el menú de Desarrollo — exporta el estado de la caché como JSON para análisis fuera de línea. Nueva acción DatabaseTester para pruebas de estrés en desarrollo. Se agregó registro del módulo Jackson Hibernate6 para serialización JSON de proxies de Hibernate.
b309e9be9Mejoras en adjuntos de correo (BirthdayButler, Polls). Notificación automática por correo electrónico cuando la verificación nocturna encuentra errores.
092dbf9c5SystemService migrado a Kotlin. Paquete renombrado de systeminfo a system.
619985f48Preparativos para la versión 8.1 — fusión de PR #247, varias estabilizaciones.
1b50060c3Renombrado de métodos en BaseDao: getfind, saveinsert, getListselect, loadselect. Todos los llamantes actualizados — las llamadas DAO de AdminPage usan los nuevos nombres.
a72903e36Migración de StringBufferStringBuilder en todos los archivos Java/Kotlin. Rendimiento: StringBuilder no está sincronizado, StringBuffer sí.
3aeda5ef5Manejo de transacciones refactorizado. Se eliminó el sufijo *InTrans de los métodos DAO. PfPersistenceContext ya no se pasa como parámetro — usa ThreadLocal en su lugar.
b095e6f7dCambio importante en el manejo de transacciones. Reutiliza PfPersistenceContext. Las pruebas estaban rotas en este punto (aún no corregidas).
Precaución: Esta página no tiene autorización por acción. Cualquier usuario con acceso de administrador puede activar volcados de base de datos, exportaciones de esquema, reindexación de Hibernate y creación de datos de prueba — todo en la base de datos de producción. El menú de Desarrollo está protegido por SystemStatus.isDevelopmentMode() pero eso es una única bandera booleana sin más granularidad.
Ruta de migración: Esta es una de las páginas más antiguas que aún están en Wicket. Los equivalentes de API REST para estas operaciones de administración se están construyendo en projectforge-rest (ver SystemAdminPageRest). Una vez que la capa REST cubra todas las operaciones de administración, esta página puede ser reemplazada por un panel de administración basado en React.