diff --git a/CHANGELOG.md b/CHANGELOG.md index 79c6d80..04fd2da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [1.26.0] - 2026-11-04 + +### Added +- **Restricción Declarativa de Comandos de Plugins según Estado de Cliente y SO Activo (`PluginService`, `PluginCommand`)**: + - Incorporadas las propiedades `activeOsOnly`, `excludeClientStatus` y `requireClientStatus` en la interfaz `PluginCommand`. + - La directiva `activeOsOnly: true` exige estrictamente que el equipo esté arrancado y en ejecución en uno de los sistemas operativos declarados en `os` (ej. Windows o Linux), impidiendo que se habiliten comandos de escritorio cuando el cliente se encuentra en entorno de mantenimiento `ogLive` o apagado aunque tenga una partición con dicho SO instalada en disco. + - Soportada exclusión e inclusión explícita por estado del cliente (`excludeClientStatus: ["og-live"]`, etc.) en `isCommandSupportedForClients`. + - En `ExecuteCommandComponent`, evaluado el estado unitario (`clientState`) para garantizar que la disponibilidad de comandos en el menú contextual de cada tarjeta individual responda fielmente al estado en tiempo real. + ## [1.25.1] - 2026-11-01 ### Refactored diff --git a/ogWebconsole/package.json b/ogWebconsole/package.json index b705791..0b821cc 100644 --- a/ogWebconsole/package.json +++ b/ogWebconsole/package.json @@ -1,6 +1,6 @@ { "name": "og-webconsole", - "version": "1.25.1", + "version": "1.26.0", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts b/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts index cc602b1..0dcbd40 100644 --- a/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts +++ b/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts @@ -173,9 +173,13 @@ export class ExecuteCommandComponent implements OnInit { }); if (this.pluginGroups && this.pluginGroups.length > 0) { + const clientsToCheck = this.clientData.length > 0 + ? this.clientData + : (this.clientState ? [{ status: this.clientState }] : []); + for (const group of this.pluginGroups) { for (const cmd of group.commands) { - cmd.disabled = !hasClients || !this.pluginService.isCommandSupportedForClients(cmd, this.clientData, group.plugin.name); + cmd.disabled = !hasClients || !this.pluginService.isCommandSupportedForClients(cmd, clientsToCheck, group.plugin.name); // Adaptar dinámicamente la etiqueta de activar/desactivar en ogaquarium si hay un solo cliente seleccionado if (cmd.slug === 'ogaquarium-toggle-status' && this.clientData.length === 1) { diff --git a/ogWebconsole/src/app/services/plugin.service.ts b/ogWebconsole/src/app/services/plugin.service.ts index c1510e8..9572f55 100644 --- a/ogWebconsole/src/app/services/plugin.service.ts +++ b/ogWebconsole/src/app/services/plugin.service.ts @@ -240,12 +240,18 @@ export class PluginService { return true; } + // 1. Filtrado por estado de SO del cliente if (command.os && command.os.length > 0) { const requiredOsList = command.os.map(os => os.toLowerCase()); const osSupported = clients.every(client => { const statusStr = (client.status || '').toLowerCase(); const matchesStatus = requiredOsList.some(req => statusStr.includes(req)); + // Si se requiere expresamente que el SO esté arrancado activamente, no admitir og-live ni particiones apagadas + if (command.activeOsOnly) { + return matchesStatus; + } + const hasMatchingPartition = (client.partitions || []).some((partition: any) => { const osName = (partition.operativeSystem?.name || partition.operativeSystem || '').toLowerCase(); return requiredOsList.some(req => osName.includes(req)); @@ -259,6 +265,33 @@ export class PluginService { } } + // 2. Exclusión explícita por estado del cliente (ej. og-live, off) + if (command.excludeClientStatus && command.excludeClientStatus.length > 0) { + const excluded = command.excludeClientStatus.map(s => s.toLowerCase()); + const clientSupported = clients.every(client => { + const statusStr = (client.status || '').toLowerCase(); + return !excluded.some(req => statusStr.includes(req)); + }); + + if (!clientSupported) { + return false; + } + } + + // 3. Requisito explícito por estado del cliente (ej. windows, linux) + if (command.requireClientStatus && command.requireClientStatus.length > 0) { + const required = command.requireClientStatus.map(s => s.toLowerCase()); + const clientSupported = clients.every(client => { + const statusStr = (client.status || '').toLowerCase(); + return required.some(req => statusStr.includes(req)); + }); + + if (!clientSupported) { + return false; + } + } + + // 4. Filtrado por estado de negocio del plugin (ej. FREE, OCCUPIED, DISABLED) if (pluginName && (command.requireStatus || command.excludeStatus)) { return clients.every(client => { const idKey = client.id ? String(client.id) : null; diff --git a/ogWebconsole/src/app/services/plugin/plugin.types.ts b/ogWebconsole/src/app/services/plugin/plugin.types.ts index d0e59e1..28bbe00 100644 --- a/ogWebconsole/src/app/services/plugin/plugin.types.ts +++ b/ogWebconsole/src/app/services/plugin/plugin.types.ts @@ -23,6 +23,9 @@ export interface PluginCommand { roles?: string[]; // Roles autorizados por defecto (ej. ['ROLE_SUPER_ADMIN', 'ROLE_ORGANIZATIONAL_UNIT_ADMIN']) requireStatus?: string[]; // Estados requeridos del plugin para habilitar el comando excludeStatus?: string[]; // Estados del plugin que deshabilitan el comando + activeOsOnly?: boolean; // Requiere que el cliente esté arrancado activamente en uno de los SO indicados en 'os' + excludeClientStatus?: string[]; // Estados del cliente (ej. ['og-live', 'off']) que inhabilitan el comando + requireClientStatus?: string[]; // Estados del cliente (ej. ['windows', 'linux']) requeridos para habilitar el comando } export interface RoleDefinition {