Add "reset" page
This commit is contained in:
parent
96af04433c
commit
d32eb379ba
95
resources/assets/src/components/auth/Reset.vue
Normal file
95
resources/assets/src/components/auth/Reset.vue
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<template>
|
||||||
|
<form>
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<input
|
||||||
|
v-model="password"
|
||||||
|
type="password"
|
||||||
|
class="form-control"
|
||||||
|
ref="password"
|
||||||
|
:placeholder="$t('auth.password')"
|
||||||
|
>
|
||||||
|
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<input
|
||||||
|
v-model="confirm"
|
||||||
|
type="password"
|
||||||
|
class="form-control"
|
||||||
|
ref="confirm"
|
||||||
|
:placeholder="$t('auth.repeat-pwd')"
|
||||||
|
>
|
||||||
|
<span class="glyphicon glyphicon-log-in form-control-feedback"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="callout callout-info" :class="{ hide: !infoMsg }">{{ infoMsg }}</div>
|
||||||
|
<div class="callout callout-warning" :class="{ hide: !warningMsg }">{{ warningMsg }}</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-8">
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-4">
|
||||||
|
<button v-if="pending" disabled class="btn btn-primary btn-block btn-flat">
|
||||||
|
<i class="fa fa-spinner fa-spin"></i> {{ $t('auth.resetting') }}
|
||||||
|
</button>
|
||||||
|
<button v-else @click.prevent="reset" class="btn btn-primary btn-block btn-flat">
|
||||||
|
{{ $t('auth.reset-button') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { swal } from '../../js/notify';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Reset',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uid: +this.$route[1],
|
||||||
|
password: '',
|
||||||
|
confirm: '',
|
||||||
|
infoMsg: '',
|
||||||
|
warningMsg: '',
|
||||||
|
pending: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async reset() {
|
||||||
|
const { password, confirm } = this;
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
this.infoMsg = this.$t('auth.emptyPassword');
|
||||||
|
this.$refs.password.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password.length < 8 || password.length > 32) {
|
||||||
|
this.infoMsg = this.$t('auth.invalidPassword');
|
||||||
|
this.$refs.password.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password !== confirm) {
|
||||||
|
this.infoMsg = this.$t('auth.invalidConfirmPwd');
|
||||||
|
this.$refs.confirm.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pending = true;
|
||||||
|
const { errno, msg } = await this.$http.post(
|
||||||
|
`/auth/reset/${this.uid}${location.search}`,
|
||||||
|
{ password }
|
||||||
|
);
|
||||||
|
if (errno === 0) {
|
||||||
|
await swal({ type: 'success', html: msg });
|
||||||
|
window.location = `${blessing.base_url}/auth/login`;
|
||||||
|
} else {
|
||||||
|
this.infoMsg = '';
|
||||||
|
this.warningMsg = msg;
|
||||||
|
this.pending = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -49,4 +49,9 @@ export default [
|
|||||||
component: () => import('./auth/Forgot'),
|
component: () => import('./auth/Forgot'),
|
||||||
el: 'form'
|
el: 'form'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'auth/reset/(\\d+)',
|
||||||
|
component: () => import('./auth/Reset'),
|
||||||
|
el: 'form'
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
52
resources/assets/tests/components/auth/Reset.test.js
Normal file
52
resources/assets/tests/components/auth/Reset.test.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import { mount } from '@vue/test-utils';
|
||||||
|
import Reset from '@/components/auth/Reset';
|
||||||
|
import { swal } from '@/js/notify';
|
||||||
|
|
||||||
|
jest.mock('@/js/notify');
|
||||||
|
|
||||||
|
test('reset password', async () => {
|
||||||
|
Vue.prototype.$http.post
|
||||||
|
.mockResolvedValueOnce({ errno: 1, msg: 'fail' })
|
||||||
|
.mockResolvedValueOnce({ errno: 0, msg: 'ok' });
|
||||||
|
const wrapper = mount(Reset, {
|
||||||
|
mocks: {
|
||||||
|
$route: ['/auth/reset/1', '1']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const button = wrapper.find('button');
|
||||||
|
const info = wrapper.find('.callout-info');
|
||||||
|
const warning = wrapper.find('.callout-warning');
|
||||||
|
|
||||||
|
button.trigger('click');
|
||||||
|
expect(Vue.prototype.$http.post).not.toBeCalled();
|
||||||
|
expect(info.text()).toBe('auth.emptyPassword');
|
||||||
|
|
||||||
|
wrapper.findAll('[type="password"]').at(0).setValue('123456');
|
||||||
|
button.trigger('click');
|
||||||
|
expect(Vue.prototype.$http.post).not.toBeCalled();
|
||||||
|
expect(info.text()).toBe('auth.invalidPassword');
|
||||||
|
|
||||||
|
wrapper.findAll('[type="password"]').at(0).setValue('12345678');
|
||||||
|
button.trigger('click');
|
||||||
|
expect(Vue.prototype.$http.post).not.toBeCalled();
|
||||||
|
expect(info.text()).toBe('auth.invalidConfirmPwd');
|
||||||
|
|
||||||
|
wrapper.findAll('[type="password"]').at(1).setValue('123456');
|
||||||
|
button.trigger('click');
|
||||||
|
expect(Vue.prototype.$http.post).not.toBeCalled();
|
||||||
|
expect(info.text()).toBe('auth.invalidConfirmPwd');
|
||||||
|
|
||||||
|
wrapper.findAll('[type="password"]').at(1).setValue('12345678');
|
||||||
|
button.trigger('click');
|
||||||
|
expect(Vue.prototype.$http.post).toBeCalledWith(
|
||||||
|
'/auth/reset/1', // Ignore `location.search`
|
||||||
|
{ password: '12345678' }
|
||||||
|
);
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
expect(warning.text()).toBe('fail');
|
||||||
|
|
||||||
|
button.trigger('click');
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
expect(swal).toBeCalledWith({ type: 'success', html: 'ok' });
|
||||||
|
});
|
@ -32,6 +32,7 @@ auth:
|
|||||||
forgot:
|
forgot:
|
||||||
login-link: I do remember it
|
login-link: I do remember it
|
||||||
button: Send
|
button: Send
|
||||||
|
reset-button: Reset
|
||||||
|
|
||||||
skinlib:
|
skinlib:
|
||||||
addToCloset: Add to closet
|
addToCloset: Add to closet
|
||||||
|
@ -32,6 +32,7 @@ auth:
|
|||||||
forgot:
|
forgot:
|
||||||
login-link: 我又想起来了
|
login-link: 我又想起来了
|
||||||
button: 发送
|
button: 发送
|
||||||
|
reset-button: 重置
|
||||||
|
|
||||||
skinlib:
|
skinlib:
|
||||||
addToCloset: 添加至衣柜
|
addToCloset: 添加至衣柜
|
||||||
|
@ -12,30 +12,7 @@
|
|||||||
<div class="login-box-body">
|
<div class="login-box-body">
|
||||||
<p class="login-box-msg">@lang('auth.reset.message', ['username' => $user->getNickName()])</p>
|
<p class="login-box-msg">@lang('auth.reset.message', ['username' => $user->getNickName()])</p>
|
||||||
|
|
||||||
<form id="login-form">
|
<form></form>
|
||||||
<input id="uid" type="hidden" value="{{ $user->uid }}" />
|
|
||||||
|
|
||||||
<div class="form-group has-feedback">
|
|
||||||
<input id="password" type="password" class="form-control" placeholder="@lang('auth.password')">
|
|
||||||
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-group has-feedback">
|
|
||||||
<input id="confirm-pwd" type="password" class="form-control" placeholder="@lang('auth.register.repeat-pwd')">
|
|
||||||
<span class="glyphicon glyphicon-log-in form-control-feedback"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="msg" class="callout hide"></div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-8">
|
|
||||||
</div>
|
|
||||||
<!-- /.col -->
|
|
||||||
<div class="col-xs-4">
|
|
||||||
<button id="reset-button" class="btn btn-primary btn-block btn-flat">@lang('auth.reset.button')</button>
|
|
||||||
</div>
|
|
||||||
<!-- /.col -->
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.form-box -->
|
<!-- /.form-box -->
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user