Skip to content

Commit

Permalink
Test for SSL state before creating SSL api client #173
Browse files Browse the repository at this point in the history
  • Loading branch information
fnoop committed Apr 7, 2020
1 parent e0de3a2 commit d173e89
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 114 deletions.
94 changes: 53 additions & 41 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ export default {
},
deep: true
},
'$store.state.core.apiState': {
handler: function (newValue) {
for (const api of Object.keys(newValue)) {
// If schema has been fetched, proceed to create Status query/subscription
if (newValue[api].schemaready === true) {
this.logDebug(`Creating status query/subscription for API ${this.apis[api].name}`)
this.createQuery('Status', statusQuery, api, null, null, this.processStatusQuery)
this.createSubscription('Status', statusSubscription, api, null, null, this.processStatusSubscription)
}
}
},
deep: true
},
// Watch discoveries state for any change and process
'$store.state.data.discoveries': {
handler: function (newValue) {
Expand Down Expand Up @@ -114,21 +127,45 @@ export default {
mounted () {
this.logBanner('** Welcome to Maverick Web GCS **')
// Connect to defined APIs
this.createClients()
// Set initital dark theme state
this.$vuetify.theme.dark = this.isDark
// Create a default discovery agent if one doesn't exist
this.defaultDiscovery()
// Create websocket connections for all defined discovery agents
this.createDiscoveries()
// Set initital dark theme state
this.$vuetify.theme.dark = this.isDark
// Connect to defined APIs
this.createClients()
},
methods: {
createApi (data) {
if (!this.apis[data.uuid] && data.service_type == 'maverick-api') {
this.logInfo(`Creating new API connection from discovered service: ${data.name}`)
let apidata = {
authToken: null,
colorLight: "rgba(166,11,11,0.3)",
colorDark: "rgba(166,11,11,0.9)",
httpEndpoint: data.httpEndpoint,
httpsEndpoint: data.httpsEndpoint ? data.httpsEndpoint : null,
hostname: data.hostname,
key: data.uuid,
name: data.name,
schemaEndpoint: data.schemaEndpoint,
schemasEndpoint: data.schemasEndpoint ? data.schemasEndpoint : null,
wsEndpoint: data.wsEndpoint,
wssEndpoint: data.wssEndpoint ? data.wssEndpoint : null,
websocketsOnly: data.websocketsOnly
}
this.$store.commit('data/addApi', {key: apidata.key, data: apidata})
if (this.uiSettings.notifyDiscovery) {
this.$toast.info(`Created new API connection from discovery: <strong>${data.name}</strong>`)
}
}
},
checkApis () {
// If an api hasn't been seen for more than 10 seconds, mark it as dead
for (const api in this.apis) {
let lastseen = (this.apistate && this.apistate.hasOwnProperty(api)) ? this.apistate[api].lastseen : 0
let lastseen = this.$store.state.core.apiSeen.hasOwnProperty(api) ? this.$store.state.core.apiSeen[api] : 0
if (this.appVisible && performance.now() - lastseen > 10000) {
// this.logInfo(`deadapi? api: ${api}, timestamp: ${lastseen}`)
this.$store.commit('core/setApiState', { api: api, field: 'state', value: false })
Expand All @@ -141,16 +178,6 @@ export default {
if (!this.$apollo.provider.clients.hasOwnProperty(api)) {
this.createClient(api, this.apis[api])
}
this.createQuery('Status', statusQuery, api, null, null, this.processStatusQuery)
this.createSubscription('Status', statusSubscription, api, null, null, this.processStatusSubscription)
}
},
defaultDiscovery() {
if (!this.$store.state.data.discoveries[window.location.hostname]) {
const ws_url = 'ws://' + window.location.hostname + ':6001'
const wss_url = 'wss://' + window.location.hostname + ':6002'
this.logInfo(`Creating default discovery agent: ${ws_url} :: ${wss_url}`)
this.$store.commit('data/addDiscovery', { key: window.location.hostname, data: { ws_url: ws_url, wss_url: wss_url, host: window.location.hostname } })
}
},
createDiscoveries() {
Expand Down Expand Up @@ -187,35 +214,13 @@ export default {
}
}
},
createApi (data) {
if (!this.apis[data.uuid] && data.service_type == 'maverick-api') {
this.logInfo(`Creating new API connection from discovered service: ${data.name}`)
let apidata = {
key: data.uuid,
"httpEndpoint": data.httpEndpoint,
"httpsEndpoint": data.httpsEndpoint ? data.httpsEndpoint : null,
"wsEndpoint": data.wsEndpoint,
"wssEndpoint": data.wssEndpoint ? data.wssEndpoint : null,
"schemaEndpoint": data.schemaEndpoint,
"schemasEndpoint": data.schemasEndpoint ? data.schemasEndpoint : null,
"websocketsOnly": data.websocketsOnly,
"name": data.name,
"colorLight": "rgba(166,11,11,0.3)",
"colorDark": "rgba(166,11,11,0.9)",
"authToken": null
}
this.$store.commit('data/addApi', {key: apidata.key, data: apidata})
if (this.uiSettings.notifyDiscovery) {
this.$toast.info(`Created new API connection from discovery: <strong>${data.name}</strong>`)
}
}
},
createVideo (data) {
if (!this.$store.state.data.videostreams[data.uuid] && data.service_type == 'webrtc') {
this.logInfo(`Creating new Video stream from discovered service: ${data.name}`)
let videodata = {
key: data.uuid,
name: data.name,
hostnamne: data.hostanme,
webrtcEndpoint: data.wsEndpoint,
enabled: false,
action: 'start'
Expand All @@ -226,6 +231,14 @@ export default {
}
}
},
defaultDiscovery() {
if (!this.$store.state.data.discoveries[window.location.hostname]) {
const ws_url = 'ws://' + window.location.hostname + ':6001'
const wss_url = 'wss://' + window.location.hostname + ':6002'
this.logInfo(`Creating default discovery agent: ${ws_url} :: ${wss_url}`)
this.$store.commit('data/addDiscovery', { key: window.location.hostname, data: { ws_url: ws_url, wss_url: wss_url, host: window.location.hostname } })
}
},
/*
processX() are async callbacks that process incoming GQL messages
Expand Down Expand Up @@ -253,7 +266,7 @@ export default {
this.createSubscription('MaverickService', maverickServicesSubscription, api, null, null, this.processServiceSubscription)
}, 5000)
}
if (this.apistate[api].lastseen === null) this.$store.commit('core/setApiState', {api: api, field: 'lastseen', value: performance.now() })
this.$store.commit('core/setApiSeen', {api: api, lastseen: performance.now() })
if (!(api in this.$store.state.core.statusData)) {
this.$store.commit('core/setStatusData', { api: api, message: data.data.Status })
}
Expand All @@ -263,8 +276,7 @@ export default {
const api = key.split('___')[0]
// Store the message data and set the api state to active, for subsequent subscription callbacks
// if (data.data && this.$store.state.core.apis[api].state !== true) this.$store.commit('data/setApiState', { api: api, value: true })
// this.$store.commit('core/setApiSeen', { api: api, value: performance.now() })
this.$store.commit('core/setApiState', {api: api, field: 'lastseen', value: performance.now()})
this.$store.commit('core/setApiSeen', {api: api, lastseen: performance.now() })
if (data.data && this.$store.state.core.statusData[api] !== data.data.Status) {
this.$store.commit('core/setStatusData', { api: api, message: data.data.Status })
}
Expand Down
75 changes: 63 additions & 12 deletions src/components/modules/config/ConfigConnections.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ div
v-list-item-content {{ apistate[item.key].icon }}
v-icon(v-if="apistate[item.key].icon" color='success') {{ apistate[item.key].icon }}
v-icon(v-else color='error') mdi-alert-circle-outline

v-divider
// img(:src="`https://${item.hostname}/img/misc/onepixel.png`" @error="imgError('http', item)" style="display:none")
// img(:src="`http://${item.hostname}/img/misc/onepixel.png`" @error="imgError('https', item)" style="display:none")
v-dialog(v-model="dialog" max-width="600px")
v-card
v-card-title.headline(class="primary" primary-title)
Expand Down Expand Up @@ -157,18 +160,12 @@ export default {
return Object.values(this.apis)
}
},
mounted () {
for (const api of Object.keys(this.apis)) {
// this.testSsl(api)
}
},
methods: {
lastseen (api) {
let lastseen = (this.apistate && this.apistate.hasOwnProperty(api)) ? this.apistate[api].lastseen : 0
return (performance.now() - lastseen)
},
save(apiData) {
this.$store.commit('data/setApiData', {api: apiData.key, data: apiData})
// If any of the endpoints have changed, destroy and recreate the client
// this.deleteQueries(apiData.key)
// delete this.$apollo.provider.clients[apiData.key]
// this.createClient(apiData.key+'new', apiData)
},
connect(apiData) {
this.logDebug('Connecting: ' + apiData.key)
if (!(this.$apollo.provider.clients[apiData.key])) {
Expand All @@ -193,6 +190,22 @@ export default {
}
this.$store.commit('data/addApi', {key: data.key, data: data})
},
/*
imgError (protocol, item) {
this.logDebug(`protocol: ${protocol}`)
this.logDebug(item)
if (event.type == "error" && item.hasOwnProperty('hostname')) {
this.logError(`Error connecting to API (${item.name}) over SSL.`)
this.logDebug(event)
} else if (! item.hasOwnProperty('hostname')) {
this.logError(`Error: This API definition (${item.name}) does not have a hostname set. Please update maverick-api.`)
}
},
*/
lastseen (api) {
let lastseen = (this.$store.state.core.apiSeen.hasOwnProperty(api)) ? this.$store.state.core.apiSeen[api] : 0
return (performance.now() - lastseen)
},
remove(item) {
this.deleteitem = item
this.deleteDialog = true
Expand All @@ -207,6 +220,44 @@ export default {
delete this.$apollo.provider.clients[this.deleteitem.key]
this.$store.commit('data/removeApi', this.deleteitem.key)
this.deleteitem = null
},
save(apiData) {
this.$store.commit('data/setApiData', {api: apiData.key, data: apiData})
// If any of the endpoints have changed, destroy and recreate the client
// this.deleteQueries(apiData.key)
// delete this.$apollo.provider.clients[apiData.key]
// this.createClient(apiData.key+'new', apiData)
},
async testSsl(api) {
// Define an internal method function promise that fetches the image and watches for completion or error
function testImage(imgPath) {
return new Promise((resolve, reject) => {
const testImg = new Image()
testImg.addEventListener("load", () => resolve(testImg))
testImg.addEventListener("error", err => reject(err))
testImg.src = imgPath
})
}
const item = this.apis[api]
/*
// http can't be loaded from https link
let httpState = null
let httpLoad = testImage(`http://${item.hostname}/img/misc/onepixel.png`)
.then(img => { httpState = true })
.catch(err => { this.logDebug('Error loading http image'); httpState = false })
await httpLoad
*/
let httpsState = null
let httpsLoad = testImage(`https://${item.hostname}/img/misc/onepixel.png`)
.then(img => { httpsState = true })
.catch(err => { this.logDebug('Error loading https image'); httpsState = false })
await httpsLoad
this.logDebug(`SSL state for ${item.name}: ${httpsState}`)
}
}
}
Expand Down
Loading

0 comments on commit d173e89

Please sign in to comment.