import { AfterContentInit, Component, Input, EventEmitter, Output, SimpleChanges, OnInit, OnChanges, } from '@angular/core'; import { catchError, exhaustMap, map, tap, take } from 'rxjs/operators'; import { Subscription, Observable, of } from 'rxjs'; import { DiscoverZone, Zone, Host, Port, Service } from '@overflow/commons-typescript/model/discovery'; import { TreeNode, Message, Tree } from 'primeng/primeng'; import { ProbeHost } from '@overflow/commons-typescript/model/probe'; import { Anim } from './animation'; import { DiscoveryNotify } from '../subscriber/discovery.subscriber'; import { InfraHost, InfraService } from '@overflow/commons-typescript/model/infra'; import { TargetService } from '@overflow/target/service/target.service'; import { Target } from '@overflow/commons-typescript/model/target'; @Component({ selector: 'of-discovery-result', templateUrl: './search-result.component.html', animations: Anim, }) export class SearchResultComponent implements OnInit, OnChanges { @Input() probeHost: ProbeHost; @Input() filterWord: string; @Input() filterServices: Map; @Input() finished: boolean; discoverySubscription: Subscription; zoneNode: TreeNode[] = []; hostNode: TreeNode[] = []; selectedItems = []; msgs: Message[]; error$: Observable; targetSaveSucceed: boolean; displayTargetDone: boolean; constructor( private targetService: TargetService ) { this.targetSaveSucceed = false; this.displayTargetDone = false; } ngOnInit(): void { this.zoneNode.push({ label: this.probeHost.probe.cidr, type: 'ZONE', data: { }, children: this.hostNode, expanded: true }); } ngOnChanges(changes: SimpleChanges): void { if (changes['finished'] && changes['finished'].currentValue === true) { this.msgs = []; this.msgs.push({ severity: 'success', summary: 'Discovery가 완료되었습니다. 모니터링 대상(들)을 선택 후 저장하세요.', }); } } addHost(host: Host) { // this.targetService.findExistHostTarget(this.probeHost.probe.id, host.ipv4) // .pipe( // map((target: Target) => { // }), // catchError(error => { // this.error$ = of(error); // return of(); // }), // ).subscribe(); const idx = this.findHostIndex(host); this.hostNode.splice(idx, 0, { type: 'HOST', label: host.ipv4, data: { exist: false, ip: this.convertIPtoNumber(host.ipv4), ipv6: host.ipv6, mac: host.mac, openPorts: [], target: host }, expanded: true, children: [] }); } addService(service: Service) { const targetHostNode = this.findHostNodeByService(service); const idx = this.findServiceIndex(targetHostNode.children, service); targetHostNode.children.splice(idx, 0, { type: 'SERVICE', label: service.serviceName + ' (' + service.port.portNumber + ')', data: { name: service.serviceName, portType: service.port.portType, portNumber: service.port.portNumber, target: service }, }); } addPort(port: Port) { this.hostNode.forEach(node => { if (node.data.id === port.host.id) { node.data.openPorts.push(port); return; } }); } onTargetSelect(e, node: TreeNode) { const data = node.data.target; if (e.checked) { this.selectedItems.push(data); } else { const index = this.selectedItems.indexOf(data); this.selectedItems.splice(index, 1); } } findHostIndex(host: Host): number { let index = 0; this.hostNode.forEach(node => { if (node.data.ip < this.convertIPtoNumber(host.ipv4)) { index++; } }); return index; } findServiceIndex(serviceNodes: TreeNode[], service: Service) { let index = 0; serviceNodes.forEach(node => { // if (node.data.portNumber < service.port.portNumber) { // index++; // } if (node.data.name.toUpperCase().localeCompare(service.serviceName.toUpperCase()) === -1) { index++; } }); return index; } findHostNodeByService(service: Service) { let targetHost = null; this.hostNode.forEach((value, i) => { if (value.data.ip === this.convertIPtoNumber(service.port.host.ipv4)) { targetHost = value; return; } }); return targetHost; } convertIPtoNumber(ip: string) { return ip.split('.').map((octet, index, array) => { // tslint:disable-next-line:radix return parseInt(octet) * Math.pow(256, (array.length - index - 1)); }).reduce((prev, curr) => { return prev + curr; }); } checkHighlight(label: string, type: number) { let highlight = true; if (this.filterWord && (label.toUpperCase().indexOf(this.filterWord.toUpperCase()) < 0)) { highlight = false; } if (type === 1 && this.filterServices[label] === false) { highlight = false; } return highlight; } saveTargets() { const hosts: Host[] = []; const services: Service[] = []; this.selectedItems.forEach(value => { if (value.ipv4) { hosts.push(value); } else { services.push(value); } }); this.targetService.registDiscoveredTargets(this.probeHost.probe.id, hosts, services) .pipe( tap(() => { this.targetSaveSucceed = false; }), map((targets: Target[]) => { if (targets) { this.displayTargetDone = true; } }), catchError(error => { this.error$ = of(error); return of(); }), tap(() => { this.targetSaveSucceed = true; }), take(1), ).subscribe(); } }