diff options
author | Levi Bard <taktaktaktaktaktaktaktaktaktak@gmail.com> | 2020-06-03 09:42:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-03 09:42:07 +0200 |
commit | 3092e9bbb05fe292fd13bc685b89069c3dda55d9 (patch) | |
tree | 42b9d04dd7749e835e09cb912677aaad21333a5d /server | |
parent | 78646451c9896db3c2239270cd7e100305749f41 (diff) | |
download | PeerTube-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
Diffstat (limited to 'server')
-rw-r--r-- | server/helpers/video.ts | 20 | ||||
-rw-r--r-- | server/initializers/checker-before-init.ts | 3 | ||||
-rw-r--r-- | server/initializers/config.ts | 5 | ||||
-rw-r--r-- | server/models/video/video.ts | 16 | ||||
-rw-r--r-- | server/tests/api/videos/video-privacy.ts | 51 |
5 files changed, 75 insertions, 20 deletions
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 { | |||
15 | import { Response } from 'express' | 15 | import { Response } from 'express' |
16 | import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants' | 16 | import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants' |
17 | import { JobQueue } from '@server/lib/job-queue' | 17 | import { JobQueue } from '@server/lib/job-queue' |
18 | import { VideoTranscodingPayload } from '@shared/models' | 18 | import { VideoPrivacy, VideoTranscodingPayload } from '@shared/models' |
19 | import { CONFIG } from "@server/initializers/config" | ||
19 | 20 | ||
20 | type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes' | 21 | type 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 | ||
100 | function 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 | |||
107 | function getPrivaciesForFederation () { | ||
108 | return (CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true) | ||
109 | ? [ { privacy: VideoPrivacy.PUBLIC }, { privacy: VideoPrivacy.UNLISTED } ] | ||
110 | : [ { privacy: VideoPrivacy.PUBLIC } ] | ||
111 | } | ||
112 | |||
99 | export { | 113 | export { |
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' | |||
126 | import { buildListQuery, BuildVideosQueryOptions, wrapForAPIResults } from './video-query-builder' | 126 | import { buildListQuery, BuildVideosQueryOptions, wrapForAPIResults } from './video-query-builder' |
127 | import { buildNSFWFilter } from '@server/helpers/express-utils' | 127 | import { buildNSFWFilter } from '@server/helpers/express-utils' |
128 | import { getServerActor } from '@server/models/application/application' | 128 | import { getServerActor } from '@server/models/application/application' |
129 | import { getPrivaciesForFederation, isPrivacyForFederation } from "@server/helpers/video" | ||
129 | 130 | ||
130 | export enum ScopeNames { | 131 | export 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' | |||
5 | import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' | 5 | import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum' |
6 | import { | 6 | import { |
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' | |||
22 | const expect = chai.expect | 22 | const expect = chai.expect |
23 | 23 | ||
24 | describe('Test video privacy', function () { | 24 | describe('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') |