parent
c89703a359
commit
8ee5abb1a5
@ -0,0 +1,62 @@
|
|||||||
|
import { mapState } from 'vuex'
|
||||||
|
import passwordResetApi from '../../services/new_api/password_reset.js'
|
||||||
|
|
||||||
|
const passwordReset = {
|
||||||
|
data: () => ({
|
||||||
|
user: {
|
||||||
|
email: ''
|
||||||
|
},
|
||||||
|
isPending: false,
|
||||||
|
success: false,
|
||||||
|
throttled: false,
|
||||||
|
error: null
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
signedIn: (state) => !!state.users.currentUser,
|
||||||
|
instance: state => state.instance
|
||||||
|
}),
|
||||||
|
mailerEnabled () {
|
||||||
|
return this.instance.mailerEnabled
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
if (this.signedIn) {
|
||||||
|
this.$router.push({ name: 'root' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
dismissError () {
|
||||||
|
this.error = null
|
||||||
|
},
|
||||||
|
submit () {
|
||||||
|
this.isPending = true
|
||||||
|
const email = this.user.email
|
||||||
|
const instance = this.instance.server
|
||||||
|
|
||||||
|
passwordResetApi({ instance, email }).then(({ status }) => {
|
||||||
|
this.isPending = false
|
||||||
|
this.user.email = ''
|
||||||
|
|
||||||
|
if (status === 204) {
|
||||||
|
this.success = true
|
||||||
|
this.error = null
|
||||||
|
} else if (status === 404 || status === 400) {
|
||||||
|
this.error = this.$t('password_reset.not_found')
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.email.focus()
|
||||||
|
})
|
||||||
|
} else if (status === 429) {
|
||||||
|
this.throttled = true
|
||||||
|
this.error = this.$t('password_reset.too_many_requests')
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.isPending = false
|
||||||
|
this.user.email = ''
|
||||||
|
this.error = this.$t('general.generic_error')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default passwordReset
|
@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<div class="settings panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
{{ $t('password_reset.password_reset') }}
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form
|
||||||
|
class="password-reset-form"
|
||||||
|
@submit.prevent="submit"
|
||||||
|
>
|
||||||
|
<div class="container">
|
||||||
|
<div v-if="!mailerEnabled">
|
||||||
|
<p>
|
||||||
|
{{ $t('password_reset.password_reset_disabled') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="success || throttled">
|
||||||
|
<p v-if="success">
|
||||||
|
{{ $t('password_reset.check_email') }}
|
||||||
|
</p>
|
||||||
|
<div class="form-group text-center">
|
||||||
|
<router-link :to="{name: 'root'}">
|
||||||
|
{{ $t('password_reset.return_home') }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<p>
|
||||||
|
{{ $t('password_reset.instruction') }}
|
||||||
|
</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<input
|
||||||
|
ref="email"
|
||||||
|
v-model="user.email"
|
||||||
|
:disabled="isPending"
|
||||||
|
:placeholder="$t('password_reset.placeholder')"
|
||||||
|
class="form-control"
|
||||||
|
type="input"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button
|
||||||
|
:disabled="isPending"
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-default btn-block"
|
||||||
|
>
|
||||||
|
{{ $t('general.submit') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
v-if="error"
|
||||||
|
class="alert error notice-dismissible"
|
||||||
|
>
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
<a
|
||||||
|
class="button-icon dismiss"
|
||||||
|
@click.prevent="dismissError()"
|
||||||
|
>
|
||||||
|
<i class="icon-cancel" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./password_reset.js"></script>
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.password-reset-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0.6em;
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 0;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 0.6em;
|
||||||
|
max-width: 18rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
padding: 0.3em 0.0em 0.3em;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
text-align: center;
|
||||||
|
animation-name: shakeError;
|
||||||
|
animation-duration: 0.4s;
|
||||||
|
animation-timing-function: ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0.3em 0.0em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-dismissible {
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-cancel {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,18 @@
|
|||||||
|
import { reduce } from 'lodash'
|
||||||
|
|
||||||
|
const MASTODON_PASSWORD_RESET_URL = `/auth/password`
|
||||||
|
|
||||||
|
const resetPassword = ({ instance, email }) => {
|
||||||
|
const params = { email }
|
||||||
|
const query = reduce(params, (acc, v, k) => {
|
||||||
|
const encoded = `${k}=${encodeURIComponent(v)}`
|
||||||
|
return `${acc}&${encoded}`
|
||||||
|
}, '')
|
||||||
|
const url = `${instance}${MASTODON_PASSWORD_RESET_URL}?${query}`
|
||||||
|
|
||||||
|
return window.fetch(url, {
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default resetPassword
|
Loading…
Reference in new issue