summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmorita <link.morita@gmail.com>2023-03-09 07:58:53 +0900
committerGitHub <noreply@github.com>2023-03-09 07:58:53 +0900
commitaad70a97dbcbecb5d0edad8ba1db1280c5f8878e (patch)
tree9e0befbdec9258b31fbdbd5e7c4f39279c6e387e
parentfix(server): videoThumbnailGeneratorが適用されない問題を修正 (diff)
downloadmisskey-aad70a97dbcbecb5d0edad8ba1db1280c5f8878e.tar.gz
misskey-aad70a97dbcbecb5d0edad8ba1db1280c5f8878e.tar.bz2
misskey-aad70a97dbcbecb5d0edad8ba1db1280c5f8878e.zip
fix: チャンネルの編集権限をチャンネル所有者とモデレーターに限定する (#10268)
* チャンネルの編集権限をチャンネルオーナーとモデレーターに限定する * PR 指摘点対応(共有ボタンを全員に表示、$i の nullable 対応、fix a typo) * everyOne -> share
-rw-r--r--packages/backend/src/server/api/endpoints/channels/update.ts8
-rw-r--r--packages/frontend/src/pages/channel.vue41
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 d006e89bd2..a86cc2565a 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<typeof meta, typeof paramDef> {
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<typeof meta, typeof paramDef> {
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 65edb97e83..76f11faab8 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<void> => {
- 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<void> => {
+ 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',