Captcha.vue 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <template>
  2. <div class="d-flex flex-column">
  3. <vue-hcaptcha
  4. :sitekey="siteKey"
  5. @verify="onVerify"
  6. @expired="onExpire"
  7. @challenge-expired="onChallengeExpire"
  8. @error="onError"
  9. />
  10. <v-checkbox
  11. v-model="honeyPotChecked"
  12. :rules="[validateCaptchaState]"
  13. class="hidden-ctrl"
  14. />
  15. </div>
  16. </template>
  17. <script setup lang="ts">
  18. import VueHcaptcha from '@hcaptcha/vue3-hcaptcha'
  19. import type { Ref } from 'vue'
  20. const runtimeConfig = useRuntimeConfig()
  21. const siteKey = runtimeConfig.public.hCaptchaSiteKey
  22. const verified: Ref<boolean> = ref(false)
  23. const expired: Ref<boolean> = ref(false)
  24. const token: Ref<string> = ref('')
  25. const eKey: Ref<string> = ref('')
  26. const error: Ref<string> = ref('')
  27. // La case étant masquée, si elle est cochée, alors on peut en déduire
  28. // qu'on a affaire un robot (voir mécanisme du honey pot)
  29. const honeyPotChecked: Ref<boolean> = ref(false)
  30. const emit = defineEmits(['update'])
  31. const validateCaptchaState = () =>
  32. (verified.value && !honeyPotChecked.value) ||
  33. 'Veuillez procéder à la vérification'
  34. function onVerify(tokenStr: string, ekey: string) {
  35. verified.value = true
  36. token.value = tokenStr
  37. eKey.value = ekey
  38. emit('update', true)
  39. }
  40. function onExpire() {
  41. verified.value = false
  42. token.value = ''
  43. eKey.value = ''
  44. expired.value = true
  45. }
  46. function onChallengeExpire() {
  47. verified.value = false
  48. token.value = ''
  49. eKey.value = ''
  50. expired.value = true
  51. }
  52. function onError(err: string) {
  53. token.value = ''
  54. eKey.value = ''
  55. error.value = err
  56. console.log(`Error: ${err}`)
  57. if (process.dev) {
  58. console.log('Dev mode: force captcha validation')
  59. verified.value = true
  60. }
  61. }
  62. </script>
  63. <style scoped lang="scss">
  64. .hidden-ctrl {
  65. :deep(.v-input__control) {
  66. display: none;
  67. }
  68. }
  69. </style>