Fix tests
[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 { logger } from '../../helpers'
5 import { isAccountIdExist } from '../../helpers/custom-validators/accounts'
6 import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc'
7 import {
8   isVideoChannelDescriptionValid,
9   isVideoChannelExist,
10   isVideoChannelNameValid
11 } from '../../helpers/custom-validators/video-channels'
12 import { UserModel } from '../../models/account/user'
13 import { VideoChannelModel } from '../../models/video/video-channel'
14 import { VideoChannelShareModel } from '../../models/video/video-channel-share'
15 import { areValidationErrors } from './utils'
16
17 const listVideoAccountChannelsValidator = [
18   param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'),
19
20   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
21     logger.debug('Checking listVideoAccountChannelsValidator parameters', { parameters: req.body })
22
23     if (areValidationErrors(req, res)) return
24     if (!await isAccountIdExist(req.params.accountId, res)) return
25
26     return next()
27   }
28 ]
29
30 const videoChannelsAddValidator = [
31   body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
32   body('description').custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
33
34   (req: express.Request, res: express.Response, next: express.NextFunction) => {
35     logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body })
36
37     if (areValidationErrors(req, res)) return
38
39     return next()
40   }
41 ]
42
43 const videoChannelsUpdateValidator = [
44   param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
45   body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
46   body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
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.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 const videoChannelsShareValidator = [
102   param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
103   param('accountId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid account id'),
104
105   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
106     logger.debug('Checking videoChannelShare parameters', { parameters: req.params })
107
108     if (areValidationErrors(req, res)) return
109     if (!await isVideoChannelExist(req.params.id, res)) return
110
111     const share = await VideoChannelShareModel.load(res.locals.video.id, req.params.accountId, undefined)
112     if (!share) {
113       return res.status(404)
114         .end()
115     }
116
117     res.locals.videoChannelShare = share
118
119     return next()
120   }
121 ]
122
123 // ---------------------------------------------------------------------------
124
125 export {
126   listVideoAccountChannelsValidator,
127   videoChannelsAddValidator,
128   videoChannelsUpdateValidator,
129   videoChannelsRemoveValidator,
130   videoChannelsGetValidator,
131   videoChannelsShareValidator
132 }
133
134 // ---------------------------------------------------------------------------
135
136 function checkUserCanDeleteVideoChannel (user: UserModel, videoChannel: VideoChannelModel, res: express.Response) {
137   // Retrieve the user who did the request
138   if (videoChannel.isOwned() === false) {
139     res.status(403)
140               .json({ error: 'Cannot remove video channel of another server.' })
141               .end()
142
143     return false
144   }
145
146   // Check if the user can delete the video channel
147   // The user can delete it if s/he is an admin
148   // Or if s/he is the video channel's account
149   if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) {
150     res.status(403)
151               .json({ error: 'Cannot remove video channel of another user' })
152               .end()
153
154     return false
155   }
156
157   return true
158 }
159
160 async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
161   const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id)
162
163   if (count <= 1) {
164     res.status(409)
165       .json({ error: 'Cannot remove the last channel of this user' })
166       .end()
167
168     return false
169   }
170
171   return true
172 }