Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
samunohito committed Dec 20, 2024
1 parent ce7f205 commit ddbb0a4
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 115 deletions.
2 changes: 1 addition & 1 deletion packages/backend/src/server/api/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
101 changes: 70 additions & 31 deletions packages/backend/src/server/api/endpoints/admin/captcha/save.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Expand All @@ -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;
Expand Down Expand Up @@ -68,22 +86,43 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // 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);
}
}
});
}
Expand Down
76 changes: 21 additions & 55 deletions packages/frontend/src/pages/admin/bot-protection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkCaptcha v-model="captchaResult" provider="testcaptcha" :sitekey="null"/>
</FormSlot>
</template>

<MkInfo v-if="!verifyResult && verifyErrorText" warn>
{{ verifyErrorText }}
</MkInfo>
</div>
</MkFolder>
</template>
Expand All @@ -170,16 +166,14 @@ const MkCaptcha = defineAsyncComponent(() => import('@/components/MkCaptcha.vue'
const meta = await misskeyApi('admin/meta');

const captchaResult = ref<string | null>(null);
const verifyResult = ref<boolean>(false);
const verifyErrorText = ref<string | null>(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({
Expand All @@ -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'
Expand All @@ -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;
});
</script>

<style lang="scss" module>
Expand Down
8 changes: 2 additions & 6 deletions packages/misskey-js/etc/misskey-js.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,7 @@ type AdminAvatarDecorationsListResponse = operations['admin___avatar-decorations
type AdminAvatarDecorationsUpdateRequest = operations['admin___avatar-decorations___update']['requestBody']['content']['application/json'];

// @public (undocumented)
type AdminCaptchaTestRequest = operations['admin___captcha___test']['requestBody']['content']['application/json'];

// @public (undocumented)
type AdminCaptchaTestResponse = operations['admin___captcha___test']['responses']['200']['content']['application/json'];
type AdminCaptchaSaveRequest = operations['admin___captcha___save']['requestBody']['content']['application/json'];

// @public (undocumented)
type AdminDeleteAccountRequest = operations['admin___delete-account']['requestBody']['content']['application/json'];
Expand Down Expand Up @@ -1267,8 +1264,7 @@ declare namespace entities {
AdminAvatarDecorationsListRequest,
AdminAvatarDecorationsListResponse,
AdminAvatarDecorationsUpdateRequest,
AdminCaptchaTestRequest,
AdminCaptchaTestResponse,
AdminCaptchaSaveRequest,
AdminDeleteAllFilesOfAUserRequest,
AdminUnsetUserAvatarRequest,
AdminUnsetUserBannerRequest,
Expand Down
2 changes: 1 addition & 1 deletion packages/misskey-js/src/autogen/apiClientJSDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ declare module '../api.js' {
* **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties.
* **Credential required**: *Yes* / **Permission**: *read:admin:captcha*
*/
request<E extends 'admin/captcha/test', P extends Endpoints[E]['req']>(
request<E extends 'admin/captcha/save', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
Expand Down
5 changes: 2 additions & 3 deletions packages/misskey-js/src/autogen/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ import type {
AdminAvatarDecorationsListRequest,
AdminAvatarDecorationsListResponse,
AdminAvatarDecorationsUpdateRequest,
AdminCaptchaTestRequest,
AdminCaptchaTestResponse,
AdminCaptchaSaveRequest,
AdminDeleteAllFilesOfAUserRequest,
AdminUnsetUserAvatarRequest,
AdminUnsetUserBannerRequest,
Expand Down Expand Up @@ -606,7 +605,7 @@ export type Endpoints = {
'admin/avatar-decorations/delete': { req: AdminAvatarDecorationsDeleteRequest; res: EmptyResponse };
'admin/avatar-decorations/list': { req: AdminAvatarDecorationsListRequest; res: AdminAvatarDecorationsListResponse };
'admin/avatar-decorations/update': { req: AdminAvatarDecorationsUpdateRequest; res: EmptyResponse };
'admin/captcha/test': { req: AdminCaptchaTestRequest; res: AdminCaptchaTestResponse };
'admin/captcha/save': { req: AdminCaptchaSaveRequest; res: EmptyResponse };
'admin/delete-all-files-of-a-user': { req: AdminDeleteAllFilesOfAUserRequest; res: EmptyResponse };
'admin/unset-user-avatar': { req: AdminUnsetUserAvatarRequest; res: EmptyResponse };
'admin/unset-user-banner': { req: AdminUnsetUserBannerRequest; res: EmptyResponse };
Expand Down
3 changes: 1 addition & 2 deletions packages/misskey-js/src/autogen/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ export type AdminAvatarDecorationsDeleteRequest = operations['admin___avatar-dec
export type AdminAvatarDecorationsListRequest = operations['admin___avatar-decorations___list']['requestBody']['content']['application/json'];
export type AdminAvatarDecorationsListResponse = operations['admin___avatar-decorations___list']['responses']['200']['content']['application/json'];
export type AdminAvatarDecorationsUpdateRequest = operations['admin___avatar-decorations___update']['requestBody']['content']['application/json'];
export type AdminCaptchaTestRequest = operations['admin___captcha___test']['requestBody']['content']['application/json'];
export type AdminCaptchaTestResponse = operations['admin___captcha___test']['responses']['200']['content']['application/json'];
export type AdminCaptchaSaveRequest = operations['admin___captcha___save']['requestBody']['content']['application/json'];
export type AdminDeleteAllFilesOfAUserRequest = operations['admin___delete-all-files-of-a-user']['requestBody']['content']['application/json'];
export type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json'];
export type AdminUnsetUserBannerRequest = operations['admin___unset-user-banner']['requestBody']['content']['application/json'];
Expand Down
24 changes: 8 additions & 16 deletions packages/misskey-js/src/autogen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,15 +215,15 @@ export type paths = {
*/
post: operations['admin___avatar-decorations___update'];
};
'/admin/captcha/test': {
'/admin/captcha/save': {
/**
* admin/captcha/test
* admin/captcha/save
* @description No description provided.
*
* **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties.
* **Credential required**: *Yes* / **Permission**: *read:admin:captcha*
*/
post: operations['admin___captcha___test'];
post: operations['admin___captcha___save'];
};
'/admin/delete-all-files-of-a-user': {
/**
Expand Down Expand Up @@ -6575,13 +6575,13 @@ export type operations = {
};
};
/**
* admin/captcha/test
* admin/captcha/save
* @description No description provided.
*
* **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties.
* **Credential required**: *Yes* / **Permission**: *read:admin:captcha*
*/
admin___captcha___test: {
admin___captcha___save: {
requestBody: {
content: {
'application/json': {
Expand All @@ -6595,17 +6595,9 @@ export type operations = {
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': {
success: boolean;
error: {
code: string;
message: string;
} | null;
};
};
/** @description OK (without any results) */
204: {
content: never;
};
/** @description Client error */
400: {
Expand Down

0 comments on commit ddbb0a4

Please sign in to comment.