See #187: Front logic for password reset
This commit is contained in:
parent
22f0b1a2d8
commit
3b9024129d
|
@ -0,0 +1,12 @@
|
||||||
|
{% load i18n %}{% autoescape off %}
|
||||||
|
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
|
||||||
|
|
||||||
|
{% trans "Please go to the following page and choose a new password:" %}
|
||||||
|
{{ funkwhale_url }}/auth/password/reset/confirm?uid={{ uid }}&token={{ token }}
|
||||||
|
{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }}
|
||||||
|
|
||||||
|
{% trans "Thanks for using our site!" %}
|
||||||
|
|
||||||
|
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
|
||||||
|
|
||||||
|
{% endautoescape %}
|
|
@ -12,9 +12,15 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<i18next tag="label" path="Username or email"/>
|
<label>
|
||||||
|
{{ $t('Username or email') }} |
|
||||||
|
<router-link :to="{path: '/signup'}">
|
||||||
|
{{ $t('Create an account') }}
|
||||||
|
</router-link>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
ref="username"
|
ref="username"
|
||||||
|
tabindex="1"
|
||||||
required
|
required
|
||||||
type="text"
|
type="text"
|
||||||
autofocus
|
autofocus
|
||||||
|
@ -23,18 +29,16 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<i18next tag="label" path="Password"/>
|
<label>
|
||||||
<input
|
{{ $t('Password') }} |
|
||||||
required
|
<router-link :to="{name: 'auth.password-reset', query: {email: credentials.username}}">
|
||||||
type="password"
|
{{ $t('Reset your password') }}
|
||||||
placeholder="Enter your password"
|
|
||||||
v-model="credentials.password"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<button :class="['ui', {'loading': isLoading}, 'button']" type="submit"><i18next path="Login"/></button>
|
|
||||||
<router-link class="ui right floated basic button" :to="{path: '/signup'}">
|
|
||||||
<i18next path="Create an account"/>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
|
</label>
|
||||||
|
<password-input :index="2" required v-model="credentials.password" />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<button tabindex="3" :class="['ui', {'loading': isLoading}, 'right', 'floated', 'green', 'button']" type="submit"><i18next path="Login"/></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,12 +46,15 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import PasswordInput from '@/components/forms/PasswordInput'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'login',
|
|
||||||
props: {
|
props: {
|
||||||
next: {type: String, default: '/'}
|
next: {type: String, default: '/'}
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
PasswordInput
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
// We need to initialize the component with any
|
// We need to initialize the component with any
|
||||||
|
|
|
@ -9,6 +9,8 @@ import Signup from '@/components/auth/Signup'
|
||||||
import Profile from '@/components/auth/Profile'
|
import Profile from '@/components/auth/Profile'
|
||||||
import Settings from '@/components/auth/Settings'
|
import Settings from '@/components/auth/Settings'
|
||||||
import Logout from '@/components/auth/Logout'
|
import Logout from '@/components/auth/Logout'
|
||||||
|
import PasswordReset from '@/views/auth/PasswordReset'
|
||||||
|
import PasswordResetConfirm from '@/views/auth/PasswordResetConfirm'
|
||||||
import Library from '@/components/library/Library'
|
import Library from '@/components/library/Library'
|
||||||
import LibraryHome from '@/components/library/Home'
|
import LibraryHome from '@/components/library/Home'
|
||||||
import LibraryArtist from '@/components/library/Artist'
|
import LibraryArtist from '@/components/library/Artist'
|
||||||
|
@ -59,6 +61,23 @@ export default new Router({
|
||||||
component: Login,
|
component: Login,
|
||||||
props: (route) => ({ next: route.query.next || '/library' })
|
props: (route) => ({ next: route.query.next || '/library' })
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/auth/password/reset',
|
||||||
|
name: 'auth.password-reset',
|
||||||
|
component: PasswordReset,
|
||||||
|
props: (route) => ({
|
||||||
|
defaultEmail: route.query.email
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/auth/password/reset/confirm',
|
||||||
|
name: 'auth.password-reset-confirm',
|
||||||
|
component: PasswordResetConfirm,
|
||||||
|
props: (route) => ({
|
||||||
|
defaultUid: route.query.uid,
|
||||||
|
defaultToken: route.query.token
|
||||||
|
})
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/signup',
|
path: '/signup',
|
||||||
name: 'signup',
|
name: 'signup',
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div class="main pusher" v-title="$t('Reset your password')">
|
||||||
|
<div class="ui vertical stripe segment">
|
||||||
|
<div class="ui small text container">
|
||||||
|
<h2>{{ $t('Reset your password') }}</h2>
|
||||||
|
<form class="ui form" @submit.prevent="submit()">
|
||||||
|
<div v-if="errors.length > 0" class="ui negative message">
|
||||||
|
<div class="header">{{ $('Error while asking for a password reset') }}</div>
|
||||||
|
<ul class="list">
|
||||||
|
<li v-for="error in errors">{{ error }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<p>{{ $t('Use this form to request a password reset. We will send an email to the given address with instructions to reset your password.') }}</p>
|
||||||
|
<div class="field">
|
||||||
|
<label>{{ $t('Account\'s email') }}</label>
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
ref="email"
|
||||||
|
type="email"
|
||||||
|
autofocus
|
||||||
|
:placeholder="$t('Input the email address binded to your account')"
|
||||||
|
v-model="email">
|
||||||
|
</div>
|
||||||
|
<router-link :to="{path: '/login'}">
|
||||||
|
{{ $t('Back to login') }}
|
||||||
|
</router-link>
|
||||||
|
<button :class="['ui', {'loading': isLoading}, 'right', 'floated', 'green', 'button']" type="submit">
|
||||||
|
{{ $t('Ask for a password reset') }}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['defaultEmail'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
email: this.defaultEmail,
|
||||||
|
isLoading: false,
|
||||||
|
errors: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$refs.email.focus()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit () {
|
||||||
|
let self = this
|
||||||
|
self.isLoading = true
|
||||||
|
self.errors = []
|
||||||
|
let payload = {
|
||||||
|
email: this.email
|
||||||
|
}
|
||||||
|
return axios.post('auth/password/reset/', payload).then(response => {
|
||||||
|
self.isLoading = false
|
||||||
|
self.$router.push({
|
||||||
|
name: 'auth.password-reset-confirm'
|
||||||
|
})
|
||||||
|
}, error => {
|
||||||
|
self.errors = error.backendErrors
|
||||||
|
self.isLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
|
@ -0,0 +1,85 @@
|
||||||
|
<template>
|
||||||
|
<div class="main pusher" v-title="$t('Change your password')">
|
||||||
|
<div class="ui vertical stripe segment">
|
||||||
|
<div class="ui small text container">
|
||||||
|
<h2>{{ $t('Change your password') }}</h2>
|
||||||
|
<form v-if="!success" class="ui form" @submit.prevent="submit()">
|
||||||
|
<div v-if="errors.length > 0" class="ui negative message">
|
||||||
|
<div class="header">{{ $('Error while changing your password') }}</div>
|
||||||
|
<ul class="list">
|
||||||
|
<li v-for="error in errors">{{ error }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<template v-if="token && uid">
|
||||||
|
<div class="field">
|
||||||
|
<label>{{ $t('New password') }}</label>
|
||||||
|
<password-input v-model="newPassword" />
|
||||||
|
</div>
|
||||||
|
<router-link :to="{path: '/login'}">
|
||||||
|
{{ $t('Back to login') }}
|
||||||
|
</router-link>
|
||||||
|
<button :class="['ui', {'loading': isLoading}, 'right', 'floated', 'green', 'button']" type="submit">
|
||||||
|
{{ $t('Update your password') }}</button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<p>{{ $t('If the email address provided in the previous step is valid and binded to a user account, you should receive an email with reset instructions in the next couple of minutes.') }}</p>
|
||||||
|
</template>
|
||||||
|
</form>
|
||||||
|
<div v-else class="ui positive message">
|
||||||
|
<div class="header">{{ $t('Password updated successfully') }}</div>
|
||||||
|
<p>{{ $t('Your password has been updated successfully.') }}</p>
|
||||||
|
<router-link :to="{name: 'login'}">
|
||||||
|
{{ $t('Proceed to login') }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
import PasswordInput from '@/components/forms/PasswordInput'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['defaultToken', 'defaultUid'],
|
||||||
|
components: {
|
||||||
|
PasswordInput
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
newPassword: '',
|
||||||
|
isLoading: false,
|
||||||
|
errors: [],
|
||||||
|
token: this.defaultToken,
|
||||||
|
uid: this.defaultUid,
|
||||||
|
success: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit () {
|
||||||
|
let self = this
|
||||||
|
self.isLoading = true
|
||||||
|
self.errors = []
|
||||||
|
let payload = {
|
||||||
|
uid: this.uid,
|
||||||
|
token: this.token,
|
||||||
|
new_password1: this.newPassword,
|
||||||
|
new_password2: this.newPassword
|
||||||
|
}
|
||||||
|
return axios.post('auth/password/reset/confirm/', payload).then(response => {
|
||||||
|
self.isLoading = false
|
||||||
|
self.success = true
|
||||||
|
}, error => {
|
||||||
|
self.errors = error.backendErrors
|
||||||
|
self.isLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
Loading…
Reference in New Issue