Merge pull request #349 from YunoHost/fix-postinstall-diskspace

Fix postinstall validation errors and add --force-diskspace admin equivalent
This commit is contained in:
Alexandre Aubin 2021-04-10 20:14:10 +02:00 committed by GitHub
commit 1d67aaf141
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 16 deletions

View file

@ -47,6 +47,7 @@ class APIBadRequestError extends APIError {
constructor (method, response, errorData) { constructor (method, response, errorData) {
super(method, response, errorData) super(method, response, errorData)
this.name = 'APIBadRequestError' this.name = 'APIBadRequestError'
this.key = errorData.error_key
} }
} }

View file

@ -10,7 +10,10 @@
<slot name="default" /> <slot name="default" />
<slot name="server-error"> <slot name="server-error">
<b-alert variant="danger" :show="serverError !== ''" v-html="serverError" /> <b-alert
variant="danger" class="my-3"
:show="serverError !== ''" v-html="serverError"
/>
</slot> </slot>
</b-form> </b-form>
</template> </template>

View file

@ -314,6 +314,9 @@
"permission_show_tile_enabled": "Visible as tile in user portal", "permission_show_tile_enabled": "Visible as tile in user portal",
"port": "Port", "port": "Port",
"ports": "Ports", "ports": "Ports",
"postinstall": {
"force": "Force the post-install"
},
"postinstall_domain": "This is the first domain name linked to your YunoHost server, but also the one which will be used by your server's users to access the authentication portal. Accordingly, it will be visible by everyone, so choose it carefully.", "postinstall_domain": "This is the first domain name linked to your YunoHost server, but also the one which will be used by your server's users to access the authentication portal. Accordingly, it will be visible by everyone, so choose it carefully.",
"postinstall_intro_1": "Congratulations! YunoHost has been successfully installed.", "postinstall_intro_1": "Congratulations! YunoHost has been successfully installed.",
"postinstall_intro_2": "Two more configuration steps are required to activate you server's services.", "postinstall_intro_2": "Two more configuration steps are required to activate you server's services.",

View file

@ -32,9 +32,13 @@
export default { export default {
name: 'Login', name: 'Login',
props: {
skipInstallCheck: { type: Boolean, default: false }
},
data () { data () {
return { return {
disabled: true, disabled: !this.skipInstallCheck,
password: '', password: '',
isValid: null, isValid: null,
apiError: undefined apiError: undefined
@ -51,6 +55,7 @@ export default {
}, },
created () { created () {
if (this.skipInstallCheck) return
this.$store.dispatch('CHECK_INSTALL').then(installed => { this.$store.dispatch('CHECK_INSTALL').then(installed => {
if (installed) { if (installed) {
this.disabled = false this.disabled = false

View file

@ -12,43 +12,63 @@
<span v-html="$t('postinstall_intro_3')" /> <span v-html="$t('postinstall_intro_3')" />
</p> </p>
<b-button size="lg" variant="primary" @click="step = 'domain'"> <b-button size="lg" variant="primary" @click="goToStep('domain')">
{{ $t('begin') }} {{ $t('begin') }}
</b-button> </b-button>
</template> </template>
<!-- DOMAIN SETUP STEP --> <!-- DOMAIN SETUP STEP -->
<template v-else-if="step === 'domain'"> <template v-else-if="step === 'domain'">
<domain-form @submit="setDomain" :title="$t('postinstall_set_domain')" :submit-text="$t('next')"> <domain-form
:title="$t('postinstall_set_domain')" :submit-text="$t('next')" :server-error="serverError"
@submit="setDomain"
>
<template #disclaimer> <template #disclaimer>
<p class="alert alert-info" v-t="'postinstall_domain'" /> <p class="alert alert-info" v-t="'postinstall_domain'" />
</template> </template>
</domain-form> </domain-form>
<b-button variant="primary" @click="step = 'start'" class="mt-3"> <b-button variant="primary" @click="goToStep('start')" class="mt-3">
<icon iname="chevron-left" /> {{ $t('previous') }} <icon iname="chevron-left" /> {{ $t('previous') }}
</b-button> </b-button>
</template> </template>
<!-- PASSWORD SETUP STEP --> <!-- PASSWORD SETUP STEP -->
<template v-else-if="step === 'password'"> <template v-else-if="step === 'password'">
<password-form :title="$t('postinstall_set_password')" :submit-text="$t('next')" @submit="setPassword"> <password-form
:title="$t('postinstall_set_password')" :submit-text="$t('next')" :server-error="serverError"
@submit="setPassword"
>
<template #disclaimer> <template #disclaimer>
<p class="alert alert-warning" v-t="'postinstall_password'" /> <p class="alert alert-warning" v-t="'postinstall_password'" />
</template> </template>
</password-form> </password-form>
<b-button variant="primary" @click="step = 'domain'" class="mt-3"> <b-button variant="primary" @click="goToStep('domain')" class="mt-3">
<icon iname="chevron-left" /> {{ $t('previous') }} <icon iname="chevron-left" /> {{ $t('previous') }}
</b-button> </b-button>
</template> </template>
<template v-else-if="step === 'rootfsspace-error'">
<card no-body header-class="d-none" footer-bg-variant="danger">
<b-card-body class="alert alert-danger m-0">
{{ serverError }}
</b-card-body>
<template #buttons>
<b-button variant="light" size="sm" @click="performPostInstall(true)">
<icon iname="warning" /> {{ $t('postinstall.force') }}
</b-button>
</template>
</card>
</template>
<!-- POST-INSTALL SUCCESS STEP --> <!-- POST-INSTALL SUCCESS STEP -->
<template v-else-if="step === 'login'"> <template v-else-if="step === 'login'">
<p class="alert alert-success"> <p class="alert alert-success">
<icon iname="thumbs-up" /> {{ $t('installation_complete') }} <icon iname="thumbs-up" /> {{ $t('installation_complete') }}
</p> </p>
<login /> <login skip-install-check />
</template> </template>
</div> </div>
</template> </template>
@ -71,14 +91,20 @@ export default {
return { return {
step: 'start', step: 'start',
domain: undefined, domain: undefined,
password: undefined password: undefined,
serverError: ''
} }
}, },
methods: { methods: {
goToStep (step) {
this.serverError = ''
this.step = step
},
setDomain ({ domain }) { setDomain ({ domain }) {
this.domain = domain this.domain = domain
this.step = 'password' this.goToStep('password')
}, },
async setPassword ({ password }) { async setPassword ({ password }) {
@ -90,11 +116,23 @@ export default {
this.performPostInstall() this.performPostInstall()
}, },
performPostInstall () { performPostInstall (force = false) {
// FIXME does the api will throw an error for bad passwords ? // FIXME does the api will throw an error for bad passwords ?
api.post('postinstall', { domain: this.domain, password: this.password }).then(data => { api.post('postinstall' + (force ? '?force_diskspace' : ''), { domain: this.domain, password: this.password }).then(data => {
// Display success message and allow the user to login // Display success message and allow the user to login
this.step = 'login' this.goToStep('login')
}).catch(err => {
if (err.name !== 'APIBadRequestError') throw err
if (err.key === 'postinstall_low_rootfsspace') {
this.step = 'rootfsspace-error'
} else if (err.key.includes('password')) {
this.step = 'password'
} else if (['domain', 'dyndns'].some(word => err.key.includes(word))) {
this.step = 'domain'
} else {
throw err
}
this.serverError = err.message
}) })
} }
}, },

View file

@ -61,9 +61,7 @@ export default {
props: { props: {
title: { type: String, required: true }, title: { type: String, required: true },
submitText: { type: String, default: null }, submitText: { type: String, default: null },
serverError: { type: String, default: '' }, serverError: { type: String, default: '' }
// Do not query the api (used by postinstall)
noStore: { type: Boolean, default: false }
}, },
data () { data () {