validate unique username

This commit is contained in:
Moriz Wahl 2023-05-16 01:36:29 +02:00
parent c5eb9311e6
commit 4a5c82f10d
9 changed files with 55 additions and 20 deletions

View File

@ -8,7 +8,7 @@
containsLowercaseCharacter: true, containsLowercaseCharacter: true,
containsUppercaseCharacter: true, containsUppercaseCharacter: true,
containsNumericCharacter: true, containsNumericCharacter: true,
atLeastEightCharactera: true, atLeastEightCharacters: true,
atLeastOneSpecialCharater: true, atLeastOneSpecialCharater: true,
noWhitespaceCharacters: true, noWhitespaceCharacters: true,
}" }"

View File

@ -5,6 +5,7 @@
:name="name" :name="name"
:bails="!showAllErrors" :bails="!showAllErrors"
:immediate="immediate" :immediate="immediate"
vid="username"
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }" v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
> >
<b-form-group :label-for="labelFor"> <b-form-group :label-for="labelFor">
@ -41,10 +42,6 @@ export default {
default: () => { default: () => {
return { return {
required: true, required: true,
min: 3,
max: 20,
usernameAllowedChars: true,
usernameHyphens: true,
} }
}, },
}, },
@ -54,6 +51,7 @@ export default {
value: { required: true, type: String }, value: { required: true, type: String },
showAllErrors: { type: Boolean, default: false }, showAllErrors: { type: Boolean, default: false },
immediate: { type: Boolean, default: false }, immediate: { type: Boolean, default: false },
unique: { type: Boolean, required: true },
}, },
data() { data() {
return { return {

View File

@ -16,7 +16,7 @@
</div> </div>
<div> <div>
<validation-observer ref="observer" v-slot="{ handleSubmit, invalid }"> <validation-observer ref="usernameObserver" v-slot="{ handleSubmit, invalid }">
<b-form @submit.stop.prevent="handleSubmit(onSubmit)"> <b-form @submit.stop.prevent="handleSubmit(onSubmit)">
<b-row class="mb-3"> <b-row class="mb-3">
<b-col class="col-12"> <b-col class="col-12">
@ -38,6 +38,8 @@
:name="$t('form.username')" :name="$t('form.username')"
:placeholder="$t('form.username-placeholder')" :placeholder="$t('form.username-placeholder')"
:showAllErrors="true" :showAllErrors="true"
:unique="true"
:rules="rules"
/> />
</b-col> </b-col>
</b-row> </b-row>
@ -48,7 +50,6 @@
:variant="disabled(invalid) ? 'light' : 'success'" :variant="disabled(invalid) ? 'light' : 'success'"
@click="onSubmit" @click="onSubmit"
type="submit" type="submit"
class="mt-4"
:disabled="disabled(invalid)" :disabled="disabled(invalid)"
> >
{{ $t('form.save') }} {{ $t('form.save') }}
@ -74,11 +75,20 @@ export default {
return { return {
showUserData: true, showUserData: true,
username: this.$store.state.username || '', username: this.$store.state.username || '',
usernameUnique: false,
rules: {
required: true,
min: 3,
max: 20,
usernameAllowedChars: true,
usernameHyphens: true,
usernameUnique: true,
},
} }
}, },
methods: { methods: {
cancelEdit() { cancelEdit() {
this.username = this.$store.state.username this.username = this.$store.state.username || ''
this.showUserData = true this.showUserData = true
}, },
async onSubmit(event) { async onSubmit(event) {

View File

@ -89,6 +89,12 @@ export const queryOptIn = gql`
} }
` `
export const checkUsername = gql`
query($username: String!) {
checkUsername(username: $username)
}
`
export const queryTransactionLink = gql` export const queryTransactionLink = gql`
query($code: String!) { query($code: String!) {
queryTransactionLink(code: $code) { queryTransactionLink(code: $code) {

View File

@ -172,9 +172,9 @@
"gddCreationTime": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens einer Nachkommastelle sein", "gddCreationTime": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens einer Nachkommastelle sein",
"gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein", "gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein",
"is-not": "Du kannst dir selbst keine Gradidos überweisen", "is-not": "Du kannst dir selbst keine Gradidos überweisen",
"usernmae-allowed-chars": "Der Nutzername darf nur aus Buchstaben (ohne Umlaute), Zahlen, Binde - oder Unterstrichen bestehen.", "username-allowed-chars": "Der Nutzername darf nur aus Buchstaben (ohne Umlaute), Zahlen, Binde - oder Unterstrichen bestehen.",
"usernmae-hyphens": "Binde- oder Unterstriche müssen zwischen Buchstaben oder Zahlen stehen.", "username-hyphens": "Binde- oder Unterstriche müssen zwischen Buchstaben oder Zahlen stehen.",
"usernmae-unique": "Der Username ist bereits vergeben." "username-unique": "Der Nutzername ist bereits vergeben."
}, },
"your_amount": "Dein Betrag" "your_amount": "Dein Betrag"
}, },

View File

@ -172,9 +172,9 @@
"gddCreationTime": "The field {_field_} must be a number between {min} and {max} with at most one decimal place.", "gddCreationTime": "The field {_field_} must be a number between {min} and {max} with at most one decimal place.",
"gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits after the decimal point", "gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits after the decimal point",
"is-not": "You cannot send Gradidos to yourself", "is-not": "You cannot send Gradidos to yourself",
"usernmae-allowed-chars": "The username may online contain letters, numbers, hyphens or underscores.", "username-allowed-chars": "The username may online contain letters, numbers, hyphens or underscores.",
"usernmae-hyphens": "Hyphens or underscores must be in between letters or numbers.", "username-hyphens": "Hyphens or underscores must be in between letters or numbers.",
"usernmae-unique": "This username is already taken." "username-unique": "This username is already taken."
}, },
"your_amount": "Your amount" "your_amount": "Your amount"
}, },

View File

@ -27,7 +27,7 @@ const filters = loadFilters(i18n)
Vue.filter('amount', filters.amount) Vue.filter('amount', filters.amount)
Vue.filter('GDD', filters.GDD) Vue.filter('GDD', filters.GDD)
loadAllRules(i18n) loadAllRules(i18n, apolloProvider.defaultClient)
addNavigationGuards(router, store, apolloProvider.defaultClient) addNavigationGuards(router, store, apolloProvider.defaultClient)

View File

@ -1,8 +1,9 @@
import { configure, extend } from 'vee-validate' import { configure, extend } from 'vee-validate'
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
import { required, email, min, max, is_not } from 'vee-validate/dist/rules' import { required, email, min, max, is_not } from 'vee-validate/dist/rules'
import { checkUsername } from '@/graphql/queries'
export const loadAllRules = (i18nCallback) => { export const loadAllRules = (i18nCallback, apollo) => {
configure({ configure({
defaultMessage: (field, values) => { defaultMessage: (field, values) => {
// eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys // eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
@ -96,7 +97,7 @@ export const loadAllRules = (i18nCallback) => {
message: (_, values) => i18nCallback.t('site.signup.one_number', values), message: (_, values) => i18nCallback.t('site.signup.one_number', values),
}) })
extend('atLeastEightCharactera', { extend('atLeastEightCharacters', {
validate(value) { validate(value) {
return !!value.match(/.{8,}/) return !!value.match(/.{8,}/)
}, },
@ -128,13 +129,33 @@ export const loadAllRules = (i18nCallback) => {
validate(value) { validate(value) {
return !!value.match(/^[a-zA-Z0-9_-]+$/) return !!value.match(/^[a-zA-Z0-9_-]+$/)
}, },
message: (_, values) => i18nCallback.t('form.validation.usernmae-allowed-chars', values), message: (_, values) => i18nCallback.t('form.validation.username-allowed-chars', values),
}) })
extend('usernameHyphens', { extend('usernameHyphens', {
validate(value) { validate(value) {
return !!value.match(/^[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9])*$/) return !!value.match(/^[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9])*$/)
}, },
message: (_, values) => i18nCallback.t('form.validation.usernmae-hyphens', values), message: (_, values) => i18nCallback.t('form.validation.username-hyphens', values),
})
extend('usernameUnique', {
validate(value) {
if (value.match(/^(?=.{3,20}$)[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9])*$/)) {
return apollo
.query({
query: checkUsername,
variables: { username: value },
})
.then(({ data }) => {
return {
valid: data.checkUsername,
}
})
} else {
return false
}
},
message: (_, values) => i18nCallback.t('form.validation.username-unique', values),
}) })
} }

View File

@ -34,7 +34,7 @@ const i18nMock = {
n: (value, format) => value, n: (value, format) => value,
} }
loadAllRules(i18nMock) loadAllRules(i18nMock, { query: jest.fn().mockResolvedValue({ data: { checkUsername: true } }) })
global.localVue = createLocalVue() global.localVue = createLocalVue()