summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorzyoshoka <107108195+zyoshoka@users.noreply.github.com>2024-03-30 13:51:53 +0900
committerGitHub <noreply@github.com>2024-03-30 13:51:53 +0900
commitb35ae97ba7b57ae2b04eb0cc25dd3360e321e537 (patch)
tree322b4c657fa6dc09a6cff5fb8b97906c45879ed4 /packages
parentfix: report progress out of 100% in CleanRemoteFilesProcessorService (#13633) (diff)
downloadsharkey-b35ae97ba7b57ae2b04eb0cc25dd3360e321e537.tar.gz
sharkey-b35ae97ba7b57ae2b04eb0cc25dd3360e321e537.tar.bz2
sharkey-b35ae97ba7b57ae2b04eb0cc25dd3360e321e537.zip
fix(backend): better `notes/translate` error response (#13631)
* fix(backend): better `notes/translate` error response * Update CHANGELOG.md * test(backend): perform administrative operations as `root` --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Diffstat (limited to 'packages')
-rw-r--r--packages/backend/src/server/api/endpoints/notes/translate.ts13
-rw-r--r--packages/backend/test/e2e/note.ts107
-rw-r--r--packages/misskey-js/src/autogen/types.ts4
3 files changed, 96 insertions, 28 deletions
diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts
index 78812351f4..38a9660aa2 100644
--- a/packages/backend/src/server/api/endpoints/notes/translate.ts
+++ b/packages/backend/src/server/api/endpoints/notes/translate.ts
@@ -21,7 +21,7 @@ export const meta = {
res: {
type: 'object',
- optional: false, nullable: false,
+ optional: true, nullable: false,
properties: {
sourceLang: { type: 'string' },
text: { type: 'string' },
@@ -39,6 +39,11 @@ export const meta = {
code: 'NO_SUCH_NOTE',
id: 'bea9b03f-36e0-49c5-a4db-627a029f8971',
},
+ cannotTranslateInvisibleNote: {
+ message: 'Cannot translate invisible note.',
+ code: 'CANNOT_TRANSLATE_INVISIBLE_NOTE',
+ id: 'ea29f2ca-c368-43b3-aaf1-5ac3e74bbe5d',
+ },
},
} as const;
@@ -72,17 +77,17 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
});
if (!(await this.noteEntityService.isVisibleForMe(note, me.id))) {
- return 204; // TODO: 良い感じのエラー返す
+ throw new ApiError(meta.errors.cannotTranslateInvisibleNote);
}
if (note.text == null) {
- return 204;
+ return;
}
const instance = await this.metaService.fetch();
if (instance.deeplAuthKey == null) {
- return 204; // TODO: 良い感じのエラー返す
+ throw new ApiError(meta.errors.unavailable);
}
let targetLang = ps.targetLang;
diff --git a/packages/backend/test/e2e/note.ts b/packages/backend/test/e2e/note.ts
index 11016f58ae..bda31d9640 100644
--- a/packages/backend/test/e2e/note.ts
+++ b/packages/backend/test/e2e/note.ts
@@ -8,12 +8,13 @@ process.env.NODE_ENV = 'test';
import * as assert from 'assert';
import { MiNote } from '@/models/Note.js';
import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
-import { api, initTestDb, post, signup, uploadFile, uploadUrl } from '../utils.js';
+import { api, initTestDb, post, role, signup, uploadFile, uploadUrl } from '../utils.js';
import type * as misskey from 'misskey-js';
describe('Note', () => {
let Notes: any;
+ let root: misskey.entities.SignupResponse;
let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse;
let tom: misskey.entities.SignupResponse;
@@ -21,6 +22,7 @@ describe('Note', () => {
beforeAll(async () => {
const connection = await initTestDb(true);
Notes = connection.getRepository(MiNote);
+ root = await signup({ username: 'root' });
alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' });
tom = await signup({ username: 'tom', host: 'example.com' });
@@ -473,14 +475,14 @@ describe('Note', () => {
value: true,
},
} as any,
- }, alice);
+ }, root);
assert.strictEqual(res.status, 200);
const assign = await api('admin/roles/assign', {
userId: alice.id,
roleId: res.body.id,
- }, alice);
+ }, root);
assert.strictEqual(assign.status, 204);
assert.strictEqual(file.body!.isSensitive, false);
@@ -508,11 +510,11 @@ describe('Note', () => {
await api('admin/roles/unassign', {
userId: alice.id,
roleId: res.body.id,
- });
+ }, root);
await api('admin/roles/delete', {
roleId: res.body.id,
- }, alice);
+ }, root);
});
});
@@ -644,7 +646,7 @@ describe('Note', () => {
sensitiveWords: [
'test',
],
- }, alice);
+ }, root);
assert.strictEqual(sensitive.status, 204);
@@ -663,7 +665,7 @@ describe('Note', () => {
sensitiveWords: [
'/Test/i',
],
- }, alice);
+ }, root);
assert.strictEqual(sensitive.status, 204);
@@ -680,7 +682,7 @@ describe('Note', () => {
sensitiveWords: [
'Test hoge',
],
- }, alice);
+ }, root);
assert.strictEqual(sensitive.status, 204);
@@ -697,7 +699,7 @@ describe('Note', () => {
prohibitedWords: [
'test',
],
- }, alice);
+ }, root);
assert.strictEqual(prohibited.status, 204);
@@ -716,7 +718,7 @@ describe('Note', () => {
prohibitedWords: [
'/Test/i',
],
- }, alice);
+ }, root);
assert.strictEqual(prohibited.status, 204);
@@ -733,7 +735,7 @@ describe('Note', () => {
prohibitedWords: [
'Test hoge',
],
- }, alice);
+ }, root);
assert.strictEqual(prohibited.status, 204);
@@ -750,7 +752,7 @@ describe('Note', () => {
prohibitedWords: [
'test',
],
- }, alice);
+ }, root);
assert.strictEqual(prohibited.status, 204);
@@ -785,7 +787,7 @@ describe('Note', () => {
value: 0,
},
} as any,
- }, alice);
+ }, root);
assert.strictEqual(res.status, 200);
@@ -794,7 +796,7 @@ describe('Note', () => {
const assign = await api('admin/roles/assign', {
userId: alice.id,
roleId: res.body.id,
- }, alice);
+ }, root);
assert.strictEqual(assign.status, 204);
@@ -810,11 +812,11 @@ describe('Note', () => {
await api('admin/roles/unassign', {
userId: alice.id,
roleId: res.body.id,
- });
+ }, root);
await api('admin/roles/delete', {
roleId: res.body.id,
- }, alice);
+ }, root);
});
test('ダイレクト投稿もエラーになる', async () => {
@@ -839,7 +841,7 @@ describe('Note', () => {
value: 0,
},
} as any,
- }, alice);
+ }, root);
assert.strictEqual(res.status, 200);
@@ -848,7 +850,7 @@ describe('Note', () => {
const assign = await api('admin/roles/assign', {
userId: alice.id,
roleId: res.body.id,
- }, alice);
+ }, root);
assert.strictEqual(assign.status, 204);
@@ -866,11 +868,11 @@ describe('Note', () => {
await api('admin/roles/unassign', {
userId: alice.id,
roleId: res.body.id,
- });
+ }, root);
await api('admin/roles/delete', {
roleId: res.body.id,
- }, alice);
+ }, root);
});
test('ダイレクトの宛先とメンションが同じ場合は重複してカウントしない', async () => {
@@ -895,7 +897,7 @@ describe('Note', () => {
value: 1,
},
} as any,
- }, alice);
+ }, root);
assert.strictEqual(res.status, 200);
@@ -904,7 +906,7 @@ describe('Note', () => {
const assign = await api('admin/roles/assign', {
userId: alice.id,
roleId: res.body.id,
- }, alice);
+ }, root);
assert.strictEqual(assign.status, 204);
@@ -921,11 +923,11 @@ describe('Note', () => {
await api('admin/roles/unassign', {
userId: alice.id,
roleId: res.body.id,
- });
+ }, root);
await api('admin/roles/delete', {
roleId: res.body.id,
- }, alice);
+ }, root);
});
});
@@ -960,4 +962,61 @@ describe('Note', () => {
assert.strictEqual(mainNote.repliesCount, 0);
});
});
+
+ describe('notes/translate', () => {
+ describe('翻訳機能の利用が許可されていない場合', () => {
+ let cannotTranslateRole: misskey.entities.Role;
+
+ beforeAll(async () => {
+ cannotTranslateRole = await role(root, {}, { canUseTranslator: false });
+ await api('admin/roles/assign', { roleId: cannotTranslateRole.id, userId: alice.id }, root);
+ });
+
+ test('翻訳機能の利用が許可されていない場合翻訳できない', async () => {
+ const aliceNote = await post(alice, { text: 'Hello' });
+ const res = await api('notes/translate', {
+ noteId: aliceNote.id,
+ targetLang: 'ja',
+ }, alice);
+
+ assert.strictEqual(res.status, 400);
+ assert.strictEqual(res.body.error.code, 'UNAVAILABLE');
+ });
+
+ afterAll(async () => {
+ await api('admin/roles/unassign', { roleId: cannotTranslateRole.id, userId: alice.id }, root);
+ });
+ });
+
+ test('存在しないノートは翻訳できない', async () => {
+ const res = await api('notes/translate', { noteId: 'foo', targetLang: 'ja' }, alice);
+
+ assert.strictEqual(res.status, 400);
+ assert.strictEqual(res.body.error.code, 'NO_SUCH_NOTE');
+ });
+
+ test('不可視なノートは翻訳できない', async () => {
+ const aliceNote = await post(alice, { visibility: 'followers', text: 'Hello' });
+ const bobTranslateAttempt = await api('notes/translate', { noteId: aliceNote.id, targetLang: 'ja' }, bob);
+
+ assert.strictEqual(bobTranslateAttempt.status, 400);
+ assert.strictEqual(bobTranslateAttempt.body.error.code, 'CANNOT_TRANSLATE_INVISIBLE_NOTE');
+ });
+
+ test('text: null なノートを翻訳すると空のレスポンスが返ってくる', async () => {
+ const aliceNote = await post(alice, { text: null, poll: { choices: ['kinoko', 'takenoko'] } });
+ const res = await api('notes/translate', { noteId: aliceNote.id, targetLang: 'ja' }, alice);
+
+ assert.strictEqual(res.status, 204);
+ });
+
+ test('サーバーに DeepL 認証キーが登録されていない場合翻訳できない', async () => {
+ const aliceNote = await post(alice, { text: 'Hello' });
+ const res = await api('notes/translate', { noteId: aliceNote.id, targetLang: 'ja' }, alice);
+
+ // NOTE: デフォルトでは登録されていないので落ちる
+ assert.strictEqual(res.status, 400);
+ assert.strictEqual(res.body.error.code, 'UNAVAILABLE');
+ });
+ });
});
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 4b2ad16b0f..b6b26c000c 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -21864,6 +21864,10 @@ export type operations = {
};
};
};
+ /** @description OK (without any results) */
+ 204: {
+ content: never;
+ };
/** @description Client error */
400: {
content: {