diff --git a/CHANGELOG.md b/CHANGELOG.md index b9535fa94..d119d3d73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## v6.0.3 + +### IMPORTANT NOTES + + * If you upgrade from PeerTube **< v6.0.0**, please follow v6.0.0 IMPORTANT NOTES + * If you upgrade from PeerTube **v6.0.0**, please follow v6.0.1 IMPORTANT NOTES + +### SECURITY + + * Prevent nginx from serving private/internal/password protected HLS video static files + * You must update your nginx configuration like in [this commit](https://github.com/Chocobozzz/PeerTube/commit/12ea8f0dd11e3fb5fbb8955f5b7d52f27332d619#diff-be9f96b9b1de67284047e610821493f9a5bec86bfcdf81a7d8d6e7904474c186) (line `202` replace `location ~ ^(/static/(webseed|web-videos|streaming-playlists)/private/)|^/download {` by `location ~ ^(/static/(webseed|web-videos|streaming-playlists/hls)/private/)|^/download {`) + +### Bug fixes + + * Fix HTML meta tags with attributes that contain quotes + * Fix time parsing resulting in broken video start time in some cases + * Fix WebTorrent video import crash + * Reload *Discover* page on logout + * Fix privacy error when updating a live, even if the privacy has not changed + * Fix invalid remote live state change notification that causes the player to reload + * Don't apply big play button skin to settings menu + * Fix downloading video files from object storage with some video names (that include emojis, quotes etc) + * Fix thumbnail generation when ffmpeg cannot seek the input + * Fix theme colors on stats page + * Fix input mask (used for chapters, playlist timecodes...) with 10h+ videos + * Fix chapter *position* width consistency + * Fix player ratio with audio only videos + * Also update video playlist URLs when using `update-host` script + * Fix upload/import/update of videos that contain multiple chapters with the same timecode + + ## v6.0.2 ### IMPORTANT NOTES diff --git a/client/package.json b/client/package.json index 26037a7cd..d49df4173 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "peertube-client", - "version": "6.0.2", + "version": "6.0.3", "private": true, "license": "AGPL-3.0", "author": { diff --git a/package.json b/package.json index 572218a44..decfc6529 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "peertube", "description": "PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.", - "version": "6.0.2", + "version": "6.0.3", "private": true, "licence": "AGPL-3.0", "engines": { diff --git a/packages/tests/src/nginx.ts b/packages/tests/src/nginx.ts new file mode 100644 index 000000000..b9cdbad8e --- /dev/null +++ b/packages/tests/src/nginx.ts @@ -0,0 +1,42 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ + +import { HttpStatusCode } from '@peertube/peertube-models' +import { + makeRawRequest +} from '@peertube/peertube-server-commands' + +describe('Test nginx', function () { + + it('Should serve public HLS/web video files', async function () { + const urls = [ + // eslint-disable-next-line max-len + 'https://peertube2.cpy.re/static/streaming-playlists/hls/85c8e811-3eb7-4823-8dc5-3c268b6dad60/efad77e7-805d-4b20-8bc9-6e99cee38b20-240-fragmented.mp4', + // eslint-disable-next-line max-len + 'https://peertube2.cpy.re/static/streaming-playlists/hls/85c8e811-3eb7-4823-8dc5-3c268b6dad60/1afbabfa-5f16-452e-8165-fe9a9a21cdb2-master.m3u8', + // eslint-disable-next-line max-len + 'https://peertube2.cpy.re/static/streaming-playlists/hls/85c8e811-3eb7-4823-8dc5-3c268b6dad60/efad77e7-805d-4b20-8bc9-6e99cee38b20-240.m3u8' + ] + + for (const url of urls) { + await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 }) + } + }) + + it('Should not serve private HLS/web video files', async function () { + const urls = [ + // eslint-disable-next-line max-len + 'https://peertube2.cpy.re/static/streaming-playlists/hls/private/72f0e8ee-84b9-44b1-9202-3e72ee7f1b65/531f27fe-bb86-42ed-9cf1-eb5bffc4a609-master.m3u8', + // eslint-disable-next-line max-len + 'https://peertube2.cpy.re/static/streaming-playlists/hls/private/72f0e8ee-84b9-44b1-9202-3e72ee7f1b65/057dbf01-0557-414c-a546-a1cc82ac5d99-480.m3u8', + // eslint-disable-next-line max-len + 'https://peertube2.cpy.re/static/streaming-playlists/hls/private/72f0e8ee-84b9-44b1-9202-3e72ee7f1b65/c9ef3aa7-5ab6-41c5-91c2-058c50a70c3c-segments-sha256.json', + // eslint-disable-next-line max-len + 'https://peertube2.cpy.re/static/streaming-playlists/hls/private/72f0e8ee-84b9-44b1-9202-3e72ee7f1b65/057dbf01-0557-414c-a546-a1cc82ac5d99-480-fragmented.mp4', + 'https://peertube2.cpy.re/static/web-videos/private/72f0e8ee-84b9-44b1-9202-3e72ee7f1b65-480.mp4' + ] + + for (const url of urls) { + await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) + } + }) +}) diff --git a/scripts/ci.sh b/scripts/ci.sh index 9544daf91..3d29b7ae9 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -59,7 +59,7 @@ elif [ "$1" = "client" ]; then feedsFiles=$(findTestFiles ./packages/tests/dist/feeds) clientFiles=$(findTestFiles ./packages/tests/dist/client) - miscFiles="./packages/tests/dist/misc-endpoints.js" + miscFiles="./packages/tests/dist/misc-endpoints.js ./packages/tests/dist/nginx.js" # Not in their own task, they need an index.html pluginFiles="./packages/tests/dist/plugins/html-injection.js ./packages/tests/dist/api/server/plugins.js" diff --git a/server/core/lib/video-chapters.ts b/server/core/lib/video-chapters.ts index 71e2a7cf4..740493f4a 100644 --- a/server/core/lib/video-chapters.ts +++ b/server/core/lib/video-chapters.ts @@ -79,12 +79,18 @@ async function createChapters (options: { }) { const { chapters, transaction, videoId } = options + const existingTimecodes = new Set() + for (const chapter of chapters) { + if (existingTimecodes.has(chapter.timecode)) continue + await VideoChapterModel.create({ title: chapter.title, timecode: chapter.timecode, videoId }, { transaction }) + + existingTimecodes.add(chapter.timecode) } } diff --git a/support/nginx/peertube b/support/nginx/peertube index d5cf89e56..ba4388883 100644 --- a/support/nginx/peertube +++ b/support/nginx/peertube @@ -199,7 +199,7 @@ server { alias /var/www/peertube/peertube-latest/client/dist/$1; } - location ~ ^(/static/(webseed|web-videos|streaming-playlists)/private/)|^/download { + location ~ ^(/static/(webseed|web-videos|streaming-playlists/hls)/private/)|^/download { # We can't rate limit a try_files directive, so we need to duplicate @api proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;