Implement password change in basic user settings

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2019-09-24 18:47:35 +02:00
parent f129d4137d
commit 3806295e83
5 changed files with 135 additions and 5 deletions

View File

@@ -25,6 +25,14 @@ mutation ValidateUser($token: String!) {
}
`;
export const CHANGE_PASSWORD = gql`
mutation ChangePassword($oldPassword: String!, $newPassword: String!) {
changePassword(oldPassword: $oldPassword, newPassword: $newPassword) {
id
}
}
`;
export const CURRENT_USER_CLIENT = gql`
query {
currentUser @client {

View File

@@ -7,6 +7,7 @@ import SendPasswordReset from '@/views/User/SendPasswordReset.vue';
import PasswordReset from '@/views/User/PasswordReset.vue';
import { beforeRegisterGuard } from '@/router/guards/register-guard';
import { RouteConfig } from 'vue-router';
import PasswordChange from '@/views/User/PasswordChange.vue';
export enum UserRouteName {
REGISTER = 'Register',
@@ -16,6 +17,7 @@ export enum UserRouteName {
PASSWORD_RESET = 'PasswordReset',
VALIDATE = 'Validate',
LOGIN = 'Login',
PASSWORD_CHANGE = 'PasswordChange',
}
export const userRoutes: RouteConfig[] = [
@@ -70,4 +72,10 @@ export const userRoutes: RouteConfig[] = [
props: true,
meta: { requiredAuth: false },
},
{
path: '/my-account/password',
name: UserRouteName.PASSWORD_CHANGE,
component: PasswordChange,
meta: { requiredAuth: true },
},
];

View File

@@ -1,5 +1,10 @@
<template>
<section class="container">
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li class="is-active"><router-link :to="{ name: MyAccountRouteName.UPDATE_IDENTITY }" aria-current="page">{{ $t('My account') }}</router-link></li>
</ul>
</nav>
<div v-if="currentActor">
<div class="header">
<figure v-if="currentActor.banner" class="image is-3by1">
@@ -10,6 +15,9 @@
<div class="columns">
<div class="identities column is-4">
<identities v-bind:currentIdentityName="currentIdentityName"></identities>
<div class="buttons">
<b-button tag="router-link" type="is-secondary" :to="{ name: UserRouteName.PASSWORD_CHANGE }">{{ $t('Change password') }}</b-button>
</div>
</div>
<div class="column is-8">
<router-view></router-view>
@@ -27,6 +35,10 @@
.identities {
padding-right: 45px;
margin-right: 45px;
.buttons {
margin-top: 1.2rem;
}
}
</style>
@@ -36,6 +48,8 @@ import { Component, Vue, Watch } from 'vue-property-decorator';
import EventCard from '@/components/Event/EventCard.vue';
import { IPerson } from '@/types/actor';
import Identities from '@/components/Account/Identities.vue';
import { UserRouteName } from '@/router/user';
import { MyAccountRouteName } from '@/router/actor';
@Component({
components: {
@@ -52,6 +66,9 @@ export default class MyAccount extends Vue {
currentActor!: IPerson;
currentIdentityName: string | null = null;
UserRouteName = UserRouteName;
MyAccountRouteName = MyAccountRouteName;
@Watch('$route.params.identityName', { immediate: true })
async onIdentityParamChanged (val: string) {
await this.redirectIfNoIdentitySelected(val);

View File

@@ -0,0 +1,94 @@
<template>
<section class="section">
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><router-link :to="{ name: MyAccountRouteName.UPDATE_IDENTITY }">{{ $t('My account') }}</router-link></li>
<li class="is-active"><router-link :to="{ name: UserRouteName.PASSWORD_CHANGE }" aria-current="page">{{ $t('Password change') }}</router-link></li>
</ul>
</nav>
<h1 class="title">{{ $t('Password') }}</h1>
<b-notification
type="is-danger"
has-icon
aria-close-label="Close notification"
role="alert"
:key="error"
v-for="error in errors"
>
{{ error }}
</b-notification>
<form @submit="resetAction" class="form">
<b-field :label="$t('Old password')">
<b-input
aria-required="true"
required
type="password"
password-reveal
minlength="6"
v-model="oldPassword"
/>
</b-field>
<b-field :label="$t('New password')">
<b-input
aria-required="true"
required
type="password"
password-reveal
minlength="6"
v-model="newPassword"
/>
</b-field>
<button class="button is-primary">
{{ $t('Change my password') }}
</button>
</form>
</section>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { CHANGE_PASSWORD } from '@/graphql/user';
import { UserRouteName } from '@/router/user';
import { MyAccountRouteName } from '@/router/actor';
@Component
export default class PasswordChange extends Vue {
oldPassword: string = '';
newPassword: string = '';
errors: string[] = [];
MyAccountRouteName = MyAccountRouteName;
UserRouteName = UserRouteName;
async resetAction(e) {
e.preventDefault();
this.errors = [];
try {
await this.$apollo.mutate({
mutation: CHANGE_PASSWORD,
variables: {
oldPassword: this.oldPassword,
newPassword: this.newPassword,
},
});
this.$notifier.success(this.$t('The password was successfully changed') as string);
} catch (err) {
this.handleError(err);
}
}
private handleError(err: any) {
console.error(err);
if (err.graphQLErrors !== undefined) {
err.graphQLErrors.forEach(({ message }) => {
this.errors.push(message);
});
}
}
}
</script>
<style lang="scss">
</style>