fix: チャンネルの編集権限をチャンネル所有者とモデレーターに限定する (#10268)
* チャンネルの編集権限をチャンネルオーナーとモデレーターに限定する * PR 指摘点対応(共有ボタンを全員に表示、$i の nullable 対応、fix a typo) * everyOne -> share
This commit is contained in:
parent
97a43bc30f
commit
aad70a97db
|
@ -4,6 +4,7 @@ import type { DriveFilesRepository, ChannelsRepository } from '@/models/index.js
|
||||||
import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
|
import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { ApiError } from '../../error.js';
|
import { ApiError } from '../../error.js';
|
||||||
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ['channels'],
|
tags: ['channels'],
|
||||||
|
@ -61,7 +62,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||||
private driveFilesRepository: DriveFilesRepository,
|
private driveFilesRepository: DriveFilesRepository,
|
||||||
|
|
||||||
private channelEntityService: ChannelEntityService,
|
private channelEntityService: ChannelEntityService,
|
||||||
) {
|
|
||||||
|
private roleService: RoleService,
|
||||||
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const channel = await this.channelsRepository.findOneBy({
|
const channel = await this.channelsRepository.findOneBy({
|
||||||
id: ps.channelId,
|
id: ps.channelId,
|
||||||
|
@ -71,7 +74,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||||
throw new ApiError(meta.errors.noSuchChannel);
|
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);
|
throw new ApiError(meta.errors.accessDenied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ import MkTimeline from '@/components/MkTimeline.vue';
|
||||||
import XChannelFollowButton from '@/components/MkChannelFollowButton.vue';
|
import XChannelFollowButton from '@/components/MkChannelFollowButton.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { useRouter } from '@/router';
|
import { useRouter } from '@/router';
|
||||||
import { $i } from '@/account';
|
import { $i, iAmModerator } from '@/account';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
import { deviceKind } from '@/scripts/device-kind';
|
import { deviceKind } from '@/scripts/device-kind';
|
||||||
|
@ -90,21 +90,30 @@ function openPostForm() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerActions = $computed(() => channel && channel.userId ? [{
|
const headerActions = $computed(() => {
|
||||||
icon: 'ti ti-share',
|
if (channel && channel.userId) {
|
||||||
text: i18n.ts.share,
|
const share = {
|
||||||
handler: async (): Promise<void> => {
|
icon: 'ti ti-share',
|
||||||
navigator.share({
|
text: i18n.ts.share,
|
||||||
title: channel.name,
|
handler: async (): Promise<void> => {
|
||||||
text: channel.description,
|
navigator.share({
|
||||||
url: `${url}/channels/${channel.id}`,
|
title: channel.name,
|
||||||
});
|
text: channel.description,
|
||||||
},
|
url: `${url}/channels/${channel.id}`,
|
||||||
}, {
|
});
|
||||||
icon: 'ti ti-settings',
|
},
|
||||||
text: i18n.ts.edit,
|
};
|
||||||
handler: edit,
|
|
||||||
}] : null);
|
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(() => [{
|
const headerTabs = $computed(() => [{
|
||||||
key: 'overview',
|
key: 'overview',
|
||||||
|
|
Loading…
Reference in a new issue