update api calls for Tool views

This commit is contained in:
axolotle 2021-02-19 18:52:54 +01:00
parent bad17d01ef
commit b65bd23d08
6 changed files with 70 additions and 52 deletions

View file

@ -40,20 +40,24 @@ export default {
}, },
methods: { methods: {
onSubmit ({ password, currentPassword }) { onSubmit ({ currentPassword, password }) {
this.serverError = '' this.serverError = ''
// Use `api.fetch` to avoid automatic redirect on 401 (Unauthorized).
api.fetch('POST', 'login', { password: currentPassword }).then(response => { api.fetchAll(
if (response.status === 401) { [['POST', 'login', { password: currentPassword }, { websocket: false }],
// Dispatch `SERVER_RESPONDED` to hide waiting overlay and display error. ['PUT', 'admisnpw', { new_password: password }]],
this.$store.dispatch('SERVER_RESPONDED', true) { wait: true }
this.serverError = this.$i18n.t('wrong_password') ).then(() => {
} else if (response.ok) {
api.put('adminpw', { new_password: password }).then(() => {
this.$store.dispatch('DISCONNECT') this.$store.dispatch('DISCONNECT')
}).catch(error => { }).catch(err => {
this.serverError = error.message if (err.name === 'APIUnauthorizedError') {
}) // Prevent automatic disconnect if error in current password.
this.serverError = this.$i18n.t('wrong_password')
} else if (err.name === 'APIBadRequestError') {
// Display form error
this.serverError = err.message
} else {
throw err
} }
}) })
} }

View file

@ -1,6 +1,6 @@
<template> <template>
<view-base <view-base
:queries="queries" @queries-response="formatFirewallData" :queries="queries" @queries-response="onQueriesResponse"
ref="view" skeleton="card-form-skeleton" ref="view" skeleton="card-form-skeleton"
> >
<!-- PORTS --> <!-- PORTS -->
@ -98,7 +98,9 @@ export default {
data () { data () {
return { return {
queries: ['/firewall?raw'], queries: [
['GET', '/firewall?raw']
],
serverError: '', serverError: '',
// Ports tables data // Ports tables data
@ -145,7 +147,7 @@ export default {
}, },
methods: { methods: {
formatFirewallData (data) { onQueriesResponse (data) {
const ports = Object.values(data).reduce((ports, protocols) => { const ports = Object.values(data).reduce((ports, protocols) => {
for (const type of ['TCP', 'UDP']) { for (const type of ['TCP', 'UDP']) {
for (const port of protocols[type]) { for (const port of protocols[type]) {
@ -181,7 +183,11 @@ export default {
).then(confirmed => { ).then(confirmed => {
if (confirmed) { if (confirmed) {
const method = action === 'open' ? 'post' : 'delete' const method = action === 'open' ? 'post' : 'delete'
api[method](`/firewall/port?${connection}_only`, { port, protocol }).then(() => { api[method](
`/firewall/port?${connection}_only`,
{ port, protocol },
{ wait: false }
).then(() => {
resolve(confirmed) resolve(confirmed)
}).catch(error => { }).catch(error => {
reject(error) reject(error)
@ -198,10 +204,11 @@ export default {
const confirmed = await this.$askConfirmation(this.$i18n.t('confirm_upnp_' + action)) const confirmed = await this.$askConfirmation(this.$i18n.t('confirm_upnp_' + action))
if (!confirmed) return if (!confirmed) return
api.get('firewall/upnp?action=' + action).then(() => { api.get('firewall/upnp?action=' + action, null, { websocket: true, wait: true }).then(() => {
// FIXME Couldn't test when it works. // FIXME Couldn't test when it works.
this.$refs.view.fetchQueries() this.$refs.view.fetchQueries()
}).catch(err => { }).catch(err => {
if (err.name !== 'APIBadRequestError') throw err
this.upnpError = err.message this.upnpError = err.message
}) })
}, },

View file

@ -1,6 +1,6 @@
<template> <template>
<view-base <view-base
:queries="queries" @queries-response="formatLogData" :queries="queries" @queries-response="onQueriesResponse"
ref="view" skeleton="card-info-skeleton" ref="view" skeleton="card-info-skeleton"
> >
<!-- INFO CARD --> <!-- INFO CARD -->
@ -90,12 +90,12 @@ export default {
with_suboperations: '', with_suboperations: '',
number: this.numberOfLines number: this.numberOfLines
}) })
return [`logs/${this.name}?${queryString}`] return [['GET', `logs/${this.name}?${queryString}`]]
} }
}, },
methods: { methods: {
formatLogData (log) { onQueriesResponse (log) {
if (log.logs.length === this.numberOfLines) { if (log.logs.length === this.numberOfLines) {
this.moreLogsAvailable = true this.moreLogsAvailable = true
this.numberOfLines *= 10 this.numberOfLines *= 10
@ -125,7 +125,7 @@ export default {
}, },
shareLogs () { shareLogs () {
api.get(`/logs/${this.name}?share`).then(({ url }) => { api.get(`logs/${this.name}?share`, null, { websocket: true }).then(({ url }) => {
window.open(url, '_blank') window.open(url, '_blank')
}) })
} }

View file

@ -5,7 +5,7 @@
:filtered-items="filteredOperations" :filtered-items="filteredOperations"
items-name="logs" items-name="logs"
:queries="queries" :queries="queries"
@queries-response="formatLogsData" @queries-response="onQueriesResponse"
skeleton="card-list-skeleton" skeleton="card-list-skeleton"
> >
<card :title="$t('logs_operation')" icon="wrench" no-body> <card :title="$t('logs_operation')" icon="wrench" no-body>
@ -32,7 +32,9 @@ export default {
data () { data () {
return { return {
queries: [`logs?limit=${25}&with_details`], queries: [
['GET', `logs?limit=${25}&with_details`]
],
search: '', search: '',
operations: undefined operations: undefined
} }
@ -50,7 +52,7 @@ export default {
}, },
methods: { methods: {
formatLogsData ({ operation }) { onQueriesResponse ({ operation }) {
operation.forEach((log, index) => { operation.forEach((log, index) => {
if (log.success === '?') { if (log.success === '?') {
operation[index].icon = 'question' operation[index].icon = 'question'

View file

@ -1,5 +1,5 @@
<template> <template>
<view-base :queries="queries" @queries-response="formatMigrationsData" ref="view"> <view-base :queries="queries" @queries-response="onQueriesResponse" ref="view">
<!-- PENDING MIGRATIONS --> <!-- PENDING MIGRATIONS -->
<card :title="$t('migrations_pending')" icon="cogs" no-body> <card :title="$t('migrations_pending')" icon="cogs" no-body>
<template #header-buttons v-if="pending"> <template #header-buttons v-if="pending">
@ -90,8 +90,8 @@ export default {
data () { data () {
return { return {
queries: [ queries: [
'migrations?pending', ['GET', 'migrations?pending'],
'migrations?done' ['GET', 'migrations?done']
], ],
pending: undefined, pending: undefined,
done: undefined, done: undefined,
@ -100,7 +100,7 @@ export default {
}, },
methods: { methods: {
formatMigrationsData ({ migrations: pending }, { migrations: done }) { onQueriesResponse ({ migrations: pending }, { migrations: done }) {
this.done = done.length ? done.reverse() : null this.done = done.length ? done.reverse() : null
pending.forEach(migration => { pending.forEach(migration => {
if (migration.disclaimer) { if (migration.disclaimer) {

View file

@ -1,16 +1,17 @@
<template> <template>
<div> <div>
<div v-if="inProcess"> <template v-if="canReconnect">
<b-alert variant="success" v-t="'tools_power_up'" />
<login-view />
</template>
<div v-else-if="inProcess">
<b-alert variant="info" v-t="'tools_' + action + '_done'" /> <b-alert variant="info" v-t="'tools_' + action + '_done'" />
<b-alert variant="warning"> <b-alert variant="warning">
<icon :iname="action === 'reboot' ? 'refresh' : 'power-off'" /> <icon :iname="action === 'reboot' ? 'refresh' : 'power-off'" />
{{ $t(action === 'reboot' ? 'tools_rebooting' : 'tools_shuttingdown') }} {{ $t(action === 'reboot' ? 'tools_rebooting' : 'tools_shuttingdown') }}
</b-alert> </b-alert>
<template v-if="canReconnect">
<b-alert variant="success" v-t="'tools_power_up'" />
<login-view />
</template>
</div> </div>
<card v-else :title="$t('operations')" icon="wrench"> <card v-else :title="$t('operations')" icon="wrench">
@ -45,6 +46,10 @@ import LoginView from '@/views/Login'
export default { export default {
name: 'ToolPower', name: 'ToolPower',
components: {
LoginView
},
data () { data () {
return { return {
action: '', action: '',
@ -65,29 +70,29 @@ export default {
// Use 'RESET_CONNECTED' and not 'DISCONNECT' else user will be redirect to login // Use 'RESET_CONNECTED' and not 'DISCONNECT' else user will be redirect to login
this.$store.dispatch('RESET_CONNECTED') this.$store.dispatch('RESET_CONNECTED')
this.inProcess = true this.inProcess = true
this.tryToReconnect() return this.tryToReconnect(4000)
}).then(() => {
this.canReconnect = true
}) })
}, },
tryToReconnect () { tryToReconnect (delay = 2000) {
// FIXME need to be tested out of webpack-dev-server // FIXME need to be tested out of webpack-dev-server
return new Promise(resolve => {
setTimeout(() => { setTimeout(() => {
// Try to get a response from the server after boot/reboot // Try to get a response from the server after boot/reboot
// use `api.fetch` to not trigger base response handlers api.get('logout').catch(err => {
api.fetch('GET', 'logout').then(response => { if (err.name === 'APIUnauthorizedError') {
// Server responds with `Unauthorized`, we can display the login input // Means the server is accessible
if (response.status === 401) { resolve()
this.canReconnect = true
} else { } else {
this.tryToReconnect() // FIXME could be improved by checking error types since yunohost
resolve(this.tryToReconnect())
} }
}).catch(() => {
this.tryToReconnect()
}) })
}, 1000) }, delay)
})
}
} }
},
components: { LoginView }
} }
</script> </script>