import { Component, Input, Output, EventEmitter, ViewChild, OnInit } from '@angular/core'; import { NgForm } from '@angular/forms'; import { Configuration } from '../config'; import { ScanningResultService, SystemInfo, SystemInfoService } from '../../service/index'; import { ErrorHandler } from '../../error-handler/index'; import { toPromise } from '../../utils'; import { TranslateService } from '@ngx-translate/core'; import { ClairDetail } from '../../service/interface'; const ONE_HOUR_SECONDS: number = 3600; const ONE_DAY_SECONDS: number = 24 * ONE_HOUR_SECONDS; @Component({ selector: 'vulnerability-config', templateUrl: './vulnerability-config.component.html', styles: ['./vulnerability-config.component.scss', '../registry-config.component.scss'] }) export class VulnerabilityConfigComponent implements OnInit { _localTime: Date = new Date(); onSubmitting: boolean = false; config: Configuration; openState: boolean = false; @Output() configChange: EventEmitter = new EventEmitter(); @Input() get vulnerabilityConfig(): Configuration { return this.config; } set vulnerabilityConfig(cfg: Configuration) { this.config = cfg; if (this.config.scan_all_policy && this.config.scan_all_policy.value) { if (this.config.scan_all_policy.value.type === "daily") { if (!this.config.scan_all_policy.value.parameter) { this.config.scan_all_policy.value.parameter = { daily_time: 0 }; } } } this.configChange.emit(this.config); } @Input() showSubTitle: boolean = false; @Input() showScanningNamespaces: boolean = false; systemInfo: SystemInfo; get scanAvailable(): boolean { let dt: Date = new Date(); return !this.onSubmitting && (this.nextScanTime <= 0 || dt.getTime() > ((this.nextScanTime + 300) * 1000)); } get nextScanTimestamp(): Date { return this.nextScanTime > 0 ? this.convertToLocalTime(this.nextScanTime) : null; } get nextScanTime(): number { return this.systemInfo && this.systemInfo.next_scan_all ? this.systemInfo.next_scan_all : 0; } get updatedTimestamp(): Date { if (this.systemInfo && this.systemInfo.clair_vulnerability_status && this.systemInfo.clair_vulnerability_status.overall_last_update > 0) { return this.convertToLocalTime(this.systemInfo.clair_vulnerability_status.overall_last_update); } return null; } get namespaceTimestamps(): ClairDetail[] { if (this.systemInfo && this.systemInfo.clair_vulnerability_status && this.systemInfo.clair_vulnerability_status.details && this.systemInfo.clair_vulnerability_status.details.length > 0) { return this.systemInfo.clair_vulnerability_status.details; } return []; } // UTC time get dailyTime(): string { if (!(this.config && this.config.scan_all_policy && this.config.scan_all_policy.value && this.config.scan_all_policy.value.type === "daily")) { return "00:00"; } let timeOffset: number = 0; // seconds if (this.config.scan_all_policy.value.parameter) { let daily_time = this.config.scan_all_policy.value.parameter.daily_time; if (daily_time && typeof daily_time === "number") { timeOffset = +daily_time; } } // Convert to current time let timezoneOffset: number = this._localTime.getTimezoneOffset(); // Local time timeOffset = timeOffset - timezoneOffset * 60; if (timeOffset < 0) { timeOffset = timeOffset + ONE_DAY_SECONDS; } if (timeOffset >= ONE_DAY_SECONDS) { timeOffset -= ONE_DAY_SECONDS; } // To time string let hours: number = Math.floor(timeOffset / ONE_HOUR_SECONDS); let minutes: number = Math.floor((timeOffset - hours * ONE_HOUR_SECONDS) / 60); let timeStr: string = "" + hours; if (hours < 10) { timeStr = "0" + timeStr; } if (minutes < 10) { timeStr += ":0"; } else { timeStr += ":"; } timeStr += minutes; return timeStr; } set dailyTime(v: string) { if (!v || v === "") { return; } if (!(this.config && this.config.scan_all_policy && this.config.scan_all_policy.value && this.config.scan_all_policy.value.type === "daily")) { return; } // Double confirm inner parameter existing. if (!this.config.scan_all_policy.value.parameter) { this.config.scan_all_policy.value.parameter = { daily_time: 0 }; } let values: string[] = v.split(":"); if (!values || values.length !== 2) { return; } let hours: number = +values[0]; let minutes: number = +values[1]; // Convert to UTC time let timezoneOffset: number = this._localTime.getTimezoneOffset(); let utcTimes: number = hours * ONE_HOUR_SECONDS + minutes * 60; utcTimes += timezoneOffset * 60; if (utcTimes < 0) { utcTimes += ONE_DAY_SECONDS; } if (utcTimes >= ONE_DAY_SECONDS) { utcTimes -= ONE_DAY_SECONDS; } this.config.scan_all_policy.value.parameter.daily_time = utcTimes; } // Scanning type get scanningType(): string { if (this.config && this.config.scan_all_policy && this.config.scan_all_policy.value) { return this.config.scan_all_policy.value.type; } else { // default return "none"; } } set scanningType(v: string) { if (this.config && this.config.scan_all_policy && this.config.scan_all_policy.value) { let type: string = (v && v.trim() !== "") ? v : "none"; this.config.scan_all_policy.value.type = type; if (type !== "daily") { // No parameter if (this.config.scan_all_policy.value.parameter) { delete (this.config.scan_all_policy.value.parameter); } } else { // Has parameter if (!this.config.scan_all_policy.value.parameter) { this.config.scan_all_policy.value.parameter = { daily_time: 0 }; } } } } @ViewChild("systemConfigFrom") systemSettingsForm: NgForm; get editable(): boolean { return this.vulnerabilityConfig && this.vulnerabilityConfig.scan_all_policy && this.vulnerabilityConfig.scan_all_policy.editable; } get isValid(): boolean { return this.systemSettingsForm && this.systemSettingsForm.valid; } get showTimePicker(): boolean { return this.vulnerabilityConfig && this.vulnerabilityConfig.scan_all_policy && this.vulnerabilityConfig.scan_all_policy.value && this.vulnerabilityConfig.scan_all_policy.value.type === "daily"; } get isClairDBFullyReady(): boolean { return this.systemInfo && this.systemInfo.clair_vulnerability_status && this.systemInfo.clair_vulnerability_status.overall_last_update > 0; } constructor( private scanningService: ScanningResultService, private errorHandler: ErrorHandler, private translate: TranslateService, private systemInfoService: SystemInfoService ) { } ngOnInit(): void { this.getSystemInfo(); } convertToLocalTime(utcTime: number): Date { let dt: Date = new Date(); dt.setTime(utcTime * 1000); return dt; } scanNow(): void { if (this.onSubmitting) { return; // Aoid duplicated submitting } if (!this.scanAvailable) { return; // Aoid page hacking } this.onSubmitting = true; toPromise(this.scanningService.startScanningAll()) .then(() => { this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_SUCCESS").subscribe((res: string) => { this.errorHandler.info(res); }); // Update system info this.getSystemInfo().then(() => { this.onSubmitting = false; }).catch(() => { this.onSubmitting = false; }); }) .catch(error => { if (error && error.status && error.status === 412) { this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_FAIL", { error: '' + error }).subscribe((res: string) => { this.errorHandler.error(res); }); } else { this.errorHandler.error(error); } this.onSubmitting = false; }); } getSystemInfo(): Promise { return toPromise(this.systemInfoService.getSystemInfo()) .then((info: SystemInfo) => this.systemInfo = info) .catch(error => this.errorHandler.error(error)); } }