diff --git a/plugins/ui/files.go b/plugins/ui/files.go index 9af8e513f637c38ad2935bbce8db0d91c746fb06..9bd67d4be25af9bcfed545c7bacd8f76e9d0dab0 100644 --- a/plugins/ui/files.go +++ b/plugins/ui/files.go @@ -241,7 +241,10 @@ body.fade { <span>Password:</span> <input class="input" placeholder="Username" name="password"> </div> - <button type="submit" class="button is-primary">Login</button> + <button type="submit" :disabled="loginError?true:false" + :class="loginError?'button is-danger':'button is-primary'"> + {{ loginButtonText }} + </button> </form> </div> @@ -452,6 +455,7 @@ Vue.component('empty-icon', { info: {}, selectedTxHash:null, tps:0, + loginError:'', } `, "js/main.js":`new Vue({ @@ -469,9 +473,14 @@ Vue.component('empty-icon', { const formData = new FormData(e.target); const pass = formData.get('password') const user = formData.get('username') - const r = await api.get('login?username='+user+'&password='+pass) - if(r.token){ - this.init() + try{ + const r = await api.get('login?username='+user+'&password='+pass) + if(r.token){ + this.init() + } + }catch(e){ + this.loginError = 'Not Authorized' + setTimeout(()=>this.loginError='',2000) } }, async init() { @@ -499,11 +508,11 @@ Vue.component('empty-icon', { }, footerContainerStyle() { const size = Math.max(window.innerHeight-this.headerSize, 300) - return 'height:calc('+(size-1 )+'px - 3.6rem);' + return 'height:calc('+(size-1)+'px - 3.6rem);' }, startSpam() { console.log('start spam', this.tpsToSpam) - api.get('spammer?cmd=start&tps='+this.tpsToSpam+')') + api.get('spammer?cmd=start&tps='+this.tpsToSpam) }, stopSpam() { console.log('stop spam') @@ -576,6 +585,9 @@ Vue.component('empty-icon', { infoKeys() { return ['TPS', 'Node ID', 'Neighbors', 'Peers', 'Uptime'] }, + loginButtonText() { + return this.loginError || 'Login' + }, infoValues() { const i = this.info return i.id ? [ @@ -922,23 +934,37 @@ const logLevels = [{ const api = { get: async function(u) { const url = this.trim('/'+u) - const r = await fetch(this.addToken(url)) - const j = await r.json() - if(url.startsWith('login') && j.token) { - localStorage.setItem('token', j.token) - await sleep(1) + try{ + const r = await fetch(this.addToken(url)) + const j = await r.json() + if (!(r.status >= 200 && r.status < 300)) { + throw new Error(j) + } + if(url.startsWith('login') && j.token) { + localStorage.setItem('token', j.token) + await sleep(1) + } + return j + } catch(e) { + throw e } - return j }, post: async function(u, data){ const url = this.trim('/'+u) - const r = await fetch(this.addToken(url), { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - data: JSON.stringify(data) - }) - const j = await r.json() - return j + try{ + const r = await fetch(this.addToken(url), { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + data: JSON.stringify(data) + }) + const j = await r.json() + if (!(r.status >= 200 && r.status < 300)) { + throw new Error(j) + } + return j + } catch(e) { + throw e + } }, trim: function(s) { return s.replace(/^\//, ''); diff --git a/plugins/ui/src/index.html b/plugins/ui/src/index.html index 92448db2d841841522b5ceaa240bdacea1ca51ef..b3825fe06ea35507bd540845894c64578f8f702f 100644 --- a/plugins/ui/src/index.html +++ b/plugins/ui/src/index.html @@ -33,7 +33,10 @@ <span>Password:</span> <input class="input" placeholder="Username" name="password"> </div> - <button type="submit" class="button is-primary">Login</button> + <button type="submit" :disabled="loginError?true:false" + :class="loginError?'button is-danger':'button is-primary'"> + {{ loginButtonText }} + </button> </form> </div> diff --git a/plugins/ui/src/js/initials.js b/plugins/ui/src/js/initials.js index 93157c1ac6520edd8e3ccf0a6b551816bce889bb..d059a9d28337a0d42405b7311b6535070892bb1a 100644 --- a/plugins/ui/src/js/initials.js +++ b/plugins/ui/src/js/initials.js @@ -10,4 +10,5 @@ var initialData = { info: {}, selectedTxHash:null, tps:0, + loginError:'', } diff --git a/plugins/ui/src/js/main.js b/plugins/ui/src/js/main.js index c007ef90aa812bdb55f9e78467b22bb50f5ed47f..17f5a38827ef8d4922d40a3d6bcc4c3be4303dd5 100644 --- a/plugins/ui/src/js/main.js +++ b/plugins/ui/src/js/main.js @@ -13,9 +13,14 @@ new Vue({ const formData = new FormData(e.target); const pass = formData.get('password') const user = formData.get('username') - const r = await api.get('login?username='+user+'&password='+pass) - if(r.token){ - this.init() + try{ + const r = await api.get('login?username='+user+'&password='+pass) + if(r.token){ + this.init() + } + }catch(e){ + this.loginError = 'Not Authorized' + setTimeout(()=>this.loginError='',2000) } }, async init() { @@ -43,11 +48,11 @@ new Vue({ }, footerContainerStyle() { const size = Math.max(window.innerHeight-this.headerSize, 300) - return 'height:calc('+(size-1 )+'px - 3.6rem);' + return 'height:calc('+(size-1)+'px - 3.6rem);' }, startSpam() { console.log('start spam', this.tpsToSpam) - api.get('spammer?cmd=start&tps='+this.tpsToSpam+')') + api.get('spammer?cmd=start&tps='+this.tpsToSpam) }, stopSpam() { console.log('stop spam') @@ -120,6 +125,9 @@ new Vue({ infoKeys() { return ['TPS', 'Node ID', 'Neighbors', 'Peers', 'Uptime'] }, + loginButtonText() { + return this.loginError || 'Login' + }, infoValues() { const i = this.info return i.id ? [ diff --git a/plugins/ui/src/js/utils.js b/plugins/ui/src/js/utils.js index d61b55e13d864739b609cbbfe12e26dd8fe5cef3..5f99f30f5cca451b44d4ad4fe4ee122c087adac7 100644 --- a/plugins/ui/src/js/utils.js +++ b/plugins/ui/src/js/utils.js @@ -36,23 +36,37 @@ const logLevels = [{ const api = { get: async function(u) { const url = this.trim('/'+u) - const r = await fetch(this.addToken(url)) - const j = await r.json() - if(url.startsWith('login') && j.token) { - localStorage.setItem('token', j.token) - await sleep(1) + try{ + const r = await fetch(this.addToken(url)) + const j = await r.json() + if (!(r.status >= 200 && r.status < 300)) { + throw new Error(j) + } + if(url.startsWith('login') && j.token) { + localStorage.setItem('token', j.token) + await sleep(1) + } + return j + } catch(e) { + throw e } - return j }, post: async function(u, data){ const url = this.trim('/'+u) - const r = await fetch(this.addToken(url), { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - data: JSON.stringify(data) - }) - const j = await r.json() - return j + try{ + const r = await fetch(this.addToken(url), { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + data: JSON.stringify(data) + }) + const j = await r.json() + if (!(r.status >= 200 && r.status < 300)) { + throw new Error(j) + } + return j + } catch(e) { + throw e + } }, trim: function(s) { return s.replace(/^\//, '');