DRY up password validations

This commit is contained in:
Robert Schäfer 2019-07-08 18:57:57 +02:00
parent 47a9d38790
commit 4207aee09d
8 changed files with 88 additions and 122 deletions

View File

@ -278,7 +278,7 @@ When("I fill the password form with:", table => {
.type(table["Your old password"])
.get("input[id=newPassword]")
.type(table["Your new passsword"])
.get("input[id=confirmPassword]")
.get("input[id=passwordConfirmation]")
.type(table["Confirm new password"]);
});

View File

@ -54,7 +54,7 @@ describe('ChangePassword.vue', () => {
describe('match', () => {
beforeEach(() => {
wrapper.find('input#oldPassword').setValue('some secret')
wrapper.find('input#newPassword').setValue('some secret')
wrapper.find('input#password').setValue('some secret')
})
it('invalid', () => {
@ -90,8 +90,8 @@ describe('ChangePassword.vue', () => {
describe('given valid input', () => {
beforeEach(() => {
wrapper.find('input#oldPassword').setValue('supersecret')
wrapper.find('input#newPassword').setValue('superdupersecret')
wrapper.find('input#confirmPassword').setValue('superdupersecret')
wrapper.find('input#password').setValue('superdupersecret')
wrapper.find('input#passwordConfirmation').setValue('superdupersecret')
})
describe('submit form', () => {
@ -109,8 +109,8 @@ describe('ChangePassword.vue', () => {
expect.objectContaining({
variables: {
oldPassword: 'supersecret',
newPassword: 'superdupersecret',
confirmPassword: 'superdupersecret',
password: 'superdupersecret',
passwordConfirmation: 'superdupersecret',
},
}),
)
@ -135,8 +135,8 @@ describe('ChangePassword.vue', () => {
/* describe('mutation rejects', () => {
beforeEach(async () => {
await wrapper.find('input#oldPassword').setValue('supersecret')
await wrapper.find('input#newPassword').setValue('supersecret')
await wrapper.find('input#confirmPassword').setValue('supersecret')
await wrapper.find('input#password').setValue('supersecret')
await wrapper.find('input#passwordConfirmation').setValue('supersecret')
})
it('displays error message', async () => {

View File

@ -1,9 +1,5 @@
<template>
<ds-form
v-model="formData"
:schema="formSchema"
@submit="handleSubmit"
>
<ds-form v-model="formData" :schema="formSchema" @submit="handleSubmit">
<template slot-scope="{ errors }">
<ds-input
id="oldPassword"
@ -13,20 +9,20 @@
:label="$t('settings.security.change-password.label-old-password')"
/>
<ds-input
id="newPassword"
model="newPassword"
id="password"
model="password"
type="password"
autocomplete="off"
:label="$t('settings.security.change-password.label-new-password')"
/>
<ds-input
id="confirmPassword"
model="confirmPassword"
id="passwordConfirmation"
model="passwordConfirmation"
type="password"
autocomplete="off"
:label="$t('settings.security.change-password.label-new-password-confirm')"
/>
<password-strength :password="formData.newPassword" />
<password-strength :password="formData.password" />
<ds-space margin-top="base">
<ds-button :loading="loading" :disabled="errors" primary>
{{ $t('settings.security.change-password.button') }}
@ -39,6 +35,7 @@
<script>
import gql from 'graphql-tag'
import PasswordStrength from './Strength'
import PasswordForm from '~/components/utils/PasswordFormHelper'
export default {
name: 'ChangePassword',
@ -46,11 +43,11 @@ export default {
PasswordStrength,
},
data() {
const passwordForm = PasswordForm({ translate: this.$t })
return {
formData: {
oldPassword: '',
newPassword: '',
confirmPassword: '',
...passwordForm.formData,
},
formSchema: {
oldPassword: {
@ -58,21 +55,7 @@ export default {
required: true,
message: this.$t('settings.security.change-password.message-old-password-required'),
},
newPassword: {
type: 'string',
required: true,
message: this.$t('settings.security.change-password.message-new-password-required'),
},
confirmPassword: [
{ validator: this.matchPassword },
{
type: 'string',
required: true,
message: this.$t(
'settings.security.change-password.message-new-password-confirm-required',
),
},
],
...passwordForm.formSchema,
},
loading: false,
disabled: true,
@ -82,8 +65,8 @@ export default {
async handleSubmit(data) {
this.loading = true
const mutation = gql`
mutation($oldPassword: String!, $newPassword: String!) {
changePassword(oldPassword: $oldPassword, newPassword: $newPassword)
mutation($oldPassword: String!, $password: String!) {
changePassword(oldPassword: $oldPassword, newPassword: $password)
}
`
const variables = this.formData
@ -94,8 +77,8 @@ export default {
this.$toast.success(this.$t('settings.security.change-password.success'))
this.formData = {
oldPassword: '',
newPassword: '',
confirmPassword: '',
password: '',
passwordConfirmation: '',
}
} catch (err) {
this.$toast.error(err.message)
@ -103,15 +86,6 @@ export default {
this.loading = false
}
},
matchPassword(rule, value, callback, source, options) {
var errors = []
if (this.formData.newPassword !== value) {
errors.push(
new Error(this.$t('settings.security.change-password.message-new-password-missmatch')),
)
}
callback(errors)
},
},
}
</script>

View File

@ -47,8 +47,8 @@ describe('ChangePassword ', () => {
describe('submitting new password', () => {
beforeEach(() => {
wrapper = Wrapper()
wrapper.find('input#newPassword').setValue('supersecret')
wrapper.find('input#confirmPassword').setValue('supersecret')
wrapper.find('input#password').setValue('supersecret')
wrapper.find('input#passwordConfirmation').setValue('supersecret')
wrapper.find('form').trigger('submit')
})
@ -58,7 +58,7 @@ describe('ChangePassword ', () => {
it('delivers new password to backend', () => {
const expected = expect.objectContaining({
variables: { code: '123456', email: 'mail@example.org', newPassword: 'supersecret' },
variables: { code: '123456', email: 'mail@example.org', password: 'supersecret' },
})
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
})

View File

@ -10,20 +10,20 @@
>
<template slot-scope="{ errors }">
<ds-input
id="newPassword"
model="newPassword"
id="password"
model="password"
type="password"
autocomplete="off"
:label="$t('settings.security.change-password.label-new-password')"
/>
<ds-input
id="confirmPassword"
model="confirmPassword"
id="passwordConfirmation"
model="passwordConfirmation"
type="password"
autocomplete="off"
:label="$t('settings.security.change-password.label-new-password-confirm')"
/>
<password-strength :password="formData.newPassword" />
<password-strength :password="formData.password" />
<ds-space margin-top="base">
<ds-button :loading="$apollo.loading" :disabled="errors" primary>
{{ $t('settings.security.change-password.button') }}
@ -55,6 +55,7 @@
import PasswordStrength from '../Password/Strength'
import gql from 'graphql-tag'
import { SweetalertIcon } from 'vue-sweetalert-icons'
import PasswordForm from '~/components/utils/PasswordFormHelper'
export default {
components: {
@ -66,27 +67,13 @@ export default {
code: { type: String, required: true },
},
data() {
const passwordForm = PasswordForm({ translate: this.$t })
return {
formData: {
newPassword: '',
confirmPassword: '',
...passwordForm.formData,
},
formSchema: {
newPassword: {
type: 'string',
required: true,
message: this.$t('settings.security.change-password.message-new-password-required'),
},
confirmPassword: [
{ validator: this.matchPassword },
{
type: 'string',
required: true,
message: this.$t(
'settings.security.change-password.message-new-password-confirm-required',
),
},
],
...passwordForm.formSchema,
},
disabled: true,
changePasswordResult: null,
@ -95,13 +82,13 @@ export default {
methods: {
async handleSubmitPassword() {
const mutation = gql`
mutation($code: String!, $email: String!, $newPassword: String!) {
resetPassword(code: $code, email: $email, newPassword: $newPassword)
mutation($code: String!, $email: String!, $password: String!) {
resetPassword(code: $code, email: $email, newPassword: $password)
}
`
const { newPassword } = this.formData
const { password } = this.formData
const { email, code } = this
const variables = { newPassword, email, code }
const variables = { password, email, code }
try {
const {
data: { resetPassword },
@ -111,22 +98,13 @@ export default {
this.$emit('passwordResetResponse', this.changePasswordResult)
}, 3000)
this.formData = {
newPassword: '',
confirmPassword: '',
password: '',
passwordConfirmation: '',
}
} catch (err) {
this.$toast.error(err.message)
}
},
matchPassword(rule, value, callback, source, options) {
var errors = []
if (this.formData.newPassword !== value) {
errors.push(
new Error(this.$t('settings.security.change-password.message-new-password-missmatch')),
)
}
callback(errors)
},
},
}
</script>

View File

@ -54,7 +54,7 @@ describe('CreateUserAccount', () => {
wrapper = Wrapper()
wrapper.find('input#name').setValue('John Doe')
wrapper.find('input#password').setValue('hellopassword')
wrapper.find('input#confirmPassword').setValue('hellopassword')
wrapper.find('input#passwordConfirmation').setValue('hellopassword')
await wrapper.find('form').trigger('submit')
await wrapper.html()
}
@ -123,7 +123,7 @@ describe('CreateUserAccount', () => {
it('displays form errors', async () => {
await action()
expect(wrapper.find('.errors').text()).toContain('Invalid nonce')
expect(wrapper.find('.backendErrors').text()).toContain('Invalid nonce')
})
})
})

View File

@ -39,17 +39,17 @@
:label="$t('settings.security.change-password.label-new-password')"
/>
<ds-input
id="confirmPassword"
model="confirmPassword"
id="passwordConfirmation"
model="passwordConfirmation"
type="password"
autocomplete="off"
:label="$t('settings.security.change-password.label-new-password-confirm')"
/>
<password-strength :password="formData.password" />
<template slot="footer">
<ds-space class="errors" v-if="errors">
<ds-space class="backendErrors" v-if="backendErrors">
<ds-text align="center" bold color="danger">
{{ errors.message }}
{{ backendErrors.message }}
</ds-text>
</ds-space>
<ds-button
@ -72,6 +72,7 @@
import gql from 'graphql-tag'
import PasswordStrength from '../Password/Strength'
import { SweetalertIcon } from 'vue-sweetalert-icons'
import PasswordForm from '~/components/utils/PasswordFormHelper'
export const SignupVerificationMutation = gql`
mutation($nonce: String!, $name: String!, $email: String!, $password: String!) {
@ -88,12 +89,12 @@ export default {
SweetalertIcon,
},
data() {
const passwordForm = PasswordForm({ translate: this.$t })
return {
formData: {
name: '',
about: '',
password: '',
confirmPassword: '',
...passwordForm.formData,
},
formSchema: {
name: {
@ -105,25 +106,11 @@ export default {
type: 'string',
required: false,
},
password: {
type: 'string',
required: true,
message: this.$t('settings.security.change-password.message-new-password-required'),
},
confirmPassword: [
{ validator: this.matchPassword },
{
type: 'string',
required: true,
message: this.$t(
'settings.security.change-password.message-new-password-confirm-required',
),
},
],
...passwordForm.formSchema,
},
disabled: true,
success: null,
errors: null,
backendErrors: null,
}
},
props: {
@ -147,18 +134,9 @@ export default {
})
}, 3000)
} catch (err) {
this.errors = err
this.backendErrors = err
}
},
matchPassword(rule, value, callback, source, options) {
var errors = []
if (this.formData.password !== value) {
errors.push(
new Error(this.$t('settings.security.change-password.message-new-password-missmatch')),
)
}
callback(errors)
},
},
}
</script>

View File

@ -0,0 +1,36 @@
export default function PasswordForm({ translate }) {
const passwordMismatchMessage = translate(
'settings.security.change-password.message-new-password-missmatch',
)
return {
formData: {
password: '',
passwordConfirmation: '',
},
formSchema: {
password: {
type: 'string',
required: true,
message: translate('settings.security.change-password.message-new-password-required'),
},
passwordConfirmation: [
{
validator(rule, value, callback, source, options) {
var errors = []
if (source.password !== value) {
errors.push(new Error(passwordMismatchMessage))
}
callback(errors)
},
},
{
type: 'string',
required: true,
message: translate(
'settings.security.change-password.message-new-password-confirm-required',
),
},
],
},
}
}