From aad70a97dbcbecb5d0edad8ba1db1280c5f8878e Mon Sep 17 00:00:00 2001 From: mmorita Date: Thu, 9 Mar 2023 07:58:53 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E7=B7=A8=E9=9B=86=E6=A8=A9=E9=99=90=E3=82=92?= =?UTF-8?q?=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D=E3=83=AB=E6=89=80=E6=9C=89?= =?UTF-8?q?=E8=80=85=E3=81=A8=E3=83=A2=E3=83=87=E3=83=AC=E3=83=BC=E3=82=BF?= =?UTF-8?q?=E3=83=BC=E3=81=AB=E9=99=90=E5=AE=9A=E3=81=99=E3=82=8B=20(#1026?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * チャンネルの編集権限をチャンネルオーナーとモデレーターに限定する * PR 指摘点対応(共有ボタンを全員に表示、$i の nullable 対応、fix a typo) * everyOne -> share --- .../server/api/endpoints/channels/update.ts | 8 +++- packages/frontend/src/pages/channel.vue | 41 +++++++++++-------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts index d006e89bd..a86cc2565 100644 --- a/packages/backend/src/server/api/endpoints/channels/update.ts +++ b/packages/backend/src/server/api/endpoints/channels/update.ts @@ -4,6 +4,7 @@ import type { DriveFilesRepository, ChannelsRepository } from '@/models/index.js import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../error.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['channels'], @@ -61,7 +62,9 @@ export default class extends Endpoint { private driveFilesRepository: DriveFilesRepository, private channelEntityService: ChannelEntityService, - ) { + + private roleService: RoleService, + ) { super(meta, paramDef, async (ps, me) => { const channel = await this.channelsRepository.findOneBy({ id: ps.channelId, @@ -71,7 +74,8 @@ export default class extends Endpoint { throw new ApiError(meta.errors.noSuchChannel); } - if (channel.userId !== me.id) { + const iAmModerator = await this.roleService.isModerator(me); + if (channel.userId !== me.id && !iAmModerator) { throw new ApiError(meta.errors.accessDenied); } diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index 65edb97e8..76f11faab 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -46,7 +46,7 @@ import MkTimeline from '@/components/MkTimeline.vue'; import XChannelFollowButton from '@/components/MkChannelFollowButton.vue'; import * as os from '@/os'; import { useRouter } from '@/router'; -import { $i } from '@/account'; +import { $i, iAmModerator } from '@/account'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import { deviceKind } from '@/scripts/device-kind'; @@ -90,21 +90,30 @@ function openPostForm() { }); } -const headerActions = $computed(() => channel && channel.userId ? [{ - icon: 'ti ti-share', - text: i18n.ts.share, - handler: async (): Promise => { - navigator.share({ - title: channel.name, - text: channel.description, - url: `${url}/channels/${channel.id}`, - }); - }, -}, { - icon: 'ti ti-settings', - text: i18n.ts.edit, - handler: edit, -}] : null); +const headerActions = $computed(() => { + if (channel && channel.userId) { + const share = { + icon: 'ti ti-share', + text: i18n.ts.share, + handler: async (): Promise => { + navigator.share({ + title: channel.name, + text: channel.description, + url: `${url}/channels/${channel.id}`, + }); + }, + }; + + const canEdit = ($i && $i.id === channel.userId) || iAmModerator; + return canEdit ? [share, { + icon: 'ti ti-settings', + text: i18n.ts.edit, + handler: edit, + }] : [share]; + } else { + return null; + } +}); const headerTabs = $computed(() => [{ key: 'overview',