From 5ac6bc5463789ec15eaea14a37fe09381d5cdb98 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 3 Apr 2022 06:57:26 +0200 Subject: [PATCH] fix: validation (better #8456) (#8461) * Revert "revert 484e023c0" This reverts commit c03b70c949923b830a6d0361d1aa4d5f5614b7b7. * also allow pure renote * fix checks for pure renote --- packages/backend/src/models/schema/emoji.ts | 1 + packages/backend/src/models/schema/user.ts | 1 + .../server/api/endpoints/admin/drive/files.ts | 7 +- .../api/endpoints/admin/drive/show-file.ts | 20 +++-- .../api/endpoints/admin/emoji/list-remote.ts | 8 +- .../server/api/endpoints/admin/emoji/list.ts | 5 +- .../admin/emoji/set-category-bulk.ts | 6 +- .../api/endpoints/admin/emoji/update.ts | 6 +- .../server/api/endpoints/admin/show-users.ts | 9 +- .../server/api/endpoints/channels/pin-note.ts | 0 .../src/server/api/endpoints/clips/create.ts | 2 +- .../server/api/endpoints/drive/files/show.ts | 27 +++--- .../api/endpoints/federation/instances.ts | 2 +- .../api/endpoints/messaging/messages.ts | 19 +++-- .../endpoints/messaging/messages/create.ts | 17 +++- .../backend/src/server/api/endpoints/meta.ts | 1 + .../src/server/api/endpoints/mute/create.ts | 6 +- .../backend/src/server/api/endpoints/notes.ts | 2 +- .../src/server/api/endpoints/notes/create.ts | 83 ++++++++++++------- .../api/endpoints/notes/global-timeline.ts | 6 +- .../api/endpoints/notes/hybrid-timeline.ts | 6 +- .../api/endpoints/notes/local-timeline.ts | 6 +- .../api/endpoints/notes/search-by-tag.ts | 39 +++++++-- .../src/server/api/endpoints/notes/search.ts | 6 +- .../server/api/endpoints/notes/timeline.ts | 6 +- .../api/endpoints/notes/user-list-timeline.ts | 6 +- .../src/server/api/endpoints/pages/show.ts | 21 +++-- .../server/api/endpoints/users/followers.ts | 23 ++++- .../server/api/endpoints/users/following.ts | 23 ++++- .../users/search-by-username-and-host.ts | 5 +- .../src/server/api/endpoints/users/show.ts | 36 ++++++-- 31 files changed, 300 insertions(+), 105 deletions(-) delete mode 100644 packages/backend/src/server/api/endpoints/channels/pin-note.ts diff --git a/packages/backend/src/models/schema/emoji.ts b/packages/backend/src/models/schema/emoji.ts index 5f9af88db..e97fdd5ef 100644 --- a/packages/backend/src/models/schema/emoji.ts +++ b/packages/backend/src/models/schema/emoji.ts @@ -27,6 +27,7 @@ export const packedEmojiSchema = { host: { type: 'string', optional: false, nullable: true, + description: 'The local host is represented with `null`.', }, url: { type: 'string', diff --git a/packages/backend/src/models/schema/user.ts b/packages/backend/src/models/schema/user.ts index 616bedc0d..253681695 100644 --- a/packages/backend/src/models/schema/user.ts +++ b/packages/backend/src/models/schema/user.ts @@ -21,6 +21,7 @@ export const packedUserLiteSchema = { type: 'string', nullable: true, optional: false, example: 'misskey.example.com', + description: 'The local host is represented with `null`.', }, avatarUrl: { type: 'string', diff --git a/packages/backend/src/server/api/endpoints/admin/drive/files.ts b/packages/backend/src/server/api/endpoints/admin/drive/files.ts index 646d85a1e..119c4db19 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/files.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/files.ts @@ -27,7 +27,12 @@ export const paramDef = { untilId: { type: 'string', format: 'misskey:id' }, type: { type: 'string', nullable: true, pattern: /^[a-zA-Z0-9\/\-*]+$/.toString().slice(1, -1) }, origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, - hostname: { type: 'string', nullable: true, default: null }, + hostname: { + type: 'string', + nullable: true, + default: null, + description: 'The local host is represented with `null`.', + }, }, required: [], } as const; diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts index 4b27fc018..039df74f1 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts @@ -40,6 +40,7 @@ export const meta = { userHost: { type: 'string', optional: false, nullable: true, + description: 'The local host is represented with `null`.', }, md5: { type: 'string', @@ -151,11 +152,20 @@ export const meta = { export const paramDef = { type: 'object', - properties: { - fileId: { type: 'string', format: 'misskey:id' }, - url: { type: 'string' }, - }, - required: [], + anyOf: [ + { + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], + }, + { + properties: { + url: { type: 'string' }, + }, + required: ['url'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index f19c3ddbd..d16689a28 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -40,6 +40,7 @@ export const meta = { host: { type: 'string', optional: false, nullable: true, + description: 'The local host is represented with `null`.', }, url: { type: 'string', @@ -54,7 +55,12 @@ export const paramDef = { type: 'object', properties: { query: { type: 'string', nullable: true, default: null }, - host: { type: 'string', nullable: true, default: null }, + host: { + type: 'string', + nullable: true, + default: null, + description: 'Use `null` to represent the local host.', + }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index f488a71a0..6192978fa 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -38,8 +38,9 @@ export const meta = { optional: false, nullable: true, }, host: { - type: 'string', - optional: false, nullable: true, + type: 'null', + optional: false, + description: 'The local host is represented with `null`. The field exists for compatibility with other API endpoints that return files.', }, url: { type: 'string', diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts index 6063f3e3b..cff58d617 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts @@ -17,7 +17,11 @@ export const paramDef = { ids: { type: 'array', items: { type: 'string', format: 'misskey:id', } }, - category: { type: 'string', nullable: true }, + category: { + type: 'string', + nullable: true, + description: 'Use `null` to reset the category.', + }, }, required: ['ids'], } as const; diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index e26514e0c..5b547b3b7 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -23,7 +23,11 @@ export const paramDef = { properties: { id: { type: 'string', format: 'misskey:id' }, name: { type: 'string' }, - category: { type: 'string', nullable: true }, + category: { + type: 'string', + nullable: true, + description: 'Use `null` to reset the category.', + }, aliases: { type: 'array', items: { type: 'string', } }, diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index 1ec86fef2..2703b4b9d 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -26,8 +26,13 @@ export const paramDef = { sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] }, state: { type: 'string', enum: ['all', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: "all" }, origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, - username: { type: 'string', default: null }, - hostname: { type: 'string', default: null }, + username: { type: 'string', nullable: true, default: null }, + hostname: { + type: 'string', + nullable: true, + default: null, + description: 'The local host is represented with `null`.', + }, }, required: [], } as const; diff --git a/packages/backend/src/server/api/endpoints/channels/pin-note.ts b/packages/backend/src/server/api/endpoints/channels/pin-note.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/backend/src/server/api/endpoints/clips/create.ts b/packages/backend/src/server/api/endpoints/clips/create.ts index a2dbef12e..4afe4222a 100644 --- a/packages/backend/src/server/api/endpoints/clips/create.ts +++ b/packages/backend/src/server/api/endpoints/clips/create.ts @@ -20,7 +20,7 @@ export const paramDef = { type: 'object', properties: { name: { type: 'string', minLength: 1, maxLength: 100 }, - isPublic: { type: 'boolean' }, + isPublic: { type: 'boolean', default: false }, description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, }, required: ['name'], diff --git a/packages/backend/src/server/api/endpoints/drive/files/show.ts b/packages/backend/src/server/api/endpoints/drive/files/show.ts index c8e9d3dd9..a2bc0c7aa 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/show.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/show.ts @@ -28,22 +28,25 @@ export const meta = { code: 'ACCESS_DENIED', id: '25b73c73-68b1-41d0-bad1-381cfdf6579f', }, - - fileIdOrUrlRequired: { - message: 'fileId or url required.', - code: 'INVALID_PARAM', - id: '89674805-722c-440c-8d88-5641830dc3e4', - }, }, } as const; export const paramDef = { type: 'object', - properties: { - fileId: { type: 'string', format: 'misskey:id' }, - url: { type: 'string' }, - }, - required: [], + anyOf: [ + { + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], + }, + { + properties: { + url: { type: 'string' }, + }, + required: ['url'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export @@ -62,8 +65,6 @@ export default define(meta, paramDef, async (ps, user) => { thumbnailUrl: ps.url, }], }); - } else { - throw new ApiError(meta.errors.fileIdOrUrlRequired); } if (file == null) { diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index e27297176..07e5c07c6 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -22,7 +22,7 @@ export const meta = { export const paramDef = { type: 'object', properties: { - host: { type: 'string', nullable: true }, + host: { type: 'string', nullable: true, description: 'Omit or use `null` to not filter by host.' }, blocked: { type: 'boolean', nullable: true }, notResponding: { type: 'boolean', nullable: true }, suspended: { type: 'boolean', nullable: true }, diff --git a/packages/backend/src/server/api/endpoints/messaging/messages.ts b/packages/backend/src/server/api/endpoints/messaging/messages.ts index 9760709c2..dbf1f6c86 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages.ts @@ -47,14 +47,25 @@ export const meta = { export const paramDef = { type: 'object', properties: { - userId: { type: 'string', format: 'misskey:id' }, - groupId: { type: 'string', format: 'misskey:id' }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, markAsRead: { type: 'boolean', default: true }, }, - required: [], + anyOf: [ + { + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], + }, + { + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export @@ -126,7 +137,5 @@ export default define(meta, paramDef, async (ps, user) => { return await Promise.all(messages.map(message => MessagingMessages.pack(message, user, { populateGroup: false, }))); - } else { - throw new Error(); } }); diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts index 8c1226b0f..405af5ec1 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts @@ -67,12 +67,23 @@ export const meta = { export const paramDef = { type: 'object', properties: { - userId: { type: 'string', format: 'misskey:id' }, - groupId: { type: 'string', format: 'misskey:id' }, text: { type: 'string', nullable: true, maxLength: 3000 }, fileId: { type: 'string', format: 'misskey:id' }, }, - required: [], + anyOf: [ + { + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], + }, + { + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 057d22f33..e1ae282a9 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -169,6 +169,7 @@ export const meta = { host: { type: 'string', optional: false, nullable: true, + description: 'The local host is represented with `null`.', }, url: { type: 'string', diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index 0c3a3453f..7e857e673 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -38,7 +38,11 @@ export const paramDef = { type: 'object', properties: { userId: { type: 'string', format: 'misskey:id' }, - expiresAt: { type: 'integer', nullable: true }, + expiresAt: { + type: 'integer', + nullable: true, + description: 'A Unix Epoch timestamp that must lie in the future. `null` means an indefinite mute.', + }, }, required: ['userId'], } as const; diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts index 96657f8d3..99c8b973f 100644 --- a/packages/backend/src/server/api/endpoints/notes.ts +++ b/packages/backend/src/server/api/endpoints/notes.ts @@ -19,7 +19,7 @@ export const meta = { export const paramDef = { type: 'object', properties: { - local: { type: 'boolean' }, + local: { type: 'boolean', default: false }, reply: { type: 'boolean' }, renote: { type: 'boolean' }, withFiles: { type: 'boolean' }, diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 961983f5f..24d0c8134 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -59,12 +59,6 @@ export const meta = { id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15', }, - contentRequired: { - message: 'Content required. You need to set text, fileIds, renoteId or poll.', - code: 'CONTENT_REQUIRED', - id: '6f57e42b-c348-439b-bc45-993995cc515a', - }, - cannotCreateAlreadyExpiredPoll: { message: 'Poll is already expired.', code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL', @@ -92,29 +86,41 @@ export const paramDef = { visibleUserIds: { type: 'array', uniqueItems: true, items: { type: 'string', format: 'misskey:id', } }, - text: { type: 'string', nullable: true, maxLength: MAX_NOTE_TEXT_LENGTH, default: null }, + text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true }, cw: { type: 'string', nullable: true, maxLength: 100 }, localOnly: { type: 'boolean', default: false }, noExtractMentions: { type: 'boolean', default: false }, noExtractHashtags: { type: 'boolean', default: false }, noExtractEmojis: { type: 'boolean', default: false }, - fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: { - type: 'string', format: 'misskey:id', - } }, - mediaIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: { - type: 'string', format: 'misskey:id', - } }, + fileIds: { + type: 'array', + uniqueItems: true, + minItems: 1, + maxItems: 16, + items: { type: 'string', format: 'misskey:id' }, + }, + mediaIds: { + deprecated: true, + description: 'Use `fileIds` instead. If both are specified, this property is discarded.', + type: 'array', + uniqueItems: true, + minItems: 1, + maxItems: 16, + items: { type: 'string', format: 'misskey:id' }, + }, replyId: { type: 'string', format: 'misskey:id', nullable: true }, renoteId: { type: 'string', format: 'misskey:id', nullable: true }, channelId: { type: 'string', format: 'misskey:id', nullable: true }, poll: { - type: 'object', nullable: true, + type: 'object', + nullable: true, properties: { choices: { - type: 'array', uniqueItems: true, minItems: 2, maxItems: 10, - items: { - type: 'string', minLength: 1, maxLength: 50, - }, + type: 'array', + uniqueItems: true, + minItems: 2, + maxItems: 10, + items: { type: 'string', minLength: 1, maxLength: 50 }, }, multiple: { type: 'boolean', default: false }, expiresAt: { type: 'integer', nullable: true }, @@ -123,7 +129,34 @@ export const paramDef = { required: ['choices'], }, }, - required: [], + anyOf: [ + { + // (re)note with text, files and poll are optional + properties: { + text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: false }, + }, + required: ['text'], + }, + { + // (re)note with files, text and poll are optional + required: ['fileIds'], + }, + { + // (re)note with files, text and poll are optional + required: ['mediaIds'], + }, + { + // (re)note with poll, text and files are optional + properties: { + poll: { type: 'object', nullable: false, }, + }, + required: ['poll'], + }, + { + // pure renote + required: ['renoteId'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export @@ -152,7 +185,7 @@ export default define(meta, paramDef, async (ps, user) => { if (renote == null) { throw new ApiError(meta.errors.noSuchRenoteTarget); - } else if (renote.renoteId && !renote.text && !renote.fileIds) { + } else if (renote.renoteId && !renote.text && !renote.fileIds && !renote.poll) { throw new ApiError(meta.errors.cannotReRenote); } @@ -175,10 +208,7 @@ export default define(meta, paramDef, async (ps, user) => { if (reply == null) { throw new ApiError(meta.errors.noSuchReplyTarget); - } - - // 返信対象が引用でないRenoteだったらエラー - if (reply.renoteId && !reply.text && !reply.fileIds) { + } else if (reply.renoteId && !reply.text && !reply.fileIds && !renote.poll) { throw new ApiError(meta.errors.cannotReplyToPureRenote); } @@ -204,11 +234,6 @@ export default define(meta, paramDef, async (ps, user) => { } } - // テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー - if (!(ps.text || files.length || renote || ps.poll)) { - throw new ApiError(meta.errors.contentRequired); - } - let channel: Channel | undefined; if (ps.channelId != null) { channel = await Channels.findOneBy({ id: ps.channelId }); diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index 09a819466..cb402ecaa 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -35,7 +35,11 @@ export const meta = { export const paramDef = { type: 'object', properties: { - withFiles: { type: 'boolean' }, + withFiles: { + type: 'boolean', + default: false, + description: 'Only show notes that have attached files.', + }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index 7c9c12296..f9893527e 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -48,7 +48,11 @@ export const paramDef = { includeMyRenotes: { type: 'boolean', default: true }, includeRenotedMyNotes: { type: 'boolean', default: true }, includeLocalRenotes: { type: 'boolean', default: true }, - withFiles: { type: 'boolean' }, + withFiles: { + type: 'boolean', + default: false, + description: 'Only show notes that have attached files.', + }, }, required: [], } as const; diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index bb0bbe2a2..03edf30b3 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -37,7 +37,11 @@ export const meta = { export const paramDef = { type: 'object', properties: { - withFiles: { type: 'boolean' }, + withFiles: { + type: 'boolean', + default: false, + description: 'Only show notes that have attached files.', + }, fileType: { type: 'array', items: { type: 'string', } }, diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts index c6503eb05..bb85c9200 100644 --- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts +++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts @@ -25,21 +25,44 @@ export const meta = { export const paramDef = { type: 'object', properties: { - tag: { type: 'string' }, - query: { type: 'array', items: { - type: 'array', items: { - type: 'string', - }, - } }, reply: { type: 'boolean', nullable: true, default: null }, renote: { type: 'boolean', nullable: true, default: null }, - withFiles: { type: 'boolean' }, + withFiles: { + type: 'boolean', + default: false, + description: 'Only show notes that have attached files.', + }, poll: { type: 'boolean', nullable: true, default: null }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, }, - required: [], + anyOf: [ + { + properties: { + tag: { type: 'string', minLength: 1 }, + }, + required: ['tag'], + }, + { + properties: { + query: { + type: 'array', + description: 'The outer arrays are chained with OR, the inner arrays are chained with AND.', + items: { + type: 'array', + items: { + type: 'string', + minLength: 1, + }, + minItems: 1, + }, + minItems: 1, + }, + }, + required: ['query'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index e77892b15..af9b5f0a1 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -35,7 +35,11 @@ export const paramDef = { untilId: { type: 'string', format: 'misskey:id' }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, offset: { type: 'integer', default: 0 }, - host: { type: 'string', nullable: true }, + host: { + type: 'string', + nullable: true, + description: 'The local host is represented with `null`.', + }, userId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, channelId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, }, diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index fde66b241..0f976d18b 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -38,7 +38,11 @@ export const paramDef = { includeMyRenotes: { type: 'boolean', default: true }, includeRenotedMyNotes: { type: 'boolean', default: true }, includeLocalRenotes: { type: 'boolean', default: true }, - withFiles: { type: 'boolean' }, + withFiles: { + type: 'boolean', + default: false, + description: 'Only show notes that have attached files.', + }, }, required: [], } as const; diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index 866e306d8..6c6402603 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -42,7 +42,11 @@ export const paramDef = { includeMyRenotes: { type: 'boolean', default: true }, includeRenotedMyNotes: { type: 'boolean', default: true }, includeLocalRenotes: { type: 'boolean', default: true }, - withFiles: { type: 'boolean' }, + withFiles: { + type: 'boolean', + default: false, + description: 'Only show notes that have attached files.', + }, }, required: ['listId'], } as const; diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts index 1c218acfd..3dcce8550 100644 --- a/packages/backend/src/server/api/endpoints/pages/show.ts +++ b/packages/backend/src/server/api/endpoints/pages/show.ts @@ -26,12 +26,21 @@ export const meta = { export const paramDef = { type: 'object', - properties: { - pageId: { type: 'string', format: 'misskey:id' }, - name: { type: 'string' }, - username: { type: 'string' }, - }, - required: [], + anyOf: [ + { + properties: { + pageId: { type: 'string', format: 'misskey:id' }, + }, + required: ['pageId'], + }, + { + properties: { + name: { type: 'string' }, + username: { type: 'string' }, + }, + required: ['name', 'username'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index 5de624312..26b1f20df 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -38,14 +38,29 @@ export const meta = { export const paramDef = { type: 'object', properties: { - userId: { type: 'string', format: 'misskey:id' }, - username: { type: 'string' }, - host: { type: 'string', nullable: true }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, }, - required: [], + anyOf: [ + { + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], + }, + { + properties: { + username: { type: 'string' }, + host: { + type: 'string', + nullable: true, + description: 'The local host is represented with `null`.', + }, + }, + required: ['username', 'host'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 55460f7c6..42cf5216e 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -38,14 +38,29 @@ export const meta = { export const paramDef = { type: 'object', properties: { - userId: { type: 'string', format: 'misskey:id' }, - username: { type: 'string' }, - host: { type: 'string', nullable: true }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, }, - required: [], + anyOf: [ + { + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], + }, + { + properties: { + username: { type: 'string' }, + host: { + type: 'string', + nullable: true, + description: 'The local host is represented with `null`.', + }, + }, + required: ['username', 'host'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 897b5de3f..f74d80e2a 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -28,7 +28,10 @@ export const paramDef = { limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, detail: { type: 'boolean', default: true }, }, - required: [], + anyOf: [ + { required: ['username'] }, + { required: ['host'] }, + ], } as const; // TODO: avatar,bannerをJOINしたいけどエラーになる diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 775a4b29f..b1a568145 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -46,15 +46,33 @@ export const meta = { export const paramDef = { type: 'object', - properties: { - userId: { type: 'string', format: 'misskey:id' }, - userIds: { type: 'array', uniqueItems: true, items: { - type: 'string', format: 'misskey:id', - } }, - username: { type: 'string' }, - host: { type: 'string', nullable: true }, - }, - required: [], + anyOf: [ + { + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], + }, + { + properties: { + userIds: { type: 'array', uniqueItems: true, items: { + type: 'string', format: 'misskey:id', + } }, + }, + required: ['userIds'], + }, + { + properties: { + username: { type: 'string' }, + host: { + type: 'string', + nullable: true, + description: 'The local host is represented with `null`.', + }, + }, + required: ['username', 'host'], + }, + ], } as const; // eslint-disable-next-line import/no-default-export