aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/users.ts2
-rw-r--r--server/middlewares/validators/videos.ts63
-rw-r--r--server/tests/api/check-params/videos.ts537
-rw-r--r--server/tests/api/index.ts1
-rw-r--r--server/tests/api/single-pod.ts23
-rw-r--r--server/tests/api/users.ts15
-rw-r--r--server/tests/api/video-privacy.ts158
-rw-r--r--server/tests/utils/videos.ts45
8 files changed, 440 insertions, 404 deletions
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index dcd407fdf..bacfc4552 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -171,7 +171,7 @@ async function getUserInformation (req: express.Request, res: express.Response,
171} 171}
172 172
173function getUser (req: express.Request, res: express.Response, next: express.NextFunction) { 173function getUser (req: express.Request, res: express.Response, next: express.NextFunction) {
174 return res.json(res.locals.oauth.token.User.toFormattedJSON()) 174 return res.json(res.locals.user.toFormattedJSON())
175} 175}
176 176
177async function getUserVideoRating (req: express.Request, res: express.Response, next: express.NextFunction) { 177async function getUserVideoRating (req: express.Request, res: express.Response, next: express.NextFunction) {
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index e197d4606..15b4629c1 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -24,6 +24,7 @@ import {
24 isVideoPrivacyValid 24 isVideoPrivacyValid
25} from '../../helpers' 25} from '../../helpers'
26import { UserRight, VideoPrivacy } from '../../../shared' 26import { UserRight, VideoPrivacy } from '../../../shared'
27import { authenticate } from '../oauth'
27 28
28const videosAddValidator = [ 29const videosAddValidator = [
29 body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage( 30 body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage(
@@ -112,7 +113,7 @@ const videosUpdateValidator = [
112 body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), 113 body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'),
113 body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), 114 body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'),
114 body('nsfw').optional().custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), 115 body('nsfw').optional().custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'),
115 body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), 116 body('privacy').optional().custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'),
116 body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), 117 body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'),
117 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), 118 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'),
118 119
@@ -155,7 +156,22 @@ const videosGetValidator = [
155 logger.debug('Checking videosGet parameters', { parameters: req.params }) 156 logger.debug('Checking videosGet parameters', { parameters: req.params })
156 157
157 checkErrors(req, res, () => { 158 checkErrors(req, res, () => {
158 checkVideoExists(req.params.id, res, next) 159 checkVideoExists(req.params.id, res, () => {
160 const video = res.locals.video
161
162 // Video is not private, anyone can access it
163 if (video.privacy !== VideoPrivacy.PRIVATE) return next()
164
165 authenticate(req, res, () => {
166 if (video.VideoChannel.Author.userId !== res.locals.oauth.token.User.id) {
167 return res.status(403)
168 .json({ error: 'Cannot get this private video of another user' })
169 .end()
170 }
171
172 next()
173 })
174 })
159 }) 175 })
160 } 176 }
161] 177]
@@ -232,28 +248,23 @@ export {
232 248
233function checkUserCanDeleteVideo (userId: number, res: express.Response, callback: () => void) { 249function checkUserCanDeleteVideo (userId: number, res: express.Response, callback: () => void) {
234 // Retrieve the user who did the request 250 // Retrieve the user who did the request
235 db.User.loadById(userId) 251 if (res.locals.video.isOwned() === false) {
236 .then(user => { 252 return res.status(403)
237 if (res.locals.video.isOwned() === false) { 253 .json({ error: 'Cannot remove video of another pod, blacklist it' })
238 return res.status(403) 254 .end()
239 .json({ error: 'Cannot remove video of another pod, blacklist it' }) 255 }
240 .end() 256
241 } 257 // Check if the user can delete the video
242 258 // The user can delete it if s/he is an admin
243 // Check if the user can delete the video 259 // Or if s/he is the video's author
244 // The user can delete it if s/he is an admin 260 const author = res.locals.video.VideoChannel.Author
245 // Or if s/he is the video's author 261 const user = res.locals.oauth.token.User
246 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && res.locals.video.Author.userId !== res.locals.oauth.token.User.id) { 262 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && author.userId !== user.id) {
247 return res.status(403) 263 return res.status(403)
248 .json({ error: 'Cannot remove video of another user' }) 264 .json({ error: 'Cannot remove video of another user' })
249 .end() 265 .end()
250 } 266 }
251 267
252 // If we reach this comment, we can delete the video 268 // If we reach this comment, we can delete the video
253 callback() 269 callback()
254 })
255 .catch(err => {
256 logger.error('Error in video request validator.', err)
257 return res.sendStatus(500)
258 })
259} 270}
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
index c59f5da93..5860e9195 100644
--- a/server/tests/api/check-params/videos.ts
+++ b/server/tests/api/check-params/videos.ts
@@ -19,12 +19,46 @@ import {
19 createUser, 19 createUser,
20 getUserAccessToken 20 getUserAccessToken
21} from '../../utils' 21} from '../../utils'
22import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
22 23
23describe('Test videos API validator', function () { 24describe('Test videos API validator', function () {
24 const path = '/api/v1/videos/' 25 const path = '/api/v1/videos/'
25 let server: ServerInfo 26 let server: ServerInfo
26 let channelId: number 27 let channelId: number
27 28
29 function getCompleteVideoUploadAttributes () {
30 return {
31 name: 'my super name',
32 category: 5,
33 licence: 1,
34 language: 6,
35 nsfw: false,
36 description: 'my super description',
37 tags: [ 'tag1', 'tag2' ],
38 privacy: VideoPrivacy.PUBLIC,
39 channelId
40 }
41 }
42
43 function getCompleteVideoUpdateAttributes () {
44 return {
45 name: 'my super name',
46 category: 5,
47 licence: 2,
48 language: 6,
49 nsfw: false,
50 description: 'my super description',
51 privacy: VideoPrivacy.PUBLIC,
52 tags: [ 'tag1', 'tag2' ]
53 }
54 }
55
56 function getVideoUploadAttaches () {
57 return {
58 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
59 }
60 }
61
28 // --------------------------------------------------------------- 62 // ---------------------------------------------------------------
29 63
30 before(async function () { 64 before(async function () {
@@ -99,6 +133,37 @@ describe('Test videos API validator', function () {
99 }) 133 })
100 }) 134 })
101 135
136 describe('When listing my videos', function () {
137 const path = '/api/v1/users/me/videos'
138
139 it('Should fail with a bad start pagination', async function () {
140 await request(server.url)
141 .get(path)
142 .set('Authorization', 'Bearer ' + server.accessToken)
143 .query({ start: 'hello' })
144 .set('Accept', 'application/json')
145 .expect(400)
146 })
147
148 it('Should fail with a bad count pagination', async function () {
149 await request(server.url)
150 .get(path)
151 .set('Authorization', 'Bearer ' + server.accessToken)
152 .query({ count: 'hello' })
153 .set('Accept', 'application/json')
154 .expect(400)
155 })
156
157 it('Should fail with an incorrect sort', async function () {
158 await request(server.url)
159 .get(path)
160 .set('Authorization', 'Bearer ' + server.accessToken)
161 .query({ sort: 'hello' })
162 .set('Accept', 'application/json')
163 .expect(400)
164 })
165 })
166
102 describe('When adding a video', function () { 167 describe('When adding a video', function () {
103 it('Should fail with nothing', async function () { 168 it('Should fail with nothing', async function () {
104 const fields = {} 169 const fields = {}
@@ -107,219 +172,108 @@ describe('Test videos API validator', function () {
107 }) 172 })
108 173
109 it('Should fail without name', async function () { 174 it('Should fail without name', async function () {
110 const fields = { 175 const fields = getCompleteVideoUploadAttributes()
111 category: 5, 176 delete fields.name
112 licence: 1, 177
113 language: 6, 178 const attaches = getVideoUploadAttaches()
114 nsfw: false,
115 description: 'my super description',
116 tags: [ 'tag1', 'tag2' ],
117 channelId
118 }
119 const attaches = {
120 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
121 }
122 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 179 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
123 }) 180 })
124 181
125 it('Should fail with a long name', async function () { 182 it('Should fail with a long name', async function () {
126 const fields = { 183 const fields = getCompleteVideoUploadAttributes()
127 name: 'My very very very very very very very very very very very very very very very very very ' + 184 fields.name = 'My very very very very very very very very very very very very very very very very very ' +
128 'very very very very very very very very very very very very very very very very long long' + 185 'very very very very very very very very very very very very very very very very long long' +
129 'very very very very very very very very very very very very very very very very long name', 186 'very very very very very very very very very very very very very very very very long name'
130 category: 5, 187
131 licence: 1, 188 const attaches = getVideoUploadAttaches
132 language: 6,
133 nsfw: false,
134 description: 'my super description',
135 tags: [ 'tag1', 'tag2' ],
136 channelId
137 }
138 const attaches = {
139 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
140 }
141 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 189 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
142 }) 190 })
143 191
144 it('Should fail without a category', async function () { 192 it('Should fail without a category', async function () {
145 const fields = { 193 const fields = getCompleteVideoUploadAttributes()
146 name: 'my super name', 194 delete fields.category
147 licence: 1, 195
148 language: 6, 196 const attaches = getVideoUploadAttaches
149 nsfw: false,
150 description: 'my super description',
151 tags: [ 'tag1', 'tag2' ],
152 channelId
153 }
154 const attaches = {
155 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
156 }
157 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 197 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
158 }) 198 })
159 199
160 it('Should fail with a bad category', async function () { 200 it('Should fail with a bad category', async function () {
161 const fields = { 201 const fields = getCompleteVideoUploadAttributes()
162 name: 'my super name', 202 fields.category = 125
163 category: 125, 203
164 licence: 1, 204 const attaches = getVideoUploadAttaches
165 language: 6,
166 nsfw: false,
167 description: 'my super description',
168 tags: [ 'tag1', 'tag2' ],
169 channelId
170 }
171 const attaches = {
172 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
173 }
174 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 205 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
175 }) 206 })
176 207
177 it('Should fail without a licence', async function () { 208 it('Should fail without a licence', async function () {
178 const fields = { 209 const fields = getCompleteVideoUploadAttributes()
179 name: 'my super name', 210 delete fields.licence
180 category: 5, 211
181 language: 6, 212 const attaches = getVideoUploadAttaches()
182 nsfw: false,
183 description: 'my super description',
184 tags: [ 'tag1', 'tag2' ],
185 channelId
186 }
187 const attaches = {
188 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
189 }
190 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 213 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
191 }) 214 })
192 215
193 it('Should fail with a bad licence', async function () { 216 it('Should fail with a bad licence', async function () {
194 const fields = { 217 const fields = getCompleteVideoUploadAttributes()
195 name: 'my super name', 218 fields.licence = 125
196 category: 5, 219
197 licence: 125, 220 const attaches = getVideoUploadAttaches()
198 language: 6,
199 nsfw: false,
200 description: 'my super description',
201 tags: [ 'tag1', 'tag2' ],
202 channelId
203 }
204 const attaches = {
205 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
206 }
207 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 221 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
208 }) 222 })
209 223
210 it('Should fail with a bad language', async function () { 224 it('Should fail with a bad language', async function () {
211 const fields = { 225 const fields = getCompleteVideoUploadAttributes()
212 name: 'my super name', 226 fields.language = 563
213 category: 5, 227
214 licence: 4, 228 const attaches = getVideoUploadAttaches()
215 language: 563,
216 nsfw: false,
217 description: 'my super description',
218 tags: [ 'tag1', 'tag2' ],
219 channelId
220 }
221 const attaches = {
222 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
223 }
224 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 229 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
225 }) 230 })
226 231
227 it('Should fail without nsfw attribute', async function () { 232 it('Should fail without nsfw attribute', async function () {
228 const fields = { 233 const fields = getCompleteVideoUploadAttributes()
229 name: 'my super name', 234 delete fields.nsfw
230 category: 5, 235
231 licence: 4, 236 const attaches = getVideoUploadAttaches()
232 language: 6,
233 description: 'my super description',
234 tags: [ 'tag1', 'tag2' ],
235 channelId
236 }
237 const attaches = {
238 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
239 }
240 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 237 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
241 }) 238 })
242 239
243 it('Should fail with a bad nsfw attribute', async function () { 240 it('Should fail with a bad nsfw attribute', async function () {
244 const fields = { 241 const fields = getCompleteVideoUploadAttributes()
245 name: 'my super name', 242 fields.nsfw = 2 as any
246 category: 5, 243
247 licence: 4, 244 const attaches = getVideoUploadAttaches()
248 language: 6,
249 nsfw: 2,
250 description: 'my super description',
251 tags: [ 'tag1', 'tag2' ],
252 channelId
253 }
254 const attaches = {
255 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
256 }
257 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 245 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
258 }) 246 })
259 247
260 it('Should fail without description', async function () { 248 it('Should fail without description', async function () {
261 const fields = { 249 const fields = getCompleteVideoUploadAttributes()
262 name: 'my super name', 250 delete fields.description
263 category: 5, 251
264 licence: 1, 252 const attaches = getVideoUploadAttaches()
265 language: 6,
266 nsfw: false,
267 tags: [ 'tag1', 'tag2' ],
268 channelId
269 }
270 const attaches = {
271 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
272 }
273 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 253 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
274 }) 254 })
275 255
276 it('Should fail with a long description', async function () { 256 it('Should fail with a long description', async function () {
277 const fields = { 257 const fields = getCompleteVideoUploadAttributes()
278 name: 'my super name', 258 fields.description = 'my super description which is very very very very very very very very very very very very long'.repeat(35)
279 category: 5, 259
280 licence: 1, 260 const attaches = getVideoUploadAttaches()
281 language: 6,
282 nsfw: false,
283 description: 'my super description which is very very very very very very very very very very very very very very long'.repeat(35),
284 tags: [ 'tag1', 'tag2' ],
285 channelId
286 }
287 const attaches = {
288 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
289 }
290 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 261 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
291 }) 262 })
292 263
293 it('Should fail without a channel', async function () { 264 it('Should fail without a channel', async function () {
294 const fields = { 265 const fields = getCompleteVideoUploadAttributes()
295 name: 'my super name', 266 delete fields.channelId
296 category: 5, 267
297 licence: 1, 268 const attaches = getVideoUploadAttaches()
298 language: 6,
299 nsfw: false,
300 description: 'my super description',
301 tags: [ 'tag1', 'tag2' ]
302 }
303 const attaches = {
304 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
305 }
306 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 269 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
307 }) 270 })
308 271
309 it('Should fail with a bad channel', async function () { 272 it('Should fail with a bad channel', async function () {
310 const fields = { 273 const fields = getCompleteVideoUploadAttributes()
311 name: 'my super name', 274 fields.channelId = 545454
312 category: 5, 275
313 licence: 1, 276 const attaches = getVideoUploadAttaches()
314 language: 6,
315 nsfw: false,
316 description: 'my super description',
317 tags: [ 'tag1', 'tag2' ],
318 channelId: 545454
319 }
320 const attaches = {
321 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
322 }
323 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 277 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
324 }) 278 })
325 279
@@ -332,101 +286,47 @@ describe('Test videos API validator', function () {
332 286
333 const accessTokenUser = await getUserAccessToken(server, user) 287 const accessTokenUser = await getUserAccessToken(server, user)
334 const res = await getMyUserInformation(server.url, accessTokenUser) 288 const res = await getMyUserInformation(server.url, accessTokenUser)
335 const channelId = res.body.videoChannels[0].id 289 const customChannelId = res.body.videoChannels[0].id
336 290
337 const fields = { 291 const fields = getCompleteVideoUploadAttributes()
338 name: 'my super name', 292 fields.channelId = customChannelId
339 category: 5, 293
340 licence: 1, 294 const attaches = getVideoUploadAttaches()
341 language: 6,
342 nsfw: false,
343 description: 'my super description',
344 tags: [ 'tag1', 'tag2' ],
345 channelId
346 }
347 const attaches = {
348 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
349 }
350 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 295 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
351 }) 296 })
352 297
353 it('Should fail with too many tags', async function () { 298 it('Should fail with too many tags', async function () {
354 const fields = { 299 const fields = getCompleteVideoUploadAttributes()
355 name: 'my super name', 300 fields.tags = [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ]
356 category: 5, 301
357 licence: 1, 302 const attaches = getVideoUploadAttaches()
358 language: 6,
359 nsfw: false,
360 description: 'my super description',
361 tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ],
362 channelId
363 }
364 const attaches = {
365 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
366 }
367 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 303 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
368 }) 304 })
369 305
370 it('Should fail with a tag length too low', async function () { 306 it('Should fail with a tag length too low', async function () {
371 const fields = { 307 const fields = getCompleteVideoUploadAttributes()
372 name: 'my super name', 308 fields.tags = [ 'tag1', 't' ]
373 category: 5, 309
374 licence: 1, 310 const attaches = getVideoUploadAttaches()
375 language: 6,
376 nsfw: false,
377 description: 'my super description',
378 tags: [ 'tag1', 't' ],
379 channelId
380 }
381 const attaches = {
382 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
383 }
384 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 311 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
385 }) 312 })
386 313
387 it('Should fail with a tag length too big', async function () { 314 it('Should fail with a tag length too big', async function () {
388 const fields = { 315 const fields = getCompleteVideoUploadAttributes()
389 name: 'my super name', 316 fields.tags = [ 'my_super_tag_too_long_long_long_long_long_long', 'tag1' ]
390 category: 5, 317
391 licence: 1, 318 const attaches = getVideoUploadAttaches()
392 language: 6,
393 nsfw: false,
394 description: 'my super description',
395 tags: [ 'my_super_tag_too_long_long_long_long_long_long', 'tag1' ],
396 channelId
397 }
398 const attaches = {
399 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
400 }
401 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 319 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
402 }) 320 })
403 321
404 it('Should fail without an input file', async function () { 322 it('Should fail without an input file', async function () {
405 const fields = { 323 const fields = getCompleteVideoUploadAttributes()
406 name: 'my super name',
407 category: 5,
408 licence: 1,
409 language: 6,
410 nsfw: false,
411 description: 'my super description',
412 tags: [ 'tag1', 'tag2' ],
413 channelId
414 }
415 const attaches = {} 324 const attaches = {}
416 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 325 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
417 }) 326 })
418 327
419 it('Should fail without an incorrect input file', async function () { 328 it('Should fail without an incorrect input file', async function () {
420 const fields = { 329 const fields = getCompleteVideoUploadAttributes()
421 name: 'my super name',
422 category: 5,
423 licence: 1,
424 language: 6,
425 nsfw: false,
426 description: 'my super description',
427 tags: [ 'tag1', 'tag2' ],
428 channelId
429 }
430 const attaches = { 330 const attaches = {
431 'videofile': join(__dirname, '..', 'fixtures', 'video_short_fake.webm') 331 'videofile': join(__dirname, '..', 'fixtures', 'video_short_fake.webm')
432 } 332 }
@@ -434,16 +334,7 @@ describe('Test videos API validator', function () {
434 }) 334 })
435 335
436 it('Should fail with a too big duration', async function () { 336 it('Should fail with a too big duration', async function () {
437 const fields = { 337 const fields = getCompleteVideoUploadAttributes()
438 name: 'my super name',
439 category: 5,
440 licence: 1,
441 language: 6,
442 nsfw: false,
443 description: 'my super description',
444 tags: [ 'tag1', 'tag2' ],
445 channelId
446 }
447 const attaches = { 338 const attaches = {
448 'videofile': join(__dirname, '..', 'fixtures', 'video_too_long.webm') 339 'videofile': join(__dirname, '..', 'fixtures', 'video_too_long.webm')
449 } 340 }
@@ -453,19 +344,8 @@ describe('Test videos API validator', function () {
453 it('Should succeed with the correct parameters', async function () { 344 it('Should succeed with the correct parameters', async function () {
454 this.timeout(10000) 345 this.timeout(10000)
455 346
456 const fields = { 347 const fields = getCompleteVideoUploadAttributes()
457 name: 'my super name', 348 const attaches = getVideoUploadAttaches()
458 category: 5,
459 licence: 1,
460 language: 6,
461 nsfw: false,
462 description: 'my super description',
463 tags: [ 'tag1', 'tag2' ],
464 channelId
465 }
466 const attaches = {
467 'videofile': join(__dirname, '..', 'fixtures', 'video_short.webm')
468 }
469 349
470 await makePostUploadRequest({ 350 await makePostUploadRequest({
471 url: server.url, 351 url: server.url,
@@ -512,26 +392,13 @@ describe('Test videos API validator', function () {
512 }) 392 })
513 393
514 it('Should fail without a valid uuid', async function () { 394 it('Should fail without a valid uuid', async function () {
515 const fields = { 395 const fields = getCompleteVideoUpdateAttributes()
516 category: 5,
517 licence: 2,
518 language: 6,
519 nsfw: false,
520 description: 'my super description',
521 tags: [ 'tag1', 'tag2' ]
522 }
523 await makePutBodyRequest({ url: server.url, path: path + 'blabla', token: server.accessToken, fields }) 396 await makePutBodyRequest({ url: server.url, path: path + 'blabla', token: server.accessToken, fields })
524 }) 397 })
525 398
526 it('Should fail with an unknown id', async function () { 399 it('Should fail with an unknown id', async function () {
527 const fields = { 400 const fields = getCompleteVideoUpdateAttributes()
528 category: 5, 401
529 licence: 2,
530 language: 6,
531 nsfw: false,
532 description: 'my super description',
533 tags: [ 'tag1', 'tag2' ]
534 }
535 await makePutBodyRequest({ 402 await makePutBodyRequest({
536 url: server.url, 403 url: server.url,
537 path: path + '4da6fde3-88f7-4d16-b119-108df5630b06', 404 path: path + '4da6fde3-88f7-4d16-b119-108df5630b06',
@@ -542,127 +409,77 @@ describe('Test videos API validator', function () {
542 }) 409 })
543 410
544 it('Should fail with a long name', async function () { 411 it('Should fail with a long name', async function () {
545 const fields = { 412 const fields = getCompleteVideoUpdateAttributes()
546 name: 'My very very very very very very very very very very very very very very very very very ' + 413 fields.name = 'My very very very very very very very very very very very very very very very very long'.repeat(3)
547 'very very very very very very very very very very very very very very very very long long' + 414
548 'very very very very very very very very very very very very very very very very long name',
549 category: 5,
550 licence: 2,
551 language: 6,
552 nsfw: false,
553 description: 'my super description',
554 tags: [ 'tag1', 'tag2' ]
555 }
556 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 415 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
557 }) 416 })
558 417
559 it('Should fail with a bad category', async function () { 418 it('Should fail with a bad category', async function () {
560 const fields = { 419 const fields = getCompleteVideoUpdateAttributes()
561 name: 'my super name', 420 fields.category = 128
562 category: 128, 421
563 licence: 2,
564 language: 6,
565 nsfw: false,
566 description: 'my super description',
567 tags: [ 'tag1', 'tag2' ]
568 }
569 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 422 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
570 }) 423 })
571 424
572 it('Should fail with a bad licence', async function () { 425 it('Should fail with a bad licence', async function () {
573 const fields = { 426 const fields = getCompleteVideoUpdateAttributes()
574 name: 'my super name', 427 fields.licence = 128
575 category: 5, 428
576 licence: 128,
577 language: 6,
578 nsfw: false,
579 description: 'my super description',
580 tags: [ 'tag1', 'tag2' ]
581 }
582 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 429 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
583 }) 430 })
584 431
585 it('Should fail with a bad language', async function () { 432 it('Should fail with a bad language', async function () {
586 const fields = { 433 const fields = getCompleteVideoUpdateAttributes()
587 name: 'my super name', 434 fields.language = 896
588 category: 5, 435
589 licence: 3,
590 language: 896,
591 nsfw: false,
592 description: 'my super description',
593 tags: [ 'tag1', 'tag2' ]
594 }
595 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 436 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
596 }) 437 })
597 438
598 it('Should fail with a bad nsfw attribute', async function () { 439 it('Should fail with a bad nsfw attribute', async function () {
599 const fields = { 440 const fields = getCompleteVideoUpdateAttributes()
600 name: 'my super name', 441 fields.nsfw = (-4 as any)
601 category: 5, 442
602 licence: 5,
603 language: 6,
604 nsfw: -4,
605 description: 'my super description',
606 tags: [ 'tag1', 'tag2' ]
607 }
608 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 443 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
609 }) 444 })
610 445
611 it('Should fail with a long description', async function () { 446 it('Should fail with a long description', async function () {
612 const fields = { 447 const fields = getCompleteVideoUpdateAttributes()
613 name: 'my super name', 448 fields.description = 'my super description which is very very very very very very very very very very very very very long'.repeat(35)
614 category: 5, 449
615 licence: 2,
616 language: 6,
617 nsfw: false,
618 description: 'my super description which is very very very very very very very very very very very very very long'.repeat(35),
619 tags: [ 'tag1', 'tag2' ]
620 }
621 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 450 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
622 }) 451 })
623 452
624 it('Should fail with too many tags', async function () { 453 it('Should fail with too many tags', async function () {
625 const fields = { 454 const fields = getCompleteVideoUpdateAttributes()
626 name: 'my super name', 455 fields.tags = [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ]
627 category: 5, 456
628 licence: 2,
629 language: 6,
630 nsfw: false,
631 description: 'my super description',
632 tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ]
633 }
634 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 457 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
635 }) 458 })
636 459
637 it('Should fail with a tag length too low', async function () { 460 it('Should fail with a tag length too low', async function () {
638 const fields = { 461 const fields = getCompleteVideoUpdateAttributes()
639 name: 'my super name', 462 fields.tags = [ 'tag1', 't' ]
640 category: 5, 463
641 licence: 2,
642 language: 6,
643 nsfw: false,
644 description: 'my super description',
645 tags: [ 'tag1', 't' ]
646 }
647 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 464 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
648 }) 465 })
649 466
650 it('Should fail with a tag length too big', async function () { 467 it('Should fail with a tag length too big', async function () {
651 const fields = { 468 const fields = getCompleteVideoUpdateAttributes()
652 name: 'my super name', 469 fields.tags = [ 'my_super_tag_too_long_long_long_long', 'tag1' ]
653 category: 5, 470
654 licence: 2,
655 language: 6,
656 nsfw: false,
657 description: 'my super description',
658 tags: [ 'my_super_tag_too_long_long_long_long', 'tag1' ]
659 }
660 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) 471 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
661 }) 472 })
662 473
663 it('Should fail with a video of another user') 474 it('Should fail with a video of another user')
664 475
665 it('Should fail with a video of another pod') 476 it('Should fail with a video of another pod')
477
478 it('Should succeed with the correct parameters', async function () {
479 const fields = getCompleteVideoUpdateAttributes()
480
481 await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields, statusCodeExpected: 204 })
482 })
666 }) 483 })
667 484
668 describe('When getting a video', function () { 485 describe('When getting a video', function () {
diff --git a/server/tests/api/index.ts b/server/tests/api/index.ts
index 2ff0ecf24..371f1bc43 100644
--- a/server/tests/api/index.ts
+++ b/server/tests/api/index.ts
@@ -8,6 +8,7 @@ import './video-abuse'
8import './video-blacklist' 8import './video-blacklist'
9import './video-blacklist-management' 9import './video-blacklist-management'
10import './video-description' 10import './video-description'
11import './video-privacy'
11import './multiple-pods' 12import './multiple-pods'
12import './services' 13import './services'
13import './request-schedulers' 14import './request-schedulers'
diff --git a/server/tests/api/single-pod.ts b/server/tests/api/single-pod.ts
index d3a982436..3a05d0727 100644
--- a/server/tests/api/single-pod.ts
+++ b/server/tests/api/single-pod.ts
@@ -22,6 +22,7 @@ import {
22 getVideoCategories, 22 getVideoCategories,
23 getVideoLicences, 23 getVideoLicences,
24 getVideoLanguages, 24 getVideoLanguages,
25 getVideoPrivacies,
25 testVideoImage, 26 testVideoImage,
26 webtorrentAdd, 27 webtorrentAdd,
27 getVideo, 28 getVideo,
@@ -76,6 +77,15 @@ describe('Test a single pod', function () {
76 expect(languages[3]).to.equal('Mandarin') 77 expect(languages[3]).to.equal('Mandarin')
77 }) 78 })
78 79
80 it('Should list video privacies', async function () {
81 const res = await getVideoPrivacies(server.url)
82
83 const privacies = res.body
84 expect(Object.keys(privacies)).to.have.length.at.least(3)
85
86 expect(privacies[3]).to.equal('Private')
87 })
88
79 it('Should not have videos', async function () { 89 it('Should not have videos', async function () {
80 const res = await getVideosList(server.url) 90 const res = await getVideosList(server.url)
81 91
@@ -482,19 +492,6 @@ describe('Test a single pod', function () {
482 // }) 492 // })
483 // }) 493 // })
484 494
485 it('Should search the right magnetUri video', async function () {
486 const video = videosListBase[0]
487 const res = await getVideo(server.url, video.id)
488 const videoDetails = res.body
489
490 const res2 = await searchVideoWithPagination(server.url, encodeURIComponent(videoDetails.files[0].magnetUri), 'magnetUri', 0, 15)
491
492 const videos = res2.body.data
493 expect(res2.body.total).to.equal(1)
494 expect(videos.length).to.equal(1)
495 expect(videos[0].name).to.equal(video.name)
496 })
497
498 it('Should list and sort by name in descending order', async function () { 495 it('Should list and sort by name in descending order', async function () {
499 const res = await getVideosListSort(server.url, '-name') 496 const res = await getVideosListSort(server.url, '-name')
500 497
diff --git a/server/tests/api/users.ts b/server/tests/api/users.ts
index bdef62c46..6f40ca3c9 100644
--- a/server/tests/api/users.ts
+++ b/server/tests/api/users.ts
@@ -31,6 +31,7 @@ import {
31 getBlacklistedVideosList 31 getBlacklistedVideosList
32} from '../utils' 32} from '../utils'
33import { UserRole } from '../../../shared' 33import { UserRole } from '../../../shared'
34import { getMyVideos } from '../utils/videos'
34 35
35describe('Test users', function () { 36describe('Test users', function () {
36 let server: ServerInfo 37 let server: ServerInfo
@@ -197,10 +198,22 @@ describe('Test users', function () {
197 it('Should be able to upload a video with this user', async function () { 198 it('Should be able to upload a video with this user', async function () {
198 this.timeout(5000) 199 this.timeout(5000)
199 200
200 const videoAttributes = {} 201 const videoAttributes = {
202 name: 'super user video'
203 }
201 await uploadVideo(server.url, accessTokenUser, videoAttributes) 204 await uploadVideo(server.url, accessTokenUser, videoAttributes)
202 }) 205 })
203 206
207 it('Should be able to list my videos', async function () {
208 const res = await getMyVideos(server.url, accessTokenUser, 0, 5)
209 expect(res.body.total).to.equal(1)
210
211 const videos = res.body.data
212 expect(videos).to.have.lengthOf(1)
213
214 expect(videos[0].name).to.equal('super user video')
215 })
216
204 it('Should list all the users', async function () { 217 it('Should list all the users', async function () {
205 const res = await getUsersList(server.url) 218 const res = await getUsersList(server.url)
206 const result = res.body 219 const result = res.body
diff --git a/server/tests/api/video-privacy.ts b/server/tests/api/video-privacy.ts
new file mode 100644
index 000000000..beac1613e
--- /dev/null
+++ b/server/tests/api/video-privacy.ts
@@ -0,0 +1,158 @@
1/* tslint:disable:no-unused-expression */
2
3import 'mocha'
4import * as chai from 'chai'
5const expect = chai.expect
6
7import {
8 ServerInfo,
9 flushTests,
10 uploadVideo,
11 makeFriends,
12 getVideosList,
13 wait,
14 setAccessTokensToServers,
15 flushAndRunMultipleServers,
16 killallServers
17} from '../utils'
18import { VideoPrivacy } from '../../../shared/models/videos/video-privacy.enum'
19import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../utils/videos'
20import { createUser } from '../utils/users'
21import { getUserAccessToken } from '../utils/login'
22
23describe('Test video privacy', function () {
24 let servers: ServerInfo[] = []
25 let privateVideoId
26 let privateVideoUUID
27 let unlistedVideoUUID
28
29 before(async function () {
30 this.timeout(120000)
31
32 // Run servers
33 servers = await flushAndRunMultipleServers(2)
34
35 // Get the access tokens
36 await setAccessTokensToServers(servers)
37
38 // Pod 1 makes friend with pod 2
39 await makeFriends(servers[0].url, servers[0].accessToken)
40 })
41
42 it('Should upload a private video on pod 1', async function () {
43 this.timeout(15000)
44
45 const attributes = {
46 privacy: VideoPrivacy.PRIVATE
47 }
48 await uploadVideo(servers[0].url, servers[0].accessToken, attributes)
49
50 await wait(11000)
51 })
52
53 it('Should not have this private video on pod 2', async function () {
54 const res = await getVideosList(servers[1].url)
55
56 expect(res.body.total).to.equal(0)
57 expect(res.body.data).to.have.lengthOf(0)
58 })
59
60 it('Should list my (private) videos', async function () {
61 const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 1)
62
63 expect(res.body.total).to.equal(1)
64 expect(res.body.data).to.have.lengthOf(1)
65
66 privateVideoId = res.body.data[0].id
67 privateVideoUUID = res.body.data[0].uuid
68 })
69
70 it('Should not be able to watch this video with non authenticated user', async function () {
71 await getVideo(servers[0].url, privateVideoUUID, 401)
72 })
73
74 it('Should not be able to watch this private video with another user', async function () {
75 const user = {
76 username: 'hello',
77 password: 'super password'
78 }
79 await createUser(servers[0].url, servers[0].accessToken, user.username, user.password)
80
81 const token = await getUserAccessToken(servers[0], user)
82 await getVideoWithToken(servers[0].url, token, privateVideoUUID, 403)
83 })
84
85 it('Should be able to watch this video with the correct user', async function () {
86 await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID)
87 })
88
89 it('Should upload a unlisted video on pod 2', async function () {
90 this.timeout(30000)
91
92 const attributes = {
93 name: 'unlisted video',
94 privacy: VideoPrivacy.UNLISTED
95 }
96 await uploadVideo(servers[1].url, servers[1].accessToken, attributes)
97
98 await wait(22000)
99 })
100
101 it('Should not have this unlisted video listed on pod 1 and 2', async function () {
102 for (const server of servers) {
103 const res = await getVideosList(server.url)
104
105 expect(res.body.total).to.equal(0)
106 expect(res.body.data).to.have.lengthOf(0)
107 }
108 })
109
110 it('Should list my (unlisted) videos', async function () {
111 const res = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 1)
112
113 expect(res.body.total).to.equal(1)
114 expect(res.body.data).to.have.lengthOf(1)
115
116 unlistedVideoUUID = res.body.data[0].uuid
117 })
118
119 it('Should be able to get this unlisted video', async function () {
120 for (const server of servers) {
121 const res = await getVideo(server.url, unlistedVideoUUID)
122
123 expect(res.body.name).to.equal('unlisted video')
124 }
125 })
126
127 it('Should update the private video to public on pod 1', async function () {
128 this.timeout(15000)
129
130 const attribute = {
131 name: 'super video public',
132 privacy: VideoPrivacy.PUBLIC
133 }
134
135 await updateVideo(servers[0].url, servers[0].accessToken, privateVideoId, attribute)
136
137 await wait(11000)
138 })
139
140 it('Should not have this new unlisted video listed on pod 1 and 2', async function () {
141 for (const server of servers) {
142 const res = await getVideosList(server.url)
143
144 expect(res.body.total).to.equal(1)
145 expect(res.body.data).to.have.lengthOf(1)
146 expect(res.body.data[0].name).to.equal('super video public')
147 }
148 })
149
150 after(async function () {
151 killallServers(servers)
152
153 // Keep the logs if the test failed
154 if (this['ok']) {
155 await flushTests()
156 }
157 })
158})
diff --git a/server/tests/utils/videos.ts b/server/tests/utils/videos.ts
index 2a5d00255..d4d5faf0a 100644
--- a/server/tests/utils/videos.ts
+++ b/server/tests/utils/videos.ts
@@ -7,6 +7,7 @@ import { makeGetRequest } from './requests'
7import { readFilePromise } from './miscs' 7import { readFilePromise } from './miscs'
8import { ServerInfo } from './servers' 8import { ServerInfo } from './servers'
9import { getMyUserInformation } from './users' 9import { getMyUserInformation } from './users'
10import { VideoPrivacy } from '../../../shared'
10 11
11type VideoAttributes = { 12type VideoAttributes = {
12 name?: string 13 name?: string
@@ -17,6 +18,7 @@ type VideoAttributes = {
17 description?: string 18 description?: string
18 tags?: string[] 19 tags?: string[]
19 channelId?: number 20 channelId?: number
21 privacy?: VideoPrivacy
20 fixture?: string 22 fixture?: string
21} 23}
22 24
@@ -38,6 +40,12 @@ function getVideoLanguages (url: string) {
38 return makeGetRequest(url, path) 40 return makeGetRequest(url, path)
39} 41}
40 42
43function getVideoPrivacies (url: string) {
44 const path = '/api/v1/videos/privacies'
45
46 return makeGetRequest(url, path)
47}
48
41function getAllVideosListBy (url: string) { 49function getAllVideosListBy (url: string) {
42 const path = '/api/v1/videos' 50 const path = '/api/v1/videos'
43 51
@@ -51,14 +59,23 @@ function getAllVideosListBy (url: string) {
51 .expect('Content-Type', /json/) 59 .expect('Content-Type', /json/)
52} 60}
53 61
54function getVideo (url: string, id: number | string) { 62function getVideo (url: string, id: number | string, expectedStatus = 200) {
55 const path = '/api/v1/videos/' + id 63 const path = '/api/v1/videos/' + id
56 64
57 return request(url) 65 return request(url)
58 .get(path) 66 .get(path)
59 .set('Accept', 'application/json') 67 .set('Accept', 'application/json')
60 .expect(200) 68 .expect(expectedStatus)
61 .expect('Content-Type', /json/) 69}
70
71function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
72 const path = '/api/v1/videos/' + id
73
74 return request(url)
75 .get(path)
76 .set('Authorization', 'Bearer ' + token)
77 .set('Accept', 'application/json')
78 .expect(expectedStatus)
62} 79}
63 80
64function getVideoDescription (url: string, descriptionPath: string) { 81function getVideoDescription (url: string, descriptionPath: string) {
@@ -80,6 +97,22 @@ function getVideosList (url: string) {
80 .expect('Content-Type', /json/) 97 .expect('Content-Type', /json/)
81} 98}
82 99
100function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
101 const path = '/api/v1/users/me/videos'
102
103 const req = request(url)
104 .get(path)
105 .query({ start: start })
106 .query({ count: count })
107
108 if (sort) req.query({ sort })
109
110 return req.set('Accept', 'application/json')
111 .set('Authorization', 'Bearer ' + accessToken)
112 .expect(200)
113 .expect('Content-Type', /json/)
114}
115
83function getVideosListPagination (url: string, start: number, count: number, sort?: string) { 116function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
84 const path = '/api/v1/videos' 117 const path = '/api/v1/videos'
85 118
@@ -191,6 +224,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg
191 nsfw: true, 224 nsfw: true,
192 description: 'my super description', 225 description: 'my super description',
193 tags: [ 'tag' ], 226 tags: [ 'tag' ],
227 privacy: VideoPrivacy.PUBLIC,
194 fixture: 'video_short.webm' 228 fixture: 'video_short.webm'
195 } 229 }
196 attributes = Object.assign(attributes, videoAttributesArg) 230 attributes = Object.assign(attributes, videoAttributesArg)
@@ -204,6 +238,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg
204 .field('licence', attributes.licence.toString()) 238 .field('licence', attributes.licence.toString())
205 .field('nsfw', JSON.stringify(attributes.nsfw)) 239 .field('nsfw', JSON.stringify(attributes.nsfw))
206 .field('description', attributes.description) 240 .field('description', attributes.description)
241 .field('privacy', attributes.privacy.toString())
207 .field('channelId', attributes.channelId) 242 .field('channelId', attributes.channelId)
208 243
209 if (attributes.language !== undefined) { 244 if (attributes.language !== undefined) {
@@ -236,6 +271,7 @@ function updateVideo (url: string, accessToken: string, id: number, attributes:
236 if (attributes.nsfw) body['nsfw'] = attributes.nsfw 271 if (attributes.nsfw) body['nsfw'] = attributes.nsfw
237 if (attributes.description) body['description'] = attributes.description 272 if (attributes.description) body['description'] = attributes.description
238 if (attributes.tags) body['tags'] = attributes.tags 273 if (attributes.tags) body['tags'] = attributes.tags
274 if (attributes.privacy) body['privacy'] = attributes.privacy
239 275
240 return request(url) 276 return request(url)
241 .put(path) 277 .put(path)
@@ -274,9 +310,12 @@ export {
274 getVideoDescription, 310 getVideoDescription,
275 getVideoCategories, 311 getVideoCategories,
276 getVideoLicences, 312 getVideoLicences,
313 getVideoPrivacies,
277 getVideoLanguages, 314 getVideoLanguages,
278 getAllVideosListBy, 315 getAllVideosListBy,
316 getMyVideos,
279 getVideo, 317 getVideo,
318 getVideoWithToken,
280 getVideosList, 319 getVideosList,
281 getVideosListPagination, 320 getVideosListPagination,
282 getVideosListSort, 321 getVideosListSort,