import { INodeDetailResolverService } from '../../app/services/nodedetailresolver' ; import { IMinemeldConfigService } from '../../app/services/config' ; import { IConfirmService } from '../../app/services/confirm' ; import { IMinemeldValidateService } from '../../app/services/validate' ; import { IMinemeldStatusService , IMinemeldStatusNode , IMinemeldStatus } from '../../app/services/status' ; import { IThrottled , IThrottleService } from '../../app/services/throttle' ; import { NodeDetailStatsController } from './nodedetail.stats.controller' ; declare var he ; declare var jsyaml ; class SyslogMinerStatsController extends NodeDetailStatsController { protected updateMetricsNames ( ) { this . metrics_names = Object . keys ( this . metrics ) ; angular . forEach ( Object . keys ( this . nodeState . statistics ) , ( key ) => { if ( this . metrics_names . indexOf ( key ) === - 1 ) { this . metrics_names . push ( key ) ; } } ) ; this . metrics_names = this . metrics_names . filter ( ( metric ) => { if ( metric . indexOf ( 'rule.' ) === 0 ) { return false ; } return true ; } ) ; } } class SyslogMinerRulesController { MinemeldConfigService : IMinemeldConfigService ; toastr : any ; DTOptionsBuilder : any ; DTColumnBuilder : any ; $scope : angular . IScope ; $compile : angular . ICompileService ; $modal : angular . ui . bootstrap . IModalService ; ConfirmService : IConfirmService ; MinemeldStatusService : IMinemeldStatusService ; $interval : angular . IIntervalService ; dtOptions : any ; dtColumns : any ; dtRules : any = { } ; changed : boolean = false ; cfd_rules_list : string ; rules_list : any [ ] ; nodename : string ; mmStatusListener : any ; mmThrottledUpdate : IThrottled ; ngInject constructor ( toastr , MinemeldConfigService , DTOptionsBuilder , DTColumnBuilder , $compile , $scope , $modal , MinemeldStatusService , $interval , ConfirmService , $rootScope , ThrottleService ) { this . MinemeldConfigService = MinemeldConfigService ; this . toastr = toastr ; this . DTColumnBuilder = DTColumnBuilder ; this . DTOptionsBuilder = DTOptionsBuilder ; this . $compile = $compile ; this . $scope = $scope ; this . $modal = $modal ; this . ConfirmService = ConfirmService ; this . MinemeldStatusService = MinemeldStatusService ; this . $interval = $interval ; this . nodename = $scope . $parent [ 'nodedetail' ] [ 'nodename' ] ; this . cfd_rules_list = this . nodename + '_rules' ; this . setupRulesTable ( ) ; this . mmThrottledUpdate = ThrottleService . throttle ( this . updateMinemeldStatus . bind ( this ) , 500 ) ; this . mmStatusListener = $rootScope . $on ( 'mm-status-changed' , this . mmThrottledUpdate ) ; this . $scope . $on ( '$destroy' , ( ) => { this . destroy ( ) ; } ) ; } reload ( ) { this . dtRules . reloadData ( ) ; } addRule ( ) { var mi ; mi = this . $modal . open ( { templateUrl : 'app/nodedetail/syslogminer.edit.modal.html' , controller : SyslogMinerEditRuleController , controllerAs : 'vm' , bindToController : true , backdrop : 'static' , animation : false , size : 'lg' , resolve : { title : ( ) => { return 'ADD RULE' ; } , rule : ( ) => { return undefined ; } , rule_names : ( ) => { return this . rules_list . map ( ( x ) => { return x . name . toUpperCase ( ) ; } ) ; } } } ) ; mi . result . then ( ( result ) => { this . rules_list . push ( result ) ; this . saveRulesList ( ) . catch ( ( error ) => { this . toastr . error ( 'ERROR ADDING RULE: ' + error . statusText ) ; this . dtRules . reloadData ( ) ; } ) ; } ) ; } editRule ( rulen ) { var mi ; mi = this . $modal . open ( { templateUrl : 'app/nodedetail/syslogminer.edit.modal.html' , controller : SyslogMinerEditRuleController , controllerAs : 'vm' , bindToController : true , backdrop : 'static' , animation : false , size : 'lg' , resolve : { title : ( ) => { return 'EDIT RULE' ; } , rule : ( ) => { return this . rules_list [ rulen ] ; } , rule_names : ( ) => { return this . rules_list . map ( ( x ) => { return x . name . toUpperCase ( ) ; } ) . filter ( ( x ) => { return x !== this . rules_list [ rulen ] . name . toUpperCase ( ) ; } ) ; } } } ) ; mi . result . then ( ( result ) => { var oldname = this . rules_list [ rulen ] . name ; var metric ; this . rules_list [ rulen ] = result ; this . saveRulesList ( ) . catch ( ( error ) => { this . toastr . error ( 'ERROR ADDING RULE: ' + error . statusText ) ; this . dtRules . reloadData ( ) ; } ) ; if ( oldname !== result . name ) { metric = name . replace ( /[^a-zA-Z0-9_-]/g , '_' ) ; angular . element ( '#' + metric ) . attr ( 'id' , metric ) ; this . updateMinemeldStatus ( ) ; } } ) ; } removeRule ( rulen ) { var p ; var n ; n = this . rules_list [ rulen ] . name ; p = this . ConfirmService . show ( 'DELETE INDICATOR' , 'Are you sure you want to delete indicator ' + n + ' ?' ) ; p . then ( ( result ) => { this . rules_list . splice ( rulen , 1 ) ; this . saveRulesList ( ) . catch ( ( error ) => { this . toastr . error ( 'ERROR REMOVING INDICATOR: ' + error . statusText ) ; this . dtRules . reloadData ( ) ; } ) ; } ) ; } updateMinemeldStatus ( ) { var ns ; this . MinemeldStatusService . getStatus ( ) . then ( ( currentStatus ) => { ns = currentStatus [ this . nodename ] ; angular . forEach ( ns . statistics , ( value , key ) => { var metric ; if ( ! key . startsWith ( 'rule.' ) ) { return ; } metric = key . split ( '.' , 2 ) [ 1 ] ; angular . element ( '#' + metric ) . text ( value ) ; } ) ; } ) ; } private destroy ( ) { if ( this . mmThrottledUpdate ) { this . mmThrottledUpdate . cancel ( ) ; } if ( this . mmStatusListener ) { this . mmStatusListener ( ) ; } } private saveRulesList ( ) { return this . MinemeldConfigService . saveDataFile ( this . cfd_rules_list , this . rules_list , this . nodename ) . then ( ( result ) => { this . toastr . success ( 'CHANGES SAVED' ) ; this . dtRules . reloadData ( ) ; } ) ; } private setupRulesTable ( ) { var vm = this ; this . dtOptions = this . DTOptionsBuilder . fromFnPromise ( function ( ) { return vm . MinemeldConfigService . getDataFile ( vm . cfd_rules_list ) . then ( ( result ) => { vm . changed = false ; if ( result === null ) { return [ ] ; } return result ; } , ( error ) => { vm . toastr . error ( 'ERROR LOADING RULES LIST: ' + error . statusText ) ; throw error ; } ) . then ( ( result ) => { vm . rules_list = result ; return result ; } ) ; } ) . withBootstrap ( ) . withPaginationType ( 'simple_numbers' ) . withOption ( 'fnInitComplete' , ( ) => { this . updateMinemeldStatus ( ) ; } ) . withOption ( 'aaSorting' , [ ] ) . withOption ( 'aaSortingFixed' , [ ] ) . withOption ( 'lengthMenu' , [ [ 50 , - 1 ] , [ 50 , 'All' ] ] ) . withOption ( 'createdRow' , function ( row , data , index ) { var fc ; var j ; row . className += ' config-table-row' ; fc = < HTMLElement > ( row . childNodes [ 4 ] ) ; fc . setAttribute ( 'ng-click' , 'vm.removeRule(' + index + ')' ) ; fc . style . textAlign = 'center' ; fc . style . verticalAlign = 'middle' ; fc . setAttribute ( 'tooltip' , 'delete rule' ) ; fc . setAttribute ( 'tooltip-popup-delay' , '500' ) ; fc . className += ' config-table-clickable' ; for ( j = 0 ; j < row . childNodes . length - 2 ; j ++ ) { fc = < HTMLElement > ( row . childNodes [ j ] ) ; fc . setAttribute ( 'ng-click' , 'vm.editRule(' + index + ')' ) ; fc . className += ' config-table-clickable' ; } fc = < HTMLElement > ( row . childNodes [ row . childNodes . length - 2 ] ) ; fc . setAttribute ( 'id' , data . name . replace ( /[^a-zA-Z0-9_]/g , '_' ) ) ; vm . $compile ( angular . element ( row ) . contents ( ) ) ( vm . $scope ) ; } ) . withLanguage ( { 'oPaginate' : { 'sNext' : '>' , 'sPrevious' : '<' } } ) ; this . dtColumns = [ this . DTColumnBuilder . newColumn ( 'name' ) . withTitle ( 'NAME' ) . renderWith ( function ( data , type , full ) { return he . encode ( data , { strict : true } ) ; } ) , this . DTColumnBuilder . newColumn ( 'comment' ) . withTitle ( 'COMMENT' ) . withOption ( 'defaultContent' , ' ' ) . renderWith ( function ( data , type , full ) { if ( data ) { return he . encode ( data , { strict : true } ) ; } return '' ; } ) , this . DTColumnBuilder . newColumn ( null ) . withTitle ( 'DETAILS' ) . renderWith ( function ( data , type , full ) { var result = [ ] ; if ( data . conditions ) { result . push ( '' + data . conditions . length + ' conditions' ) ; } else { result . push ( '0 conditions' ) ; } if ( data . indicators ) { result . push ( '' + data . indicators . length + ' indicators' ) ; } else { result . push ( '0 indicators' ) ; } if ( data . fields ) { result . push ( ' ' + data . fields . length + ' fields' ) ; } else { result . push ( '0 fields' ) ; } return '<i>' + result . join ( ', ' ) + '</i>' ; } ) , this . DTColumnBuilder . newColumn ( null ) . withTitle ( 'HITS' ) . renderWith ( function ( data , type , full ) { return 0 ; } ) , this . DTColumnBuilder . newColumn ( null ) . withTitle ( '' ) . notSortable ( ) . renderWith ( function ( data , type , full ) { return '<span class="config-table-icon glyphicon glyphicon-remove"></span>' ; } ) . withOption ( 'width' , '30px' ) ] ; } } class SyslogMinerEditRuleController { $modalInstance : angular . ui . bootstrap . IModalServiceInstance ; MinemeldValidateService : IMinemeldValidateService ; toastr : any ; title : string ; rule_names : string [ ] ; name : string ; definition : string ; comment : string ; nameReadOnly : boolean = false ; validated : boolean = false ; editorChanged : any ; ngInject constructor ( $modalInstance , title , rule , rule_names , MinemeldValidateService , toastr ) { var trule ; this . title = title ; this . rule_names = rule_names ; if ( rule ) { trule = { } ; this . name = rule . name ; this . nameReadOnly = true ; angular . forEach ( rule , ( value , key ) => { if ( ( key === 'name' ) || ( key === 'comment' ) ) { return ; } trule [ key ] = value ; } ) ; this . definition = jsyaml . safeDump ( trule ) ; this . comment = rule . comment ; } if ( ! this . definition ) { this . definition = 'conditions:\n\nindicators:\n\nfields:\n\n' ; } this . $modalInstance = $modalInstance ; this . MinemeldValidateService = MinemeldValidateService ; this . toastr = toastr ; this . editorChanged = ( ) => { this . validated = false ; } ; } editorLoaded ( editor_ ) { editor_ . setShowInvisibles ( false ) ; angular . element ( '.ace_text-input' ) . on ( 'focus' , ( event ) => { angular . element ( event . currentTarget . parentNode ) . addClass ( 'ace-focus' ) ; } ) ; angular . element ( '.ace_text-input' ) . on ( 'blur' , ( event ) => { angular . element ( event . currentTarget . parentNode ) . removeClass ( 'ace-focus' ) ; } ) ; } valid ( ) { var result = true ; var rule ; if ( ! this . name ) { result = false ; } if ( this . name && this . rule_names . indexOf ( this . name . toUpperCase ( ) ) !== - 1 ) { angular . element ( '#fgRuleName' ) . addClass ( 'has-error' ) ; result = false ; } else { angular . element ( '#fgRuleName' ) . removeClass ( 'has-error' ) ; } if ( ( ! this . definition ) || ( this . definition . length === 0 ) ) { result = false ; } try { if ( this . definition ) { rule = jsyaml . safeLoad ( this . definition ) ; if ( typeof ( rule ) !== 'object' ) { throw 'definition is not a valid object' ; } angular . element ( '#ruleDefinition' ) . removeClass ( 'has-error' ) ; } } catch ( err ) { angular . element ( '#ruleDefinition' ) . addClass ( 'has-error' ) ; result = false ; } return result ; } validate ( ) { var rule ; rule = jsyaml . safeLoad ( this . definition ) ; rule . name = this . name ; if ( this . comment ) { rule . comment = this . comment ; } this . MinemeldValidateService . syslogMinerRule ( rule ) . then ( ( result ) => { this . validated = true ; } , ( error ) => { if ( error . status === 400 ) { this . toastr . error ( 'ERROR VALIDATING RULE: ' + error . data . error . message ) ; } else { this . toastr . error ( 'ERROR VALIDATING RULE: ' + error . statusText ) ; angular . element ( '#ruleDefinition' ) . addClass ( 'has-error' ) ; } } ) ; } save ( ) { var result ; result = jsyaml . safeLoad ( this . definition ) ; result . name = this . name ; if ( this . comment ) { result . comment = this . comment ; } this . $modalInstance . close ( result ) ; } cancel ( ) { this . $modalInstance . dismiss ( ) ; } } ngInject function syslogMinerRouterConfig ( $stateProvider ) { $stateProvider . state ( 'nodedetail.syslogminerrules' , { templateUrl : 'app/nodedetail/syslogminer.rules.html' , controller : SyslogMinerRulesController , controllerAs : 'vm' } ) . state ( 'nodedetail.syslogminerstats' , { templateUrl : 'app/nodedetail/view.stats.html' , controller : SyslogMinerStatsController , controllerAs : 'nodedetailstats' } ) ; } ngInject function syslogMinerRegisterClass ( NodeDetailResolver ) { NodeDetailResolver . registerClass ( 'minemeld.ft.syslog.SyslogMiner' , { tabs : [ { icon : 'fa fa-circle-o' , tooltip : 'INFO' , state : 'nodedetail.info' , active : false } , { icon : 'fa fa-area-chart' , tooltip : 'STATS' , state : 'nodedetail.syslogminerstats' , active : false } , { icon : 'fa fa-bars' , tooltip : 'RULES' , state : 'nodedetail.syslogminerrules' , active : false } , { icon : 'fa fa-asterisk' , tooltip : 'GRAPH' , state : 'nodedetail.graph' , active : false } ] } ) ; } console . log ( 'Loading syslog miner' ) ; angular . module ( 'minemeldWebui' ) . config ( syslogMinerRouterConfig ) . run ( syslogMinerRegisterClass ) ;