Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebastianconcept/c08cb7885d6cc7a45065fb5ca90422e9 to your computer and use it in GitHub Desktop.
Save sebastianconcept/c08cb7885d6cc7a45065fb5ca90422e9 to your computer and use it in GitHub Desktop.
SignInRecoverPassword
//
// MIXIN
//
import { Component, Vue } from 'vue-property-decorator'
import stringEntropy from 'fast-password-entropy'
@Component({})
export default class PasswordDefinition extends Vue {
public showPassword: boolean = false
public showConfirmation: boolean = false
public password: string = ''
public confirmation: string = ''
public passwordQualifiers: Array<[[number, number], string]> = [
[[0, 26], 'error'],
[[27, 39], 'warning'],
[[40, 59], 'success'],
[[60, 79], 'success'],
[[80, 112], 'success'],
[[113, Number.POSITIVE_INFINITY], 'success'],
]
validate(ref: { validate: () => boolean }) {
return ref.validate() && this.hasMatchingPasswords()
}
get passwordQuality(): string {
return this.qualifies(this.strength(this.password))
}
getForm() {
console.warn('Component responsibility. Should never execute this')
return new Vue //
}
strength(password: string): number {
return stringEntropy(password)
}
qualifies(value: number): string {
if (!value) return ''
const inRange = (x: number, min: number, max: number): boolean => (x - min) * (x - max) <= 0
const quality = this.passwordQualifiers.find(each => inRange(value, each[0][0], each[0][1]))
if (!quality) return ''
return quality[1]
}
passwordRules() {
return [
(v: string) => !!v || 'Password is required',
(v: string) => (v && v.length) >= 8 || 'Password must be at least 8 characters',
]
}
confirmationRules() {
return [
(v: string) => !!v || 'Please confirm re-typing your password',
(v: string) => (v && v.length >= 8 && this.hasMatchingPasswords()) || `The passwords doesn't match`,
]
}
hasMatchingPasswords() {
return this.password === this.confirmation
}
}
//
// COMPONENT
//
<template>
<v-container fill-height>
<v-form ref="form" class="sign-in-recover-password" lazy-validation @submit.prevent="complete">
<v-layout column justify-space-between fill-height>
<v-flex xs12>
<h1 class="font-weight-black title mb-4">Reset password</h1>
<p>
To protect your sign-in and password, we use a password reset method. Use the fields below to set the
password that you want to use from now on.
</p>
<v-text-field
v-model="password"
:type="showPassword ? 'text' : 'password'"
:append-icon="showPassword ? 'visibility_off' : 'visibility'"
:rules="passwordRules()"
hint="At least 8 characters"
counter
label="New Password"
required
@click:append="showPassword = !showPassword"
></v-text-field>
<v-progress-linear :value="strength(password)" :color="passwordQuality" height="7"></v-progress-linear>
<v-text-field
v-model="confirmation"
:type="showConfirmation ? 'text' : 'password'"
:append-icon="showConfirmation ? 'visibility_off' : 'visibility'"
:rules="confirmationRules()"
counter
label="Confirm New Password"
required
@click:append="showConfirmation = !showConfirmation"
></v-text-field>
</v-flex>
<v-flex fill-height hidden-md-and-up></v-flex>
<v-btn
class="font-weight-bold mb-4"
type="submit"
rounded
depressed
:disabled="!isValid"
color="primary"
>Reset password</v-btn>
</v-layout>
</v-form>
</v-container>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { mixins } from 'vue-class-component'
import PasswordDefinition from '@/mixins/PasswordDefinition'
import { constants } from 'crypto'
@Component({})
// export default class SignInRecoverPassword extends Vue {
export default class SignInRecoverPassword extends mixins(PasswordDefinition) {
get isValid(): boolean {
console.log('SignInRecoverPassword', this.$refs.form)
debugger
if (!this.$refs.form) {
return false
}
return (this.$refs.form as Vue & { validate: () => boolean }).validate()
}
complete() {
if (!this.isValid) return
return this.$store.dispatch('auth/password', {
password: this.password,
router: this.$router,
})
}
}
</script>
<style scoped>
/* "scoped" attribute limit the CSS to this component only */
.sign-in-recover-password {
margin-top: 40px;
height: 100%;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment