375 lines
11 KiB
TypeScript
375 lines
11 KiB
TypeScript
import { Component, Input, OnInit } from '@angular/core';
|
|
import { HttpClient } from '@angular/common/http';
|
|
import { Router } from "@angular/router";
|
|
import { ToastrService } from "ngx-toastr";
|
|
import { ConfigService } from '@services/config.service';
|
|
import { BootSoPartitionComponent } from "./boot-so-partition/boot-so-partition.component";
|
|
import { MatDialog } from "@angular/material/dialog";
|
|
import { RemoveCacheImageComponent } from "./remove-cache-image/remove-cache-image.component";
|
|
import { AuthService } from '@services/auth.service';
|
|
import {SoftwareProfilePartitionComponent} from "./software-profile-partition/software-profile-partition.component";
|
|
|
|
@Component({
|
|
selector: 'app-execute-command',
|
|
templateUrl: './execute-command.component.html',
|
|
styleUrls: ['./execute-command.component.css']
|
|
})
|
|
export class ExecuteCommandComponent implements OnInit {
|
|
@Input() runScriptContext: any = null;
|
|
@Input() clientState: string = 'off';
|
|
@Input() clientData: any[] = [];
|
|
@Input() buttonType: 'icon' | 'text' | 'menu-item' = 'icon';
|
|
@Input() buttonText: string = 'Ejecutar Comandos';
|
|
@Input() icon: string = 'terminal';
|
|
@Input() disabled: boolean = false;
|
|
baseUrl: string;
|
|
loading: boolean = true;
|
|
|
|
arrayCommands: any[] = [
|
|
{ translationKey: 'executeCommands.powerOn', slug: 'power-on', disabled: false },
|
|
{ translationKey: 'executeCommands.powerOff', slug: 'power-off', disabled: false },
|
|
{ translationKey: 'executeCommands.reboot', slug: 'reboot', disabled: false },
|
|
{ translationKey: 'executeCommands.login', slug: 'login', disabled: true },
|
|
{ translationKey: 'executeCommands.createImage', slug: 'create-image', disabled: false },
|
|
{ translationKey: 'executeCommands.deployImage', slug: 'deploy-image', disabled: false },
|
|
{ translationKey: 'executeCommands.deleteImageCache', slug: 'remove-cache-image', disabled: false },
|
|
{ translationKey: 'executeCommands.partition', slug: 'partition', disabled: false },
|
|
{ translationKey: 'executeCommands.softwareInventory', slug: 'software-inventory', disabled: false },
|
|
{ translationKey: 'executeCommands.hardwareInventory', slug: 'hardware-inventory', disabled: false },
|
|
{ translationKey: 'executeCommands.runScript', slug: 'run-script', disabled: false },
|
|
];
|
|
|
|
client: any = {};
|
|
|
|
constructor(
|
|
private http: HttpClient,
|
|
private router: Router,
|
|
private configService: ConfigService,
|
|
private toastService: ToastrService,
|
|
public auth: AuthService,
|
|
private dialog: MatDialog,
|
|
) {
|
|
this.baseUrl = this.configService.apiUrl;
|
|
}
|
|
|
|
ngOnInit(): void {
|
|
this.clientData = this.clientData || [];
|
|
const allowed = this.getAllowedCommandsByRole();
|
|
this.arrayCommands = this.arrayCommands.filter(c => allowed.includes(c.slug));
|
|
|
|
this.updateCommandStates();
|
|
}
|
|
|
|
ngOnChanges(): void {
|
|
this.updateCommandStates();
|
|
}
|
|
|
|
private getAllowedCommandsByRole(): string[] {
|
|
const role = this.auth.userCategory;
|
|
|
|
const permissions: Record<string, string[]> = {
|
|
'super-admin': ['*'],
|
|
'ou-admin': ['*'],
|
|
'ou-operator': [
|
|
'power-on',
|
|
'power-off',
|
|
'reboot',
|
|
'login',
|
|
'deploy-image',
|
|
'software-inventory',
|
|
'hardware-inventory',
|
|
'remove-cache-image',
|
|
'partition'
|
|
],
|
|
'ou-minimal': [
|
|
'power-on',
|
|
'power-off'
|
|
]
|
|
};
|
|
|
|
const allowed = permissions[role] || [];
|
|
return allowed.includes('*') ? this.arrayCommands.map(c => c.slug) : allowed;
|
|
}
|
|
|
|
|
|
private updateCommandStates(): void {
|
|
let states: string[] = [];
|
|
|
|
if (this.clientData.length > 0) {
|
|
states = this.clientData.map(client => client.status);
|
|
} else if (this.clientState) {
|
|
states = [this.clientState];
|
|
}
|
|
|
|
const allOffOrDisconnected = states.every(state => state === 'off' || state === 'disconnected');
|
|
const allSameState = states.every(state => state === states[0]);
|
|
const multipleClients = this.clientData.length > 1;
|
|
|
|
this.arrayCommands = this.arrayCommands.map(command => {
|
|
if (allOffOrDisconnected) {
|
|
command.disabled = command.slug !== 'power-on' && command.slug !== 'create-image';
|
|
} else if (allSameState) {
|
|
if (states[0] === 'off' || states[0] === 'disconnected') {
|
|
command.disabled = !['power-on', 'create-image'].includes(command.slug);
|
|
} else {
|
|
command.disabled = !['power-off', 'reboot', 'login', 'create-image', 'deploy-image', 'remove-cache-image', 'partition', 'run-script', 'software-inventory', 'hardware-inventory'].includes(command.slug);
|
|
}
|
|
} else {
|
|
if (command.slug === 'software-inventory') {
|
|
command.disabled = multipleClients;
|
|
} else if (
|
|
['power-on', 'power-off', 'reboot', 'login', 'deploy-image', 'partition', 'remove-cache-image', 'run-script', 'create-image'].includes(command.slug)
|
|
) {
|
|
command.disabled = false;
|
|
} else {
|
|
command.disabled = true;
|
|
}
|
|
}
|
|
return command;
|
|
});
|
|
}
|
|
|
|
onCommandSelect(action: any): void {
|
|
if (action === 'partition') {
|
|
this.openPartitionAssistant();
|
|
}
|
|
|
|
if (action === 'create-image') {
|
|
this.openCreateImageAssistant();
|
|
}
|
|
|
|
if (action === 'deploy-image') {
|
|
this.openDeployImageAssistant();
|
|
}
|
|
|
|
if (action === 'run-script') {
|
|
this.openRunScriptAssistant();
|
|
}
|
|
|
|
if (action === 'login') {
|
|
this.loginClient();
|
|
}
|
|
|
|
if (action === 'reboot') {
|
|
this.rebootClient();
|
|
}
|
|
|
|
if (action === 'power-off') {
|
|
this.powerOffClient();
|
|
}
|
|
|
|
if (action === 'power-on') {
|
|
this.powerOnClient();
|
|
}
|
|
|
|
if (action === 'remove-cache-image') {
|
|
this.removeImageCache();
|
|
}
|
|
|
|
if (action === 'hardware-inventory') {
|
|
this.hardwareInventory();
|
|
}
|
|
|
|
if (action === 'software-inventory') {
|
|
this.softwareInventory();
|
|
}
|
|
}
|
|
|
|
rebootClient(): void {
|
|
this.http.post(`${this.baseUrl}/clients/server/reboot`, {
|
|
clients: this.clientData.map((client: any) => client['@id'])
|
|
}).subscribe(
|
|
response => {
|
|
this.toastService.success('Cliente actualizado correctamente');
|
|
},
|
|
error => {
|
|
this.toastService.error(error.error['hydra:description'] || 'Error de conexión con el cliente');
|
|
}
|
|
);
|
|
}
|
|
|
|
loginClient(): void {
|
|
const clientDataToSend = this.clientData.map(client => ({
|
|
name: client.name,
|
|
mac: client.mac,
|
|
uuid: '/clients/' + client.uuid,
|
|
status: client.status,
|
|
partitions: client.partitions,
|
|
firmwareType: client.firmwareType,
|
|
ip: client.ip
|
|
}));
|
|
|
|
const dialogRef = this.dialog.open(BootSoPartitionComponent, {
|
|
width: '70vw',
|
|
height: 'auto',
|
|
data: { clients: clientDataToSend }
|
|
});
|
|
|
|
dialogRef.afterClosed().subscribe(result => {
|
|
if (result) {
|
|
this.toastService.success('Petición de arranque de SO enviada correctamente');
|
|
}
|
|
});
|
|
}
|
|
|
|
removeImageCache(): void {
|
|
const clientDataToSend = this.clientData.map(client => ({
|
|
name: client.name,
|
|
mac: client.mac,
|
|
uuid: '/clients/' + client.uuid,
|
|
status: client.status,
|
|
partitions: client.partitions,
|
|
firmwareType: client.firmwareType,
|
|
ip: client.ip
|
|
}));
|
|
|
|
const dialogRef = this.dialog.open(RemoveCacheImageComponent, {
|
|
width: '70vw',
|
|
height: 'auto',
|
|
data: { clients: clientDataToSend }
|
|
});
|
|
|
|
dialogRef.afterClosed().subscribe(result => {
|
|
if (result) {
|
|
this.toastService.success('Petición de borrado de caché de imagen enviada correctamente');
|
|
}
|
|
});
|
|
}
|
|
|
|
hardwareInventory(): void {
|
|
if (this.clientData.length === 0) {
|
|
this.toastService.error('No hay clientes seleccionados');
|
|
return;
|
|
}
|
|
|
|
const clientId = this.clientData[0].uuid;
|
|
|
|
this.http.post(`${this.baseUrl}/clients/server/${clientId}/hardware-inventory`, {
|
|
clients: this.clientData.map((client: any) => client['@id'])
|
|
}).subscribe(
|
|
response => {
|
|
this.toastService.success('Inventario de hardware actualizado correctamente');
|
|
},
|
|
error => {
|
|
this.toastService.error(error.error['hydra:description'] || 'Error de conexión con el cliente');
|
|
}
|
|
);
|
|
}
|
|
|
|
softwareInventory(): void {
|
|
if (this.clientData.length === 0) {
|
|
this.toastService.error('No hay clientes seleccionados');
|
|
return;
|
|
}
|
|
|
|
const clientDataToSend = {
|
|
clientId: this.clientData[0].uuid,
|
|
name: this.clientData[0].name,
|
|
mac: this.clientData[0].mac,
|
|
status: this.clientData[0].status,
|
|
partitions: this.clientData[0].partitions,
|
|
firmwareType: this.clientData[0].firmwareType,
|
|
ip: this.clientData[0].ip
|
|
}
|
|
|
|
const clientId = this.clientData[0].uuid;
|
|
|
|
const dialogRef = this.dialog.open(SoftwareProfilePartitionComponent, {
|
|
width: '70vw',
|
|
height: 'auto',
|
|
data: { client: clientDataToSend }
|
|
});
|
|
|
|
dialogRef.afterClosed().subscribe(result => {
|
|
|
|
});
|
|
}
|
|
|
|
powerOnClient(): void {
|
|
this.http.post(`${this.baseUrl}/image-repositories/wol`, {
|
|
clients: this.clientData.map((client: any) => client['@id'])
|
|
}).subscribe(
|
|
response => {
|
|
this.toastService.success('Petición de encendido enviada correctamente');
|
|
},
|
|
error => {
|
|
this.toastService.error(error.error['hydra:description'] || 'Error de conexión con el cliente');
|
|
}
|
|
);
|
|
}
|
|
|
|
powerOffClient(): void {
|
|
this.http.post(`${this.baseUrl}/clients/server/power-off`, {
|
|
clients: this.clientData.map((client: any) => client['@id'])
|
|
}).subscribe(
|
|
response => {
|
|
this.toastService.success('Petición de apagado enviada correctamente');
|
|
},
|
|
error => {
|
|
this.toastService.error(error.error['hydra:description'] || 'Error de conexión con el cliente');
|
|
}
|
|
);
|
|
}
|
|
|
|
openPartitionAssistant(): void {
|
|
const clientDataToSend = this.clientData.map(client => ({
|
|
name: client.name,
|
|
mac: client.mac,
|
|
uuid: '/clients/' + client.uuid,
|
|
status: client.status,
|
|
partitions: client.partitions,
|
|
firmwareType: client.firmwareType,
|
|
ip: client.ip
|
|
}));
|
|
|
|
this.router.navigate(['/clients/partition-assistant'], {
|
|
queryParams: {
|
|
clientData: JSON.stringify(clientDataToSend),
|
|
runScriptContext: JSON.stringify(this.runScriptContext)
|
|
}
|
|
});
|
|
}
|
|
|
|
openCreateImageAssistant(): void {
|
|
this.router.navigate([`/clients/${this.clientData[0].uuid}/create-image`]).then(r => {
|
|
console.log('navigated', r);
|
|
});
|
|
}
|
|
|
|
openDeployImageAssistant(): void {
|
|
const clientDataToSend = this.clientData.map(client => ({
|
|
name: client.name,
|
|
mac: client.mac,
|
|
uuid: '/clients/' + client.uuid,
|
|
status: client.status,
|
|
partitions: client.partitions,
|
|
ip: client.ip
|
|
}));
|
|
|
|
this.router.navigate(['/clients/deploy-image'], {
|
|
queryParams: {
|
|
clientData: JSON.stringify(clientDataToSend),
|
|
runScriptContext: JSON.stringify(this.runScriptContext)
|
|
}
|
|
});
|
|
}
|
|
|
|
openRunScriptAssistant(): void {
|
|
const clientDataToSend = this.clientData.map(client => ({
|
|
name: client.name,
|
|
mac: client.mac,
|
|
uuid: '/clients/' + client.uuid,
|
|
status: client.status,
|
|
partitions: client.partitions,
|
|
ip: client.ip
|
|
}));
|
|
|
|
this.router.navigate(['/clients/run-script'], {
|
|
queryParams: {
|
|
clientData: JSON.stringify(clientDataToSend),
|
|
runScriptContext: JSON.stringify(this.runScriptContext)
|
|
}
|
|
})
|
|
}
|
|
}
|