import { INodeDetailResolverService } from '../../app/services/nodedetailresolver' ; import { IMinemeldConfigService } from '../../app/services/config' ; import { IConfirmService } from '../../app/services/confirm' ; declare var he ; declare var moment ; class NodeDetailLocalDbIndicatorsController { MinemeldConfigService : IMinemeldConfigService ; toastr : any ; $scope : angular . IScope ; DTOptionsBuilder : any ; DTColumnBuilder : any ; $compile : angular . ICompileService ; $modal : angular . ui . bootstrap . IModalService ; ConfirmService : IConfirmService ; changed : boolean = false ; nodename : string ; cfd_indicators : string ; dtIndicators : any = { } ; dtColumns : any [ ] ; dtOptions : any ; indicators : any [ ] ; ngInject constructor ( toastr , MinemeldConfigService , $scope , DTOptionsBuilder , DTColumnBuilder , $compile , $modal , ConfirmService ) { this . MinemeldConfigService = MinemeldConfigService ; this . $scope = $scope ; this . toastr = toastr ; this . DTColumnBuilder = DTColumnBuilder ; this . DTOptionsBuilder = DTOptionsBuilder ; this . $compile = $compile ; this . $modal = $modal ; this . ConfirmService = ConfirmService ; this . nodename = $scope . $parent [ 'nodedetail' ] [ 'nodename' ] ; this . cfd_indicators = this . nodename + '_indicators' ; this . setupIndicatorsTable ( ) ; } addIndicator ( ) { var mi ; mi = this . $modal . open ( { templateUrl : 'app/nodedetail/localdb.indicator.modal.html' , controller : LocalDbIndicatorController , controllerAs : 'vm' , bindToController : true , backdrop : 'static' , size : 'lg' , animation : false , resolve : { indicator : ( ) => { return undefined ; } } } ) ; mi . result . then ( result => { this . iorIndicator ( result ) . then ( ( ) => { this . toastr . success ( 'INDICATOR ' + result . indicator + ' ADDED' ) ; this . dtIndicators . reloadData ( ) ; } , ( error ) => { this . toastr . error ( 'ERROR ADDING INDICATOR: ' + error . statusText ) ; this . dtIndicators . reloadData ( ) ; } ) ; } ) ; } showIndicator ( index ) { var mi ; mi = this . $modal . open ( { templateUrl : 'app/nodedetail/localdb.indicator.modal.html' , controller : LocalDbIndicatorController , controllerAs : 'vm' , bindToController : true , backdrop : 'static' , animation : false , size : 'lg' , resolve : { indicator : ( ) => { return this . indicators [ index ] ; } } } ) ; mi . result . then ( result => { this . iorIndicator ( result ) . then ( ( ) => { this . toastr . success ( 'INDICATOR ' + result . indicator + ' UPDATED' ) ; this . dtIndicators . reloadData ( ) ; } , ( error ) => { this . toastr . error ( 'ERROR UPDATING INDICATOR: ' + error . statusText ) ; this . dtIndicators . reloadData ( ) ; } ) ; } ) ; } removeIndicator ( inum ) { var p ; var indicator ; indicator = this . indicators [ inum ] ; p = this . ConfirmService . show ( 'DELETE INDICATOR' , 'Are you sure you want to delete indicator ' + indicator . indicator + ' ?' ) ; p . then ( ( result ) => { this . indicators . splice ( inum , 1 ) ; this . iorIndicator ( indicator . indicator , indicator . type , - 1 , { removed : true } ) . then ( ( ) => { this . toastr . success ( 'INDICATOR ' + indicator . indicator + ' REMOVED' ) ; this . dtIndicators . reloadData ( ) ; } , ( error ) => { this . toastr . error ( 'ERROR REMOVING INDICATOR: ' + error . statusText ) ; this . dtIndicators . reloadData ( ) ; } ) ; } ) ; } reload ( ) { this . dtIndicators . reloadData ( ) ; } private setupIndicatorsTable ( ) { this . dtOptions = this . DTOptionsBuilder . fromFnPromise ( ( ) => { return this . MinemeldConfigService . getDataFile ( this . cfd_indicators , 'localdb' ) . then ( ( result ) => { this . changed = false ; if ( result === null ) { return [ ] ; } return result ; } , ( error ) => { this . toastr . error ( 'ERROR LOADING INDICATORS LIST: ' + error . statusText ) ; throw error ; } ) . then ( ( result ) => { this . indicators = result ; return result ; } ) ; } ) . withBootstrap ( ) . withPaginationType ( 'simple_numbers' ) . withOption ( 'aaSorting' , [ ] ) . withOption ( 'aaSortingFixed' , [ ] ) . withOption ( 'stateSave' , true ) . withOption ( 'deferRender' , true ) . withOption ( 'lengthMenu' , [ [ 50 , 200 , - 1 ] , [ 50 , 200 , 'All' ] ] ) . withOption ( 'createdRow' , ( row , data , index ) => { var fc ; row . className += ' config-table-row' ; for ( var j = 0 ; j < row . childNodes . length - 1 ; j ++ ) { fc = < HTMLElement > ( row . childNodes [ j ] ) ; fc . setAttribute ( 'ng-click' , 'vm.showIndicator(' + index + ')' ) ; } fc = < HTMLElement > ( row . childNodes [ 5 ] ) ; fc . setAttribute ( 'ng-click' , 'vm.removeIndicator(' + index + ')' ) ; fc . style . textAlign = 'center' ; fc . style . verticalAlign = 'middle' ; fc . setAttribute ( 'tooltip' , 'delete indicator' ) ; fc . setAttribute ( 'tooltip-popup-delay' , '500' ) ; fc . setAttribute ( 'tooltip-append-to-body' , 'true' ) ; fc . className += ' config-table-clickable' ; this . $compile ( angular . element ( row ) . contents ( ) ) ( this . $scope ) ; } ) . withLanguage ( { 'oPaginate' : { 'sNext' : '>' , 'sPrevious' : '<' } } ) ; this . dtColumns = [ this . DTColumnBuilder . newColumn ( 'indicator' ) . withTitle ( 'INDICATOR' ) . withOption ( 'width' , '20%' ) . renderWith ( ( data , type , full ) => { if ( data ) { return he . encode ( data , { strict : true } ) ; } return '' ; } ) , this . DTColumnBuilder . newColumn ( 'type' ) . withTitle ( 'TYPE' ) . withOption ( 'defaultContent' , ' ' ) . renderWith ( function ( data , type , full ) { if ( data ) { return he . encode ( data , { strict : true } ) ; } return '' ; } ) , 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 ( '_update_ts' ) . withTitle ( 'LAST UPDATE' ) . withOption ( 'defaultContent' , ' ' ) . withOption ( 'width' , '20%' ) . renderWith ( function ( data , type , full ) { if ( data ) { return moment ( data ) . format ( 'DD/MM/YYYY HH:mm:ss Z' ) ; } return 'N/A' ; } ) , this . DTColumnBuilder . newColumn ( '_expiration_ts' ) . withTitle ( 'EXPIRATION' ) . withOption ( 'defaultContent' , ' ' ) . withOption ( 'width' , '20%' ) . renderWith ( function ( data , type , full ) { if ( data === 'disabled' ) { return '<i>Disabled</i>' ; } if ( data ) { return moment ( data ) . format ( 'DD/MM/YYYY HH:mm:ss Z' ) ; } return '<i>Default</i>' ; } ) , this . DTColumnBuilder . newColumn ( null ) . withTitle ( '' ) . notSortable ( ) . renderWith ( function ( data , type , full ) { return '<span class="config-table-icon glyphicon glyphicon-remove"></span>' ; } ) . withOption ( 'width' , '30px' ) ] ; } private iorIndicator ( indicator , type ? , ttl ? , attributes ? ) { let data ; data = indicator ; if ( typeof ( type ) !== 'undefined' ) { data = angular . copy ( attributes ) ; data . indicator = indicator ; data . type = type ; data . ttl = ttl ; } Object . keys ( data ) . forEach ( ( key ) => { if ( key [ 0 ] === '_' ) { delete data [ key ] ; } } ) ; return this . MinemeldConfigService . appendDataFile ( this . cfd_indicators , data , this . nodename , 'localdb' ) ; } } class AttributesAnnotation { private _annotations : { [ key ] : string [ ] ; } = { } ; constructor ( ) { } addAnnotation ( row , annotation ) { if ( ! ( row in this . _annotations ) ) { this . _annotations [ row ] = [ ] ; } this . _annotations [ row ] . push ( annotation ) ; } getAnnotations ( ) { var result = [ ] ; Object . keys ( this . _annotations ) . forEach ( ( row ) => { result . push ( { row : + row , column : 0 , type : 'error' , text : this . _annotations [ row ] . join ( '\n' ) } ) ; } ) ; return result ; } length ( ) { return Object . keys ( this . _annotations ) . length ; } firstRowNumber ( ) { var rows ; rows = Object . keys ( this . _annotations ) . map ( ( v ) : number => { return + v ; } ) ; if ( rows . length !== 0 ) { return Math . min . apply ( null , rows ) + 1 ; } return 0 ; } } class LocalDbIndicatorController { $modalInstance : angular . ui . bootstrap . IModalServiceInstance ; indicator : string ; type : string ; attributes : any ; attributesJSON : string ; update_ts : number ; expiration_ts : number | string ; editableIndicatorAndType : boolean = true ; editableAttributes : boolean = true ; numAnnotations : number = 0 ; firstAnnotation : number = 0 ; attributesValid : boolean = false ; availableTypes : string [ ] = [ 'IPv4' , 'IPv6' , 'URL' , 'domain' , 'user-id' , 'md5' , 'sha256' , 'sha1' , 'ssdeep' , 'email-addr' ] ; comment : string ; ttl : number ; expirationDisabled : boolean = false ; private editor : any ; ngInject constructor ( $modalInstance , indicator ) { this . $modalInstance = $modalInstance ; if ( typeof ( indicator ) !== 'undefined' ) { this . editableAttributes = false ; this . editableIndicatorAndType = false ; this . attributes = angular . copy ( indicator ) ; this . update_ts = this . attributes . _update_ts ; this . expiration_ts = this . attributes . _expiration_ts ; if ( this . expiration_ts === 'disabled' ) { this . expirationDisabled = true ; } Object . keys ( this . attributes ) . forEach ( key => { if ( key [ 0 ] === '_' ) { delete this . attributes [ key ] ; } } ) ; this . indicator = this . attributes . indicator ; delete this . attributes [ 'indicator' ] ; this . type = this . attributes . type ; delete this . attributes [ 'type' ] ; if ( this . attributes . comment ) { this . comment = this . attributes . comment ; delete this . attributes [ 'comment' ] ; } } this . attributesJSON = JSON . stringify ( this . attributes , null , 4 ) ; let vm = this ; vm . editorLoaded = ( editor_ ) => { vm . editor = 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' ) ; } ) ; editor_ . getSession ( ) . setOption ( 'useWorker' , false ) ; vm . validAttributes ( ) ; } ; vm . aceChanged = vm . validAttributes . bind ( this ) ; } save ( ) { var result = { } ; if ( this . attributesJSON && this . attributesJSON . trim ( ) . length !== 0 ) { result = JSON . parse ( this . attributesJSON ) ; } result . indicator = this . indicator ; result . type = this . type ; result . ttl = this . ttl ; if ( this . expirationDisabled ) { result . ttl = 'disabled' ; } if ( this . comment ) { result . comment = this . comment ; } this . $modalInstance . close ( result ) ; } cancel ( ) { this . $modalInstance . dismiss ( ) ; } errorClick ( ) { this . editor . gotoLine ( this . firstAnnotation , 0 , true ) ; } validate ( ) { return this . attributesValid && this . indicator && this . type ; } validAttributes ( ) { var annotations = new AttributesAnnotation ( ) ; if ( ! this . editor ) { return ; } this . attributesValid = true ; this . editor . getSession ( ) . clearAnnotations ( ) ; this . numAnnotations = 0 ; if ( ! this . attributesJSON ) { return ; } if ( this . attributesJSON . trim ( ) . length === 0 ) { return ; } try { this . attributes = JSON . parse ( this . attributesJSON ) ; } catch ( err ) { this . attributesValid = false ; this . editor . getSession ( ) . setAnnotations ( [ { row : 0 , column : 0 , text : 'Invalid JSON syntax' , type : 'error' } ] ) ; this . numAnnotations = 1 ; this . firstAnnotation = 0 ; return ; } Object . keys ( this . attributes ) . forEach ( key => { if ( key [ 0 ] === '_' ) { annotations . addAnnotation ( this . findAttribute ( key ) , 'Invalid attribute name ' + key ) ; } } ) ; this . numAnnotations = annotations . length ( ) ; this . firstAnnotation = annotations . firstRowNumber ( ) ; if ( annotations . length ( ) !== 0 ) { this . editor . getSession ( ) . setAnnotations ( annotations . getAnnotations ( ) ) ; this . attributesValid = false ; } } private findAttribute ( attribute ) { var clines ; var line ; var regexp = new RegExp ( '^\\s*"' + attribute + '"' ) ; clines = this . attributesJSON . split ( '\n' ) ; for ( var row in clines ) { line = clines [ row ] ; if ( regexp . test ( line ) ) { return row ; } } return 0 ; } } ; ngInject function localDbRouterConfig ( $stateProvider ) { $stateProvider . state ( 'nodedetail.localdbindicators' , { templateUrl : 'app/nodedetail/localdb.indicators.html' , controller : NodeDetailLocalDbIndicatorsController , controllerAs : 'vm' } ) ; } ngInject function localDbRegisterClass ( NodeDetailResolver ) { NodeDetailResolver . registerClass ( 'minemeld.ft.localdb.Miner' , { tabs : [ { icon : 'fa fa-circle-o' , tooltip : 'INFO' , state : 'nodedetail.info' , active : false } , { icon : 'fa fa-area-chart' , tooltip : 'STATS' , state : 'nodedetail.stats' , active : false } , { icon : 'fa fa-list-alt' , tooltip : 'INDICATORS' , state : 'nodedetail.localdbindicators' , active : false } , { icon : 'fa fa-asterisk' , tooltip : 'GRAPH' , state : 'nodedetail.graph' , active : false } ] } ) ; } console . log ( 'Loading localdb' ) ; angular . module ( 'minemeldWebui' ) . config ( localDbRouterConfig ) . run ( localDbRegisterClass ) ;