aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--config/production.yaml.example2
-rw-r--r--config/test-1.yaml2
-rw-r--r--config/test-2.yaml2
-rw-r--r--config/test-3.yaml2
-rw-r--r--config/test-4.yaml2
-rw-r--r--config/test-5.yaml2
-rw-r--r--config/test-6.yaml2
-rw-r--r--server/controllers/activitypub/client.ts2
-rw-r--r--server/controllers/api/users/my-video-playlists.ts2
-rw-r--r--server/middlewares/validators/videos/video-playlists.ts5
-rw-r--r--server/models/video/video-playlist.ts5
-rw-r--r--server/tests/api/check-params/video-playlists.ts46
-rw-r--r--server/tests/api/redundancy/redundancy.ts4
-rw-r--r--server/tests/api/videos/video-hls.ts6
-rw-r--r--server/tests/api/videos/video-playlists.ts42
-rw-r--r--shared/utils/videos/video-playlists.ts16
16 files changed, 121 insertions, 21 deletions
diff --git a/config/production.yaml.example b/config/production.yaml.example
index c227d5fcc..306e5576d 100644
--- a/config/production.yaml.example
+++ b/config/production.yaml.example
@@ -49,7 +49,7 @@ storage:
49 tmp: '/var/www/peertube/storage/tmp/' # Used to download data (imports etc), store uploaded files before processing... 49 tmp: '/var/www/peertube/storage/tmp/' # Used to download data (imports etc), store uploaded files before processing...
50 avatars: '/var/www/peertube/storage/avatars/' 50 avatars: '/var/www/peertube/storage/avatars/'
51 videos: '/var/www/peertube/storage/videos/' 51 videos: '/var/www/peertube/storage/videos/'
52 playlists: '/var/www/peertube/storage/playlists/' 52 streaming_playlists: '/var/www/peertube/storage/streaming-playlists/'
53 redundancy: '/var/www/peertube/storage/videos/' 53 redundancy: '/var/www/peertube/storage/videos/'
54 logs: '/var/www/peertube/storage/logs/' 54 logs: '/var/www/peertube/storage/logs/'
55 previews: '/var/www/peertube/storage/previews/' 55 previews: '/var/www/peertube/storage/previews/'
diff --git a/config/test-1.yaml b/config/test-1.yaml
index fb69818f3..413390ecd 100644
--- a/config/test-1.yaml
+++ b/config/test-1.yaml
@@ -13,7 +13,7 @@ storage:
13 tmp: 'test1/tmp/' 13 tmp: 'test1/tmp/'
14 avatars: 'test1/avatars/' 14 avatars: 'test1/avatars/'
15 videos: 'test1/videos/' 15 videos: 'test1/videos/'
16 playlists: 'test1/playlists/' 16 streaming_playlists: 'test1/streaming-playlists/'
17 redundancy: 'test1/redundancy/' 17 redundancy: 'test1/redundancy/'
18 logs: 'test1/logs/' 18 logs: 'test1/logs/'
19 previews: 'test1/previews/' 19 previews: 'test1/previews/'
diff --git a/config/test-2.yaml b/config/test-2.yaml
index 5caddaaa8..a5515afa4 100644
--- a/config/test-2.yaml
+++ b/config/test-2.yaml
@@ -13,7 +13,7 @@ storage:
13 tmp: 'test2/tmp/' 13 tmp: 'test2/tmp/'
14 avatars: 'test2/avatars/' 14 avatars: 'test2/avatars/'
15 videos: 'test2/videos/' 15 videos: 'test2/videos/'
16 playlists: 'test2/playlists/' 16 streaming_playlists: 'test2/streaming-playlists/'
17 redundancy: 'test2/redundancy/' 17 redundancy: 'test2/redundancy/'
18 logs: 'test2/logs/' 18 logs: 'test2/logs/'
19 previews: 'test2/previews/' 19 previews: 'test2/previews/'
diff --git a/config/test-3.yaml b/config/test-3.yaml
index fac7ebee1..ef6780328 100644
--- a/config/test-3.yaml
+++ b/config/test-3.yaml
@@ -13,7 +13,7 @@ storage:
13 tmp: 'test3/tmp/' 13 tmp: 'test3/tmp/'
14 avatars: 'test3/avatars/' 14 avatars: 'test3/avatars/'
15 videos: 'test3/videos/' 15 videos: 'test3/videos/'
16 playlists: 'test3/playlists/' 16 streaming_playlists: 'test3/streaming-playlists/'
17 redundancy: 'test3/redundancy/' 17 redundancy: 'test3/redundancy/'
18 logs: 'test3/logs/' 18 logs: 'test3/logs/'
19 previews: 'test3/previews/' 19 previews: 'test3/previews/'
diff --git a/config/test-4.yaml b/config/test-4.yaml
index 33033773a..e84b2d118 100644
--- a/config/test-4.yaml
+++ b/config/test-4.yaml
@@ -13,7 +13,7 @@ storage:
13 tmp: 'test4/tmp/' 13 tmp: 'test4/tmp/'
14 avatars: 'test4/avatars/' 14 avatars: 'test4/avatars/'
15 videos: 'test4/videos/' 15 videos: 'test4/videos/'
16 playlists: 'test4/playlists/' 16 streaming_playlists: 'test4/streaming-playlists/'
17 redundancy: 'test4/redundancy/' 17 redundancy: 'test4/redundancy/'
18 logs: 'test4/logs/' 18 logs: 'test4/logs/'
19 previews: 'test4/previews/' 19 previews: 'test4/previews/'
diff --git a/config/test-5.yaml b/config/test-5.yaml
index d365b6f2b..e25d4cfee 100644
--- a/config/test-5.yaml
+++ b/config/test-5.yaml
@@ -13,7 +13,7 @@ storage:
13 tmp: 'test5/tmp/' 13 tmp: 'test5/tmp/'
14 avatars: 'test5/avatars/' 14 avatars: 'test5/avatars/'
15 videos: 'test5/videos/' 15 videos: 'test5/videos/'
16 playlists: 'test5/playlists/' 16 streaming_playlists: 'test5/streaming-playlists/'
17 redundancy: 'test5/redundancy/' 17 redundancy: 'test5/redundancy/'
18 logs: 'test5/logs/' 18 logs: 'test5/logs/'
19 previews: 'test5/previews/' 19 previews: 'test5/previews/'
diff --git a/config/test-6.yaml b/config/test-6.yaml
index 44541c003..a020fe869 100644
--- a/config/test-6.yaml
+++ b/config/test-6.yaml
@@ -13,7 +13,7 @@ storage:
13 tmp: 'test6/tmp/' 13 tmp: 'test6/tmp/'
14 avatars: 'test6/avatars/' 14 avatars: 'test6/avatars/'
15 videos: 'test6/videos/' 15 videos: 'test6/videos/'
16 playlists: 'test6/playlists/' 16 streaming_playlists: 'test6/streaming-playlists/'
17 redundancy: 'test6/redundancy/' 17 redundancy: 'test6/redundancy/'
18 logs: 'test6/logs/' 18 logs: 'test6/logs/'
19 previews: 'test6/previews/' 19 previews: 'test6/previews/'
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts
index 0d1dff96f..f1217f6db 100644
--- a/server/controllers/activitypub/client.ts
+++ b/server/controllers/activitypub/client.ts
@@ -357,7 +357,7 @@ async function actorFollowers (req: express.Request, actor: ActorModel) {
357 357
358async function actorPlaylists (req: express.Request, account: AccountModel) { 358async function actorPlaylists (req: express.Request, account: AccountModel) {
359 const handler = (start: number, count: number) => { 359 const handler = (start: number, count: number) => {
360 return VideoPlaylistModel.listUrlsOfForAP(account.id, start, count) 360 return VideoPlaylistModel.listPublicUrlsOfForAP(account.id, start, count)
361 } 361 }
362 362
363 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.path, handler, req.query.page) 363 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.path, handler, req.query.page)
diff --git a/server/controllers/api/users/my-video-playlists.ts b/server/controllers/api/users/my-video-playlists.ts
index 1ec175f64..42da02bff 100644
--- a/server/controllers/api/users/my-video-playlists.ts
+++ b/server/controllers/api/users/my-video-playlists.ts
@@ -22,7 +22,7 @@ export {
22// --------------------------------------------------------------------------- 22// ---------------------------------------------------------------------------
23 23
24async function doVideosInPlaylistExist (req: express.Request, res: express.Response) { 24async function doVideosInPlaylistExist (req: express.Request, res: express.Response) {
25 const videoIds = req.query.videoIds as number[] 25 const videoIds = req.query.videoIds.map(i => parseInt(i + '', 10))
26 const user = res.locals.oauth.token.User as UserModel 26 const user = res.locals.oauth.token.User as UserModel
27 27
28 const results = await VideoPlaylistModel.listPlaylistIdsOf(user.Account.id, videoIds) 28 const results = await VideoPlaylistModel.listPlaylistIdsOf(user.Account.id, videoIds)
diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts
index 87d2c7b51..3bbf796e4 100644
--- a/server/middlewares/validators/videos/video-playlists.ts
+++ b/server/middlewares/validators/videos/video-playlists.ts
@@ -4,9 +4,9 @@ import { UserRight } from '../../../../shared'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { UserModel } from '../../../models/account/user' 5import { UserModel } from '../../../models/account/user'
6import { areValidationErrors } from '../utils' 6import { areValidationErrors } from '../utils'
7import { isVideoExist, isVideoFileInfoHashValid, isVideoImage } from '../../../helpers/custom-validators/videos' 7import { isVideoExist, isVideoImage } from '../../../helpers/custom-validators/videos'
8import { CONSTRAINTS_FIELDS } from '../../../initializers' 8import { CONSTRAINTS_FIELDS } from '../../../initializers'
9import { isArrayOf, isIdOrUUIDValid, isIdValid, isUUIDValid, toArray, toValueOrNull, toIntArray } from '../../../helpers/custom-validators/misc' 9import { isArrayOf, isIdOrUUIDValid, isIdValid, isUUIDValid, toIntArray, toValueOrNull } from '../../../helpers/custom-validators/misc'
10import { 10import {
11 isVideoPlaylistDescriptionValid, 11 isVideoPlaylistDescriptionValid,
12 isVideoPlaylistExist, 12 isVideoPlaylistExist,
@@ -23,7 +23,6 @@ import { VideoModel } from '../../../models/video/video'
23import { authenticatePromiseIfNeeded } from '../../oauth' 23import { authenticatePromiseIfNeeded } from '../../oauth'
24import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model' 24import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model'
25import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model' 25import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model'
26import { areValidActorHandles } from '../../../helpers/custom-validators/activitypub/actor'
27 26
28const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([ 27const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([
29 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 28 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts
index aa42687cd..7dbe4ce8d 100644
--- a/server/models/video/video-playlist.ts
+++ b/server/models/video/video-playlist.ts
@@ -301,13 +301,14 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
301 }) 301 })
302 } 302 }
303 303
304 static listUrlsOfForAP (accountId: number, start: number, count: number) { 304 static listPublicUrlsOfForAP (accountId: number, start: number, count: number) {
305 const query = { 305 const query = {
306 attributes: [ 'url' ], 306 attributes: [ 'url' ],
307 offset: start, 307 offset: start,
308 limit: count, 308 limit: count,
309 where: { 309 where: {
310 ownerAccountId: accountId 310 ownerAccountId: accountId,
311 privacy: VideoPlaylistPrivacy.PUBLIC
311 } 312 }
312 } 313 }
313 314
diff --git a/server/tests/api/check-params/video-playlists.ts b/server/tests/api/check-params/video-playlists.ts
index 803e7afb9..4d8000dbf 100644
--- a/server/tests/api/check-params/video-playlists.ts
+++ b/server/tests/api/check-params/video-playlists.ts
@@ -522,6 +522,52 @@ describe('Test video playlists API validator', function () {
522 }) 522 })
523 }) 523 })
524 524
525 describe('When checking exists in playlist endpoint', function () {
526 const path = '/api/v1/users/me/video-playlists/videos-exist'
527
528 it('Should fail with an unauthenticated user', async function () {
529 await makeGetRequest({
530 url: server.url,
531 path,
532 query: { videoIds: [ 1, 2 ] },
533 statusCodeExpected: 401
534 })
535 })
536
537 it('Should fail with invalid video ids', async function () {
538 await makeGetRequest({
539 url: server.url,
540 token: server.accessToken,
541 path,
542 query: { videoIds: 'toto' }
543 })
544
545 await makeGetRequest({
546 url: server.url,
547 token: server.accessToken,
548 path,
549 query: { videoIds: [ 'toto' ] }
550 })
551
552 await makeGetRequest({
553 url: server.url,
554 token: server.accessToken,
555 path,
556 query: { videoIds: [ 1, 'toto' ] }
557 })
558 })
559
560 it('Should succeed with the correct params', async function () {
561 await makeGetRequest({
562 url: server.url,
563 token: server.accessToken,
564 path,
565 query: { videoIds: [ 1, 2 ] },
566 statusCodeExpected: 200
567 })
568 })
569 })
570
525 describe('When deleting an element in a playlist', function () { 571 describe('When deleting an element in a playlist', function () {
526 const getBase = (wrapper: any = {}) => { 572 const getBase = (wrapper: any = {}) => {
527 return Object.assign({ 573 return Object.assign({
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts
index fc5ffbad7..33921763d 100644
--- a/server/tests/api/redundancy/redundancy.ts
+++ b/server/tests/api/redundancy/redundancy.ts
@@ -184,7 +184,7 @@ async function check1PlaylistRedundancies (videoUUID?: string) {
184 expect(redundancy.baseUrl).to.equal(servers[0].url + '/static/redundancy/hls/' + videoUUID) 184 expect(redundancy.baseUrl).to.equal(servers[0].url + '/static/redundancy/hls/' + videoUUID)
185 } 185 }
186 186
187 const baseUrlPlaylist = servers[1].url + '/static/playlists/hls' 187 const baseUrlPlaylist = servers[1].url + '/static/streaming-playlists/hls'
188 const baseUrlSegment = servers[0].url + '/static/redundancy/hls' 188 const baseUrlSegment = servers[0].url + '/static/redundancy/hls'
189 189
190 const res = await getVideo(servers[0].url, videoUUID) 190 const res = await getVideo(servers[0].url, videoUUID)
@@ -194,7 +194,7 @@ async function check1PlaylistRedundancies (videoUUID?: string) {
194 await checkSegmentHash(baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist) 194 await checkSegmentHash(baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist)
195 } 195 }
196 196
197 for (const directory of [ 'test1/redundancy/hls', 'test2/playlists/hls' ]) { 197 for (const directory of [ 'test1/redundancy/hls', 'test2/streaming-playlists/hls' ]) {
198 const files = await readdir(join(root(), directory, videoUUID)) 198 const files = await readdir(join(root(), directory, videoUUID))
199 expect(files).to.have.length.at.least(4) 199 expect(files).to.have.length.at.least(4)
200 200
diff --git a/server/tests/api/videos/video-hls.ts b/server/tests/api/videos/video-hls.ts
index a1214bad1..3d04758b1 100644
--- a/server/tests/api/videos/video-hls.ts
+++ b/server/tests/api/videos/video-hls.ts
@@ -51,7 +51,7 @@ async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string) {
51 51
52 { 52 {
53 for (const resolution of resolutions) { 53 for (const resolution of resolutions) {
54 const res2 = await getPlaylist(`http://localhost:9001/static/playlists/hls/${videoUUID}/${resolution}.m3u8`) 54 const res2 = await getPlaylist(`http://localhost:9001/static/streaming-playlists/hls/${videoUUID}/${resolution}.m3u8`)
55 55
56 const subPlaylist = res2.text 56 const subPlaylist = res2.text
57 expect(subPlaylist).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`) 57 expect(subPlaylist).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`)
@@ -59,7 +59,7 @@ async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string) {
59 } 59 }
60 60
61 { 61 {
62 const baseUrl = 'http://localhost:9001/static/playlists/hls' 62 const baseUrl = 'http://localhost:9001/static/streaming-playlists/hls'
63 63
64 for (const resolution of resolutions) { 64 for (const resolution of resolutions) {
65 await checkSegmentHash(baseUrl, baseUrl, videoUUID, resolution, hlsPlaylist) 65 await checkSegmentHash(baseUrl, baseUrl, videoUUID, resolution, hlsPlaylist)
@@ -118,7 +118,7 @@ describe('Test HLS videos', function () {
118 it('Should have the playlists/segment deleted from the disk', async function () { 118 it('Should have the playlists/segment deleted from the disk', async function () {
119 for (const server of servers) { 119 for (const server of servers) {
120 await checkDirectoryIsEmpty(server, 'videos') 120 await checkDirectoryIsEmpty(server, 'videos')
121 await checkDirectoryIsEmpty(server, join('playlists', 'hls')) 121 await checkDirectoryIsEmpty(server, join('streaming-playlists', 'hls'))
122 } 122 }
123 }) 123 })
124 124
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
index baa2b3b8c..931491406 100644
--- a/server/tests/api/videos/video-playlists.ts
+++ b/server/tests/api/videos/video-playlists.ts
@@ -10,7 +10,7 @@ import {
10 createVideoPlaylist, 10 createVideoPlaylist,
11 deleteVideoChannel, 11 deleteVideoChannel,
12 deleteVideoPlaylist, 12 deleteVideoPlaylist,
13 doubleFollow, 13 doubleFollow, doVideosExistInMyPlaylist,
14 flushAndRunMultipleServers, 14 flushAndRunMultipleServers,
15 flushTests, 15 flushTests,
16 getAccountPlaylistsList, 16 getAccountPlaylistsList,
@@ -41,6 +41,7 @@ import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/
41import { VideoPlaylist } from '../../../../shared/models/videos/playlist/video-playlist.model' 41import { VideoPlaylist } from '../../../../shared/models/videos/playlist/video-playlist.model'
42import { Video } from '../../../../shared/models/videos' 42import { Video } from '../../../../shared/models/videos'
43import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model' 43import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model'
44import { VideoExistInPlaylist } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
44 45
45const expect = chai.expect 46const expect = chai.expect
46 47
@@ -624,6 +625,45 @@ describe('Test video playlists', function () {
624 } 625 }
625 }) 626 })
626 627
628 it('Should check videos existence in my playlist', async function () {
629 const videoIds = [
630 servers[0].videos[0].id,
631 42000,
632 servers[0].videos[3].id,
633 43000,
634 servers[0].videos[4].id
635 ]
636 const res = await doVideosExistInMyPlaylist(servers[ 0 ].url, servers[ 0 ].accessToken, videoIds)
637 const obj = res.body as VideoExistInPlaylist
638
639 {
640 const elem = obj[servers[0].videos[0].id]
641 expect(elem).to.have.lengthOf(1)
642 expect(elem[ 0 ].playlistId).to.equal(playlistServer1Id)
643 expect(elem[ 0 ].startTimestamp).to.equal(15)
644 expect(elem[ 0 ].stopTimestamp).to.equal(28)
645 }
646
647 {
648 const elem = obj[servers[0].videos[3].id]
649 expect(elem).to.have.lengthOf(1)
650 expect(elem[ 0 ].playlistId).to.equal(playlistServer1Id)
651 expect(elem[ 0 ].startTimestamp).to.equal(1)
652 expect(elem[ 0 ].stopTimestamp).to.equal(35)
653 }
654
655 {
656 const elem = obj[servers[0].videos[4].id]
657 expect(elem).to.have.lengthOf(1)
658 expect(elem[ 0 ].playlistId).to.equal(playlistServer1Id)
659 expect(elem[ 0 ].startTimestamp).to.equal(45)
660 expect(elem[ 0 ].stopTimestamp).to.equal(null)
661 }
662
663 expect(obj[42000]).to.have.lengthOf(0)
664 expect(obj[43000]).to.have.lengthOf(0)
665 })
666
627 it('Should delete some elements', async function () { 667 it('Should delete some elements', async function () {
628 this.timeout(30000) 668 this.timeout(30000)
629 669
diff --git a/shared/utils/videos/video-playlists.ts b/shared/utils/videos/video-playlists.ts
index b84b21623..ad65bec56 100644
--- a/shared/utils/videos/video-playlists.ts
+++ b/shared/utils/videos/video-playlists.ts
@@ -275,6 +275,18 @@ function getVideoPlaylistPrivacies (url: string) {
275 }) 275 })
276} 276}
277 277
278function doVideosExistInMyPlaylist (url: string, token: string, videoIds: number[]) {
279 const path = '/api/v1/users/me/video-playlists/videos-exist'
280
281 return makeGetRequest({
282 url,
283 token,
284 path,
285 query: { videoIds },
286 statusCodeExpected: 200
287 })
288}
289
278// --------------------------------------------------------------------------- 290// ---------------------------------------------------------------------------
279 291
280export { 292export {
@@ -298,5 +310,7 @@ export {
298 310
299 reorderVideosPlaylist, 311 reorderVideosPlaylist,
300 312
301 checkPlaylistFilesWereRemoved 313 checkPlaylistFilesWereRemoved,
314
315 doVideosExistInMyPlaylist
302} 316}