Implement support field in video and video channel
[oweals/peertube.git] / server / middlewares / validators / video-channels.ts
1 import * as express from 'express'
2 import { body, param } from 'express-validator/check'
3 import { UserRight } from '../../../shared'
4 import { isAccountIdExist } from '../../helpers/custom-validators/accounts'
5 import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
6 import {
7   isVideoChannelDescriptionValid, isVideoChannelExist,
8   isVideoChannelNameValid, isVideoChannelSupportValid
9 } from '../../helpers/custom-validators/video-channels'
10 import { logger } from '../../helpers/logger'
11 import { UserModel } from '../../models/account/user'
12 import { VideoChannelModel } from '../../models/video/video-channel'
13 import { areValidationErrors } from './utils'
14
15 const listVideoAccountChannelsValidator = [
16   param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'),
17
18   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
19     logger.debug('Checking listVideoAccountChannelsValidator parameters', { parameters: req.body })
20
21     if (areValidationErrors(req, res)) return
22     if (!await isAccountIdExist(req.params.accountId, res)) return
23
24     return next()
25   }
26 ]
27
28 const videoChannelsAddValidator = [
29   body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
30   body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
31   body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
32
33   (req: express.Request, res: express.Response, next: express.NextFunction) => {
34     logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body })
35
36     if (areValidationErrors(req, res)) return
37
38     return next()
39   }
40 ]
41
42 const videoChannelsUpdateValidator = [
43   param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
44   body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
45   body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
46   body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
47
48   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
49     logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
50
51     if (areValidationErrors(req, res)) return
52     if (!await isVideoChannelExist(req.params.id, res)) return
53
54     // We need to make additional checks
55     if (res.locals.videoChannel.Actor.isOwned() === false) {
56       return res.status(403)
57         .json({ error: 'Cannot update video channel of another server' })
58         .end()
59     }
60
61     if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) {
62       return res.status(403)
63         .json({ error: 'Cannot update video channel of another user' })
64         .end()
65     }
66
67     return next()
68   }
69 ]
70
71 const videoChannelsRemoveValidator = [
72   param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
73
74   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
75     logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
76
77     if (areValidationErrors(req, res)) return
78     if (!await isVideoChannelExist(req.params.id, res)) return
79
80     // Check if the user who did the request is able to delete the video
81     if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return
82     if (!await checkVideoChannelIsNotTheLastOne(res)) return
83
84     return next()
85   }
86 ]
87
88 const videoChannelsGetValidator = [
89   param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
90
91   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
92     logger.debug('Checking videoChannelsGet parameters', { parameters: req.params })
93
94     if (areValidationErrors(req, res)) return
95     if (!await isVideoChannelExist(req.params.id, res)) return
96
97     return next()
98   }
99 ]
100
101 // ---------------------------------------------------------------------------
102
103 export {
104   listVideoAccountChannelsValidator,
105   videoChannelsAddValidator,
106   videoChannelsUpdateValidator,
107   videoChannelsRemoveValidator,
108   videoChannelsGetValidator
109 }
110
111 // ---------------------------------------------------------------------------
112
113 function checkUserCanDeleteVideoChannel (user: UserModel, videoChannel: VideoChannelModel, res: express.Response) {
114   if (videoChannel.Actor.isOwned() === false) {
115     res.status(403)
116               .json({ error: 'Cannot remove video channel of another server.' })
117               .end()
118
119     return false
120   }
121
122   // Check if the user can delete the video channel
123   // The user can delete it if s/he is an admin
124   // Or if s/he is the video channel's account
125   if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) {
126     res.status(403)
127               .json({ error: 'Cannot remove video channel of another user' })
128               .end()
129
130     return false
131   }
132
133   return true
134 }
135
136 async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
137   const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id)
138
139   if (count <= 1) {
140     res.status(409)
141       .json({ error: 'Cannot remove the last channel of this user' })
142       .end()
143
144     return false
145   }
146
147   return true
148 }