mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2026-09-03 20:53:09 -05:00
Give moderators access to edit channels (#4608)
* give admins access to edit all channels
closes #4598
* test(channels): +admin update another users channel
* Fix tests
* fix(server): delete another users channel
Since the channel owner isn't necessary the auth user we need to check
the right account whether it's the last video or not.
* REMOVE_ANY_VIDEO_CHANNEL > MANAGE_ANY_VIDEO_CHANNEL
Merge REMOVE_ANY_VIDEO_CHANNEL and MANY_VIDEO_CHANNELS to
MANAGE_ANY_VIDEO_CHANNEL.
* user-right: moderator can't manage admins channel
* client: MyVideoChannelCreateComponent > VideoChannelCreateComponent
* client: MyVideoChannelEdit > VideoChannelEdit
* Revert "user-right: moderator can't manage admins channel"
This reverts commit 2c627c154e.
* server: clean dupl validator functionality
* fix ensureUserCanManageChannel usage
It's not async anymore.
* server: merge channel validator middleares
ensureAuthUserOwnsChannelValidator & ensureUserCanManageChannel gets
merged into one middleware.
* client(VideoChannelEdit): redirect to prev route
* fix(VideoChannels): handle anon users
* client: new routes for create/update channel
* Refactor channel validators
Co-authored-by: Chocobozzz <me@florianbigard.com>
This commit is contained in:
co-authored by
Chocobozzz
parent
11e520b50d
commit
a37e9e74ff
@@ -3,12 +3,6 @@ import { VideoChannelModel } from '@server/models/video/video-channel'
|
||||
import { MChannelBannerAccountDefault } from '@server/types/models'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
|
||||
async function doesLocalVideoChannelNameExist (name: string, res: express.Response) {
|
||||
const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name)
|
||||
|
||||
return processVideoChannelExist(videoChannel, res)
|
||||
}
|
||||
|
||||
async function doesVideoChannelIdExist (id: number, res: express.Response) {
|
||||
const videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id)
|
||||
|
||||
@@ -24,7 +18,6 @@ async function doesVideoChannelNameWithHostExist (nameWithDomain: string, res: e
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
doesLocalVideoChannelNameExist,
|
||||
doesVideoChannelIdExist,
|
||||
doesVideoChannelNameWithHostExist
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { body, param, query } from 'express-validator'
|
||||
import { omit } from 'lodash'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { MUserDefault } from '@server/types/models'
|
||||
import { HttpStatusCode, UserRegister, UserRole } from '@shared/models'
|
||||
import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models'
|
||||
import { isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
|
||||
import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
|
||||
import {
|
||||
@@ -490,14 +490,17 @@ const ensureAuthUserOwnsAccountValidator = [
|
||||
}
|
||||
]
|
||||
|
||||
const ensureAuthUserOwnsChannelValidator = [
|
||||
const ensureCanManageChannel = [
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
const user = res.locals.oauth.token.User
|
||||
const user = res.locals.oauth.token.user
|
||||
const isUserOwner = res.locals.videoChannel.Account.userId === user.id
|
||||
|
||||
if (!isUserOwner && user.hasRight(UserRight.MANAGE_ANY_VIDEO_CHANNEL) === false) {
|
||||
const message = `User ${user.username} does not have right to manage channel ${req.params.nameWithHost}.`
|
||||
|
||||
if (res.locals.videoChannel.Account.userId !== user.id) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.FORBIDDEN_403,
|
||||
message: 'Only owner of this video channel can access this ressource'
|
||||
message
|
||||
})
|
||||
}
|
||||
|
||||
@@ -542,8 +545,8 @@ export {
|
||||
usersVerifyEmailValidator,
|
||||
userAutocompleteValidator,
|
||||
ensureAuthUserOwnsAccountValidator,
|
||||
ensureAuthUserOwnsChannelValidator,
|
||||
ensureCanManageUser
|
||||
ensureCanManageUser,
|
||||
ensureCanManageChannel
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import express from 'express'
|
||||
import { body, param, query } from 'express-validator'
|
||||
import { MChannelAccountDefault, MUser } from '@server/types/models'
|
||||
import { UserRight } from '../../../../shared'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { MChannelAccountDefault } from '@server/types/models'
|
||||
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
|
||||
import { isBooleanValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc'
|
||||
import {
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { ActorModel } from '../../../models/actor/actor'
|
||||
import { VideoChannelModel } from '../../../models/video/video-channel'
|
||||
import { areValidationErrors, doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../shared'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { areValidationErrors, doesVideoChannelNameWithHostExist } from '../shared'
|
||||
|
||||
const videoChannelsAddValidator = [
|
||||
body('name').custom(isVideoChannelUsernameValid).withMessage('Should have a valid channel name'),
|
||||
@@ -71,16 +70,10 @@ const videoChannelsUpdateValidator = [
|
||||
]
|
||||
|
||||
const videoChannelsRemoveValidator = [
|
||||
param('nameWithHost').exists().withMessage('Should have an video channel name with host'),
|
||||
|
||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
if (!await doesVideoChannelNameWithHostExist(req.params.nameWithHost, res)) return
|
||||
|
||||
if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return
|
||||
if (!await checkVideoChannelIsNotTheLastOne(res)) return
|
||||
if (!await checkVideoChannelIsNotTheLastOne(res.locals.videoChannel, res)) return
|
||||
|
||||
return next()
|
||||
}
|
||||
@@ -100,14 +93,14 @@ const videoChannelsNameWithHostValidator = [
|
||||
}
|
||||
]
|
||||
|
||||
const localVideoChannelValidator = [
|
||||
param('name').custom(isVideoChannelDisplayNameValid).withMessage('Should have a valid video channel name'),
|
||||
|
||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking localVideoChannelValidator parameters', { parameters: req.params })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
if (!await doesLocalVideoChannelNameExist(req.params.name, res)) return
|
||||
const ensureIsLocalChannel = [
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
if (res.locals.videoChannel.Actor.isOwned() === false) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.FORBIDDEN_403,
|
||||
message: 'This channel is not owned.'
|
||||
})
|
||||
}
|
||||
|
||||
return next()
|
||||
}
|
||||
@@ -144,38 +137,15 @@ export {
|
||||
videoChannelsUpdateValidator,
|
||||
videoChannelsRemoveValidator,
|
||||
videoChannelsNameWithHostValidator,
|
||||
ensureIsLocalChannel,
|
||||
videoChannelsListValidator,
|
||||
localVideoChannelValidator,
|
||||
videoChannelStatsValidator
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function checkUserCanDeleteVideoChannel (user: MUser, videoChannel: MChannelAccountDefault, res: express.Response) {
|
||||
if (videoChannel.Actor.isOwned() === false) {
|
||||
res.fail({
|
||||
status: HttpStatusCode.FORBIDDEN_403,
|
||||
message: 'Cannot remove video channel of another server.'
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the user can delete the video channel
|
||||
// The user can delete it if s/he is an admin
|
||||
// Or if s/he is the video channel's account
|
||||
if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) {
|
||||
res.fail({
|
||||
status: HttpStatusCode.FORBIDDEN_403,
|
||||
message: 'Cannot remove video channel of another user'
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
|
||||
const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id)
|
||||
async function checkVideoChannelIsNotTheLastOne (videoChannel: MChannelAccountDefault, res: express.Response) {
|
||||
const count = await VideoChannelModel.countByAccount(videoChannel.Account.id)
|
||||
|
||||
if (count <= 1) {
|
||||
res.fail({
|
||||
|
||||
Reference in New Issue
Block a user