From ddbb0a4c01ecfd5a6f3d781ce4e5ae72c2ab2f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?= <46447427+samunohito@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:35:58 +0900 Subject: [PATCH] fix --- packages/backend/src/server/api/endpoints.ts | 2 +- .../api/endpoints/admin/captcha/save.ts | 101 ++++++++++++------ .../src/pages/admin/bot-protection.vue | 76 ++++--------- packages/misskey-js/etc/misskey-js.api.md | 8 +- .../misskey-js/src/autogen/apiClientJSDoc.ts | 2 +- packages/misskey-js/src/autogen/endpoint.ts | 5 +- packages/misskey-js/src/autogen/entities.ts | 3 +- packages/misskey-js/src/autogen/types.ts | 24 ++--- 8 files changed, 106 insertions(+), 115 deletions(-) diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 68c333a7cf74..72db473de59c 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -421,7 +421,7 @@ const eps = [ ['admin/avatar-decorations/delete', ep___admin_avatarDecorations_delete], ['admin/avatar-decorations/list', ep___admin_avatarDecorations_list], ['admin/avatar-decorations/update', ep___admin_avatarDecorations_update], - ['admin/captcha/test', ep___admin_captcha_save], + ['admin/captcha/save', ep___admin_captcha_save], ['admin/delete-all-files-of-a-user', ep___admin_deleteAllFilesOfAUser], ['admin/unset-user-avatar', ep___admin_unsetUserAvatar], ['admin/unset-user-banner', ep___admin_unsetUserBanner], diff --git a/packages/backend/src/server/api/endpoints/admin/captcha/save.ts b/packages/backend/src/server/api/endpoints/admin/captcha/save.ts index ad41e0b36170..d3a71e32f3a3 100644 --- a/packages/backend/src/server/api/endpoints/admin/captcha/save.ts +++ b/packages/backend/src/server/api/endpoints/admin/captcha/save.ts @@ -5,7 +5,8 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { CaptchaService, supportedCaptchaProviders } from '@/core/CaptchaService.js'; +import { captchaErrorCodes, CaptchaService, supportedCaptchaProviders } from '@/core/CaptchaService.js'; +import { ApiError } from '@/server/api/error.js'; export const meta = { tags: ['admin', 'captcha'], @@ -16,25 +17,42 @@ export const meta = { kind: 'read:admin:captcha', - res: { - type: 'object', - properties: { - success: { - type: 'boolean', - }, - error: { - type: 'object', - nullable: true, - optional: false, - properties: { - code: { - type: 'string', - }, - message: { - type: 'string', - }, - }, - }, + errors: { + invalidProvider: { + message: 'Invalid provider.', + code: 'INVALID_PROVIDER', + id: '14BF7AE1-80CC-4363-ACB2-4FD61D086AF0', + httpStatusCode: 400, + }, + invalidParameters: { + message: 'Invalid parameters.', + code: 'INVALID_PARAMETERS', + id: '26654194-410E-44E2-B42E-460FF6F92476', + httpStatusCode: 400, + }, + noResponseProvided: { + message: 'No response provided.', + code: 'NO_RESPONSE_PROVIDED', + id: '40ACBBA8-0937-41FB-BB3F-474514D40AFE', + httpStatusCode: 400, + }, + requestFailed: { + message: 'Request failed.', + code: 'REQUEST_FAILED', + id: '0F4FE2F1-2C15-4D6E-B714-EFBFCDE231CD', + httpStatusCode: 500, + }, + verificationFailed: { + message: 'Verification failed.', + code: 'VERIFICATION_FAILED', + id: 'C41C067F-24F3-4150-84B2-B5A3AE8C2214', + httpStatusCode: 400, + }, + unknown: { + message: 'unknown', + code: 'UNKNOWN', + id: 'F868D509-E257-42A9-99C1-42614B031A97', + httpStatusCode: 500, }, }, } as const; @@ -68,22 +86,43 @@ export default class extends Endpoint { // eslint- private captchaService: CaptchaService, ) { super(meta, paramDef, async (ps) => { - const result = await this.captchaService.save(ps.provider, ps.captchaResult, { + const result = await this.captchaService.save(ps.provider, { sitekey: ps.sitekey, secret: ps.secret, instanceUrl: ps.instanceUrl, + captchaResult: ps.captchaResult, }); - if (result.success) { - return { success: true, error: null }; - } else { - return { - success: false, - error: { - code: result.error.code.toString(), - message: result.error.message, - }, - }; + if (!result.success) { + switch (result.error.code) { + case captchaErrorCodes.invalidProvider: + throw new ApiError({ + ...meta.errors.invalidProvider, + message: result.error.message, + }); + case captchaErrorCodes.invalidParameters: + throw new ApiError({ + ...meta.errors.invalidParameters, + message: result.error.message, + }); + case captchaErrorCodes.noResponseProvided: + throw new ApiError({ + ...meta.errors.noResponseProvided, + message: result.error.message, + }); + case captchaErrorCodes.requestFailed: + throw new ApiError({ + ...meta.errors.requestFailed, + message: result.error.message, + }); + case captchaErrorCodes.verificationFailed: + throw new ApiError({ + ...meta.errors.verificationFailed, + message: result.error.message, + }); + default: + throw new ApiError(meta.errors.unknown); + } } }); } diff --git a/packages/frontend/src/pages/admin/bot-protection.vue b/packages/frontend/src/pages/admin/bot-protection.vue index 3e6810240b33..aa41edd2195f 100644 --- a/packages/frontend/src/pages/admin/bot-protection.vue +++ b/packages/frontend/src/pages/admin/bot-protection.vue @@ -142,10 +142,6 @@ SPDX-License-Identifier: AGPL-3.0-only - - - {{ verifyErrorText }} - @@ -170,16 +166,14 @@ const MkCaptcha = defineAsyncComponent(() => import('@/components/MkCaptcha.vue' const meta = await misskeyApi('admin/meta'); const captchaResult = ref(null); -const verifyResult = ref(false); -const verifyErrorText = ref(null); const canSaving = computed((): boolean => { return (botProtectionForm.state.provider === null) || - (botProtectionForm.state.provider === 'hcaptcha' && verifyResult.value) || - (botProtectionForm.state.provider === 'mcaptcha' && verifyResult.value) || - (botProtectionForm.state.provider === 'recaptcha' && verifyResult.value) || - (botProtectionForm.state.provider === 'turnstile' && verifyResult.value) || - (botProtectionForm.state.provider === 'testcaptcha' && verifyResult.value); + (botProtectionForm.state.provider === 'hcaptcha' && !!captchaResult.value) || + (botProtectionForm.state.provider === 'mcaptcha' && !!captchaResult.value) || + (botProtectionForm.state.provider === 'recaptcha' && !!captchaResult.value) || + (botProtectionForm.state.provider === 'turnstile' && !!captchaResult.value) || + (botProtectionForm.state.provider === 'testcaptcha' && !!captchaResult.value); }); const botProtectionForm = useForm({ @@ -204,36 +198,6 @@ const botProtectionForm = useForm({ turnstileSiteKey: meta.turnstileSiteKey, turnstileSecretKey: meta.turnstileSecretKey, }, async (state) => { - await os.apiWithDialog('admin/update-meta', { - enableHcaptcha: state.provider === 'hcaptcha', - hcaptchaSiteKey: state.hcaptchaSiteKey, - hcaptchaSecretKey: state.hcaptchaSecretKey, - enableMcaptcha: state.provider === 'mcaptcha', - mcaptchaSiteKey: state.mcaptchaSiteKey, - mcaptchaSecretKey: state.mcaptchaSecretKey, - mcaptchaInstanceUrl: state.mcaptchaInstanceUrl, - enableRecaptcha: state.provider === 'recaptcha', - recaptchaSiteKey: state.recaptchaSiteKey, - recaptchaSecretKey: state.recaptchaSecretKey, - enableTurnstile: state.provider === 'turnstile', - turnstileSiteKey: state.turnstileSiteKey, - turnstileSecretKey: state.turnstileSecretKey, - enableTestcaptcha: state.provider === 'testcaptcha', - }); - fetchInstance(true); -}); - -watch(botProtectionForm.state, () => { - captchaResult.value = null; - if (botProtectionForm.state.provider === null) { - verifyResult.value = true; - } else { - verifyResult.value = false; - verifyErrorText.value = null; - } -}); - -watch(captchaResult, async () => { const provider = botProtectionForm.state.provider; const sitekey = provider === 'hcaptcha' @@ -256,22 +220,24 @@ watch(captchaResult, async () => { : null; if (captchaResult.value) { - const result = await misskeyApi('admin/captcha/test', { - provider: provider as Misskey.entities.AdminCaptchaTestRequest['provider'], - sitekey: sitekey, - secret: secret, - instanceUrl: botProtectionForm.state.mcaptchaInstanceUrl, - captchaResult: captchaResult.value, - }); - - verifyResult.value = result.success; - verifyErrorText.value = result.error - ? result.error.message - : null; - } else { - verifyResult.value = false; + await os.apiWithDialog( + 'admin/captcha/save', + { + provider: provider as Misskey.entities.AdminCaptchaSaveRequest['provider'], + sitekey: sitekey, + secret: secret, + instanceUrl: botProtectionForm.state.mcaptchaInstanceUrl, + captchaResult: captchaResult.value, + }, + ); + + await fetchInstance(true); } }); + +watch(botProtectionForm.state, () => { + captchaResult.value = null; +});