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
This commit is contained in:
parent
78646451c9
commit
3092e9bbb0
|
@ -178,6 +178,10 @@ plugins:
|
||||||
check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions
|
check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions
|
||||||
url: 'https://packages.joinpeertube.org'
|
url: 'https://packages.joinpeertube.org'
|
||||||
|
|
||||||
|
federation:
|
||||||
|
videos:
|
||||||
|
federate_unlisted: true
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
previews:
|
previews:
|
||||||
size: 500 # Max number of previews you want to cache
|
size: 500 # Max number of previews you want to cache
|
||||||
|
|
|
@ -179,6 +179,10 @@ plugins:
|
||||||
check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions
|
check_latest_versions_interval: '12 hours' # How often you want to check new plugins/themes versions
|
||||||
url: 'https://packages.joinpeertube.org'
|
url: 'https://packages.joinpeertube.org'
|
||||||
|
|
||||||
|
federation:
|
||||||
|
videos:
|
||||||
|
federate_unlisted: true
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
|
|
|
@ -15,7 +15,8 @@ import {
|
||||||
import { Response } from 'express'
|
import { Response } from 'express'
|
||||||
import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants'
|
import { DEFAULT_AUDIO_RESOLUTION } from '@server/initializers/constants'
|
||||||
import { JobQueue } from '@server/lib/job-queue'
|
import { JobQueue } from '@server/lib/job-queue'
|
||||||
import { VideoTranscodingPayload } from '@shared/models'
|
import { VideoPrivacy, VideoTranscodingPayload } from '@shared/models'
|
||||||
|
import { CONFIG } from "@server/initializers/config"
|
||||||
|
|
||||||
type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes'
|
type VideoFetchType = 'all' | 'only-video' | 'only-video-with-rights' | 'id' | 'none' | 'only-immutable-attributes'
|
||||||
|
|
||||||
|
@ -96,6 +97,19 @@ function extractVideo (videoOrPlaylist: MVideo | MStreamingPlaylistVideo) {
|
||||||
: videoOrPlaylist
|
: videoOrPlaylist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPrivacyForFederation (privacy: VideoPrivacy) {
|
||||||
|
const castedPrivacy = parseInt(privacy + '', 10)
|
||||||
|
|
||||||
|
return castedPrivacy === VideoPrivacy.PUBLIC ||
|
||||||
|
(CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true && castedPrivacy === VideoPrivacy.UNLISTED)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrivaciesForFederation () {
|
||||||
|
return (CONFIG.FEDERATION.VIDEOS.FEDERATE_UNLISTED === true)
|
||||||
|
? [ { privacy: VideoPrivacy.PUBLIC }, { privacy: VideoPrivacy.UNLISTED } ]
|
||||||
|
: [ { privacy: VideoPrivacy.PUBLIC } ]
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
VideoFetchType,
|
VideoFetchType,
|
||||||
VideoFetchByUrlType,
|
VideoFetchByUrlType,
|
||||||
|
@ -103,5 +117,7 @@ export {
|
||||||
getVideoWithAttributes,
|
getVideoWithAttributes,
|
||||||
fetchVideoByUrl,
|
fetchVideoByUrl,
|
||||||
addOptimizeOrMergeAudioJob,
|
addOptimizeOrMergeAudioJob,
|
||||||
extractVideo
|
extractVideo,
|
||||||
|
isPrivacyForFederation,
|
||||||
|
getPrivaciesForFederation
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,8 @@ function checkMissedConfig () {
|
||||||
'history.videos.max_age', 'views.videos.remote.max_age',
|
'history.videos.max_age', 'views.videos.remote.max_age',
|
||||||
'rates_limit.login.window', 'rates_limit.login.max', 'rates_limit.ask_send_email.window', 'rates_limit.ask_send_email.max',
|
'rates_limit.login.window', 'rates_limit.login.max', 'rates_limit.ask_send_email.window', 'rates_limit.ask_send_email.max',
|
||||||
'theme.default',
|
'theme.default',
|
||||||
'remote_redundancy.videos.accept_from'
|
'remote_redundancy.videos.accept_from',
|
||||||
|
'federation.videos.federate_unlisted'
|
||||||
]
|
]
|
||||||
const requiredAlternatives = [
|
const requiredAlternatives = [
|
||||||
[ // set
|
[ // set
|
||||||
|
|
|
@ -155,6 +155,11 @@ const CONFIG = {
|
||||||
URL: config.get<string>('plugins.index.url')
|
URL: config.get<string>('plugins.index.url')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
FEDERATION: {
|
||||||
|
VIDEOS: {
|
||||||
|
FEDERATE_UNLISTED: config.get<boolean>('federation.videos.federate_unlisted')
|
||||||
|
}
|
||||||
|
},
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
get EMAIL () { return config.get<string>('admin.email') }
|
get EMAIL () { return config.get<string>('admin.email') }
|
||||||
},
|
},
|
||||||
|
|
|
@ -126,6 +126,7 @@ import { ModelCache } from '@server/models/model-cache'
|
||||||
import { buildListQuery, BuildVideosQueryOptions, wrapForAPIResults } from './video-query-builder'
|
import { buildListQuery, BuildVideosQueryOptions, wrapForAPIResults } from './video-query-builder'
|
||||||
import { buildNSFWFilter } from '@server/helpers/express-utils'
|
import { buildNSFWFilter } from '@server/helpers/express-utils'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
|
import { getPrivaciesForFederation, isPrivacyForFederation } from "@server/helpers/video"
|
||||||
|
|
||||||
export enum ScopeNames {
|
export enum ScopeNames {
|
||||||
AVAILABLE_FOR_LIST_IDS = 'AVAILABLE_FOR_LIST_IDS',
|
AVAILABLE_FOR_LIST_IDS = 'AVAILABLE_FOR_LIST_IDS',
|
||||||
|
@ -864,10 +865,7 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
id: {
|
id: {
|
||||||
[Op.in]: Sequelize.literal('(' + rawQuery + ')')
|
[Op.in]: Sequelize.literal('(' + rawQuery + ')')
|
||||||
},
|
},
|
||||||
[Op.or]: [
|
[Op.or]: getPrivaciesForFederation()
|
||||||
{ privacy: VideoPrivacy.PUBLIC },
|
|
||||||
{ privacy: VideoPrivacy.UNLISTED }
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
|
@ -1582,12 +1580,6 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
return videos
|
return videos
|
||||||
}
|
}
|
||||||
|
|
||||||
private static isPrivacyForFederation (privacy: VideoPrivacy) {
|
|
||||||
const castedPrivacy = parseInt(privacy + '', 10)
|
|
||||||
|
|
||||||
return castedPrivacy === VideoPrivacy.PUBLIC || castedPrivacy === VideoPrivacy.UNLISTED
|
|
||||||
}
|
|
||||||
|
|
||||||
static getCategoryLabel (id: number) {
|
static getCategoryLabel (id: number) {
|
||||||
return VIDEO_CATEGORIES[id] || 'Misc'
|
return VIDEO_CATEGORIES[id] || 'Misc'
|
||||||
}
|
}
|
||||||
|
@ -1813,11 +1805,11 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPrivacyForFederation () {
|
hasPrivacyForFederation () {
|
||||||
return VideoModel.isPrivacyForFederation(this.privacy)
|
return isPrivacyForFederation(this.privacy)
|
||||||
}
|
}
|
||||||
|
|
||||||
isNewVideo (newPrivacy: VideoPrivacy) {
|
isNewVideo (newPrivacy: VideoPrivacy) {
|
||||||
return this.hasPrivacyForFederation() === false && VideoModel.isPrivacyForFederation(newPrivacy) === true
|
return this.hasPrivacyForFederation() === false && isPrivacyForFederation(newPrivacy) === true
|
||||||
}
|
}
|
||||||
|
|
||||||
setAsRefreshed () {
|
setAsRefreshed () {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'mocha'
|
||||||
import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
|
import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enum'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunServer,
|
||||||
getVideosList,
|
getVideosList,
|
||||||
getVideosListWithToken,
|
getVideosListWithToken,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
|
@ -22,7 +22,7 @@ import { Video } from '@shared/models'
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
describe('Test video privacy', function () {
|
describe('Test video privacy', function () {
|
||||||
let servers: ServerInfo[] = []
|
const servers: ServerInfo[] = []
|
||||||
let anotherUserToken: string
|
let anotherUserToken: string
|
||||||
|
|
||||||
let privateVideoId: number
|
let privateVideoId: number
|
||||||
|
@ -32,14 +32,24 @@ describe('Test video privacy', function () {
|
||||||
let internalVideoUUID: string
|
let internalVideoUUID: string
|
||||||
|
|
||||||
let unlistedVideoUUID: string
|
let unlistedVideoUUID: string
|
||||||
|
let nonFederatedUnlistedVideoUUID: string
|
||||||
|
|
||||||
let now: number
|
let now: number
|
||||||
|
|
||||||
|
const dontFederateUnlistedConfig = {
|
||||||
|
federation: {
|
||||||
|
videos: {
|
||||||
|
federate_unlisted: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
this.timeout(50000)
|
this.timeout(50000)
|
||||||
|
|
||||||
// Run servers
|
// Run servers
|
||||||
servers = await flushAndRunMultipleServers(2)
|
servers.push(await flushAndRunServer(1, dontFederateUnlistedConfig))
|
||||||
|
servers.push(await flushAndRunServer(2))
|
||||||
|
|
||||||
// Get the access tokens
|
// Get the access tokens
|
||||||
await setAccessTokensToServers(servers)
|
await setAccessTokensToServers(servers)
|
||||||
|
@ -164,6 +174,37 @@ describe('Test video privacy', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should upload a non-federating unlisted video to server 1', async function () {
|
||||||
|
this.timeout(30000)
|
||||||
|
|
||||||
|
const attributes = {
|
||||||
|
name: 'unlisted video',
|
||||||
|
privacy: VideoPrivacy.UNLISTED
|
||||||
|
}
|
||||||
|
await uploadVideo(servers[0].url, servers[0].accessToken, attributes)
|
||||||
|
|
||||||
|
await waitJobs(servers)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should list my new unlisted video', async function () {
|
||||||
|
const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 3)
|
||||||
|
|
||||||
|
expect(res.body.total).to.equal(3)
|
||||||
|
expect(res.body.data).to.have.lengthOf(3)
|
||||||
|
|
||||||
|
nonFederatedUnlistedVideoUUID = res.body.data[0].uuid
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should be able to get non-federated unlisted video from origin', async function () {
|
||||||
|
const res = await getVideo(servers[0].url, nonFederatedUnlistedVideoUUID)
|
||||||
|
|
||||||
|
expect(res.body.name).to.equal('unlisted video')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should not be able to get non-federated unlisted video from federated server', async function () {
|
||||||
|
await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, 404)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should update the private and internal videos to public on server 1', async function () {
|
it('Should update the private and internal videos to public on server 1', async function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
|
@ -230,8 +271,8 @@ describe('Test video privacy', function () {
|
||||||
const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5)
|
const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5)
|
||||||
const videos = res.body.data
|
const videos = res.body.data
|
||||||
|
|
||||||
expect(res.body.total).to.equal(2)
|
expect(res.body.total).to.equal(3)
|
||||||
expect(videos).to.have.lengthOf(2)
|
expect(videos).to.have.lengthOf(3)
|
||||||
|
|
||||||
const privateVideo = videos.find(v => v.name === 'private video becomes public')
|
const privateVideo = videos.find(v => v.name === 'private video becomes public')
|
||||||
const internalVideo = videos.find(v => v.name === 'internal video becomes public')
|
const internalVideo = videos.find(v => v.name === 'internal video becomes public')
|
||||||
|
|
Loading…
Reference in New Issue