Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix sign in flow #208

Merged
merged 13 commits into from
Dec 8, 2017
8 changes: 7 additions & 1 deletion app/src/renderer/components/common/NiFieldSeed.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<template lang="pug">
field.ni-field-seed(
type="textarea"
v-model="value")
@input="update($event)"
:value="value")
</template>

<script>
Expand All @@ -11,6 +12,11 @@ export default {
components: {
Field
},
methods: {
update (value) {
this.$emit('input', value)
}
},
props: ['value']
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion app/src/renderer/components/common/NiSession.vue
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export default {
&:not(.ni-form)
&.ni-form .ni-form-main
width 32rem
height 32rem
height 36rem

.ni-session-header
background app-fg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template lang="pug">
.ni-session: form-struct(:submit='onSubmit').ni-session-container
.ni-session-header
a(@click="setState('welcome')"): i.material-icons arrow_back
.ni-session-title Enter Password
a(@click="setState('sign-in')"): i.material-icons arrow_back
.ni-session-title Remove Account
a(@click="help"): i.material-icons help_outline
.ni-session-main
form-group(:error='$v.fields.deletionPassword.$error'
Expand All @@ -23,7 +23,7 @@
| I understand that Cosmos cannot recover deleted accounts without the passphrase.
form-msg(name='Deletion confirmation' type='required' v-if='!$v.fields.deletionWarning.required')
.ni-session-footer
btn(icon="exit_to_app" value="Sign In" size="lg")
btn(icon="exit_to_app" value="Sign Out and Remove Account" size="lg")
</template>

<script>
Expand Down
2 changes: 1 addition & 1 deletion app/src/renderer/components/common/NiSessionHardware.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default {
onSubmit () {
this.$store.commit('setModalSession', false)
this.$store.commit('notify', { title: 'Welcome back!', body: 'You are now signed in to your Cosmos account.' })
this.$store.commit('signIn', {password: this.fields.signInPassword})
this.$store.dispatch('signIn', {password: this.fields.signInPassword})
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions app/src/renderer/components/common/NiSessionRestore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
form-group(:error='$v.fields.restoreSeed.$error'
field-id='restore-seed' field-label='Seed')
field-seed#restore-seed(
v-model="fields.restoreSeed"
:value="fields.restoreSeed"
@input="val => fields.restoreSeed = val"
placeholder="must be exactly 12 words")
form-msg(name='Seed' type='required' v-if='!$v.fields.restoreSeed.required')

Expand Down Expand Up @@ -61,7 +62,7 @@ export default {
if (key) {
this.$store.commit('setModalSession', false)
this.$store.commit('notify', { title: 'Welcome back!', body: 'Your account has been successfully restored.' })
this.$store.commit('signIn', {password: this.fields.signInPassword})
this.$store.dispatch('signIn', {password: this.fields.signInPassword})
}
}
},
Expand Down
10 changes: 8 additions & 2 deletions app/src/renderer/components/common/NiSessionSignIn.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<template lang="pug">
.ni-session: form-struct(:submit='onSubmit').ni-session-container
.ni-session-header
a(@click="setState('welcome')"): i.material-icons arrow_back
.ni-session-title Sign In
a(@click="help"): i.material-icons help_outline
.ni-session-main
Expand All @@ -12,6 +11,8 @@
v-model="fields.signInPassword")
form-msg(name='Password' type='required' v-if='!$v.fields.signInPassword.required')
form-msg(name='Password' type='minLength' min="10" v-if='!$v.fields.signInPassword.minLength')
form-group
a(@click="setState('delete')") Sign Out and Remove Account
.ni-session-footer
btn(icon="arrow_forward" icon-pos="right" value="Next" size="lg")
</template>
Expand Down Expand Up @@ -47,7 +48,7 @@ export default {
if (this.$v.$error) return
try {
await this.$store.dispatch('testLogin', {password: this.fields.signInPassword})
this.$store.commit('signIn', {password: this.fields.signInPassword})
this.$store.dispatch('signIn', {password: this.fields.signInPassword})
this.$store.commit('setModalSession', false)
this.$store.commit('notify', { title: 'Signed In', body: `You are now signed in to your Cosmos account.` })
} catch (err) {
Expand All @@ -65,3 +66,8 @@ export default {
})
}
</script>
<style lang="stylus">
.ni-form-group
a
cursor pointer
</style>
3 changes: 2 additions & 1 deletion app/src/renderer/components/common/NiSessionSignUp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
.ni-session-main
form-group(field-id='sign-up-seed' field-label='Seed (write it down)')
field-seed#sign-up-seed(v-model="fields.signUpSeed" disabled)
form-msg(body='Please back up the seed phrase for this account. These words cannot be recovered!')

form-group(:error='$v.fields.signInPassword.$error'
field-id='sign-in-password' field-label='Password')
Expand Down Expand Up @@ -78,7 +79,7 @@ export default {
if (key) {
this.$store.commit('setModalSession', false)
this.$store.commit('notify', { title: 'Signed Up', body: 'Your account has been created.' })
this.$store.commit('signIn', {password: this.fields.signInPassword})
this.$store.dispatch('signIn', {password: this.fields.signInPassword})
}
}
},
Expand Down
14 changes: 2 additions & 12 deletions app/src/renderer/components/common/NiSessionWelcome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@
.ni-session-title Welcome to Cosmos!
a(@click="help"): i.material-icons help_outline
.ni-session-main
li-session(
v-if="accountExists"
@click.native="setState('sign-in')"
icon="lock"
title="Sign in with password"
subtitle="If you have an account, choose this option")
li-session(
@click.native="setState('sign-up')"
icon="create"
Expand Down Expand Up @@ -41,15 +35,11 @@ export default {
LiSession
},
computed: {
...mapGetters(['config']),
sessionState () {
return this.config.modals.sessions.state
}
...mapGetters(['config'])
},
methods: {
help () { this.$store.commit('setModalHelp', true) },
setState (value) { this.$store.commit('setModalSessionState', value) },
accountExists () { return !!this.$store.dispatch('accountExists') }
setState (value) { this.$store.commit('setModalSessionState', value) }
}
}
</script>
2 changes: 1 addition & 1 deletion app/src/renderer/styles/variables.styl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ bc-dim = app-fg

// anchor
link = hsl(app-hue, 88%, 70%)
hover = hsl(app-hue, 96%, 72%)
hover = hsl(app-hue, 96%, 90%)
hover-bg = hsl(app-hue, 30%, 19%)

// input
Expand Down
40 changes: 25 additions & 15 deletions app/src/renderer/vuex/modules/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ export default ({ commit, node }) => {
const state = JSON.parse(JSON.stringify(emptyUser))

const mutations = {
signIn (state, {password, account = KEY_NAME}) {
state.password = password
state.account = account
state.signedIn = true
},
activateDelegation (state) {
state.delegationActive = true
}
Expand All @@ -51,9 +46,11 @@ export default ({ commit, node }) => {
commit('notifyError', { title: `Couldn't read keys'`, body: err.message })
}
},
// testing if the provided password works so we can show the user early if he uses the wrong password
// testing this by trying to change the password... to the same password...
async testLogin (state, {password, account = KEY_NAME}) {
try {
await node.updateKey(account, {
return await node.updateKey(account, {
name: account,
password: password,
new_passphrase: password
Expand All @@ -62,18 +59,21 @@ export default ({ commit, node }) => {
commit('notifyError', { title: `Couldn't login to '${account}'`, body: err.message })
}
},
// to create a temporary seed phrase, we create a junk account with name 'trunk' for now
async createSeed ({ commit }) {
let JUNK_ACCOUNT_NAME = 'trunk'
try {
// cleanup
try {
await node.deleteKey('trunk', {
// cleanup an existing junk account
let keys = await node.listKeys()
if (keys.find(key => key.name === JUNK_ACCOUNT_NAME)) {
await node.deleteKey(JUNK_ACCOUNT_NAME, {
password: KEY_PASSWORD,
name: 'trunk'
name: JUNK_ACCOUNT_NAME
})
} catch (err) {
// ignore if this fails as we get an error anyway while creating if this fails and this fails if there is no key with that name
}
let temporaryKey = await node.generateKey({ name: 'trunk', password: KEY_PASSWORD })

// generate seedPhrase with junk account
let temporaryKey = await node.generateKey({ name: JUNK_ACCOUNT_NAME, password: KEY_PASSWORD })
return temporaryKey.seed_phrase
} catch (err) {
commit('notifyError', { title: 'Couln\'t create a seed', body: err.message })
Expand All @@ -82,7 +82,7 @@ export default ({ commit, node }) => {
async createKey ({ commit, dispatch }, { seedPhrase, password, name = KEY_NAME }) {
try {
let {key} = await node.recoverKey({ name, password, seed_phrase: seedPhrase })
dispatch('initializeWallet')
dispatch('initializeWallet', key)
return key
} catch (err) {
commit('notifyError', { title: 'Couln\'t create a key', body: err.message })
Expand All @@ -96,11 +96,21 @@ export default ({ commit, node }) => {
commit('notifyError', { title: `Couln't delete account ${name}`, body: err.message })
}
},
signOut ({ state, commit }) {
async signIn ({ state, dispatch }, {password, account = KEY_NAME}) {
state.password = password
state.account = account
state.signedIn = true

let key = await node.getKey(account)
dispatch('initializeWallet', key)
},
signOut ({ state, commit, dispatch }) {
state.password = null
state.account = null
state.signedIn = false

commit('setModalSession', true)
dispatch('showInitialScreen')
},
async submitDelegation (state, value) {
state.delegation = value
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Cosmos",
"productName": "Cosmos",
"version": "1.0.0",
"version": "0.1.0",
"description": "The electron wrapper for Cosmos UI.",
"author": "All In Bits, Inc <hello@tendermint.com>",
"license": "Apache-2.0",
Expand Down Expand Up @@ -103,7 +103,7 @@
"@nylira/vue-field": "1.1.12",
"@nylira/vue-form-msg": "^1.0.3",
"@nylira/vue-input": "^3.2.0",
"@nylira/vue-notifications": "^1.4.4",
"@nylira/vue-notifications": "^1.4.0",
"axios": "^0.17.0",
"babel-jest": "^21.2.0",
"chart.js": "^2.6.0",
Expand Down Expand Up @@ -171,7 +171,7 @@
"/build/",
"/dist/",
"/test/",
"/config/"
"/config.js"
],
"testURL": "http://localhost",
"setupFiles": [
Expand Down
4 changes: 2 additions & 2 deletions test/unit/specs/NISessionAccountDelete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ describe('NiSessionAccountDelete', () => {
expect(htmlBeautify(wrapper.html())).toMatchSnapshot()
})

it('should go back to the welcome screen on click', () => {
it('should go back to the login screen on click', () => {
wrapper.findAll('.ni-session-header a').at(0).trigger('click')
expect(store.commit.mock.calls[0]).toEqual(['setModalSessionState', 'welcome'])
expect(store.commit.mock.calls[0]).toEqual(['setModalSessionState', 'sign-in'])
})

it('should open the help model on click', () => {
Expand Down
17 changes: 8 additions & 9 deletions test/unit/specs/NISessionSignIn.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ describe('NiSessionSignIn', () => {
expect(htmlBeautify(wrapper.html())).toMatchSnapshot()
})

it('should go back to the welcome screen on click', () => {
it('should open the help model on click', () => {
wrapper.findAll('.ni-session-header a').at(0).trigger('click')
expect(store.commit.mock.calls[0][0]).toBe('setModalSessionState')
expect(store.commit.mock.calls[0][1]).toBe('welcome')
expect(store.commit).toHaveBeenCalledWith('setModalHelp', true)
})

it('should open the help model on click', () => {
wrapper.findAll('.ni-session-header a').at(1).trigger('click')
expect(store.commit.mock.calls[0]).toEqual(['setModalHelp', true])
it('should go to account removal screen', () => {
wrapper.find('.ni-session-main a').trigger('click')
expect(store.commit).toHaveBeenCalledWith('setModalSessionState', 'delete')
})

it('should close the modal on successful login', async () => {
Expand All @@ -56,9 +55,9 @@ describe('NiSessionSignIn', () => {
signInPassword: '1234567890'
}})
await wrapper.vm.onSubmit()
let calls = store.commit.mock.calls.map(args => args[0])
expect(calls).toContain('notify')
expect(calls).toContain('signIn')
let commitCalls = store.commit.mock.calls.map(args => args[0])
expect(commitCalls).toContain('notify')
expect(store.dispatch).toHaveBeenCalledWith('signIn', {password: '1234567890'})
})

it('should show error if password not 10 long', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/specs/NISessionSignUp.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('NISessionSignUp', () => {
await wrapper.vm.onSubmit()
expect(store.commit.mock.calls[1][0]).toEqual('notify')
expect(store.commit.mock.calls[1][1].title.toLowerCase()).toContain('signed up')
expect(store.commit).toHaveBeenCalledWith('signIn', {password: '1234567890'})
expect(store.dispatch).toHaveBeenCalledWith('signIn', {password: '1234567890'})
})

it('should show error if warnings not acknowledged', () => {
Expand Down
21 changes: 0 additions & 21 deletions test/unit/specs/NISessionWelcome.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@ describe('NISessionWelcome', () => {
})

it('has the expected html structure', () => {
wrapper.setData({
accountExists: false
})
expect(htmlBeautify(wrapper.html())).toMatchSnapshot()
})

it('has the expected html structure if accoutn exists', () => {
wrapper.setData({
accountExists: true
})
expect(htmlBeautify(wrapper.html())).toMatchSnapshot()
})

Expand All @@ -43,19 +33,8 @@ describe('NISessionWelcome', () => {
})

it('sets desired login method', () => {
wrapper.setData({
accountExists: false
})
wrapper.findAll(LiSession).trigger('click')
expect(store.commit.mock.calls[0][0]).toBe('setModalSessionState')
expect(store.commit.mock.calls.map(args => args[1])).toEqual(['sign-up', 'restore', 'hardware'])
})

it('sets desired login method if account exists', () => {
wrapper.setData({
accountExists: true
})
wrapper.findAll(LiSession).trigger('click')
expect(store.commit.mock.calls.map(args => args[1])).toEqual(['sign-in', 'sign-up', 'restore', 'hardware'])
})
})
2 changes: 1 addition & 1 deletion test/unit/specs/NiSessionRestore.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('NiSessionRestore', () => {
await wrapper.vm.onSubmit()
expect(store.commit.mock.calls[1][0]).toEqual('notify')
expect(store.commit.mock.calls[1][1].title.toLowerCase()).toContain('welcome back!')
expect(store.commit).toHaveBeenCalledWith('signIn', {password: '1234567890'})
expect(store.dispatch).toHaveBeenCalledWith('signIn', {password: '1234567890'})
})

it('should show error if seed is not filled in', async () => {
Expand Down
6 changes: 5 additions & 1 deletion test/unit/specs/PageBalances.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { mount, createLocalVue } from 'vue-test-utils'
import PageBalances from 'renderer/components/wallet/PageBalances'

const filters = require('renderer/vuex/modules/filters').default({})
const wallet = require('renderer/vuex/modules/wallet').default({})
const wallet = require('renderer/vuex/modules/wallet').default({
node: {
queryAccount () {}
}
})

const localVue = createLocalVue()
localVue.use(Vuex)
Expand Down
Loading