Captcha.vue 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. const runtimeConfig = useRuntimeConfig()
  20. const siteKey = runtimeConfig.public.hCaptchaSiteKey
  21. const verified: Ref<boolean> = ref(false);
  22. const expired: Ref<boolean> = ref(false);
  23. const token: Ref<string> = ref("");
  24. const eKey: Ref<string> = ref("");
  25. const error: Ref<string> = ref("");
  26. // La case étant masquée, si elle est cochée, alors on peut en déduire
  27. // qu'on a affaire un robot (voir mécanisme du honey pot)
  28. const honeyPotChecked: Ref<boolean> = ref(false)
  29. const emit = defineEmits(['update'])
  30. const validateCaptchaState = () =>
  31. verified.value && !honeyPotChecked.value ||
  32. "Veuillez procéder à la vérification";
  33. function onVerify(tokenStr: string, ekey: string) {
  34. verified.value = true;
  35. token.value = tokenStr;
  36. eKey.value = ekey;
  37. emit('update', true)
  38. }
  39. function onExpire() {
  40. verified.value = false;
  41. token.value = '';
  42. eKey.value = '';
  43. expired.value = true;
  44. }
  45. function onChallengeExpire() {
  46. verified.value = false;
  47. token.value = '';
  48. eKey.value = '';
  49. expired.value = true;
  50. }
  51. function onError(err: string) {
  52. token.value = '';
  53. eKey.value = '';
  54. error.value = err;
  55. console.log(`Error: ${err}`);
  56. if (process.dev) {
  57. console.log('Dev mode: force captcha validation')
  58. verified.value = true;
  59. }
  60. }
  61. </script>
  62. <style scoped lang="scss">
  63. .hidden-ctrl {
  64. :deep(.v-input__control) {
  65. display: none;
  66. }
  67. }
  68. </style>