TT#64750 General: As a Subscriber, I want to change my webpassword

Change-Id: I395098c7b0efa8be35e34e44ac057b881a1e7228
changes/13/32813/4
Hans-Peter Herzog 6 years ago
parent e8abe0eb2f
commit 7a56c26787

@ -9,7 +9,9 @@ import {
get, get,
patchAdd, patchAdd,
patchReplace, patchReplace,
patchReplaceFull,
patchAddFull patchAddFull
} from './common' } from './common'
import { import {
assignNumbers assignNumbers
@ -502,3 +504,17 @@ export function setSubscriberNumbers(options) {
}); });
} }
export function changePassword(subscriber, newPassword) {
return new Promise((resolve, reject)=>{
patchReplaceFull({
path: 'api/subscribers/' + subscriber,
fieldPath: 'webpassword',
value: newPassword
}).then((subscriber)=>{
resolve(subscriber);
}).catch((err)=>{
reject(err);
});
});
}

@ -35,7 +35,7 @@
QSideLink QSideLink
} from 'quasar-framework' } from 'quasar-framework'
export default { export default {
name: 'csc-user-menu', name: 'csc-language-menu',
props: [ props: [
'languageLabel', 'languageLabel',
'languageLabels' 'languageLabels'

@ -0,0 +1,68 @@
<template>
<q-list
no-border
link
>
<q-item @click="logout">
<q-item-side
icon="exit_to_app"
color="primary"
/>
<q-item-main
:label="$t('userMenu.logout')"
:sublabel="username"
>
</q-item-main>
</q-item>
<q-item
@click="settings">
<q-item-side
icon="settings_applications"
color="primary"
/>
<q-item-main
:label="$t('userMenu.settings')"
>
</q-item-main>
</q-item>
</q-list>
</template>
<script>
import {
QList,
QItem,
QItemMain,
QCollapsible,
QItemSide,
QSideLink
} from 'quasar-framework'
export default {
name: 'csc-user-menu',
props: [
'username'
],
data () {
return {}
},
components: {
QList,
QItem,
QItemMain,
QCollapsible,
QItemSide,
QSideLink
},
methods: {
logout() {
this.$emit('logout');
},
settings() {
this.$emit('settings');
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>

@ -30,8 +30,10 @@
round round
small small
> >
<q-popover ref="languagePopover"> <q-popover
<csc-user-menu ref="languagePopover"
>
<csc-language-menu
:language-label="languageLabel" :language-label="languageLabel"
:language-labels="languageLabels" :language-labels="languageLabels"
@change-language="changeLanguage" @change-language="changeLanguage"
@ -55,23 +57,14 @@
> >
{{ getUsername }} {{ getUsername }}
</span> </span>
<q-popover> <q-popover
<q-list ref="userPopover"
no-border >
link <csc-user-menu
> :username="getUsername"
<q-item @click="logout()"> @logout="logout"
<q-item-side @settings="userSettings"
icon="exit_to_app" />
color="primary"
/>
<q-item-main
label="Logout"
:sublabel="getUsername"
>
</q-item-main>
</q-item>
</q-list>
</q-popover> </q-popover>
</div> </div>
<csc-logo <csc-logo
@ -100,10 +93,11 @@
color="default" color="default"
/> />
</div> </div>
<csc-user-menu <csc-language-menu
slot="left" slot="left"
v-if="isMobile" v-if="isMobile"
:language-label="languageLabel" :language-label="languageLabel"
:language-labels="languageLabels"
@change-language="changeLanguage" @change-language="changeLanguage"
/> />
<csc-main-menu <csc-main-menu
@ -188,7 +182,8 @@
QCollapsible QCollapsible
} from 'quasar-framework' } from 'quasar-framework'
import CscMainMenu from "./MainMenu" import CscMainMenu from "./MainMenu"
import CscUserMenu from "./UserMenu" import CscLanguageMenu from "./CscLanguageMenu"
import CscUserMenu from "./CscUserMenu"
import { import {
getLanguageLabel getLanguageLabel
} from "../../i18n"; } from "../../i18n";
@ -219,7 +214,7 @@
], ],
components: { components: {
CscMainMenu, CscMainMenu,
CscUserMenu, CscLanguageMenu,
QLayout, QLayout,
QToolbar, QToolbar,
QToolbarTitle, QToolbarTitle,
@ -236,7 +231,8 @@
QCollapsible, QCollapsible,
CscCall, CscCall,
CscSendFax, CscSendFax,
CscLogo CscLogo,
CscUserMenu
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
@ -420,6 +416,12 @@
else { else {
this.$refs.languagePopover.close(); this.$refs.languagePopover.close();
} }
},
userSettings() {
if(this.$refs.userPopover) {
this.$refs.userPopover.close();
}
this.$router.push({path: '/user/settings'});
} }
}, },
watch: { watch: {

@ -0,0 +1,79 @@
<template>
<csc-page
class="csc-simple-page"
>
<div
class="row"
>
<div
class="col col-xs-12 col-md-6"
>
<csc-change-password
:loading="isPasswordChanging"
:error="changePasswordError"
:subscriber="getSubscriber"
@change="changePassword"
/>
</div>
</div>
</csc-page>
</template>
<script>
import {
showGlobalError,
showToast
} from '../../helpers/ui'
import {
RequestState
} from "../../store/common"
import {
mapState,
mapGetters,
mapActions
} from 'vuex'
import CscPage from '../CscPage'
import CscChangePassword from "./UserSettings/CscChangePassword";
export default {
name: 'csc-page-user-settings',
data () {
return {
}
},
components: {
CscChangePassword,
CscPage
},
mounted() {
},
computed: {
...mapState('user', [
'changePasswordState',
'changePasswordError'
]),
...mapGetters('user', [
'getSubscriber',
'isPasswordChanging'
])
},
methods: {
...mapActions('user', [
'changePassword'
])
},
watch: {
changePasswordState(state) {
if(state === RequestState.succeeded) {
showToast(this.$t('changePasswordToast'));
}
else if(state === RequestState.failed) {
showGlobalError(this.changePasswordError);
}
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import '../../themes/quasar.variables';
</style>

@ -0,0 +1,158 @@
<template>
<div>
<q-slide-transition>
<div
v-if="!inputEnabled"
>
<q-btn
icon="lock"
flat
dark
color="primary"
@click="enableInput"
>
{{ $t('userSettings.changePassword') }}
</q-btn>
</div>
</q-slide-transition>
<q-slide-transition>
<div
v-if="inputEnabled"
>
<q-field
icon="lock"
>
<q-input
v-model.trim="newPassword"
dark
icon="lock"
type="password"
clearable
:float-label="$t('userSettings.newPasswordLabel')"
/>
</q-field>
<q-field
icon="lock"
>
<q-input
v-model.trim="newPasswordRetyped"
dark
icon="lock"
type="password"
clearable
:float-label="$t('userSettings.newPasswordRetypedLabel')"
/>
</q-field>
<div
class="row justify-center"
>
<q-btn
flat
color="default"
icon="clear"
@click="cancel"
>
{{ $t('buttons.cancel') }}
</q-btn>
<q-btn
flat
color="primary"
icon="done"
:disable="!isValid"
@click="openConfirmDialog"
>
{{ $t('userSettings.saveNewPassword') }}
</q-btn>
</div>
</div>
</q-slide-transition>
<csc-confirm-dialog
ref="confirmDialog"
:title-icon="'lock'"
:title="$t('userSettings.changePasswordDialogTitle')"
:message="$t('userSettings.changePasswordDialogText')"
@cancel="closeConfirmDialog"
@confirm="submit"
/>
<csc-object-spinner
v-if="loading"
:loading="loading"
/>
</div>
</template>
<script>
import CscPage from '../../CscPage'
import {
QBtn,
QField,
QInput,
QSlideTransition
} from 'quasar-framework'
import CscConfirmDialog from "../../CscConfirmationDialog";
import CscObjectSpinner from "../../CscObjectSpinner";
export default {
name: 'csc-change-password',
data () {
return {
inputEnabled: false,
newPassword: '',
newPasswordRetyped: ''
}
},
props: [
'subscriber',
'loading',
'error'
],
components: {
CscConfirmDialog,
CscPage,
QBtn,
QField,
QInput,
QSlideTransition,
CscObjectSpinner
},
mounted() {
},
computed: {
isValid() {
return this.newPassword !== '' && this.newPassword === this.newPasswordRetyped;
}
},
methods: {
enableInput() {
this.inputEnabled = true;
this.reset();
},
cancel() {
this.inputEnabled = false;
this.reset();
},
reset() {
this.newPassword = '';
this.newPasswordRetyped = '';
},
submit() {
this.$emit('change', this.newPassword);
},
openConfirmDialog() {
if(this.$refs.confirmDialog) {
this.$refs.confirmDialog.open();
}
},
closeConfirmDialog() {
if(this.$refs.confirmDialog) {
this.$refs.confirmDialog.close();
}
}
},
watch: {
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import '../../../themes/quasar.variables';
</style>

@ -593,5 +593,18 @@
"exitDialogTitle": "Leave conference", "exitDialogTitle": "Leave conference",
"exitDialogText": "Leave current conference now!", "exitDialogText": "Leave current conference now!",
"leaveButtonLabel": "Leave" "leaveButtonLabel": "Leave"
},
"userSettings": {
"changePassword": "Change password",
"saveNewPassword": "Save new password",
"newPasswordLabel": "New password",
"newPasswordRetypedLabel": "New password retyped",
"changePasswordDialogTitle": "Change login password",
"changePasswordDialogText": "You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ",
"changePasswordToast": "Your password has been changed successfully"
},
"userMenu": {
"logout": "Logout",
"settings": "Settings"
} }
} }

@ -22,6 +22,7 @@ import PbxConfigurationSoundSets from './components/pages/PbxConfiguration/CscPb
import PbxConfigurationMsConfigs from './components/pages/PbxConfiguration/CscPbxMsConfigs' import PbxConfigurationMsConfigs from './components/pages/PbxConfiguration/CscPbxMsConfigs'
import Voicebox from './components/pages/Voicebox/Voicebox'; import Voicebox from './components/pages/Voicebox/Voicebox';
import Login from './components/Login' import Login from './components/Login'
import CscUserSettings from './components/pages/CscUserSettings'
import Error404 from './components/Error404' import Error404 from './components/Error404'
export default [ export default [
@ -163,6 +164,14 @@ export default [
title: i18n.t('navigation.voicebox.title'), title: i18n.t('navigation.voicebox.title'),
subtitle: i18n.t('navigation.voicebox.subTitle') subtitle: i18n.t('navigation.voicebox.subTitle')
} }
},
{
path: 'settings',
component: CscUserSettings,
meta: {
title: i18n.t('navigation.userSettings.title'),
subtitle: i18n.t('navigation.userSettings.subTitle')
}
} }
] ]
}, },

@ -15,6 +15,7 @@ import {
login, login,
getUserData getUserData
} from '../api/user'; } from '../api/user';
import {changePassword} from "../api/subscriber";
export default { export default {
namespaced: true, namespaced: true,
@ -38,7 +39,9 @@ export default {
sessionLocale: null, sessionLocale: null,
changeSessionLocaleState: RequestState.initiated, changeSessionLocaleState: RequestState.initiated,
changeSessionLocaleError: null, changeSessionLocaleError: null,
languageLabels: [] languageLabels: [],
changePasswordState: RequestState.initiated,
changePasswordError: null
}, },
getters: { getters: {
isLogged(state) { isLogged(state) {
@ -136,6 +139,12 @@ export default {
}, },
languageLabels(state) { languageLabels(state) {
return state.languageLabels; return state.languageLabels;
},
getSubscriber(state) {
return state.subscriber;
},
isPasswordChanging(state) {
return state.changePasswordState === RequestState.requesting;
} }
}, },
mutations: { mutations: {
@ -210,6 +219,18 @@ export default {
}, },
setLanguageLabels(state, languageLabels) { setLanguageLabels(state, languageLabels) {
state.languageLabels = languageLabels; state.languageLabels = languageLabels;
},
userPasswordRequesting(state) {
state.changePasswordState = RequestState.requesting;
state.changePasswordError = null;
},
userPasswordSucceeded(state) {
state.changePasswordState = RequestState.succeeded;
state.changePasswordError = null;
},
userPasswordFailed(state, error) {
state.changePasswordState = RequestState.failed;
state.changePasswordError = error;
} }
}, },
actions: { actions: {
@ -275,6 +296,16 @@ export default {
catch(error) { catch(error) {
context.commit('changeSessionLocaleFailed', error); context.commit('changeSessionLocaleFailed', error);
} }
},
changePassword(context, newPassword) {
let subscriberId = localStorage.getItem('subscriberId');
context.commit('userPasswordRequesting');
changePassword(subscriberId, newPassword).then(()=>{
context.commit('userPasswordSucceeded');
context.dispatch('logout');
}).catch((err)=>{
context.commit('userPasswordFailed', err.message);
});
} }
} }
}; };

Loading…
Cancel
Save