From 78608392208cb73351354cda5678daee232159d8 Mon Sep 17 00:00:00 2001 From: "Acid Chicken (硫酸鶏)" Date: Tue, 28 Apr 2020 14:29:33 +0900 Subject: Add support for hCaptcha --- src/@types/hcaptcha.d.ts | 9 ++++ src/client/components/hcaptcha.vue | 76 +++++++++++++++++++++++++++ src/client/components/signup.vue | 24 ++++++--- src/client/components/url-preview.vue | 2 +- src/client/pages/instance/settings.vue | 67 ++++++++++++++++++----- src/models/entities/meta.ts | 17 ++++++ src/server/api/endpoints/admin/update-meta.ts | 33 ++++++++++++ src/server/api/endpoints/meta.ts | 4 ++ src/server/api/private/signup.ts | 13 ++++- src/server/nodeinfo.ts | 1 + src/server/web/views/info.pug | 3 ++ 11 files changed, 229 insertions(+), 20 deletions(-) create mode 100644 src/@types/hcaptcha.d.ts create mode 100644 src/client/components/hcaptcha.vue (limited to 'src') diff --git a/src/@types/hcaptcha.d.ts b/src/@types/hcaptcha.d.ts new file mode 100644 index 0000000000..ef3d44256c --- /dev/null +++ b/src/@types/hcaptcha.d.ts @@ -0,0 +1,9 @@ +declare module 'hcaptcha' { + export function verify(secret: string, token: string): Promise<{ + success: boolean; + challenge_ts: string; + hostname: string; + credit?: boolean; + 'error-codes'?: unknown[]; + }>; +} diff --git a/src/client/components/hcaptcha.vue b/src/client/components/hcaptcha.vue new file mode 100644 index 0000000000..e54eb314a3 --- /dev/null +++ b/src/client/components/hcaptcha.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/client/components/signup.vue b/src/client/components/signup.vue index 9f3ae8db28..5d16a82bac 100644 --- a/src/client/components/signup.vue +++ b/src/client/components/signup.vue @@ -42,7 +42,8 @@
- {{ $t('start') }} + + {{ $t('start') }} @@ -65,6 +66,7 @@ export default Vue.extend({ MkButton, MkInput, MkSwitch, + hCaptcha: () => import('./hcaptcha.vue').then(x => x.default), }, data() { @@ -80,6 +82,7 @@ export default Vue.extend({ passwordRetypeState: null, submitting: false, ToSAgreement: false, + hCaptchaResponse: null, faLock, faExclamationTriangle, faSpinner, faCheck, faKey } }, @@ -96,7 +99,14 @@ export default Vue.extend({ meta() { return this.$store.state.instance.meta; }, - + + shouldDisableSubmitting(): boolean { + return this.submitting || + this.meta.tosUrl && !this.ToSAgreement || + this.meta.enableHcaptcha && !this.hCaptchaResponse || + this.passwordRetypeState == 'not-match'; + }, + shouldShowProfileUrl(): boolean { return (this.username != '' && this.usernameState != 'invalid-format' && @@ -115,10 +125,11 @@ export default Vue.extend({ }, mounted() { - const head = document.getElementsByTagName('head')[0]; - const script = document.createElement('script'); - script.setAttribute('src', 'https://www.google.com/recaptcha/api.js'); - head.appendChild(script); + if (this.meta.enableRecaptcha) { + const script = document.createElement('script'); + script.setAttribute('src', 'https://www.google.com/recaptcha/api.js'); + document.head.appendChild(script); + } }, methods: { @@ -177,6 +188,7 @@ export default Vue.extend({ username: this.username, password: this.password, invitationCode: this.invitationCode, + 'hcaptcha-response': this.hCaptchaResponse, 'g-recaptcha-response': this.meta.enableRecaptcha ? (window as any).grecaptcha.getResponse() : null }).then(() => { this.$root.api('signin', { diff --git a/src/client/components/url-preview.vue b/src/client/components/url-preview.vue index 94d07cbaed..c2dd0038be 100644 --- a/src/client/components/url-preview.vue +++ b/src/client/components/url-preview.vue @@ -4,7 +4,7 @@