Enable reCAPTCHA on "forgot" page

This commit is contained in:
Pig Fang 2019-03-27 11:07:04 +08:00
parent 3e7836b9ff
commit 64658fd9f2
4 changed files with 34 additions and 54 deletions

View File

@ -162,7 +162,12 @@ class AuthController extends Controller
public function forgot()
{
if (config('mail.driver') != '') {
return view('auth.forgot');
return view('auth.forgot', [
'extra' => [
'recaptcha' => option('recaptcha_sitekey'),
'invisible' => (bool) option('recaptcha_invisible'),
]
]);
} else {
throw new PrettyPageException(trans('auth.forgot.disabled'), 8);
}

View File

@ -11,30 +11,7 @@
<span class="glyphicon glyphicon-envelope form-control-feedback" />
</div>
<div class="row">
<div class="col-xs-8">
<div class="form-group has-feedback">
<input
ref="captcha"
v-model="captcha"
type="text"
class="form-control"
:placeholder="$t('auth.captcha')"
>
</div>
</div>
<div class="col-xs-4">
<img
class="pull-right captcha"
:src="`${baseUrl}/auth/captcha?v=${time}`"
alt="CAPTCHA"
:title="$t('auth.change-captcha')"
data-placement="top"
data-toggle="tooltip"
@click="refreshCaptcha"
>
</div>
</div>
<captcha ref="captcha" />
<div class="callout callout-success" :class="{ hide: !successMsg }">{{ successMsg }}</div>
<div class="callout callout-info" :class="{ hide: !infoMsg }">{{ infoMsg }}</div>
@ -61,8 +38,13 @@
</template>
<script>
import Captcha from '../../components/Captcha.vue'
export default {
name: 'Forgot',
components: {
Captcha,
},
props: {
baseUrl: {
type: String,
@ -71,8 +53,6 @@ export default {
},
data: () => ({
email: '',
captcha: '',
time: Date.now(),
successMsg: '',
infoMsg: '',
warningMsg: '',
@ -80,7 +60,7 @@ export default {
}),
methods: {
async submit() {
const { email, captcha } = this
const { email } = this
if (!email) {
this.infoMsg = this.$t('auth.emptyEmail')
@ -94,16 +74,10 @@ export default {
return
}
if (!captcha) {
this.infoMsg = this.$t('auth.emptyCaptcha')
this.$refs.captcha.focus()
return
}
this.pending = true
const { errno, msg } = await this.$http.post(
'/auth/forgot',
{ email, captcha }
{ email, captcha: await this.$refs.captcha.execute() }
)
if (errno === 0) {
this.infoMsg = ''
@ -113,13 +87,10 @@ export default {
} else {
this.infoMsg = ''
this.warningMsg = msg
this.refreshCaptcha()
this.pending = false
this.$refs.captcha.refreshCaptcha()
}
},
refreshCaptcha() {
this.time = Date.now()
},
},
}
</script>

View File

@ -1,12 +1,16 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Forgot from '@/views/auth/Forgot.vue'
import { flushPromises } from '../../utils'
test('click to refresh captcha', () => {
jest.spyOn(Date, 'now')
const wrapper = mount(Forgot)
wrapper.find('img').trigger('click')
expect(Date.now).toBeCalledTimes(2)
window.blessing.extra = {}
const Captcha = Vue.extend({
methods: {
execute() {
return Promise.resolve('captcha')
},
refreshCaptcha() { /* */ },
},
})
test('submit forgot form', async () => {
@ -14,7 +18,7 @@ test('submit forgot form', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'fail' })
.mockResolvedValueOnce({ errno: 0, msg: 'ok' })
const wrapper = mount(Forgot)
const wrapper = mount(Forgot, { stubs: { Captcha } })
const button = wrapper.find('button')
const info = wrapper.find('.callout-info')
const warning = wrapper.find('.callout-warning')
@ -31,20 +35,14 @@ test('submit forgot form', async () => {
wrapper.find('[type="email"]').setValue('a@b.c')
button.trigger('click')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyCaptcha')
wrapper.find('[type="text"]').setValue('captcha')
button.trigger('click')
await wrapper.vm.$nextTick()
await flushPromises()
expect(Vue.prototype.$http.post).toBeCalledWith(
'/auth/forgot',
{ email: 'a@b.c', captcha: 'captcha' }
)
expect(warning.text()).toBe('fail')
expect(Date.now).toBeCalledTimes(2)
button.trigger('click')
await wrapper.vm.$nextTick()
await flushPromises()
expect(success.text()).toBe('ok')
})

View File

@ -22,5 +22,11 @@
<!-- /.login-box-body -->
</div>
<!-- /.login-box -->
@include('common.recaptcha')
<script>
Object.defineProperty(blessing, 'extra', {
get: () => Object.freeze(@json($extra)),
configurable: false
})
</script>
@endsection