Skip to content

Commit

Permalink
Add ssl test/redirect to homepag #173
Browse files Browse the repository at this point in the history
  • Loading branch information
fnoop committed Apr 12, 2020
1 parent d796c29 commit 5696e21
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 66 deletions.
10 changes: 10 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
components: { BottomNav, TopNav, ActionButton },
data () {
return {
sslState: null
}
},
Expand Down Expand Up @@ -128,6 +129,8 @@ export default {
this.logBanner('** Welcome to Maverick Web GCS **')
// Set initital dark theme state
this.$vuetify.theme.dark = this.isDark
// Test SSL status
this.testSsl()
// Create a default discovery agent if one doesn't exist
this.defaultDiscovery()
// Create websocket connections for all defined discovery agents
Expand Down Expand Up @@ -311,6 +314,13 @@ export default {
if (!this.apis[api].icon) {
this.$store.commit('data/setApiIcon', { api: api, value: this.vehicleIcon(data.data.VehicleInfo.typeString) })
}
},
async testSsl(api) {
let httpsLoad = this.testImage(`https://${window.location.hostname}/img/ssl/ssltest.png`)
.then(img => { this.$store.commit('core/setSslState', true) })
.catch(err => { this.logDebug('Error loading https image'); this.$store.commit('core/setSslState', false) })
await httpsLoad
this.logDebug(`SSL state for -web: ${this.$store.state.core.sslState}`)
}
}
}
Expand Down
79 changes: 79 additions & 0 deletions src/components/common/SslDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<template lang='pug'>
v-dialog(v-model="sslDialog" max-width=600 overlay-opacity=0.85)
v-card
v-card-title.headline.primary(primary-title)
span SSL Setup
v-spacer(v-if="sslitem")
span.subtitle-1(v-if="sslitem") {{ sslitem.name }}
v-card-text(v-if="sslitem")
v-container

// Download CA cert step
v-row
v-col(cols="12" sm="12" md="12")
div 1. Please click on the button below to download the SSL Certificate
v-btn(color="primary" small :href="`http://${sslitem.hostname}/security/mavCA.crt`") Download SSL CA Certificate

// Firefox ssl guide
v-row(v-if="$browserDetect.isFirefox")
v-col(cols="12" sm="12" md="12")
div 2. In Firefox, a dialog should popup asking which permissions to give the certificate:
img(src="img/ssl/firefox-sslca.png")
div Click to enable 'Trust this CA to identify web sites'

// MacOS Chrome/Safari ssl guide
v-row(v-else-if="($browserDetect.isChrome || $browserDetect.isSafari) && (/OS X/.test($browserDetect.meta.ua) || /OSX/.test($browserDetect.meta.ua))")
v-col(cols="12" sm="12" md="12")
div 2. In MacOS Chrome or Safari, click on the downloaded file in the footer of the browser.
img(src="img/ssl/macffsafari-1.png")
div This will import the certificate into MacOS system Keychain Access app.
img(src="img/ssl/macffsafari-2.png")
div Choose the default 'login' option and click Add
v-col(cols="12" sm="12" md="12")
div 3. Double click on the untrusted certificate (with red X)
img(src="img/ssl/macffsafari-3.png")
v-col(cols="12" sm="12" md="12")
div 4. Open the 'Trust' section and change 'When using this certificate' to 'Always Trust'
img(src="img/ssl/macffsafari-4.png")
div Close the window and it will ask you to authenticate, to verify the system certificate update.

// Undetected browser ssl guide
v-row(v-else)
v-col(cols="12" sm="12" md="12")
div 2. Unknown browser - please search on the internet for installation instructions for your OS/Browser:
div {{ $browserDetect.meta.ua }}

// Add reload step
v-row
v-col(cols="12" sm="12" md="12")
div 3. Reload the website to activate the new certificate.
v-btn(color="primary" small @click="reloadPage()") Reload
v-card-actions
v-spacer
v-btn.ma-2(color="error" @click="close()") Close
</template>

<script>
export default {
name: 'SslDialog',
props: {
sslitem: {
type: Object,
default: null
}
},
data () {
return {
sslDialog: false,
}
},
methods: {
open () {
this.sslDialog = true
},
close () {
this.sslDialog = false
}
}
}
</script>
10 changes: 9 additions & 1 deletion src/components/common/TopNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,15 @@ export default {
</script>

<style scoped>
.btn {
.v-btn {
line-height: normal;
}
/* Stop the logo background changing on hover */
.v-btn:hover:before, .v-btn:focus:before {
color: transparent
}
.v-btn:before {
display: none;
}
.v-ripple__animation{ display: none; }
</style>
34 changes: 0 additions & 34 deletions src/components/modules/config/ConfigConnections.vue
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,6 @@ export default {
}
},
mounted () {
for (const api of Object.keys(this.apis)) {
// this.testSsl(api)
}
},
methods: {
connect(apiData) {
Expand Down Expand Up @@ -282,37 +279,6 @@ export default {
this.logDebug(`Opening setupSsl for Api: ${this.apis[api].name}`)
this.sslitem = this.apis[api]
this.sslDialog = true
},
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
37 changes: 36 additions & 1 deletion src/components/modules/home/HomeModule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,63 @@ v-content
v-btn(:color="data.color" :to="'/' + key" block dark)
span {{ key | capitalize }}
v-icon(right) {{ data.icon }}
v-row(v-if="!ssl && !$store.state.core.sslState" align='center' justify='center')
v-col(xs='12' sm='12' md='6' lg='6' xl='4')
v-row(align='center' justify='center')
v-alert(type='warning' border='left' outlined) Maverick-Web is not loaded over an encrypted SSL connection, and your Maverick CA certificate is not loaded into your browser.
v-row(align='center' justify='center')
v-btn(color='orange darken-2' @click="$refs.sslDialog.open()") Load Maverick CA certificate.
v-row(v-else-if="!ssl && $store.state.core.sslState" align='center' justify='center')
v-col(xs='12' sm='12' md='6' lg='6' xl='4')
v-row(align='center' justify='center')
v-alert(type='warning' border='left' outlined) Maverick-Web is not loaded over an encrypted SSL connection.
v-row(align='center' justify='center')
v-btn(color='orange darken-2' @click="gotoSsl()") Connect over SSL
v-row(v-else-if="ssl")
v-col(xs='12' sm='12' md='6' lg='6' xl='4')
v-row(align='center' justify='center')
v-alert(type='success' border='left' outlined) Maverick-Web is loaded over an encrypted SSL connection.

v-spacer
v-footer.transparent(absolute height="auto")
v-row(align='center' justify='center')
img.mb-4(:src="publicPath + 'img/logos/goodrobots-text-white.svg'" height='30px')
SslDialog(:sslitem="sslitem" ref="ssldialog")
</template>

<script>
import SslDialog from '../../common/SslDialog'
export default {
name: 'HomeModule',
components: {
SslDialog
},
data () {
return {
publicPath: process.env.BASE_URL
publicPath: process.env.BASE_URL,
sslitem: {}
}
},
computed: {
ssl () {
return (window.location.protocol == 'https:' ? true : false)
},
topLogo () {
if (this.isDark) {
return this.publicPath + 'img/logos/maverick-logo-white.svg'
} else {
return this.publicPath + 'img/logos/maverick-logo-dark.svg'
}
},
},
mounted () {
// this.$refs.ssldialog.open()
},
methods: {
gotoSsl() {
window.location.href = `https://${window.location.hostname}`
}
}
}
</script>
Expand Down
64 changes: 34 additions & 30 deletions src/store/modules/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,10 @@ import { buildClientSchema } from 'graphql'
import axios from 'axios'

const state = {
apiState: {},
apiSeen: {},
navColor: null,
navDrawer: null,
navDrawerEnable: true,
moduleName: null,
statusData: {},
vehicleData: {},
serviceData: {},
apiState: {},
graphqlSchema: {},
moduleName: null,
modules: {
'cockpit': {
'color': 'orange',
Expand Down Expand Up @@ -47,7 +41,14 @@ const state = {
'icon': 'mdi-video',
'enabled': true
}
}
},
navColor: null,
navDrawer: null,
navDrawerEnable: true,
serviceData: {},
sslState: null,
statusData: {},
vehicleData: {}
}

const actions = {
Expand Down Expand Up @@ -92,8 +93,14 @@ const mutations = {
addApiState (state, api) {
Vue.set(state.apiState, api, {state: false, schemaready: false, auth: false, uuid: null, icon: null})
},
setApiState (state, data) {
state.apiState[data.api][data.field] = data.value
clearGraphqlVerified(state, api) {
state.graphqlSchema[api].verified = {}
},
setApiAuth (state, data) {
state.apiState[data.api].auth = data.value
},
setApiIcon (state, data) {
state.apiState[data.api].icon = data.value
},
setApiSeen (state, data) {
if (!state.apiSeen.hasOwnProperty(data.api)) {
Expand All @@ -102,15 +109,12 @@ const mutations = {
state.apiSeen[data.api] = data.lastseen
}
},
setApiState (state, data) {
state.apiState[data.api][data.field] = data.value
},
setApiUuid (state, data) {
state.apiState[data.api].uuid = data.value
},
setApiIcon (state, data) {
state.apiState[data.api].icon = data.value
},
setApiAuth (state, data) {
state.apiState[data.api].auth = data.value
},
setModuleName (state, value) {
state.moduleName = value
},
Expand All @@ -123,13 +127,6 @@ const mutations = {
setNavDrawerEnable (state, value) {
state.navDrawerEnable = value
},
setStatusData (state, data) {
if (data.api in state.statusData) {
state.statusData[data.api] = data.message
} else {
Vue.set(state.statusData, data.api, data.message)
}
},
setServiceData (state, data) {
if (data.api in state.serviceData) {
if (data.name in state.serviceData[data.api]) {
Expand All @@ -142,6 +139,16 @@ const mutations = {
Vue.set(state.serviceData[data.api], data.name, data.message)
}
},
setSslState (state, value) {
state.sslState = value
},
setStatusData (state, data) {
if (data.api in state.statusData) {
state.statusData[data.api] = data.message
} else {
Vue.set(state.statusData, data.api, data.message)
}
},
setVehicleData (state, data) {
if (data.api in state.vehicleData) {
state.vehicleData[data.api] = data.message
Expand All @@ -154,16 +161,13 @@ const mutations = {
},
updateGraphqlVerified(state, {api, hash, ret}) {
state.graphqlSchema[api].verified[hash] = ret
},
clearGraphqlVerified(state, api) {
state.graphqlSchema[api].verified = {}
}
}

export default {
namespaced: true,
state,
actions,
getters,
mutations
mutations,
namespaced: true,
state
}

0 comments on commit 5696e21

Please sign in to comment.