Skip to content

Commit 5638614

Browse files
authored
Merge pull request #30 from Volentix/separate_login
Separate login
2 parents a1dd619 + fb6263e commit 5638614

File tree

9 files changed

+542
-523
lines changed

9 files changed

+542
-523
lines changed

quasar.conf.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ module.exports = function (ctx) {
6161
'QBanner',
6262
'QSpace',
6363
'QTooltip',
64-
'QChatMessage'
64+
'QChatMessage',
65+
'QForm'
6566
],
6667

6768
directives: [

src/components/GeoWidget.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div class='bg-vdark inset-shadow'>
3-
<q-banner dense inline-actions class="text-vdark bg-vgreen">
4-
The map widget is currently disabled, the data is artificial.
3+
<q-banner dense inline-actions class="text-vdark bg-vpurple">
4+
Live Nodes: The map widget is currently disabled, the data is artificial.
55
</q-banner>
66
<div id='map'></div>
77
<div id='tooltip' class='hidden bg-vgrey'>
@@ -31,7 +31,6 @@ var countries = require('../assets/geoWidgetData/countries.geo.json')
3131
3232
export default {
3333
name: 'GeoWidget',
34-
props: ['geoData'],
3534
data () {
3635
return {
3736
nodeGeoData: []

src/css/app.styl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap');
2+
23
.code {
34
font-family: 'Source Code Pro', monospace;
45
}
56
.blink {
67
animation: blinker 1s linear infinite;
78
}
8-
99
@keyframes blinker {
1010
50% {
1111
opacity: 0;
1212
}
1313
}
14+
.background-gradient {
15+
background-image: linear-gradient(to bottom right, #00F7A9, #A000FD);
16+
}
17+
1418
// app global css
1519
.bg-vgrey {
1620
background: #CECFD0;

src/pages/Index.vue

Lines changed: 319 additions & 477 deletions
Large diffs are not rendered by default.

src/pages/Login.vue

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<template>
2+
<q-layout>
3+
<q-page-container>
4+
<q-page class="bg-vblack">
5+
<div class="row">
6+
<div class="col background-gradient q-pa-xl text-center window-height">
7+
<q-img src="statics/icons/icon-512x512.png" spinner-color="vdark" style="height: 150px; max-width: 150px" />
8+
<div class="text-h5 text-vdark"><span class="text-weight-bolder">vDexNode</span> dashboard</div>
9+
<div class="text-subtitle1 text-vdark">Rent your computer to earn VTX</div>
10+
</div>
11+
<div class="col bg-white q-pa-xl window-height">
12+
<div class="text-h5">Import private key</div>
13+
<div class="text-subtitle2">Please enter your private key below to start working with vDexNode Dashboard. We will never save or transmit your your key.</div>
14+
<q-form @submit="login()">
15+
<q-input dense v-model="privateKey" :type="isPwd ? 'password' : 'text'" counter color="vdark" ref="input" @keyup.enter="login" label="Your private key" :rules="[ val => val && val.length <= 51 || 'Wrong key']">
16+
<template v-slot:append>
17+
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer" @click="isPwd = !isPwd" />
18+
</template>
19+
</q-input>
20+
<q-btn color="black" :disabled="privateKey ? false: true" unelevated rounded outline class="full-width q-mt-md" label="Continue" type="submit" />
21+
</q-form>
22+
</div>
23+
</div>
24+
</q-page>
25+
</q-page-container>
26+
</q-layout>
27+
</template>
28+
29+
<script>
30+
export default {
31+
data () {
32+
return {
33+
privateKey: '',
34+
isPwd: true
35+
}
36+
},
37+
mounted () {
38+
this.$refs.input.focus()
39+
},
40+
methods: {
41+
login () {
42+
this.$utils.login(this.privateKey)
43+
this.privateKey = ''
44+
}
45+
}
46+
}
47+
</script>

src/router/index.js

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
import Vue from 'vue'
22
import VueRouter from 'vue-router'
3-
3+
import store from '../store'
44
import routes from './routes'
55

66
Vue.use(VueRouter)
77

8-
/*
9-
* If not building with SSR mode, you can
10-
* directly export the Router instantiation
11-
*/
12-
13-
export default function (/* { store, ssrContext } */) {
14-
const Router = new VueRouter({
15-
scrollBehavior: () => ({ x: 0, y: 0 }),
16-
routes,
8+
const router = new VueRouter({
9+
scrollBehavior: () => ({ x: 0, y: 0 }),
10+
routes,
11+
mode: process.env.VUE_ROUTER_MODE,
12+
base: process.env.VUE_ROUTER_BASE
13+
})
1714

18-
// Leave these as is and change from quasar.conf.js instead!
19-
// quasar.conf.js -> build -> vueRouterMode
20-
// quasar.conf.js -> build -> publicPath
21-
mode: process.env.VUE_ROUTER_MODE,
22-
base: process.env.VUE_ROUTER_BASE
23-
})
15+
router.beforeEach((to, from, next) => {
16+
if (to.matched.some(record => record.meta.requiresAuth)) {
17+
if (store.getters.isLoggedIn) {
18+
next()
19+
return
20+
}
21+
next('/login')
22+
} else {
23+
next()
24+
}
25+
})
2426

25-
return Router
26-
}
27+
export default router

src/router/routes.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
const routes = [
33
{
44
path: '/',
5-
component: () => import('pages/Index.vue')
5+
component: () => import('pages/Index.vue'),
6+
meta: {
7+
requiresAuth: true
8+
}
9+
},
10+
{
11+
path: '/login',
12+
component: () => import('pages/Login.vue')
613
}
714
]
815

src/store/index.js

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,43 +11,75 @@ Vue.use(Vuex)
1111

1212
function initialState () {
1313
return {
14-
loggedIn: false
14+
loggedIn: false,
15+
identity: {
16+
voted_i: [],
17+
voted_for: []
18+
}
1519
}
1620
}
1721

1822
const store = new Vuex.Store({
1923
// plugins: [vuexPersist.plugin],
2024
state: initialState,
2125
getters: {
22-
getLoggedIn: state => {
23-
return state.loggedIn
24-
}
26+
isLoggedIn: state => state.loggedIn,
27+
getIdentity: state => state.identity
2528
},
2629
mutations: {
27-
resetState: (state) => {
30+
logout: (state) => {
2831
Object.assign(state, initialState())
2932
},
33+
setPrivateKey: (state, privateKey) => {
34+
state.identity.privateKey = privateKey
35+
},
36+
setPublicKey: (state, publicKey) => {
37+
state.identity.publicKey = publicKey
38+
},
39+
setAccountName: (state, accountName) => {
40+
state.identity.accountName = accountName
41+
},
3042
setLoggedIn: state => {
3143
state.loggedIn = true
44+
},
45+
setBalance: (state, balance) => {
46+
state.identity.balance = balance
47+
},
48+
setRank: (state, rank) => {
49+
state.identity.rank = rank
50+
},
51+
setTotalRanks: (state, total) => {
52+
state.identity.totalRanks = total
53+
},
54+
setUptime: (state, uptime) => {
55+
state.identity.uptime = uptime
56+
},
57+
setEarned: (state, earned) => {
58+
state.identity.earned = earned
59+
},
60+
setVotedI: (state, data) => {
61+
state.identity.voted_i = data
62+
},
63+
setVotedFor: (state, data) => {
64+
state.identity.voted_for = data
3265
}
3366
},
3467
actions: {
35-
// logout: (context) => {
36-
// return new Promise((resolve, reject) => {
37-
// context.commit('resetState')
38-
// resolve()
39-
// })
40-
// },
41-
// login: ({ context }, privateKey, publicKey, accountName) => {
42-
// console.log(privateKey, publicKey, accountName)
43-
// return new Promise((resolve, reject) => {
44-
// context.commit('setLoggedIn')
45-
// context.commit('setPrivateKey', privateKey)
46-
// context.commit('setPublicKey', publicKey)
47-
// context.commit('setAccountName', accountName)
48-
// resolve()
49-
// })
50-
// }
68+
login ({ commit }, data) {
69+
return new Promise((resolve, reject) => {
70+
commit('setPrivateKey', data.privateKey)
71+
commit('setPublicKey', data.publicKey)
72+
commit('setAccountName', data.accountName)
73+
commit('setLoggedIn')
74+
resolve()
75+
})
76+
},
77+
logout ({ commit }) {
78+
return new Promise((resolve, reject) => {
79+
commit('logout')
80+
resolve()
81+
})
82+
}
5183
}
5284
})
5385

src/util/utils.js

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
import Vue from 'vue'
12
import { shell } from 'electron'
3+
import EosWrapper from '@/util/EosWrapper'
4+
import { userError } from '@/util/errorHandler'
5+
import { userResult } from '@/util/resultHandler'
6+
import axios from 'axios'
27
import store from '@/store'
8+
import router from '@/router'
9+
const { app, dialog } = require('electron').remote
10+
const fs = require('fs')
311

412
/**
513
* Function returns an array with removed duplicates by any field in the object
@@ -66,10 +74,88 @@ function formatBytes (bytes, decimals) {
6674
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
6775
}
6876

77+
async function login (privateKey) {
78+
try {
79+
var eos = new EosWrapper(privateKey)
80+
Vue.prototype.$eos = eos
81+
} catch (error) {
82+
userError(error, 'Login action: instance of EosWrapper')
83+
throw error
84+
}
85+
86+
try {
87+
var publicKey = eos.privateToPublic(privateKey)
88+
} catch (error) {
89+
userError(error, 'Login action: get public key')
90+
throw error
91+
}
92+
93+
try {
94+
let accounts = await eos.getAccounts(publicKey)
95+
var accountName = accounts.account_names[0] ? accounts.account_names[0] : ''
96+
if (!accountName) {
97+
userError('Seems like you don\'t have an EOS account. An account is required to work with a vDexNode. Please create one using your public key.', 'Login action: get account name')
98+
throw new Error('EOS account is required')
99+
}
100+
} catch (error) {
101+
userError(error, 'Login action: get account name')
102+
throw error
103+
}
104+
105+
store.dispatch('login', { privateKey, publicKey, accountName }).then(() => {
106+
router.push('/')
107+
}).catch(error => {
108+
userError(error, 'Login action: Saving')
109+
})
110+
}
111+
112+
function logout () {
113+
store.dispatch('logout').then(() => {
114+
router.push('/login')
115+
})
116+
}
117+
118+
function getInstaller () {
119+
let way = process.env.NODE_WAY
120+
if (way.includes('readme')) {
121+
require('electron').shell.openExternal(process.env.README)
122+
} else if (way.includes('installer')) {
123+
axios({
124+
method: 'get',
125+
url: process.env.INSTALLER,
126+
responseType: 'arraybuffer'
127+
}).then(response => {
128+
forceFileDownload(response)
129+
}).catch((error) => {
130+
userError(error, 'Get Installer action')
131+
throw error
132+
})
133+
}
134+
}
135+
136+
function forceFileDownload (response) {
137+
var options = {
138+
title: 'Save installer',
139+
defaultPath: 'installer',
140+
buttonLabel: 'Save',
141+
142+
filters: [
143+
{ name: 'sh', extensions: ['sh'] }
144+
]
145+
}
146+
147+
dialog.showSaveDialog(options, (filename) => {
148+
fs.writeFileSync(filename, response.data, 'utf-8')
149+
})
150+
}
151+
69152
export {
70153
getUnique,
71154
sortByKey,
72155
openExternal,
73156
formatBytes,
74-
getUniqueLocations
157+
getUniqueLocations,
158+
login,
159+
logout,
160+
getInstaller
75161
}

0 commit comments

Comments
 (0)