Skip to content

Commit

Permalink
Merge pull request #570 from cosmos/fabo/552-error-optin
Browse files Browse the repository at this point in the history
Error collection optin
  • Loading branch information
jbibla authored Apr 2, 2018
2 parents 9cced9f + c788b53 commit 30105e2
Show file tree
Hide file tree
Showing 23 changed files with 613 additions and 186 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ A list of all environment variables and their purpose:
|--|--|--|--|
|NODE_ENV|'production', 'development'|||
|LOGGING|'true', 'false'|'true'|Disable logging|
|COSMOS_ANALYTICS|'true', 'false'|'false'|Disable code that should not run in e2e tests, like crash reporting|
|COSMOS_NETWORK|{path to network configuration folder}|'../networks/gaia-1'|Network to connect to|
|COSMOS_HOME|{path to config persistence folder}|'$HOME/voyager[-dev]'||
|COSMOS_NODE|{ip of a certain node}||Node to connect to|
Expand Down
28 changes: 7 additions & 21 deletions app/src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ const winURL = DEV
: `file://${__dirname}/index.html`
const LCD_PORT = DEV ? config.lcd_port : config.lcd_port_prod
const NODE = process.env.COSMOS_NODE
const ANALYTICS = process.env.COSMOS_ANALYTICS ? JSON.parse(process.env.COSMOS_ANALYTICS) : (process.env.NODE_ENV === 'production' && config.analytics_networks.indexOf(config.default_network) !== -1)
// set analytics for renderer
process.env.COSMOS_ANALYTICS = ANALYTICS

let SERVER_BINARY = 'gaia' + (WIN ? '.exe' : '')

Expand Down Expand Up @@ -329,6 +326,9 @@ function handleIPC () {
event.sender.send('connected', nodeIP)
}
})
ipcMain.on('error-collection', (event, optin) => {
Raven.uninstall().config(optin ? config.sentry_dsn : '', { captureUnhandledRejections: false }).install()
})
}

// check if LCD is initialized as the configs could be corrupted
Expand Down Expand Up @@ -400,17 +400,9 @@ async function reconnect (seeds) {
return nodeIP
}

function setupAnalytics () {
if (ANALYTICS) {
log('Adding analytics')
}

// only enable sending of error events in production setups and if the network is a testnet
Raven.config(ANALYTICS ? config.sentry_dsn : '', { captureUnhandledRejections: false }).install()
}

async function main () {
setupAnalytics()
// we only enable error collection after users opted in
Raven.config('', { captureUnhandledRejections: false }).install()

let appVersionPath = join(root, 'app_version')
let genesisPath = join(root, 'genesis.json')
Expand Down Expand Up @@ -499,12 +491,7 @@ async function main () {

// pick a random seed node from config.toml
// TODO: user-specified nodes, support switching?
let configText
try {
configText = fs.readFileSync(configPath, 'utf8')
} catch (e) {
throw new Error(`Can't open config.toml: ${e.message}`)
}
let configText = fs.readFileSync(configPath, 'utf8') // checked before if the file exists
let configTOML = toml.parse(configText)
seeds = configTOML.p2p.seeds.split(',').filter(x => x !== '')
if (seeds.length === 0) {
Expand All @@ -530,6 +517,5 @@ module.exports = main()
})
.then(() => ({
shutdown,
processes: { lcdProcess },
analytics: ANALYTICS
processes: { lcdProcess }
}))
24 changes: 21 additions & 3 deletions app/src/renderer/components/common/NiSessionImport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@
placeholder="Must be exactly 12 words")
form-msg(name='Seed' type='required' v-if='!$v.fields.importSeed.required')

form-group(field-id="error-collection" field-label=' ')
.ni-field-checkbox
.ni-field-checkbox-input
input#sign-up-warning(type="checkbox" v-model="fields.errorCollection")
label.ni-field-checkbox-label(for="error-collection")
| I'd like to opt in for remote error tracking to help improve Voyager.

.ni-session-footer
btn(icon="arrow_forward" icon-pos="right" value="Next" size="lg")
</template>
Expand Down Expand Up @@ -87,15 +94,25 @@ export default {
name: this.fields.importName
})
if (key) {
this.$store.dispatch('setErrorCollection', {
account: this.fields.importName,
optin: this.fields.errorCollection
})
this.$store.commit('setModalSession', false)
this.$store.commit('notify', { title: 'Welcome back!', body: 'Your account has been successfully imported.' })
this.$store.commit('notify', {
title: 'Welcome back!',
body: 'Your account has been successfully imported.'
})
this.$store.dispatch('signIn', {
account: this.fields.importName,
password: this.fields.importPassword
})
}
} catch (err) {
this.$store.commit('notifyError', { title: `Couldn't create account`, body: err.message })
this.$store.commit('notifyError', {
title: `Couldn't create account`,
body: err.message
})
}
}
},
Expand All @@ -107,7 +124,8 @@ export default {
importName: { required, minLength: minLength(5) },
importPassword: { required, minLength: minLength(10) },
importPasswordConfirm: { sameAsPassword: sameAs('importPassword') },
importSeed: { required }
importSeed: { required },
errorCollection: false
}
})
}
Expand Down
43 changes: 33 additions & 10 deletions app/src/renderer/components/common/NiSessionSignUp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
label.ni-field-checkbox-label(for="sign-up-backup")
| I have securely written down my seed.
form-msg(name='Backup confirmation' type='required' v-if='!$v.fields.signUpBackup.required')

form-group(field-id="error-collection" field-label=' ')
.ni-field-checkbox
.ni-field-checkbox-input
input#sign-up-warning(type="checkbox" v-model="fields.errorCollection")
label.ni-field-checkbox-label(for="error-collection")
| I'd like to opt in for remote error tracking to help improve Voyager.

.ni-session-footer
btn(icon="arrow_forward" icon-pos="right" value="Next" size="lg" :disabled="creating")
</template>
Expand Down Expand Up @@ -99,33 +107,48 @@ export default {
if (this.$v.$error) return
try {
let key = await this.$store.dispatch('createKey', {
seedPhrase: this.fields.signUpSeed, password: this.fields.signUpPassword, name: this.fields.signUpName
seedPhrase: this.fields.signUpSeed,
password: this.fields.signUpPassword,
name: this.fields.signUpName
})
if (key) {
this.$store.dispatch('setErrorCollection', {
account: this.fields.signUpName,
optin: this.fields.errorCollection
})
this.$store.commit('setModalSession', false)
this.$store.commit('notify', { title: 'Signed Up', body: 'Your account has been created.' })
this.$store.dispatch('signIn', { password: this.fields.signUpPassword, account: this.fields.signUpName })
this.$store.commit('notify', {
title: 'Signed Up',
body: 'Your account has been created.'
})
this.$store.dispatch('signIn', {
password: this.fields.signUpPassword,
account: this.fields.signUpName
})
}
} catch (err) {
this.$store.commit('notifyError', { title: `Couldn't create account`, body: err.message })
this.$store.commit('notifyError', {
title: `Couldn't create account`,
body: err.message
})
}
}
},
mounted () {
this.$el.querySelector('#sign-up-name').focus()
this.$store.dispatch('createSeed')
.then(seedPhrase => {
this.creating = false
this.fields.signUpSeed = seedPhrase
})
this.$store.dispatch('createSeed').then(seedPhrase => {
this.creating = false
this.fields.signUpSeed = seedPhrase
})
},
validations: () => ({
fields: {
signUpName: { required, minLength: minLength(5) },
signUpPassword: { required, minLength: minLength(10) },
signUpPasswordConfirm: { sameAsPassword: sameAs('signUpPassword') },
signUpWarning: { required },
signUpBackup: { required }
signUpBackup: { required },
errorCollection: false
}
})
}
Expand Down
15 changes: 15 additions & 0 deletions app/src/renderer/components/common/PageProfile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ page(title="My Profile")
part(title='My Profile')
list-item(dt="Account Name" :dd="user.account")
list-item(dt="Address" :dd="user.address")
.ni-li
.ni-li-container
.ni-li-dl
.ni-li-dt Automatic error reports
.ni-li-dd
.ni-field-checkbox
.ni-field-checkbox-input
input(type="checkbox" :checked="user.errorCollection || undefined" @change="setErrorCollection")

.ni-session-footer
btn(icon='exit_to_app' type='button' @click.native="signOut" value='Sign Out')
</template>
Expand All @@ -30,6 +39,12 @@ export default {
signOut () {
this.$store.dispatch('signOut')
this.$store.commit('notifySignOut')
},
setErrorCollection () {
this.$store.dispatch('setErrorCollection', {
account: this.user.account,
optin: !this.user.errorCollection
})
}
}
}
Expand Down
14 changes: 3 additions & 11 deletions app/src/renderer/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import Router from 'vue-router'
import Vuelidate from 'vuelidate'
import shrinkStacktrace from '../helpers/shrink-stacktrace.js'
import Raven from 'raven-js'
import { remote, ipcRenderer } from 'electron'
import enableGoogleAnalytics from './google-analytics.js'

const config = require('../../../config')
import { ipcRenderer } from 'electron'

import App from './App'
import routes from './routes'
Expand All @@ -18,13 +15,8 @@ import Store from './vuex/store'
// exporting this for testing
let store

// setup sentry remote error reporting and google analytics
const analyticsEnabled = JSON.parse(remote.getGlobal('process').env.COSMOS_ANALYTICS)
if (analyticsEnabled) {
console.log('Analytics enabled in browser')
enableGoogleAnalytics(config.google_analytics_uid)
}
Raven.config(analyticsEnabled ? config.sentry_dsn_public : '').install()
// Raven serves automatic error reporting. It is turned off by default
Raven.config('').install()

// handle uncaught errors
window.addEventListener('unhandledrejection', function (event) {
Expand Down
32 changes: 30 additions & 2 deletions app/src/renderer/vuex/modules/user.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import enableGoogleAnalytics from '../../google-analytics.js'
import Raven from 'raven-js'
const { ipcRenderer } = require('electron')
const config = require('../../../../../config')

export default ({ commit, node }) => {
const state = {
const ERROR_COLLECTION_KEY = 'voyager_error_collection'

let state = {
atoms: 0,
signedIn: false,
accounts: [],
password: null,
account: null,
address: null
address: null,
errorCollection: false
}

const mutations = {
Expand Down Expand Up @@ -81,6 +89,7 @@ export default ({ commit, node }) => {

commit('setModalSession', false)
dispatch('initializeWallet', key)
dispatch('loadErrorCollection', account)
},
signOut ({ state, commit, dispatch }) {
state.password = null
Expand All @@ -89,6 +98,25 @@ export default ({ commit, node }) => {

commit('setModalSession', true)
dispatch('showInitialScreen')
},
loadErrorCollection ({ state, dispatch }, account) {
let errorCollection = localStorage.getItem(`${ERROR_COLLECTION_KEY}_${account}`) === 'true'
dispatch('setErrorCollection', { account, optin: errorCollection })
},
setErrorCollection ({ state }, { account, optin }) {
localStorage.setItem(`${ERROR_COLLECTION_KEY}_${account}`, optin)
state.errorCollection = optin

Raven.uninstall().config(optin ? config.sentry_dsn_public : '').install()
if (optin) {
console.log('Analytics enabled in browser')
enableGoogleAnalytics(config.google_analytics_uid)
} else {
console.log('Analytics disabled in browser')
window.analytics = null
}

ipcRenderer.send('error-collection', optin)
}
}

Expand Down
4 changes: 2 additions & 2 deletions archive/components/ToggleBtn.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('TogggleBtn', () => {
store.commit = jest.fn()

beforeEach(() => {
store.commit.mockReset()
store.commit.mockClear()
wrapper = mount(TogggleBtn, {
localVue,
store,
Expand All @@ -31,7 +31,7 @@ describe('TogggleBtn', () => {
})

it('should show an active state if active set', () => {
wrapper.setProps({active: true})
wrapper.setProps({ active: true })
expect(wrapper.classes()).toContain('active')
})
})
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@
"./test/unit/helpers/setup.js",
"./test/unit/helpers/console_error_throw.js",
"./test/unit/helpers/genesis_mock.js",
"./test/unit/helpers/ipc_mock.js",
"jest-localstorage-mock"
]
}
}
}
5 changes: 5 additions & 0 deletions test/unit/helpers/ipc_mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// this mocks the IPC layer
jest.mock('electron', () => ({
ipcRenderer: { send: jest.fn() },
ipcMain: { on: jest.fn() }
}))
Loading

0 comments on commit 30105e2

Please sign in to comment.