mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
update PasswordForm and views with validations
This commit is contained in:
parent
1a19f9ef21
commit
6cb9089604
3 changed files with 95 additions and 127 deletions
|
@ -1,119 +1,84 @@
|
||||||
<template>
|
<template>
|
||||||
<b-card header-tag="h2" class="basic-form">
|
<card-form
|
||||||
<template v-slot:header>
|
:title="title" icon="key-modern" :submit-text="submitText"
|
||||||
<h2><icon iname="key-modern" /> {{ title }}</h2>
|
:validation="$v" :server-error="serverError"
|
||||||
</template>
|
@submit.prevent="onSubmit"
|
||||||
|
>
|
||||||
<b-form id="password-form" @submit.prevent="onSubmit">
|
<template #disclaimer>
|
||||||
<b-alert variant="warning" show>
|
<b-alert variant="warning" show>
|
||||||
{{ $t('good_practices_about_admin_password') }}
|
{{ $t('good_practices_about_admin_password') }}
|
||||||
</b-alert>
|
</b-alert>
|
||||||
|
<slot name="disclaimer" />
|
||||||
<slot name="message" />
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
{{ $v.form.currentPassword }}
|
||||||
<slot name="input" />
|
|
||||||
|
|
||||||
<!-- PASSWORD -->
|
|
||||||
<input-helper
|
|
||||||
id="password" type="password" :label="$t('password_new')"
|
|
||||||
v-model="form.password" :placeholder="$t('tools_adminpw_new_placeholder')"
|
|
||||||
:state="isValid.password" :error="error.password"
|
|
||||||
@input="validateNewPassword"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- PASSWORD CONFIRMATION -->
|
|
||||||
<input-helper
|
|
||||||
id="confirmation" type="password" :label="$t('password_confirmation')"
|
|
||||||
v-model="form.confirmation" :placeholder="$t('tools_adminpw_confirm_placeholder')"
|
|
||||||
:state="isValid.confirmation" :error="$t('passwords_dont_match')"
|
|
||||||
@input="validateNewPassword"
|
|
||||||
/>
|
|
||||||
</b-form>
|
|
||||||
|
|
||||||
<template v-slot:footer>
|
|
||||||
<b-button
|
|
||||||
type="submit" form="password-form" variant="success"
|
|
||||||
:disabled="!everythingValid"
|
|
||||||
>
|
|
||||||
{{ submitText ? submitText : $t('save') }}
|
|
||||||
</b-button>
|
|
||||||
</template>
|
</template>
|
||||||
</b-card>
|
|
||||||
|
<slot name="extra-fields" v-bind="{ v: $v, fields, form }" />
|
||||||
|
|
||||||
|
<!-- ADMIN PASSWORD -->
|
||||||
|
<form-field v-bind="fields.password" v-model="form.password" :validation="$v.form.password" />
|
||||||
|
|
||||||
|
<!-- ADMIN PASSWORD CONFIRMATION -->
|
||||||
|
<form-field v-bind="fields.confirmation" v-model="form.confirmation" :validation="$v.form.confirmation" />
|
||||||
|
</card-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import InputHelper from '@/components/InputHelper'
|
import { validationMixin } from 'vuelidate'
|
||||||
|
|
||||||
|
import { required, minLength, sameAs } from '@/helpers/validators'
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PasswordForm',
|
name: 'PasswordForm',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
title: {
|
title: { type: String, required: true },
|
||||||
type: String,
|
submitText: { type: String, default: null },
|
||||||
required: true
|
serverError: { type: String, default: '' },
|
||||||
},
|
extra: { type: Object, default: () => ({ form: {}, fields: {}, validations: {} }) }
|
||||||
submitText: {
|
|
||||||
type: String,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
isValid: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({
|
|
||||||
password: null,
|
|
||||||
confirmation: null
|
|
||||||
})
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({
|
|
||||||
password: '',
|
|
||||||
confirmation: ''
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
password: '',
|
password: '',
|
||||||
confirmation: ''
|
confirmation: '',
|
||||||
|
...this.extra.form
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: {
|
||||||
|
password: {
|
||||||
|
label: this.$i18n.t('password'),
|
||||||
|
props: { id: 'password', type: 'password', placeholder: '••••••••' }
|
||||||
|
},
|
||||||
|
|
||||||
|
confirmation: {
|
||||||
|
label: this.$i18n.t('password_confirmation'),
|
||||||
|
props: { id: 'confirmation', type: 'password', placeholder: '••••••••' }
|
||||||
|
},
|
||||||
|
|
||||||
|
...this.extra.fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
validations () {
|
||||||
everythingValid () {
|
return {
|
||||||
for (const key in this.isValid) {
|
form: {
|
||||||
if (this.form[key] === '') return false
|
password: { required, passwordLenght: minLength(8) },
|
||||||
if (this.isValid[key] === false) return false
|
confirmation: { required, passwordMatch: sameAs('password') },
|
||||||
|
...this.extra.validations
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onSubmit () {
|
onSubmit () {
|
||||||
if (this.everythingValid) {
|
this.$emit('submit', this.form)
|
||||||
this.$emit('submit', this.form.password)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
isValidPassword (password) {
|
mixins: [validationMixin]
|
||||||
return password.length >= 8 ? null : false
|
|
||||||
},
|
|
||||||
|
|
||||||
validateNewPassword () {
|
|
||||||
const { password, confirmation } = this.form
|
|
||||||
this.error.password = this.$i18n.t('passwords_too_short')
|
|
||||||
this.isValid.password = this.isValidPassword(password)
|
|
||||||
this.isValid.confirmation = password === confirmation ? null : false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
components: {
|
|
||||||
InputHelper
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
<!-- DOMAIN SETUP STEP -->
|
<!-- DOMAIN SETUP STEP -->
|
||||||
<template v-else-if="step === 'domain'">
|
<template v-else-if="step === 'domain'">
|
||||||
<domain-form :title="$t('postinstall_set_domain')" :submit-text="$t('next')" @submit.prevent="setDomain">
|
<domain-form :title="$t('postinstall_set_domain')" :submit-text="$t('next')" @submit="setDomain">
|
||||||
<template #disclaimer>
|
<template #disclaimer>
|
||||||
<b-alert variant="warning" show v-t="'postinstall_domain'" />
|
<b-alert variant="warning" show v-t="'postinstall_domain'" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -30,8 +30,8 @@
|
||||||
|
|
||||||
<!-- 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.prevent="setPassword">
|
<password-form :title="$t('postinstall_set_password')" :submit-text="$t('next')" @submit="setPassword">
|
||||||
<template v-slot:message>
|
<template #disclaimer>
|
||||||
<b-alert variant="warning" show v-t="'postinstall_password'" />
|
<b-alert variant="warning" show v-t="'postinstall_password'" />
|
||||||
</template>
|
</template>
|
||||||
</password-form>
|
</password-form>
|
||||||
|
@ -82,7 +82,7 @@ export default {
|
||||||
this.step = 'password'
|
this.step = 'password'
|
||||||
},
|
},
|
||||||
|
|
||||||
setPassword (password) {
|
setPassword ({ password }) {
|
||||||
this.password = password
|
this.password = password
|
||||||
this.$refs['post-install-modal'].show()
|
this.$refs['post-install-modal'].show()
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<password-form
|
<password-form
|
||||||
:title="$t('postinstall_set_password')" :submit-text="$t('next')"
|
:title="$t('postinstall_set_password')"
|
||||||
:error="error" :is-valid="isValid"
|
:server-error="serverError"
|
||||||
@submit="onSubmit"
|
@submit="onSubmit"
|
||||||
|
:extra="extra"
|
||||||
>
|
>
|
||||||
<template v-slot:input>
|
<template #extra-fields="{ v, fields, form }">
|
||||||
<!-- CURRENT ADMIN PASSWORD -->
|
<!-- CURRENT ADMIN PASSWORD -->
|
||||||
<input-helper
|
<form-field v-bind="fields.currentPassword" v-model="form.currentPassword" :validation="v.form.currentPassword" />
|
||||||
id="current-password" type="password" :label="$t('tools_adminpw_current')"
|
|
||||||
v-model="currentPassword" :placeholder="$t('tools_adminpw_current_placeholder')"
|
|
||||||
:state="isValid.currentPassword" :error="error.currentPassword"
|
|
||||||
@input="validateCurrentPassword"
|
|
||||||
/>
|
|
||||||
<hr>
|
<hr>
|
||||||
</template>
|
</template>
|
||||||
</password-form>
|
</password-form>
|
||||||
|
@ -19,53 +15,60 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
import { validationMixin } from 'vuelidate'
|
||||||
|
|
||||||
import { PasswordForm } from '@/components/reusableForms'
|
import { PasswordForm } from '@/components/reusableForms'
|
||||||
import InputHelper from '@/components/InputHelper'
|
import { required, minLength } from '@/helpers/validators'
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ToolAdminpw',
|
name: 'ToolAdminpw',
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
currentPassword: '',
|
serverError: '',
|
||||||
isValid: {
|
|
||||||
currentPassword: null,
|
extra: {
|
||||||
password: null,
|
form: {
|
||||||
confirmation: null
|
currentPassword: ''
|
||||||
},
|
},
|
||||||
error: {
|
fields: {
|
||||||
currentPassword: '',
|
currentPassword: {
|
||||||
password: '',
|
label: this.$i18n.t('tools_adminpw_current'),
|
||||||
confirmation: ''
|
description: this.$i18n.t('tools_adminpw_current_placeholder'),
|
||||||
|
props: { id: 'current-password', type: 'password', placeholder: '••••••••' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validations: {
|
||||||
|
currentPassword: { required, passwordLenght: minLength(8) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onSubmit (password) {
|
onSubmit ({ password, currentPassword }) {
|
||||||
if (this.isValid.currentPassword === false) return
|
this.serverError = ''
|
||||||
|
// Use `api.fetch` to avoid automatic redirect on 401 (Unauthorized).
|
||||||
api.post('login', { password: this.currentPassword }).then(() => {
|
api.fetch('POST', 'login', { password: currentPassword }).then(response => {
|
||||||
|
if (response.status === 401) {
|
||||||
|
// Dispatch `SERVER_RESPONDED` to hide waiting overlay and display error.
|
||||||
|
this.$store.dispatch('SERVER_RESPONDED', true)
|
||||||
|
this.serverError = this.$i18n.t('wrong_password')
|
||||||
|
} else if (response.ok) {
|
||||||
api.put('adminpw', { new_password: password }).then(() => {
|
api.put('adminpw', { new_password: password }).then(() => {
|
||||||
this.$store.dispatch('DISCONNECT')
|
this.$store.dispatch('DISCONNECT')
|
||||||
}).catch(err => {
|
}).catch(error => {
|
||||||
this.error.password = err.message
|
this.serverError = error.message
|
||||||
this.isValid.password = false
|
|
||||||
})
|
})
|
||||||
}).catch(() => {
|
}
|
||||||
this.error.currentPassword = this.$i18n.t('wrong_password')
|
|
||||||
this.isValid.currentPassword = false
|
|
||||||
})
|
})
|
||||||
},
|
|
||||||
|
|
||||||
validateCurrentPassword () {
|
|
||||||
this.error.currentPassword = this.$i18n.t('passwords_too_short')
|
|
||||||
this.isValid.currentPassword = this.currentPassword.length >= 8 ? null : false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mixins: [validationMixin],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
InputHelper,
|
|
||||||
PasswordForm
|
PasswordForm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue