update PasswordForm and views with validations

This commit is contained in:
Axolotle 2020-10-30 17:23:24 +01:00
parent 1a19f9ef21
commit 6cb9089604
3 changed files with 95 additions and 127 deletions

View file

@ -1,119 +1,84 @@
<template>
<b-card header-tag="h2" class="basic-form">
<template v-slot:header>
<h2><icon iname="key-modern" /> {{ title }}</h2>
</template>
<b-form id="password-form" @submit.prevent="onSubmit">
<card-form
:title="title" icon="key-modern" :submit-text="submitText"
:validation="$v" :server-error="serverError"
@submit.prevent="onSubmit"
>
<template #disclaimer>
<b-alert variant="warning" show>
{{ $t('good_practices_about_admin_password') }}
</b-alert>
<slot name="message" />
<slot name="disclaimer" />
<hr>
<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>
{{ $v.form.currentPassword }}
</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>
<script>
import InputHelper from '@/components/InputHelper'
import { validationMixin } from 'vuelidate'
import { required, minLength, sameAs } from '@/helpers/validators'
export default {
name: 'PasswordForm',
props: {
title: {
type: String,
required: true
},
submitText: {
type: String,
default: null
},
isValid: {
type: Object,
default: () => ({
password: null,
confirmation: null
})
},
error: {
type: Object,
default: () => ({
password: '',
confirmation: ''
})
}
title: { type: String, required: true },
submitText: { type: String, default: null },
serverError: { type: String, default: '' },
extra: { type: Object, default: () => ({ form: {}, fields: {}, validations: {} }) }
},
data () {
return {
form: {
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: {
everythingValid () {
for (const key in this.isValid) {
if (this.form[key] === '') return false
if (this.isValid[key] === false) return false
validations () {
return {
form: {
password: { required, passwordLenght: minLength(8) },
confirmation: { required, passwordMatch: sameAs('password') },
...this.extra.validations
}
return true
}
},
methods: {
onSubmit () {
if (this.everythingValid) {
this.$emit('submit', this.form.password)
}
},
isValidPassword (password) {
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
this.$emit('submit', this.form)
}
},
components: {
InputHelper
}
mixins: [validationMixin]
}
</script>

View file

@ -17,7 +17,7 @@
<!-- DOMAIN SETUP STEP -->
<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>
<b-alert variant="warning" show v-t="'postinstall_domain'" />
</template>
@ -30,8 +30,8 @@
<!-- PASSWORD SETUP STEP -->
<template v-else-if="step === 'password'">
<password-form :title="$t('postinstall_set_password')" :submit-text="$t('next')" @submit.prevent="setPassword">
<template v-slot:message>
<password-form :title="$t('postinstall_set_password')" :submit-text="$t('next')" @submit="setPassword">
<template #disclaimer>
<b-alert variant="warning" show v-t="'postinstall_password'" />
</template>
</password-form>
@ -82,7 +82,7 @@ export default {
this.step = 'password'
},
setPassword (password) {
setPassword ({ password }) {
this.password = password
this.$refs['post-install-modal'].show()
},

View file

@ -1,17 +1,13 @@
<template>
<password-form
:title="$t('postinstall_set_password')" :submit-text="$t('next')"
:error="error" :is-valid="isValid"
:title="$t('postinstall_set_password')"
:server-error="serverError"
@submit="onSubmit"
:extra="extra"
>
<template v-slot:input>
<template #extra-fields="{ v, fields, form }">
<!-- CURRENT ADMIN PASSWORD -->
<input-helper
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"
/>
<form-field v-bind="fields.currentPassword" v-model="form.currentPassword" :validation="v.form.currentPassword" />
<hr>
</template>
</password-form>
@ -19,53 +15,60 @@
<script>
import api from '@/api'
import { validationMixin } from 'vuelidate'
import { PasswordForm } from '@/components/reusableForms'
import InputHelper from '@/components/InputHelper'
import { required, minLength } from '@/helpers/validators'
export default {
name: 'ToolAdminpw',
data () {
return {
currentPassword: '',
isValid: {
currentPassword: null,
password: null,
confirmation: null
},
error: {
currentPassword: '',
password: '',
confirmation: ''
serverError: '',
extra: {
form: {
currentPassword: ''
},
fields: {
currentPassword: {
label: this.$i18n.t('tools_adminpw_current'),
description: this.$i18n.t('tools_adminpw_current_placeholder'),
props: { id: 'current-password', type: 'password', placeholder: '••••••••' }
}
},
validations: {
currentPassword: { required, passwordLenght: minLength(8) }
}
}
}
},
methods: {
onSubmit (password) {
if (this.isValid.currentPassword === false) return
api.post('login', { password: this.currentPassword }).then(() => {
api.put('adminpw', { new_password: password }).then(() => {
this.$store.dispatch('DISCONNECT')
}).catch(err => {
this.error.password = err.message
this.isValid.password = false
})
}).catch(() => {
this.error.currentPassword = this.$i18n.t('wrong_password')
this.isValid.currentPassword = false
onSubmit ({ password, currentPassword }) {
this.serverError = ''
// Use `api.fetch` to avoid automatic redirect on 401 (Unauthorized).
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(() => {
this.$store.dispatch('DISCONNECT')
}).catch(error => {
this.serverError = error.message
})
}
})
},
validateCurrentPassword () {
this.error.currentPassword = this.$i18n.t('passwords_too_short')
this.isValid.currentPassword = this.currentPassword.length >= 8 ? null : false
}
},
mixins: [validationMixin],
components: {
InputHelper,
PasswordForm
}
}