aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLevi Bard <taktaktaktaktaktaktaktaktaktak@gmail.com>2020-06-03 09:42:07 +0200
committerGitHub <noreply@github.com>2020-06-03 09:42:07 +0200
commit3092e9bbb05fe292fd13bc685b89069c3dda55d9 (patch)
tree42b9d04dd7749e835e09cb912677aaad21333a5d
parent78646451c9896db3c2239270cd7e100305749f41 (diff)
downloadPeerTube-3092e9bbb05fe292fd13bc685b89069c3dda55d9.tar.gz
PeerTube-3092e9bbb05fe292fd13bc685b89069c3dda55d9.tar.zst
PeerTube-3092e9bbb05fe292fd13bc685b89069c3dda55d9.zip
Make federation of unlisted videos an instance-level server preference (#2802)
* Add preference for federating unlisted videos * Connect unlisted video federation with new preference * Apply pull request feedback * Fix lint issues * Remove preference for federating unlisted videos from web admin interface
-rw-r--r--config/default.yaml4
-rw-r--r--config/production.yaml.example4
-rw-r--r--server/helpers/video.ts20
-rw-r--r--server/initializers/checker-before-init.ts3
-rw-r--r--server/initializers/config.ts5
-rw-r--r--server/models/video/video.ts16
-rw-r--r--server/tests/api/videos/video-privacy.ts51
7 files changed, 83 insertions, 20 deletions
diff --git a/config/default.yaml b/config/default.yaml
index 34a0a146f..f6e944298 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -178,6 +178,10 @@ plugins:
178 check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions 178 check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions
179 url: 'https://packages.joinpeertube.org' 179 url: 'https://packages.joinpeertube.org'
180 180
181federation:
182 videos:
183 federate_unlisted: true
184
181cache: 185cache:
182 previews: 186 previews:
183 size: 500 # Max number of previews you want to cache 187 size: 500 # Max number of previews you want to cache
diff --git a/config/production.yaml.example b/config/production.yaml.example
index 0ac05c515..e21528821 100644
--- a/config/production.yaml.example
+++ b/config/production.yaml.example
@@ -179,6 +179,10 @@ plugins:
179 check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions 179 check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions
180 url: 'https://packages.joinpeertube.org' 180 url: 'https://packages.joinpeertube.org'
181 181
182federation:
183 videos:
184 federate_unlisted: true
185
182 186
183############################################################################### 187###############################################################################
184# 188#
diff --git a/server/helpers/video.ts b/server/helpers/video.ts
index 6f76cbdfc..4bcc6d0b9 100644
--- a/server/helpers/video.ts
+++ b/server/helpers/video.ts
@@ -15,7 +15,8 @@ import {
15import { Response } from 'express' 15import { Response } from 'express'
16import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants' 16import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants'
17import { JobQueue } from '@server/lib/job-queue' 17import { JobQueue } from '@server/lib/job-queue'
18import { VideoTranscodingPayload } from '@shared/models' 18import { VideoPrivacy, VideoTranscodingPayload } from '@shared/models'
19import { CONFIG } from "@server/initializers/config"
19 20
20type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes' 21type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes'
21 22
@@ -96,6 +97,19 @@ function extractVideo (videoOrPlaylist: MVideo | MStreamingPlaylistVideo) {
96 : videoOrPlaylist 97 : videoOrPlaylist
97} 98}
98 99
100function isPrivacyForFederation (privacy: VideoPrivacy) {
101 const castedPrivacy = parseInt(privacy + '', 10)
102
103 return castedPrivacy === VideoPrivacy.PUBLIC ||
104 (CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true && castedPrivacy === VideoPrivacy.UNLISTED)
105}
106
107function getPrivaciesForFederation () {
108 return (CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true)
109 ? [ { privacy: VideoPrivacy.PUBLIC }, { privacy: VideoPrivacy.UNLISTED } ]
110 : [ { privacy: VideoPrivacy.PUBLIC } ]
111}
112
99export { 113export {
100 VideoFetchType, 114 VideoFetchType,
101 VideoFetchByUrlType, 115 VideoFetchByUrlType,
@@ -103,5 +117,7 @@ export {
103 getVideoWithAttributes, 117 getVideoWithAttributes,
104 fetchVideoByUrl, 118 fetchVideoByUrl,
105 addOptimizeOrMergeAudioJob, 119 addOptimizeOrMergeAudioJob,
106 extractVideo 120 extractVideo,
121 isPrivacyForFederation,
122 getPrivaciesForFederation
107} 123}
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts
index 56f8156c6..bd8f02bc0 100644
--- a/server/initializers/checker-before-init.ts
+++ b/server/initializers/checker-before-init.ts
@@ -34,7 +34,8 @@ function checkMissedConfig () {
34 'history.videos.max_age', 'views.videos.remote.max_age', 34 'history.videos.max_age', 'views.videos.remote.max_age',
35 'rates_limit.login.window', 'rates_limit.login.max', 'rates_limit.ask_send_email.window', 'rates_limit.ask_send_email.max', 35 'rates_limit.login.window', 'rates_limit.login.max', 'rates_limit.ask_send_email.window', 'rates_limit.ask_send_email.max',
36 'theme.default', 36 'theme.default',
37 'remote_redundancy.videos.accept_from' 37 'remote_redundancy.videos.accept_from',
38 'federation.videos.federate_unlisted'
38 ] 39 ]
39 const requiredAlternatives = [ 40 const requiredAlternatives = [
40 [ // set 41 [ // set
diff --git a/server/initializers/config.ts b/server/initializers/config.ts
index e2920ce9e..44fd9045b 100644
--- a/server/initializers/config.ts
+++ b/server/initializers/config.ts
@@ -155,6 +155,11 @@ const CONFIG = {
155 URL: config.get<string>('plugins.index.url') 155 URL: config.get<string>('plugins.index.url')
156 } 156 }
157 }, 157 },
158 FEDERATION: {
159 VIDEOS: {
160 FEDERATE_UNLISTED: config.get<boolean>('federation.videos.federate_unlisted')
161 }
162 },
158 ADMIN: { 163 ADMIN: {
159 get EMAIL () { return config.get<string>('admin.email') } 164 get EMAIL () { return config.get<string>('admin.email') }
160 }, 165 },
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index f5194e259..02a4c851c 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -126,6 +126,7 @@ import { ModelCache } from '@server/models/model-cache'
126import { buildListQuery, BuildVideosQueryOptions, wrapForAPIResults } from './video-query-builder' 126import { buildListQuery, BuildVideosQueryOptions, wrapForAPIResults } from './video-query-builder'
127import { buildNSFWFilter } from '@server/helpers/express-utils' 127import { buildNSFWFilter } from '@server/helpers/express-utils'
128import { getServerActor } from '@server/models/application/application' 128import { getServerActor } from '@server/models/application/application'
129import { getPrivaciesForFederation, isPrivacyForFederation } from "@server/helpers/video"
129 130
130export enum ScopeNames { 131export enum ScopeNames {
131 AVAILABLE_FOR_LIST_IDS = 'AVAILABLE_FOR_LIST_IDS', 132 AVAILABLE_FOR_LIST_IDS = 'AVAILABLE_FOR_LIST_IDS',
@@ -864,10 +865,7 @@ export class VideoModel extends Model<VideoModel> {
864 id: { 865 id: {
865 [Op.in]: Sequelize.literal('(' + rawQuery + ')') 866 [Op.in]: Sequelize.literal('(' + rawQuery + ')')
866 }, 867 },
867 [Op.or]: [ 868 [Op.or]: getPrivaciesForFederation()
868 { privacy: VideoPrivacy.PUBLIC },
869 { privacy: VideoPrivacy.UNLISTED }
870 ]
871 }, 869 },
872 include: [ 870 include: [
873 { 871 {
@@ -1582,12 +1580,6 @@ export class VideoModel extends Model<VideoModel> {
1582 return videos 1580 return videos
1583 } 1581 }
1584 1582
1585 private static isPrivacyForFederation (privacy: VideoPrivacy) {
1586 const castedPrivacy = parseInt(privacy + '', 10)
1587
1588 return castedPrivacy === VideoPrivacy.PUBLIC || castedPrivacy === VideoPrivacy.UNLISTED
1589 }
1590
1591 static getCategoryLabel (id: number) { 1583 static getCategoryLabel (id: number) {
1592 return VIDEO_CATEGORIES[id] || 'Misc' 1584 return VIDEO_CATEGORIES[id] || 'Misc'
1593 } 1585 }
@@ -1813,11 +1805,11 @@ export class VideoModel extends Model<VideoModel> {
1813 } 1805 }
1814 1806
1815 hasPrivacyForFederation () { 1807 hasPrivacyForFederation () {
1816 return VideoModel.isPrivacyForFederation(this.privacy) 1808 return isPrivacyForFederation(this.privacy)
1817 } 1809 }
1818 1810
1819 isNewVideo (newPrivacy: VideoPrivacy) { 1811 isNewVideo (newPrivacy: VideoPrivacy) {
1820 return this.hasPrivacyForFederation() === false && VideoModel.isPrivacyForFederation(newPrivacy) === true 1812 return this.hasPrivacyForFederation() === false && isPrivacyForFederation(newPrivacy) === true
1821 } 1813 }
1822 1814
1823 setAsRefreshed () { 1815 setAsRefreshed () {
diff --git a/server/tests/api/videos/video-privacy.ts b/server/tests/api/videos/video-privacy.ts
index 4bbbb90f3..38e93bbe6 100644
--- a/server/tests/api/videos/video-privacy.ts
+++ b/server/tests/api/videos/video-privacy.ts
@@ -5,7 +5,7 @@ import 'mocha'
5import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' 5import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
8 flushAndRunMultipleServers, 8 flushAndRunServer,
9 getVideosList, 9 getVideosList,
10 getVideosListWithToken, 10 getVideosListWithToken,
11 ServerInfo, 11 ServerInfo,
@@ -22,7 +22,7 @@ import { Video } from '@shared/models'
22const expect = chai.expect 22const expect = chai.expect
23 23
24describe('Test video privacy', function () { 24describe('Test video privacy', function () {
25 let servers: ServerInfo[] = [] 25 const servers: ServerInfo[] = []
26 let anotherUserToken: string 26 let anotherUserToken: string
27 27
28 let privateVideoId: number 28 let privateVideoId: number
@@ -32,14 +32,24 @@ describe('Test video privacy', function () {
32 let internalVideoUUID: string 32 let internalVideoUUID: string
33 33
34 let unlistedVideoUUID: string 34 let unlistedVideoUUID: string
35 let nonFederatedUnlistedVideoUUID: string
35 36
36 let now: number 37 let now: number
37 38
39 const dontFederateUnlistedConfig = {
40 federation: {
41 videos: {
42 federate_unlisted: false
43 }
44 }
45 }
46
38 before(async function () { 47 before(async function () {
39 this.timeout(50000) 48 this.timeout(50000)
40 49
41 // Run servers 50 // Run servers
42 servers = await flushAndRunMultipleServers(2) 51 servers.push(await flushAndRunServer(1, dontFederateUnlistedConfig))
52 servers.push(await flushAndRunServer(2))
43 53
44 // Get the access tokens 54 // Get the access tokens
45 await setAccessTokensToServers(servers) 55 await setAccessTokensToServers(servers)
@@ -164,6 +174,37 @@ describe('Test video privacy', function () {
164 } 174 }
165 }) 175 })
166 176
177 it('Should upload a non-federating unlisted video to server 1', async function () {
178 this.timeout(30000)
179
180 const attributes = {
181 name: 'unlisted video',
182 privacy: VideoPrivacy.UNLISTED
183 }
184 await uploadVideo(servers[0].url, servers[0].accessToken, attributes)
185
186 await waitJobs(servers)
187 })
188
189 it('Should list my new unlisted video', async function () {
190 const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 3)
191
192 expect(res.body.total).to.equal(3)
193 expect(res.body.data).to.have.lengthOf(3)
194
195 nonFederatedUnlistedVideoUUID = res.body.data[0].uuid
196 })
197
198 it('Should be able to get non-federated unlisted video from origin', async function () {
199 const res = await getVideo(servers[0].url, nonFederatedUnlistedVideoUUID)
200
201 expect(res.body.name).to.equal('unlisted video')
202 })
203
204 it('Should not be able to get non-federated unlisted video from federated server', async function () {
205 await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, 404)
206 })
207
167 it('Should update the private and internal videos to public on server 1', async function () { 208 it('Should update the private and internal videos to public on server 1', async function () {
168 this.timeout(10000) 209 this.timeout(10000)
169 210
@@ -230,8 +271,8 @@ describe('Test video privacy', function () {
230 const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5) 271 const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5)
231 const videos = res.body.data 272 const videos = res.body.data
232 273
233 expect(res.body.total).to.equal(2) 274 expect(res.body.total).to.equal(3)
234 expect(videos).to.have.lengthOf(2) 275 expect(videos).to.have.lengthOf(3)
235 276
236 const privateVideo = videos.find(v => v.name === 'private video becomes public') 277 const privateVideo = videos.find(v => v.name === 'private video becomes public')
237 const internalVideo = videos.find(v => v.name === 'internal video becomes public') 278 const internalVideo = videos.find(v => v.name === 'internal video becomes public')