From 2b77eb8afac04f5da28644732c29a9422be52d74 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Wed, 29 Jul 2026 00:02:36 +0200 Subject: [PATCH] Corrected ou-operator bug --- .../e2e/permissions/ou-operator.spec.ts | 5 ++++ ogWebconsole/src/app/app-routing.module.ts | 2 +- .../global-status/global-status.component.ts | 17 +++++++++++++- .../app/components/login/login.component.ts | 12 ++++++---- .../client-pending-tasks.component.ts | 8 +++---- .../client-task-logs.component.ts | 13 ++++------- .../task-logs/task-logs.component.ts | 9 ++++---- .../src/app/guards/role.guard.spec.ts | 2 +- .../app/layout/header/header.component.html | 16 ++++++++----- .../app/layout/sidebar/sidebar.component.html | 4 ++-- .../layout/sidebar/sidebar.component.spec.ts | 23 +++++++++++++++---- 11 files changed, 73 insertions(+), 38 deletions(-) diff --git a/ogWebconsole/e2e/permissions/ou-operator.spec.ts b/ogWebconsole/e2e/permissions/ou-operator.spec.ts index 75ced9d..67cf796 100644 --- a/ogWebconsole/e2e/permissions/ou-operator.spec.ts +++ b/ogWebconsole/e2e/permissions/ou-operator.spec.ts @@ -54,6 +54,11 @@ test.describe('OU Operator — solo grupos y operaciones de equipos', () => { const finalUrl = await navigateTo(page, '/clients/run-script'); expect(finalUrl).toContain('/clients/run-script'); }); + + test('accede a /commands-logs (trazas de sus acciones)', async ({ page }) => { + const finalUrl = await navigateTo(page, '/commands-logs'); + expect(finalUrl).toContain('/commands-logs'); + }); }); // ── GUI en /groups: botones de crear OU/cliente ocultos ───────────────────── diff --git a/ogWebconsole/src/app/app-routing.module.ts b/ogWebconsole/src/app/app-routing.module.ts index a4fe9fe..3465323 100644 --- a/ogWebconsole/src/app/app-routing.module.ts +++ b/ogWebconsole/src/app/app-routing.module.ts @@ -69,7 +69,7 @@ const routes: Routes = [ { path: 'commands', component: CommandsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } }, { path: 'commands-groups', component: CommandsGroupsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } }, { path: 'commands-task', component: CommandsTaskComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } }, - { path: 'commands-logs', component: TaskLogsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } }, + { path: 'commands-logs', component: TaskLogsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin', 'ou-operator'] } }, { path: 'calendars', component: CalendarComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } }, { path: 'clients/deploy-image', component: DeployImageComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin', 'ou-operator'] } }, { path: 'clients/partition-assistant', component: PartitionAssistantComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin', 'ou-operator'] } }, diff --git a/ogWebconsole/src/app/components/global-status/global-status.component.ts b/ogWebconsole/src/app/components/global-status/global-status.component.ts index a373ca2..8c03bc0 100644 --- a/ogWebconsole/src/app/components/global-status/global-status.component.ts +++ b/ogWebconsole/src/app/components/global-status/global-status.component.ts @@ -4,6 +4,7 @@ import { HttpClient } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { ConfigService } from '@services/config.service'; import { ToastrService } from "ngx-toastr"; +import { AuthService } from '@services/auth.service'; @Component({ selector: 'app-global-status', @@ -67,7 +68,8 @@ export class GlobalStatusComponent implements OnInit { constructor( private configService: ConfigService, private toastService: ToastrService, - private http: HttpClient + private http: HttpClient, + private auth: AuthService ) { this.baseUrl = this.configService.apiUrl; this.dhcpsApiUrl = `${this.baseUrl}/dhcp-servers`; @@ -115,7 +117,18 @@ export class GlobalStatusComponent implements OnInit { }); } + /** + * Las sincronizaciones con la infraestructura (subredes DHCP, plantillas PXE y + * ogLives) están restringidas a ROLE_SUPER_ADMIN en ogCore; para el resto de + * perfiles devuelven "Access Denied", así que ni siquiera se lanzan. + */ + private get canSyncInfrastructure(): boolean { + return this.auth.isSuperAdmin; + } + syncSubnets() { + if (!this.canSyncInfrastructure) return; + this.http.get(`${this.dhcpsApiUrl}?page=1&itemsPerPage=10`).subscribe(data => { const dhcps = data['hydra:member'] || []; if (dhcps.length === 0) return; @@ -155,6 +168,7 @@ export class GlobalStatusComponent implements OnInit { } syncTemplates() { + if (!this.canSyncInfrastructure) return; if (this.bootServers.length === 0) return; let pending = this.bootServers.length; @@ -189,6 +203,7 @@ export class GlobalStatusComponent implements OnInit { } syncOgLives(): void { + if (!this.canSyncInfrastructure) return; if (this.bootServers.length === 0) return; let pending = this.bootServers.length; diff --git a/ogWebconsole/src/app/components/login/login.component.ts b/ogWebconsole/src/app/components/login/login.component.ts index c5738be..b808a8c 100644 --- a/ogWebconsole/src/app/components/login/login.component.ts +++ b/ogWebconsole/src/app/components/login/login.component.ts @@ -64,10 +64,14 @@ export class LoginComponent { this.auth.refresh(); this.openSnackBar(false, 'Bienvenido ' + this.auth.username); this.router.navigateByUrl('/groups'); - this.dialog.open(GlobalStatusComponent, { - width: '65vw', - height: '80vh', - }); + // El estado global consulta y sincroniza infraestructura (ogBoot, DHCP, + // repositorios), a la que solo tienen acceso los perfiles de administración. + if (this.auth.isSuperAdmin || this.auth.isOUAdmin) { + this.dialog.open(GlobalStatusComponent, { + width: '65vw', + height: '80vh', + }); + } } this.isLoading = false; }, diff --git a/ogWebconsole/src/app/components/task-logs/client-pending-tasks/client-pending-tasks.component.ts b/ogWebconsole/src/app/components/task-logs/client-pending-tasks/client-pending-tasks.component.ts index 0eba079..8ddcfed 100644 --- a/ogWebconsole/src/app/components/task-logs/client-pending-tasks/client-pending-tasks.component.ts +++ b/ogWebconsole/src/app/components/task-logs/client-pending-tasks/client-pending-tasks.component.ts @@ -105,19 +105,19 @@ export class ClientPendingTasksComponent implements OnInit { eventSource.onmessage = (event) => { const data = JSON.parse(event.data); if (data && data['@id']) { - this.updateTracesStatus(data['@id'], data.status); + this.updateTraceFromEvent(data['@id'], data); } } } - private updateTracesStatus(clientUuid: string, newStatus: string): void { - const traceIndex = this.traces.findIndex(trace => trace['@id'] === clientUuid); + private updateTraceFromEvent(traceId: string, data: any): void { + const traceIndex = this.traces.findIndex(trace => trace['@id'] === traceId); if (traceIndex !== -1) { const updatedTraces = [...this.traces]; updatedTraces[traceIndex] = { ...updatedTraces[traceIndex], - status: newStatus + ...data }; this.traces = updatedTraces; diff --git a/ogWebconsole/src/app/components/task-logs/client-task-logs/client-task-logs.component.ts b/ogWebconsole/src/app/components/task-logs/client-task-logs/client-task-logs.component.ts index ef40cda..f1c179c 100644 --- a/ogWebconsole/src/app/components/task-logs/client-task-logs/client-task-logs.component.ts +++ b/ogWebconsole/src/app/components/task-logs/client-task-logs/client-task-logs.component.ts @@ -107,28 +107,23 @@ export class ClientTaskLogsComponent implements OnInit { eventSource.onmessage = (event) => { const data = JSON.parse(event.data); if (data && data['@id']) { - this.updateTracesStatus(data['@id'], data.status, data.progress); + this.updateTraceFromEvent(data['@id'], data); } } } - private updateTracesStatus(clientUuid: string, newStatus: string, progress: Number): void { - const traceIndex = this.traces.findIndex(trace => trace['@id'] === clientUuid); + private updateTraceFromEvent(traceId: string, data: any): void { + const traceIndex = this.traces.findIndex(trace => trace['@id'] === traceId); if (traceIndex !== -1) { const updatedTraces = [...this.traces]; updatedTraces[traceIndex] = { ...updatedTraces[traceIndex], - status: newStatus, - progress: progress + ...data }; this.traces = updatedTraces; this.cdr.detectChanges(); - - console.log(`Estado actualizado para la traza ${clientUuid}: ${newStatus}`); - } else { - console.warn(`Traza con UUID ${clientUuid} no encontrado en la lista.`); } } diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts index 36da5b0..47bc86a 100644 --- a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts +++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts @@ -157,7 +157,7 @@ export class TaskLogsComponent implements OnInit, OnDestroy { this.eventSource.onmessage = (event) => { const data = JSON.parse(event.data); if (data && data['@id']) { - this.updateTracesStatus(data['@id'], data.status, data.progress); + this.updateTraceFromEvent(data['@id'], data); } } } @@ -439,15 +439,14 @@ export class TaskLogsComponent implements OnInit, OnDestroy { }); } - private updateTracesStatus(clientUuid: string, newStatus: string, progress: Number): void { - const traceIndex = this.traces.findIndex(trace => trace['@id'] === clientUuid); + private updateTraceFromEvent(traceId: string, data: any): void { + const traceIndex = this.traces.findIndex(trace => trace['@id'] === traceId); if (traceIndex !== -1) { const updatedTraces = [...this.traces]; updatedTraces[traceIndex] = { ...updatedTraces[traceIndex], - status: newStatus, - progress: progress + ...data }; this.traces = updatedTraces; diff --git a/ogWebconsole/src/app/guards/role.guard.spec.ts b/ogWebconsole/src/app/guards/role.guard.spec.ts index 65e097d..c2fce0e 100644 --- a/ogWebconsole/src/app/guards/role.guard.spec.ts +++ b/ogWebconsole/src/app/guards/role.guard.spec.ts @@ -139,7 +139,6 @@ describe('roleGuard — control de acceso por rol', () => { // super-admin + ou-admin { path: 'commands', allowedRoles: ['super-admin', 'ou-admin'] }, { path: 'commands-task', allowedRoles: ['super-admin', 'ou-admin'] }, - { path: 'commands-logs', allowedRoles: ['super-admin', 'ou-admin'] }, { path: 'pxe-images', allowedRoles: ['super-admin', 'ou-admin'] }, { path: 'pxe', allowedRoles: ['super-admin', 'ou-admin'] }, { path: 'pxe-boot-file', allowedRoles: ['super-admin', 'ou-admin'] }, @@ -156,6 +155,7 @@ describe('roleGuard — control de acceso por rol', () => { { path: 'hardware-profiles', allowedRoles: ['super-admin', 'ou-admin'] }, { path: 'hardware-types', allowedRoles: ['super-admin', 'ou-admin'] }, // super-admin + ou-admin + ou-operator + { path: 'commands-logs', allowedRoles: ['super-admin', 'ou-admin', 'ou-operator'] }, { path: 'clients/deploy-image', allowedRoles: ['super-admin', 'ou-admin', 'ou-operator'] }, { path: 'clients/partition-assistant',allowedRoles: ['super-admin', 'ou-admin', 'ou-operator'] }, { path: 'clients/run-script', allowedRoles: ['super-admin', 'ou-admin', 'ou-operator'] }, diff --git a/ogWebconsole/src/app/layout/header/header.component.html b/ogWebconsole/src/app/layout/header/header.component.html index 0d59409..3c99c89 100644 --- a/ogWebconsole/src/app/layout/header/header.component.html +++ b/ogWebconsole/src/app/layout/header/header.component.html @@ -21,9 +21,11 @@ {{ 'downloadAgent' | translate }} - + @if (auth.userCategory === 'super-admin' || auth.userCategory === 'ou-admin') { + + } @if (auth.userCategory === 'super-admin') { + @if (auth.userCategory === 'super-admin' || auth.userCategory === 'ou-admin') { + + } @if (auth.userCategory === 'super-admin') {