1- /* global fetch, Notification */
1+ /* global Notification */
22import React , { Component } from 'react'
33import Stethoscope from './lib/Stethoscope'
44import Device from './Device'
@@ -13,11 +13,16 @@ import { HOST } from './constants'
1313import appConfig from './config.json'
1414import pkg from '../package.json'
1515import ErrorMessage from './ErrorMessage'
16+ import yaml from 'js-yaml'
1617import './App.css'
1718const socket = openSocket ( HOST )
19+
1820// CRA doesn't like importing native node modules
1921// have to use window.require AFAICT
2022const os = window . require ( 'os' )
23+ const glob = window . require ( 'glob' )
24+ const { readFileSync } = window . require ( 'fs' )
25+ const path = window . require ( 'path' )
2126const { shell, remote, ipcRenderer } = window . require ( 'electron' )
2227const settings = window . require ( 'electron-settings' )
2328const log = remote . getGlobal ( 'log' )
@@ -53,7 +58,11 @@ class App extends Component {
5358 this . setState ( { recentHang : settings . get ( 'recentHang' , 0 ) > 1 } )
5459 ipcRenderer . send ( 'scan:init' )
5560 // perform the initial policy load & scan
56- await this . loadPractices ( )
61+ try {
62+ await this . loadPractices ( )
63+ } catch ( e ) {
64+ console . error ( 'Unable to load practices' )
65+ }
5766 // flag ensures the download:start event isn't sent multiple times
5867 this . downloadStartSent = false
5968 // handle context menu
@@ -63,7 +72,8 @@ class App extends Component {
6372 // handles any errors that occur when updating (restores window size, etc.)
6473 ipcRenderer . on ( 'download:error' , this . onDownloadError )
6574 // trigger scan from main process
66- ipcRenderer . on ( 'autoscan:start' , ( { notificationOnViolation = false } ) => {
75+ ipcRenderer . on ( 'autoscan:start' , ( args = { } ) => {
76+ // const { notificationOnViolation = false } = args
6777 if ( ! this . state . scanIsRunning ) {
6878 ipcRenderer . send ( 'scan:init' )
6979 if ( Object . keys ( this . state . policy ) . length ) {
@@ -196,30 +206,33 @@ class App extends Component {
196206 * using them
197207 */
198208 loadPractices = ( ) => {
199- this . setState ( { loading : true } , ( ) => {
200- const files = [ 'config' , 'policy' , 'instructions' ]
201- const promises = files . map ( item =>
202- fetch ( `${ HOST } /${ item } ` )
203- . then ( async res => {
204- if ( ! res . ok ) {
205- log . error ( `Unable to locate ${ item } ` )
206- const response = await res . json ( )
207- throw new Error ( response . error || `Unable to locate ${ item } ` )
209+ return new Promise ( ( resolve , reject ) =>
210+ this . setState ( { loading : true } , ( ) => {
211+ const process = remote . process
212+ const dev = process . env . STETHOSCOPE_ENV === 'development'
213+ const basePath = `${ dev ? '.' : process . resourcesPath } /src/practices`
214+
215+ glob ( `${ basePath } /*.yaml` , ( err , files ) => {
216+ if ( err || ! files . length ) {
217+ reject ( err )
218+ }
219+ const configs = { }
220+ files . forEach ( filePath => {
221+ const parts = path . parse ( filePath )
222+ const handle = readFileSync ( filePath , 'utf8' )
223+ configs [ parts . name . split ( '.' ) . shift ( ) ] = yaml . safeLoad ( handle )
224+ } )
225+
226+ this . setState ( { ...configs , loading : false } , ( ) => {
227+ if ( ! this . state . scanIsRunning ) {
228+ this . handleScan ( )
208229 }
209- return res
210230 } )
211- . then ( res => res . json ( ) )
212- . catch ( this . handleErrorYAML )
213- )
214231
215- Promise . all ( promises ) . then ( ( [ config , policy , instructions ] ) => {
216- this . setState ( { config, policy, instructions } , ( ) => {
217- if ( ! this . state . scanIsRunning ) {
218- this . handleScan ( )
219- }
232+ resolve ( )
220233 } )
221- } ) . catch ( this . handleErrorGraphQL )
222- } )
234+ } )
235+ )
223236 }
224237
225238 /**
@@ -322,33 +335,37 @@ class App extends Component {
322335 // assume no errors and loaded state
323336 if ( ! content ) {
324337 const args = [ policy , result , device , instructions . practices , platform ]
325- const secInfo = Stethoscope . partitionSecurityInfo ( ...args )
326- const decoratedDevice = Object . assign ( { } , device , secInfo , { lastScanTime } )
327- const lastScanFriendly = moment ( lastScanTime ) . fromNow ( )
328-
329- content = (
330- < div >
331- < Device
332- { ...decoratedDevice }
333- org = { instructions . organization }
334- scanResult = { result }
335- strings = { instructions . strings }
336- policy = { policy }
337- lastScanTime = { lastScanFriendly }
338- lastScanDuration = { lastScanDuration }
339- scannedBy = { scannedBy }
340- onExpandPolicyViolation = { this . handleHighlightRescanButton }
341- />
342- < Footer
343- highlightRescan = { highlightRescan }
344- result = { result }
345- instructions = { instructions }
346- webScopeLink = { appConfig . stethoscopeWebURI }
347- onClickOpen = { this . handleOpenExternal }
348- onRescan = { this . handleScan }
349- />
350- </ div >
351- )
338+ try {
339+ const secInfo = Stethoscope . partitionSecurityInfo ( ...args )
340+ const decoratedDevice = Object . assign ( { } , device , secInfo , { lastScanTime } )
341+ const lastScanFriendly = moment ( lastScanTime ) . fromNow ( )
342+
343+ content = (
344+ < div >
345+ < Device
346+ { ...decoratedDevice }
347+ org = { instructions . organization }
348+ scanResult = { result }
349+ strings = { instructions . strings }
350+ policy = { policy }
351+ lastScanTime = { lastScanFriendly }
352+ lastScanDuration = { lastScanDuration }
353+ scannedBy = { scannedBy }
354+ onExpandPolicyViolation = { this . handleHighlightRescanButton }
355+ />
356+ < Footer
357+ highlightRescan = { highlightRescan }
358+ result = { result }
359+ instructions = { instructions }
360+ webScopeLink = { appConfig . stethoscopeWebURI }
361+ onClickOpen = { this . handleOpenExternal }
362+ onRescan = { this . handleScan }
363+ />
364+ </ div >
365+ )
366+ } catch ( e ) {
367+ throw new Error ( `Unable to partition data: ${ e . message } \n${ args . join ( ', ' ) } ` )
368+ }
352369 }
353370
354371 return (
0 commit comments