diff options
author | gumi <git@gumi.ca> | 2020-10-06 10:25:29 -0400 |
---|---|---|
committer | gumi <git@gumi.ca> | 2020-10-06 15:25:06 -0400 |
commit | 45c8a487106b112e36537321bd14b3f8eb418c07 (patch) | |
tree | 69f16967c3902429e2a35e17d0467eeb21a41bec | |
parent | aea2a6ef80d119d930214238289bb42eb6fb656f (diff) | |
download | website-45c8a487106b112e36537321bd14b3f8eb418c07.tar.gz website-45c8a487106b112e36537321bd14b3f8eb418c07.tar.bz2 website-45c8a487106b112e36537321bd14b3f8eb418c07.tar.xz website-45c8a487106b112e36537321bd14b3f8eb418c07.zip |
require the user to opt-in to reCAPTCHA
-rw-r--r-- | src/views/AccountRecovery.vue | 74 | ||||
-rw-r--r-- | src/views/Registration.vue | 57 |
2 files changed, 118 insertions, 13 deletions
diff --git a/src/views/AccountRecovery.vue b/src/views/AccountRecovery.vue index a9fca20..d78dda2 100644 --- a/src/views/AccountRecovery.vue +++ b/src/views/AccountRecovery.vue @@ -1,16 +1,46 @@ <template> <main> - <div v-if="step == 1"> + <div v-if="nextStep != 4"> <h1>Account Recovery</h1> <p>Use this form if you forgot your username or password.</p> <p>If it matches any account we have on file you will receive a message containing the list of your account usernames along with a password reset link, should you wish to reset your password.</p> </div> + <div v-if="step == -3"> + <h1>reCAPTCHA privacy notice</h1> + <p>This page uses Google reCAPTCHA. By continuing, you agree to use reCAPTCHA, which may register tracking cookies in your browser.</p> + <p>You may review the Google Privacy Policy at <a href="https://policies.google.com/privacy">https://policies.google.com/privacy</a>.</p> + + <button @click="start">I understand and wish to proceed</button> + <br><br> + + <h1>Proceeding without reCAPTCHA</h1> + <p>If you would rather not use reCAPTCHA, you may recover your account by contacting us by email.</p> + <br> + <address>support@themanaworld.org</address> + </div> + + <div v-if="step == -4"> + <h1>Loading...</h1> + <p>Please wait while reCAPTCHA is loading...</p> + <br><br> + + <h1>Proceeding without reCAPTCHA</h1> + <p>If you would rather not use reCAPTCHA, you may recover your account by contacting us by email.</p> + <br> + <address>support@themanaworld.org</address> + </div> + <div v-if="step == -1"> <h1>reCAPTCHA could not be loaded</h1> <p>This page requires reCAPTCHA but something prevents it from loading. If you are using an ad blocker or tracker blocker please whitelist this page and refresh to continue.</p> + + <h1>Proceeding without reCAPTCHA</h1> + <p>If you would rather not use reCAPTCHA, you may recover your account by contacting us by email.</p> + <br> + <address>support@themanaworld.org</address> </div> <div v-if="step == 1"> @@ -125,17 +155,17 @@ :data-sitekey="recaptcha_key" data-size="invisible"> </div> - - <script2 src="https://www.google.com/recaptcha/api.js" unload="Reflect.deleteProperty(self, 'grecaptcha')"/> </main> </template> <script lang="ts"> import { Vue, Component, Prop } from "vue-property-decorator" +import VS2 from "vue-script2" @Component export default class Recovery extends Vue { - step = 1; // no Begin button here + step = -3; // ask to use reCAPTCHA + nextStep = 1; // first step after reCAPTCHA confirmation notFound = false; // no accounts found visible = false; // password is visible exposed = false; // password has been breached @@ -159,20 +189,52 @@ export default class Recovery extends Vue { if (token.length > 1) { if (/^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i.test(token)) { this.emailToken = token; - this.step = 4; + this.nextStep = 4; // with token: enter username to reset } else { - this.step = -2; + this.step = -2; // invalid token + return; } } // already loaded (user returned to this page) if (Reflect.has(self, "grecaptcha")) { + if (this.step == -3) { + this.step = this.nextStep; + } + await this.$nextTick(); (self as any).grecaptcha.render("recaptcha-container", { sitekey: process.env.VUE_APP_RECAPTCHA, size: "invisible", }); (self as any).grecaptcha.reset(); + + if (this.step == 1) { + (this.$refs.email as any).focus(); + } else if (this.step == 4) { + (this.$refs.user as any).focus(); + } + } + } + + async start () { + (self as any).onRecaptchaLoad = async () => { + this.step = this.nextStep; + await this.$nextTick(); + + if (this.step == 1) { + (this.$refs.email as any).focus(); + } else if (this.step == 4) { + (this.$refs.user as any).focus(); + } + }; + + if (Reflect.has(self, "grecaptcha")) { + (self as any).onRecaptchaLoad(); + } else { + // load reCAPTCHA + VS2.load("https://www.google.com/recaptcha/api.js?onload=onRecaptchaLoad") + .catch(() => this.step = -1); } } diff --git a/src/views/Registration.vue b/src/views/Registration.vue index 41ebfeb..54bee98 100644 --- a/src/views/Registration.vue +++ b/src/views/Registration.vue @@ -7,7 +7,34 @@ <div style="background-color: #FFAAAA; text-align: center; border: 1px solid #BB5555; margin-bottom: 10px; text-color: white;"> <b>The apocalypse is upon us.</b> Due the Doomsday Event, during event times, powerful monsters may be found in otherwise safe areas, and sometimes even inside towns. <a href="https://forums.themanaworld.org/viewtopic.php?p=160290#p160290">Read more details here →</a> </div> - <button v-if="!step" @click="start">Begin!</button> + <button v-if="!step" @click="isRecaptchaAccepted ? start() : step = -2">Begin!</button> + + <div v-if="step == -2"> + <h1>reCAPTCHA privacy notice</h1> + <p>This page uses Google reCAPTCHA. By continuing, you agree to use reCAPTCHA, which may register tracking cookies in your browser.</p> + <p>You may review the Google Privacy Policy at <a href="https://policies.google.com/privacy">https://policies.google.com/privacy</a>.</p> + + <button @click="start">I understand and wish to proceed</button> + <br><br> + + <h1>Registering without reCAPTCHA</h1> + <p>If you would rather not use reCAPTCHA, you may register by contacting us by email.</p> + <p>We will create a new account for you and associate it with the email address that you used to contact us.</p> + <br> + <address>registration@themanaworld.org</address> + </div> + + <div v-if="step == -3"> + <h1>Loading...</h1> + <p>Please wait while reCAPTCHA is loading...</p> + <br><br> + + <h1>Registering without reCAPTCHA</h1> + <p>If you would rather not use reCAPTCHA, you may register by contacting us by email.</p> + <p>We will create a new account for you and associate it with the email address that you used to contact us.</p> + <br> + <address>registration@themanaworld.org</address> + </div> <div v-if="step == -1"> <h1>reCAPTCHA could not be loaded</h1> @@ -106,19 +133,25 @@ :data-sitekey="recaptcha_key" data-size="invisible"> </div> - - <script2 src="https://www.google.com/recaptcha/api.js" unload="Reflect.deleteProperty(self, 'grecaptcha')"/> </main> </template> <script lang="ts"> import Vue from "vue" import Component from "vue-class-component" +import VS2 from "vue-script2" @Component({ beforeRouteLeave: (to, from, next) => { next(); - } + }, + + computed: { + isRecaptchaAccepted () { + // the user already agreed to use reCAPTCHA (loaded) + return Reflect.has(self, 'grecaptcha'); + } + }, }) export default class Registration extends Vue { step = 0; @@ -147,9 +180,19 @@ export default class Registration extends Vue { } async start () { - this.step = Reflect.has(self, "grecaptcha") ? 1 : -1; - await this.$nextTick(); - (this.$refs.email as any).focus(); + (self as any).onRecaptchaLoad = async () => { + this.step = 1; + await this.$nextTick(); + (this.$refs.email as any).focus(); + }; + + if (Reflect.has(self, "grecaptcha")) { + (self as any).onRecaptchaLoad(); + } else { + // load reCAPTCHA + VS2.load("https://www.google.com/recaptcha/api.js?onload=onRecaptchaLoad") + .catch(() => this.step = -1); + } } async checkEmail () { |