From 12bc671511f301598d57635a7125157b963a1973 Mon Sep 17 00:00:00 2001 From: FineArchs <133759614+FineArchs@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:17:45 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20admin/emoji/update=20=E3=81=A7=E4=B8=8D?= =?UTF-8?q?=E6=AD=A3=E3=81=AA=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=8C=E7=99=BA?= =?UTF-8?q?=E7=94=9F=E3=81=99=E3=82=8B=20(#14750)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix emoji updating bug * update changelog * type fix * " -> ' * conprehensiveness check * lint * undefined -> null --- CHANGELOG.md | 3 ++ .../backend/src/core/CustomEmojiService.ts | 29 ++++++++++++---- .../api/endpoints/admin/emoji/update.ts | 33 +++++++++---------- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee37bb3c6f..b449a1b91e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ - Enhance: l10nの更新 - Fix: メールアドレス不要でCaptchaが有効な場合にアカウント登録完了後自動でのログインに失敗する問題を修正 +### Server +- Fix: `admin/emoji/update`エンドポイントのidのみ指定した時不正なエラーが発生するバグを修正 + ## 2024.10.0 ### Note diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index 5db3c5b980..4566113449 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -103,19 +103,33 @@ export class CustomEmojiService implements OnApplicationShutdown { } @bindThis - public async update(id: MiEmoji['id'], data: { + public async update(data: ( + { id: MiEmoji['id'], name?: string; } | { name: string; id?: MiEmoji['id'], } + ) & { driveFile?: MiDriveFile; - name?: string; category?: string | null; aliases?: string[]; license?: string | null; isSensitive?: boolean; localOnly?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: MiRole['id'][]; - }, moderator?: MiUser): Promise { - const emoji = await this.emojisRepository.findOneByOrFail({ id: id }); - const sameNameEmoji = await this.emojisRepository.findOneBy({ name: data.name, host: IsNull() }); - if (sameNameEmoji != null && sameNameEmoji.id !== id) throw new Error('name already exists'); + }, moderator?: MiUser): Promise< + null + | 'NO_SUCH_EMOJI' + | 'SAME_NAME_EMOJI_EXISTS' + > { + const emoji = data.id + ? await this.getEmojiById(data.id) + : await this.getEmojiByName(data.name!); + if (emoji === null) return 'NO_SUCH_EMOJI'; + const id = emoji.id; + + // IDと絵文字名が両方指定されている場合は絵文字名の変更を行うため重複チェックが必要 + const doNameUpdate = data.id && data.name && (data.name !== emoji.name); + if (doNameUpdate) { + const isDuplicate = await this.checkDuplicate(data.name!); + if (isDuplicate) return 'SAME_NAME_EMOJI_EXISTS'; + } await this.emojisRepository.update(emoji.id, { updatedAt: new Date(), @@ -135,7 +149,7 @@ export class CustomEmojiService implements OnApplicationShutdown { const packed = await this.emojiEntityService.packDetailed(emoji.id); - if (emoji.name === data.name) { + if (!doNameUpdate) { this.globalEventService.publishBroadcastStream('emojiUpdated', { emojis: [packed], }); @@ -157,6 +171,7 @@ export class CustomEmojiService implements OnApplicationShutdown { after: updated, }); } + return null; } @bindThis 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 22609a16a3..212cba5c5d 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js'; -import type { DriveFilesRepository } from '@/models/_.js'; +import type { DriveFilesRepository, MiEmoji } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; @@ -78,25 +78,14 @@ export default class extends Endpoint { // eslint- if (driveFile == null) throw new ApiError(meta.errors.noSuchFile); } - let emojiId; - if (ps.id) { - emojiId = ps.id; - const emoji = await this.customEmojiService.getEmojiById(ps.id); - if (!emoji) throw new ApiError(meta.errors.noSuchEmoji); - if (ps.name && (ps.name !== emoji.name)) { - const isDuplicate = await this.customEmojiService.checkDuplicate(ps.name); - if (isDuplicate) throw new ApiError(meta.errors.sameNameEmojiExists); - } - } else { - if (!ps.name) throw new Error('Invalid Params unexpectedly passed. This is a BUG. Please report it to the development team.'); - const emoji = await this.customEmojiService.getEmojiByName(ps.name); - if (!emoji) throw new ApiError(meta.errors.noSuchEmoji); - emojiId = emoji.id; - } + // JSON schemeのanyOfの型変換がうまくいっていないらしい + const required = { id: ps.id, name: ps.name } as + | { id: MiEmoji['id']; name?: string } + | { id?: MiEmoji['id']; name: string }; - await this.customEmojiService.update(emojiId, { + const error = await this.customEmojiService.update({ + ...required, driveFile, - name: ps.name, category: ps.category, aliases: ps.aliases, license: ps.license, @@ -104,6 +93,14 @@ export default class extends Endpoint { // eslint- localOnly: ps.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction, }, me); + + switch (error) { + case null: return; + case 'NO_SUCH_EMOJI': throw new ApiError(meta.errors.noSuchEmoji); + case 'SAME_NAME_EMOJI_EXISTS': throw new ApiError(meta.errors.sameNameEmojiExists); + } + // 網羅性チェック + const mustBeNever: never = error; }); } }