discovery

This commit is contained in:
insanity 2018-05-29 21:18:43 +09:00
parent c4bfb21e9c
commit 3c51019271
24 changed files with 370 additions and 183 deletions

View File

@ -0,0 +1,5 @@
<div *ngIf="pending">
<p-progressBar mode="indeterminate"></p-progressBar>
<p-blockUI [target]="target" [blocked]="pending">
</p-blockUI>
</div>

View File

@ -0,0 +1,18 @@
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'of-block-progressbar',
templateUrl: './block-progressbar.component.html',
})
export class BlockProgressbarComponent implements OnInit {
@Input() target: any;
@Input() pending: boolean;
constructor(
) {
}
ngOnInit() {
}
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PrimeNGModules } from '@overflow/commons/prime-ng/prime-ng.module';
import { BlockProgressbarComponent } from './block-progressbar.component';
@NgModule({
imports: [
CommonModule,
PrimeNGModules
],
declarations: [
BlockProgressbarComponent
],
exports: [
BlockProgressbarComponent
]
})
export class BlockProgressbarModule { }

View File

@ -0,0 +1 @@
<p-messages [(value)]="msgs" [closable]="closable"></p-messages>

View File

@ -0,0 +1,34 @@
import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
import { Message } from 'primeng/primeng';
@Component({
selector: 'of-message',
templateUrl: './message.component.html',
})
export class MessageComponent implements OnInit, OnChanges {
@Input() error: any;
@Input() closeAfter: number;
@Input() closable: boolean;
msgs: Message[] = [];
constructor(
) {
}
ngOnInit() {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['error'].currentValue) {
const detail = ' (' + this.error.response.code + ')';
this.msgs = [];
this.msgs.push({ severity: 'error', summary: 'Sorry. An Error has occurred.', detail: detail });
if (this.closeAfter) {
setTimeout(() => {
this.msgs = [];
}, this.closeAfter * 1000);
}
}
}
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PrimeNGModules } from '@overflow/commons/prime-ng/prime-ng.module';
import { MessageComponent } from './message.component';
@NgModule({
imports: [
CommonModule,
PrimeNGModules
],
declarations: [
MessageComponent
],
exports: [
MessageComponent
]
})
export class MessageModule { }

View File

@ -1,6 +1,7 @@
<div class="ui-g">
<div class="ui-g-12 ui-md-3">
<of-discovery-search-config (discoverySearchStartClick)="onDiscoveryStart()"></of-discovery-search-config>
<of-discovery-search-config *ngIf="selectedProbe else block" [probeHost]="selectedProbe" (requestDiscovery)="requestDiscovery.emit($event)"></of-discovery-search-config>
<ng-template #block>나는 커서 block ui가 될거얌</ng-template>
</div>
<div class="ui-g-12 ui-md-9">
<div *ngIf="selectedProbe">

View File

@ -1,7 +1,8 @@
import {
Component, Input,
Component, Input, Output, EventEmitter,
} from '@angular/core';
import { Probe, ProbeHost } from '@overflow/commons-typescript/model/probe';
import { DiscoverZone } from '@overflow/commons-typescript/model/discovery';
@Component({
selector: 'of-discovery',
@ -11,10 +12,10 @@ export class DiscoveryComponent {
private tabIdx: number;
@Input() selectedProbe: ProbeHost;
@Output() requestDiscovery = new EventEmitter<DiscoverZone>();
constructor(
) {
}
}

View File

@ -46,7 +46,7 @@ export class IpInputComponent implements OnInit, AfterContentInit {
(this.second !== '' && this.second !== undefined) &&
(this.third !== '' && this.third !== undefined) &&
(this.fourth !== '' && this.fourth !== undefined) ) {
event.target.data = this.first + '.' + this.second + '.' + this.third + '.' + this.fourth;
event.value = this.first + '.' + this.second + '.' + this.third + '.' + this.fourth;
this.inputIp.emit(event);
} else {
return;

View File

@ -1,120 +1,71 @@
<div class="ui-g">
<!--<form [formGroup]="discoveryFormGroup" (ngSubmit)="discoveryStartClick(discoveryFormGroup)" >-->
<!--<div class="ui-g-12">-->
<!--<label>Probe</label>-->
<!--</div>-->
<!--<div class="ui-g-12 ui-bottom-space-20">-->
<!--<of-probe-selector-->
<!--[preProbe]="probe"-->
<!--(probeSelected)="onProbeSelect($event)"-->
<!--&gt;</of-probe-selector>-->
<!--</div>-->
<div class="ui-g-12">
<label>IP Version</label>
</div>
<div class="ui-g-12 ui-bottom-space-20">
<div class="ui-g-6 ui-g-nopad">
<p-radioButton
name="group1"
value="0"
label="IPv4"
[(ngModel)]="ipVesion"
inputId="opt1"
></p-radioButton>
</div>
<div class="ui-g-6 ui-g-nopad">
<p-radioButton
name="group1"
value="1"
label="IPv6"
[(ngModel)]="ipVesion"
inputId="opt2"
></p-radioButton>
</div>
</div>
<div class="ui-g-12">
<label>IP Adress</label>
<input type="hidden" >
</div>
<div class="ui-g-12">
<of-ip-input
[hostIp]="startHostIp"
(inputIp)="onInputIP($event, 0)"
[title]="'Start'"
></of-ip-input>
</div>
<div class="ui-g-12">
<of-ip-input
[hostIp]="endHostIp"
(inputIp)="onInputIP($event, 1)"
[title]="'End'"></of-ip-input>
</div>
<div class="ui-g-12 ui-bottom-space-20">
<of-ip-input
[hostIp]="excludeHostIp"
(inputIp)="onInputIP($event, 2)"
[title]="'Exclude'"></of-ip-input>
</div>
<div class="ui-g-12">
<label>Port type</label>
</div>
<div class="ui-g-12 ui-bottom-space-20">
<div class="ui-g-6 ui-g-nopad">
<p-checkbox
name="group2"
value="0"
label="TCP"
[(ngModel)]="selectPortTypes"
inputId="tcp"></p-checkbox>
</div>
<div class="ui-g-6 ui-g-nopad">
<p-checkbox
name="group2"
value="1"
label="UDP"
[(ngModel)]="selectPortTypes"
inputId="udp"></p-checkbox>
</div>
</div>
<div class="ui-g-12">
<label>Port</label>
</div>
<div class="ui-g-12 ui-g-nopad ui-bottom-space-20">
<div class="ui-g-4">
<p-inputMask
slotChar=" "
mask="9999"
[(ngModel)]="startPort"
placeholder="Start"
[autoClear]="false"></p-inputMask>
</div>
<div class="ui-g-4">
<p-inputMask
mask="9999"
[(ngModel)]="endPort"
placeholder="End"
[autoClear]="false"></p-inputMask>
</div>
<div class="ui-g-4">
<p-inputMask
mask="9999"
[(ngModel)]="excludePort"
placeholder="Exclude"
[autoClear]="false"></p-inputMask>
</div>
</div>
<div class="ui-g-12">
<label>Service</label>
</div>
<div class="ui-g-12 ui-g-nopad">
<of-service-selector [(includeServices)]="includeServices"></of-service-selector>
</div>
<div class="ui-g-12" dir="rtl">
<button type="submit" label="Discovery Start" pButton class="ui-button-width-fit" (click)="discoveryStartClick()" ></button>
</div>
<!--</form>-->
<label>IP Version</label>
</div>
<div class="ui-g-12 ui-bottom-space-20">
<div class="ui-g-6 ui-g-nopad">
<p-radioButton name="group1" value="ipv4" label="IPv4" [(ngModel)]="ipVer" inputId="opt1"></p-radioButton>
</div>
<div class="ui-g-6 ui-g-nopad">
<p-radioButton [disabled]="true" name="group1" value="ipv6" label="IPv6" [(ngModel)]="ipVer"></p-radioButton>
</div>
</div>
<div class="ui-g-12">
<div>
<p-checkbox value="host" label="Host" [(ngModel)]="hostChecked" binary="true" [disabled]="true"></p-checkbox>
</div>
<label>Range</label>
</div>
<div class="ui-g-12">
<of-ip-input [hostIp]="startIP" (inputIp)="onInputIP($event, 0)" [title]="'From'"></of-ip-input>
</div>
<div class="ui-g-12">
<of-ip-input [hostIp]="endIP" (inputIp)="onInputIP($event, 1)" [title]="'To'"></of-ip-input>
</div>
<div *ngIf="ipErrMsg" class="ui-message ui-messages-error ui-corner-all">
{{ipErrMsg}}
</div>
<div class="ui-g-12">
<div>
<p-checkbox #portCheckbox value="port" label="Port" [(ngModel)]="portChecked" binary="true" (onChange)="onPortCheckChange(serviceCheckbox, $event)"></p-checkbox>
</div>
</div>
<div class="ui-g-12 ui-bottom-space-20">
<div class="ui-g-6 ui-g-nopad">
TCP &nbsp;
<p-inputSwitch [(ngModel)]="tcpChecked" [disabled]="!portChecked" binary="true"></p-inputSwitch>
</div>
<div class="ui-g-6 ui-g-nopad">
UDP &nbsp;
<p-inputSwitch [(ngModel)]="udpChecked" [disabled]="!portChecked" binary="true"></p-inputSwitch>
</div>
</div>
<div class="ui-g-12">
<label>Range</label>
</div>
<div class="ui-g-12 ui-g-nopad ui-bottom-space-20">
<div class="ui-g-4">
<input #startPort id="float-input" type="number" maxlength="5" min="1" max="65535" pInputText [disabled]="!portChecked" value="1"
(keyup)="onInputPort(startPort.value, 0)">
</div>
<div class="ui-g-4">
<input #endPort id="float-input" type="number" maxlength="5" min="1" max="65535" pInputText [disabled]="!portChecked" value="1024"
(keyup)="onInputPort(endPort.value, 1)">
</div>
</div>
<div *ngIf="portErrMsg" class="ui-message ui-messages-error ui-corner-all">
{{portErrMsg}}
</div>
<div class="ui-g-12">
<div>
<p-checkbox #serviceCheckbox value="service" label="Service" [(ngModel)]="serviceChecked" (onChange)="onServiceCheckChange(portCheckbox, $event)"
binary="true"></p-checkbox>
</div>
</div>
<div class="ui-g-12 ui-g-nopad">
<of-service-selector [disabled]="!serviceChecked" [(includeServices)]="includeServices"></of-service-selector>
</div>
<div class="ui-g-12" dir="rtl">
<button type="submit" [disabled]="!validation" label="Discovery Start" pButton class="ui-button-width-fit" (click)="onRequestDiscovery()"></button>
</div>

View File

@ -1,75 +1,188 @@
import {
AfterContentInit, Component, EventEmitter, Input,
OnInit, Output
Component, EventEmitter, Input,
Output, OnChanges, SimpleChanges
} from '@angular/core';
import {
FormBuilder,
FormGroup, Validators
} from '@angular/forms';
import { ProbeHost } from '@overflow/commons-typescript/model/probe';
import * as CIDR from 'ip-cidr';
import * as ipRangeCheck from 'ip-range-check';
import { DiscoverPort, DiscoverService, DiscoverZone } from '@overflow/commons-typescript/model/discovery';
import { Checkbox } from 'primeng/primeng';
@Component({
selector: 'of-discovery-search-config',
templateUrl: './search-config.component.html',
})
export class SearchConfigComponent implements OnInit, AfterContentInit {
export class SearchConfigComponent implements OnChanges {
@Output() discoverySearchStartClick = new EventEmitter();
@Output() selectedProbe = new EventEmitter();
includeServices = [];
discoveryFormGroup: FormGroup;
ipVesion: number;
@Input() probeHost: ProbeHost;
@Output() requestDiscovery = new EventEmitter<DiscoverZone>();
ipVer: string;
startIP: string;
endIP: string;
excludeIP: string;
startPort: string;
endPort: string;
excludePort: string;
includeServices = [];
startHostIp: string;
endHostIp: string;
excludeHostIp: string;
hostChecked = true;
portChecked = true;
serviceChecked = true;
tcpChecked = true;
udpChecked = true;
selectPortTypes: string[] = ['0'];
validation = false;
ipErrMsg: string;
portErrMsg: string;
constructor(
private formBuilder: FormBuilder,
) {
}
ngOnInit() {
this.ipVesion = 0;
this.initForm();
// this.hostIp = '192.168.1.10';
ngOnChanges(changes: SimpleChanges): void {
this.initByProbe();
this.validation = true;
}
ngAfterContentInit() {
initByProbe() {
const cidr = new CIDR(this.probeHost.probe.cidr);
if (!cidr.isValid()) {
return;
}
this.ipVer = 'ipv4';
this.startIP = cidr.addressStart.address;
this.endIP = cidr.addressEnd.address;
this.startPort = '1';
this.endPort = '1024';
// TODO: Initialize services
}
initForm() {
// this.discoveryFormGroup = this.formBuilder.group({
// probeSelect: [null],
// IPType: [null],
// startIP:[null],
// endIP: [null],
// exIP: [null],
// portType: [null],
// startPort: [null],
// endPort: [null],
// exPort: [null],
// services: [null]
// });
onRequestDiscovery() {
let discoverPort: DiscoverPort = null;
let discoverService: DiscoverService = null;
if (this.serviceChecked) {
const services = new Array();
for (const service of this.includeServices) {
services.push(service.description);
}
discoverService = {
includeServices: services,
};
}
if (this.portChecked) {
discoverPort = {
firstScanRange: Number(this.startPort),
lastScanRange: Number(this.endPort),
includeTCP: this.tcpChecked,
includeUDP: this.udpChecked,
excludePorts: null,
discoverService: discoverService
};
}
const discoverZone: DiscoverZone = {
discoverHost: {
firstScanRangev4: this.startIP,
lastScanRangev4: this.endIP,
discoverPort: discoverPort
},
};
this.requestDiscovery.emit(discoverZone);
}
discoveryStartClick() {
this.discoverySearchStartClick.emit();
onPortCheckChange(serviceCheckbox: Checkbox, checked: boolean) {
if (!checked) {
serviceCheckbox.checked = false;
this.serviceChecked = false;
}
}
onInputIP(event, idx) {
console.log(idx);
console.log(event.target.data);
onServiceCheckChange(portCheckbox: Checkbox, checked: boolean) {
if (checked) {
portCheckbox.checked = true;
this.portChecked = true;
}
}
onInputIP(e, idx: number) {
const value = e.value;
if (idx === 0) {
this.startIP = value;
} else {
this.endIP = value;
}
this.ipErrMsg = this.validateIP(value, idx);
if (this.ipErrMsg) {
this.validation = false;
} else {
this.validation = true;
}
}
validateIP(value: string, idx): string {
if (!this.isValidIPregex(value)) {
return 'Not valid IP format.';
}
if (!ipRangeCheck(value, this.probeHost.probe.cidr)) {
return 'Not valid IP range.';
}
const ipArray = [this.startIP, this.endIP];
const sortedIpArray = this.sortIP([this.startIP, this.endIP]);
if (ipArray[0] !== sortedIpArray[0]) {
return 'Not valiad range';
}
return null;
}
isValidIPregex(ip: string): boolean {
if (this.ipVer === 'ipv4') {
return /^(?=\d+\.\d+\.\d+\.\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.?){4}$/.test(ip);
}
return false;
}
sortIP(ipAddressArray) {
return ipAddressArray.sort(function (a, b) {
a = a.split('.');
b = b.split('.');
for (let i = 0; i < a.length; i++) {
// tslint:disable-next-line:radix
if ((a[i] = parseInt(a[i])) < (b[i] = parseInt(b[i]))) {
return -1;
} else if (a[i] > b[i]) {
return 1;
}
}
return 0;
});
}
onInputPort(portNum: string, idx: number) {
if (idx === 0) {
this.startPort = portNum;
} else {
this.endPort = portNum;
}
this.portErrMsg = this.validatePort(portNum);
if (this.portErrMsg) {
this.validation = false;
} else {
this.validation = true;
}
}
validatePort(portNum): string {
if (Number(this.startPort) > Number(this.endPort)) {
return 'Not valid port range.';
}
if (Number(portNum) <= 0 || Number(portNum) > 65535) {
return 'Not valid port range.';
}
return null;
}
}

View File

@ -23,6 +23,7 @@ export class ServiceSelectorComponent implements OnInit, AfterContentInit, OnDes
crawlers: MetaCrawler[];
@Output() crawlerSelected = new EventEmitter<MetaCrawler>();
@Input() includeServices;
@Input() disabled: boolean;
constructor(
private listStore: Store<any>,

View File

@ -1,2 +1,2 @@
<of-probe-selector-container [probeHostID]="probeHostID" (select)="onProbeSelect($event)"></of-probe-selector-container>
<of-discovery [selectedProbe]="selectedProbe"></of-discovery>
<of-discovery [selectedProbe]="selectedProbe" (requestDiscovery)="onRequestDiscovery($event)"></of-discovery>

View File

@ -3,6 +3,7 @@ import {
Input,
} from '@angular/core';
import { ProbeHost } from '@overflow/commons-typescript/model/probe';
import { DiscoverZone } from '@overflow/commons-typescript/model/discovery';
@Component({
selector: 'of-discovery-container',
@ -21,4 +22,9 @@ export class DiscoveryContainerComponent {
this.selectedProbe = probe;
}
onRequestDiscovery(dz: DiscoverZone) {
console.log(dz);
// this.discoverStore.dispatch(new DiscoverStore.DiscoverZone(
// { probeID: this.selectedProbe.probeKey, discoverZone: discoverZone }));
}
}

View File

@ -1,7 +1,7 @@
<h1>Probes</h1>
<p-blockUI [target]="content" [blocked]="pending">
<i class="fa ui-icon-lock block-icon"></i>
</p-blockUI>
<of-message [error]="error" [closable]="false"></of-message>
<of-block-progressbar [target]="content" [pending]="pending"></of-block-progressbar>
<p-panel #content [showHeader]="false" class="block-panel">
<p-table [value]="probeHosts" selectionMode="single" (onRowSelect)="onProbeSelect($event)" [resizableColumns]="true">
<ng-template pTemplate="header">

View File

@ -7,8 +7,9 @@ import { ProbeHost, Probe } from '@overflow/commons-typescript/model/probe';
})
export class ProbeListComponent {
@Output() select = new EventEmitter<ProbeHost>();
@Input() pending;
@Input() pending: boolean;
@Input() probeHosts: ProbeHost[];
@Input() error: any;
constructor() {
}

View File

@ -1,4 +1,4 @@
<div *ngIf="!probeHostID">
<p-dropdown *ngIf="options.length > 0" [options]="options" [(ngModel)]="selected" optionLabel="displayName" placeholder="Select a Probe"
(onChange)="onSelect($event.value)"></p-dropdown>
(onChange)="onSelect()"></p-dropdown>
</div>

View File

@ -12,6 +12,7 @@ export class ProbeSelectorComponent implements OnChanges {
@Input() probeHostID: number;
options: Probe[];
selected: Probe;
constructor() {
}
@ -34,8 +35,8 @@ export class ProbeSelectorComponent implements OnChanges {
});
}
onSelect(probe: Probe) {
const optionselected = this.probeHosts.find(probeHost => probeHost.id === probe.id);
onSelect() {
const optionselected = this.probeHosts.find(probeHost => probeHost.probe.id === this.selected.id);
this.select.emit(optionselected);
}

View File

@ -1 +1 @@
<of-probe-list [pending]="pending$ | async" (select)="onSelect($event)" [probeHosts]="probeHosts$ | async"></of-probe-list>
<of-probe-list [pending]="pending$ | async" (select)="onSelect($event)" [probeHosts]="probeHosts$ | async" [error]="error$ | async"></of-probe-list>

View File

@ -26,6 +26,8 @@ export class ProbeListContainerComponent implements OnInit {
ngOnInit() {
this.probeHosts$ = this.store.pipe(select(ProbeListContainerSelector.selectAll));
this.pending$ = this.store.pipe(select(ProbeListContainerSelector.selectPending));
this.error$ = this.store.pipe(select(ProbeListContainerSelector.selectError));
this.store.select(AuthContainerSelector.selectDomainMember).subscribe(
(domainMember: DomainMember) => {
this.store.dispatch(new ProbeEntityStore.ReadAllByDomainID(domainMember.domain.id));

View File

@ -9,6 +9,8 @@ import { PrimeNGModules } from '../commons/prime-ng/prime-ng.module';
import { FormsModule } from '@angular/forms';
import { MetaModule } from '@overflow/meta/meta.module';
import { KeyValueModule } from '@overflow/commons/component/key-value/key-value.module';
import { BlockProgressbarModule } from '../commons/component/block-progressbar/block-progressbar.module';
import { MessageModule } from 'primeng/primeng';
@NgModule({
imports: [
@ -17,7 +19,9 @@ import { KeyValueModule } from '@overflow/commons/component/key-value/key-value.
ProbeStoreModule,
FormsModule,
KeyValueModule,
MetaModule
MetaModule,
BlockProgressbarModule,
MessageModule
],
declarations: [
CONTAINER_COMPONENTS,

17
package-lock.json generated
View File

@ -5045,19 +5045,26 @@
}
},
"ip-cidr": {
"version": "1.1.2",
"resolved": "https://nexus.loafle.net/repository/npm-all/ip-cidr/-/ip-cidr-1.1.2.tgz",
"integrity": "sha512-JYrr9jiToVM4R3krXZdC47QTpIYuTKutlZWLhub1sny++WUeIS/XLnQZlWQhfy8DHnKPbxJsmFPlmBPJgbP/ww==",
"version": "2.0.0",
"resolved": "https://nexus.loafle.net/repository/npm-all/ip-cidr/-/ip-cidr-2.0.0.tgz",
"integrity": "sha512-RG2+JvxGxdrZ4vJkn0pk2wpOhywTNxxvcLW2/1wqFTMpuk2fzTagZbU33ztlgF0pwRkSmSMo0kaNCCSazJr7Rw==",
"requires": {
"ip-address": "5.8.9",
"jsbn": "0.1.1"
}
},
"ip-range-check": {
"version": "0.0.2",
"resolved": "https://nexus.loafle.net/repository/npm-all/ip-range-check/-/ip-range-check-0.0.2.tgz",
"integrity": "sha1-YFyFloeqTxhGORjUYZDYs2maKTw=",
"requires": {
"ipaddr.js": "1.6.0"
}
},
"ipaddr.js": {
"version": "1.6.0",
"resolved": "https://nexus.loafle.net/repository/npm-all/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
"integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=",
"dev": true
"integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs="
},
"is-accessor-descriptor": {
"version": "0.1.6",

View File

@ -42,8 +42,9 @@
"angular-l10n": "^5.0.0",
"angularx-qrcode": "^1.1.7",
"chart.js": "^2.7.2",
"ip-cidr": "^2.0.0",
"core-js": "^2.5.4",
"ip-cidr": "^1.1.2",
"ip-range-check": "0.0.2",
"jquery": "^3.3.1",
"ngx-cookie-service": "^1.0.10",
"openssl": "^1.1.0",

View File

@ -415,3 +415,7 @@ body .ui-progressbar .ui-progressbar-value {
.ui-panel {
border: none !important;
}
.ui-blockui.ui-widget-overlay {
opacity: 0;
}