summaryrefslogtreecommitdiff
path: root/packages/client/src/pages/admin/bot-protection.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/client/src/pages/admin/bot-protection.vue')
-rw-r--r--packages/client/src/pages/admin/bot-protection.vue138
1 files changed, 138 insertions, 0 deletions
diff --git a/packages/client/src/pages/admin/bot-protection.vue b/packages/client/src/pages/admin/bot-protection.vue
new file mode 100644
index 0000000000..8f7873baa3
--- /dev/null
+++ b/packages/client/src/pages/admin/bot-protection.vue
@@ -0,0 +1,138 @@
+<template>
+<FormBase>
+ <FormSuspense :p="init">
+ <FormRadios v-model="provider">
+ <template #desc><i class="fas fa-shield-alt"></i> {{ $ts.botProtection }}</template>
+ <option :value="null">{{ $ts.none }} ({{ $ts.notRecommended }})</option>
+ <option value="hcaptcha">hCaptcha</option>
+ <option value="recaptcha">reCAPTCHA</option>
+ </FormRadios>
+
+ <template v-if="provider === 'hcaptcha'">
+ <div class="_debobigegoItem _debobigegoNoConcat" v-sticky-container>
+ <div class="_debobigegoLabel">hCaptcha</div>
+ <div class="main">
+ <FormInput v-model="hcaptchaSiteKey">
+ <template #prefix><i class="fas fa-key"></i></template>
+ <span>{{ $ts.hcaptchaSiteKey }}</span>
+ </FormInput>
+ <FormInput v-model="hcaptchaSecretKey">
+ <template #prefix><i class="fas fa-key"></i></template>
+ <span>{{ $ts.hcaptchaSecretKey }}</span>
+ </FormInput>
+ </div>
+ </div>
+ <div class="_debobigegoItem _debobigegoNoConcat" v-sticky-container>
+ <div class="_debobigegoLabel">{{ $ts.preview }}</div>
+ <div class="_debobigegoPanel" style="padding: var(--debobigegoContentHMargin);">
+ <MkCaptcha provider="hcaptcha" :sitekey="hcaptchaSiteKey || '10000000-ffff-ffff-ffff-000000000001'"/>
+ </div>
+ </div>
+ </template>
+ <template v-else-if="provider === 'recaptcha'">
+ <div class="_debobigegoItem _debobigegoNoConcat" v-sticky-container>
+ <div class="_debobigegoLabel">reCAPTCHA</div>
+ <div class="main">
+ <FormInput v-model="recaptchaSiteKey">
+ <template #prefix><i class="fas fa-key"></i></template>
+ <span>{{ $ts.recaptchaSiteKey }}</span>
+ </FormInput>
+ <FormInput v-model="recaptchaSecretKey">
+ <template #prefix><i class="fas fa-key"></i></template>
+ <span>{{ $ts.recaptchaSecretKey }}</span>
+ </FormInput>
+ </div>
+ </div>
+ <div v-if="recaptchaSiteKey" class="_debobigegoItem _debobigegoNoConcat" v-sticky-container>
+ <div class="_debobigegoLabel">{{ $ts.preview }}</div>
+ <div class="_debobigegoPanel" style="padding: var(--debobigegoContentHMargin);">
+ <MkCaptcha provider="recaptcha" :sitekey="recaptchaSiteKey"/>
+ </div>
+ </div>
+ </template>
+
+ <FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+ </FormSuspense>
+</FormBase>
+</template>
+
+<script lang="ts">
+import { defineAsyncComponent, defineComponent } from 'vue';
+import FormRadios from '@/components/debobigego/radios.vue';
+import FormInput from '@/components/debobigego/input.vue';
+import FormButton from '@/components/debobigego/button.vue';
+import FormBase from '@/components/debobigego/base.vue';
+import FormGroup from '@/components/debobigego/group.vue';
+import FormInfo from '@/components/debobigego/info.vue';
+import FormSuspense from '@/components/debobigego/suspense.vue';
+import * as os from '@/os';
+import * as symbols from '@/symbols';
+import { fetchInstance } from '@/instance';
+
+export default defineComponent({
+ components: {
+ FormRadios,
+ FormInput,
+ FormBase,
+ FormGroup,
+ FormButton,
+ FormInfo,
+ FormSuspense,
+ MkCaptcha: defineAsyncComponent(() => import('@/components/captcha.vue')),
+ },
+
+ emits: ['info'],
+
+ data() {
+ return {
+ [symbols.PAGE_INFO]: {
+ title: this.$ts.botProtection,
+ icon: 'fas fa-shield-alt'
+ },
+ provider: null,
+ enableHcaptcha: false,
+ hcaptchaSiteKey: null,
+ hcaptchaSecretKey: null,
+ enableRecaptcha: false,
+ recaptchaSiteKey: null,
+ recaptchaSecretKey: null,
+ }
+ },
+
+ async mounted() {
+ this.$emit('info', this[symbols.PAGE_INFO]);
+ },
+
+ methods: {
+ async init() {
+ const meta = await os.api('meta', { detail: true });
+ this.enableHcaptcha = meta.enableHcaptcha;
+ this.hcaptchaSiteKey = meta.hcaptchaSiteKey;
+ this.hcaptchaSecretKey = meta.hcaptchaSecretKey;
+ this.enableRecaptcha = meta.enableRecaptcha;
+ this.recaptchaSiteKey = meta.recaptchaSiteKey;
+ this.recaptchaSecretKey = meta.recaptchaSecretKey;
+
+ this.provider = this.enableHcaptcha ? 'hcaptcha' : this.enableRecaptcha ? 'recaptcha' : null;
+
+ this.$watch(() => this.provider, () => {
+ this.enableHcaptcha = this.provider === 'hcaptcha';
+ this.enableRecaptcha = this.provider === 'recaptcha';
+ });
+ },
+
+ save() {
+ os.apiWithDialog('admin/update-meta', {
+ enableHcaptcha: this.enableHcaptcha,
+ hcaptchaSiteKey: this.hcaptchaSiteKey,
+ hcaptchaSecretKey: this.hcaptchaSecretKey,
+ enableRecaptcha: this.enableRecaptcha,
+ recaptchaSiteKey: this.recaptchaSiteKey,
+ recaptchaSecretKey: this.recaptchaSecretKey,
+ }).then(() => {
+ fetchInstance();
+ });
+ }
+ }
+});
+</script>