]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/helpers/custom-validators/videos.ts
Fix admin access to moderators
[github/Chocobozzz/PeerTube.git] / server / helpers / custom-validators / videos.ts
CommitLineData
8d468a16 1import { Response } from 'express'
fdbda9e3 2import 'express-validator'
79d5caf9 3import { values } from 'lodash'
1840c2f7 4import 'multer'
79d5caf9 5import * as validator from 'validator'
2baea0c7 6import { UserRight, VideoPrivacy, VideoRateType } from '../../../shared'
3fd3ab2d
C
7import {
8 CONSTRAINTS_FIELDS,
9 VIDEO_CATEGORIES,
28be8916
C
10 VIDEO_LICENCES,
11 VIDEO_MIMETYPE_EXT,
3fd3ab2d 12 VIDEO_PRIVACIES,
2186386c
C
13 VIDEO_RATE_TYPES,
14 VIDEO_STATES
3fd3ab2d
C
15} from '../../initializers'
16import { VideoModel } from '../../models/video/video'
ac81d1a0 17import { exists, isArray, isFileValid } from './misc'
0f320037 18import { VideoChannelModel } from '../../models/video/video-channel'
6200d8d9 19import { UserModel } from '../../models/account/user'
ce33919c 20import * as magnetUtil from 'magnet-uri'
65fcc311
C
21
22const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
0b697522 23
9d3ef9fe 24function isVideoCategoryValid (value: any) {
2186386c
C
25 return value === null || VIDEO_CATEGORIES[ value ] !== undefined
26}
27
28function isVideoStateValid (value: any) {
29 return exists(value) && VIDEO_STATES[ value ] !== undefined
6e07c3de
C
30}
31
9d3ef9fe 32function isVideoLicenceValid (value: any) {
2186386c 33 return value === null || VIDEO_LICENCES[ value ] !== undefined
6f0c39e2
C
34}
35
9d3ef9fe
C
36function isVideoLanguageValid (value: any) {
37 return value === null ||
38 (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
3092476e
C
39}
40
8e10cf1a
C
41function isVideoDurationValid (value: string) {
42 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
43}
44
9567011b
C
45function isVideoTruncatedDescriptionValid (value: string) {
46 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
47}
48
69818c93 49function isVideoDescriptionValid (value: string) {
f595d394 50 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
be587647
C
51}
52
2422c46b
C
53function isVideoSupportValid (value: string) {
54 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
55}
56
69818c93
C
57function isVideoNameValid (value: string) {
58 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
be587647
C
59}
60
0d0e8dd0
C
61function isVideoTagValid (tag: string) {
62 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
63}
64
69818c93 65function isVideoTagsValid (tags: string[]) {
2efd32f6
C
66 return tags === null || (
67 isArray(tags) &&
68 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
69 tags.every(tag => isVideoTagValid(tag))
70 )
be587647
C
71}
72
69818c93
C
73function isVideoViewsValid (value: string) {
74 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
9e167724
C
75}
76
69818c93 77function isVideoRatingTypeValid (value: string) {
57a49263 78 return value === 'none' || values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
d38b8281
C
79}
80
ac81d1a0
C
81const videoFileTypes = Object.keys(VIDEO_MIMETYPE_EXT).map(m => `(${m})`)
82const videoFileTypesRegex = videoFileTypes.join('|')
2186386c 83
b60e5f38 84function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
0c237b19 85 return isFileValid(files, videoFileTypesRegex, 'videofile', null)
ac81d1a0 86}
f6f7dfee 87
ac81d1a0 88const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
2186386c
C
89 .map(v => v.replace('.', ''))
90 .join('|')
ac81d1a0 91const videoImageTypesRegex = `image/(${videoImageTypes})`
2186386c 92
ac81d1a0 93function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
0c237b19 94 return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true)
f6f7dfee
C
95}
96
2baea0c7 97function isVideoPrivacyValid (value: number) {
2186386c 98 return validator.isInt(value + '') && VIDEO_PRIVACIES[ value ] !== undefined
d4f1e94c
C
99}
100
2baea0c7
C
101function isScheduleVideoUpdatePrivacyValid (value: number) {
102 return validator.isInt(value + '') &&
103 (
104 value === VideoPrivacy.UNLISTED ||
105 value === VideoPrivacy.PUBLIC
106 )
107}
108
2cebd797 109function isVideoFileInfoHashValid (value: string | null | undefined) {
93e1258c
C
110 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
111}
112
d4f1e94c
C
113function isVideoFileResolutionValid (value: string) {
114 return exists(value) && validator.isInt(value + '')
115}
116
3a6f351b
C
117function isVideoFPSResolutionValid (value: string) {
118 return value === null || validator.isInt(value + '')
119}
120
d4f1e94c
C
121function isVideoFileSizeValid (value: string) {
122 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
8d468a16
C
123}
124
ce33919c
C
125function isVideoMagnetUriValid (value: string) {
126 if (!exists(value)) return false
127
128 const parsed = magnetUtil.decode(value)
129 return parsed && isVideoFileInfoHashValid(parsed.infoHash)
130}
131
40e87e9e
C
132function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: UserRight, res: Response) {
133 // Retrieve the user who did the request
134 if (video.isOwned() === false) {
135 res.status(403)
136 .json({ error: 'Cannot manage a video of another server.' })
137 .end()
138 return false
139 }
140
141 // Check if the user can delete the video
142 // The user can delete it if he has the right
143 // Or if s/he is the video's account
144 const account = video.VideoChannel.Account
145 if (user.hasRight(right) === false && account.userId !== user.id) {
146 res.status(403)
147 .json({ error: 'Cannot manage a video of another user.' })
148 .end()
149 return false
150 }
151
152 return true
153}
154
627621c1 155async function isVideoExist (id: string, res: Response, fetchType: 'all' | 'only-video' | 'id' | 'none' = 'all') {
c1e791ba 156 let video: VideoModel | null
4e50b6a1 157
627621c1
C
158 if (fetchType === 'all') {
159 video = await VideoModel.loadAndPopulateAccountAndServerAndTags(id)
160 } else if (fetchType === 'only-video') {
161 video = await VideoModel.load(id)
162 } else if (fetchType === 'id' || fetchType === 'none') {
163 video = await VideoModel.loadOnlyId(id)
4e50b6a1
C
164 }
165
2cebd797 166 if (video === null) {
4e50b6a1 167 res.status(404)
2186386c
C
168 .json({ error: 'Video not found' })
169 .end()
4e50b6a1
C
170
171 return false
172 }
173
627621c1 174 if (fetchType !== 'none') res.locals.video = video
4e50b6a1
C
175 return true
176}
177
6200d8d9
C
178async function isVideoChannelOfAccountExist (channelId: number, user: UserModel, res: Response) {
179 if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) {
180 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
2cebd797 181 if (videoChannel === null) {
6200d8d9 182 res.status(400)
e78980eb 183 .json({ error: 'Unknown video `video channel` on this instance.' })
6200d8d9
C
184 .end()
185
186 return false
187 }
188
189 res.locals.videoChannel = videoChannel
190 return true
191 }
192
193 const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id)
2cebd797 194 if (videoChannel === null) {
0f320037 195 res.status(400)
e78980eb 196 .json({ error: 'Unknown video `video channel` for this account.' })
0f320037
C
197 .end()
198
199 return false
200 }
201
202 res.locals.videoChannel = videoChannel
203 return true
204}
205
55fa55a9
C
206// ---------------------------------------------------------------------------
207
65fcc311 208export {
65fcc311 209 isVideoCategoryValid,
40e87e9e 210 checkUserCanManageVideo,
65fcc311
C
211 isVideoLicenceValid,
212 isVideoLanguageValid,
9567011b 213 isVideoTruncatedDescriptionValid,
65fcc311 214 isVideoDescriptionValid,
93e1258c 215 isVideoFileInfoHashValid,
65fcc311
C
216 isVideoNameValid,
217 isVideoTagsValid,
3a6f351b 218 isVideoFPSResolutionValid,
2baea0c7 219 isScheduleVideoUpdatePrivacyValid,
65fcc311 220 isVideoFile,
ce33919c 221 isVideoMagnetUriValid,
2186386c 222 isVideoStateValid,
65fcc311 223 isVideoViewsValid,
65fcc311 224 isVideoRatingTypeValid,
8e10cf1a 225 isVideoDurationValid,
0d0e8dd0 226 isVideoTagValid,
8d468a16 227 isVideoPrivacyValid,
d4f1e94c
C
228 isVideoFileResolutionValid,
229 isVideoFileSizeValid,
ac81d1a0 230 isVideoExist,
2422c46b 231 isVideoImage,
0f320037 232 isVideoChannelOfAccountExist,
2422c46b 233 isVideoSupportValid
65fcc311 234}