<th style="width: 40px"></th>
<th i18n pSortableColumn="name">Video name <p-sortIcon field="name"></p-sortIcon></th>
<th i18n>Sensitive</th>
+ <th i18n>Unfederated</th>
<th i18n pSortableColumn="createdAt">Date <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 120px;"></th>
</tr>
</a>
</td>
- <td>{{ videoBlacklist.video.nsfw }}</td>
+ <td>{{ booleanToText(videoBlacklist.video.nsfw) }}</td>
+ <td>{{ booleanToText(videoBlacklist.unfederated) }}</td>
<td>{{ videoBlacklist.createdAt }}</td>
<td class="action-cell">
<ng-template pTemplate="rowexpansion" let-videoBlacklist>
<tr>
- <td class="moderation-expanded" colspan="5">
+ <td class="moderation-expanded" colspan="6">
<span i18n class="moderation-expanded-label">Blacklist reason:</span>
<span class="moderation-expanded-text">{{ videoBlacklist.reason }}</span>
</td>
return Video.buildClientUrl(videoBlacklist.video.uuid)
}
+ booleanToText (value: boolean) {
+ if (value === true) return this.i18n('yes')
+
+ return this.i18n('no')
+ }
+
async removeVideoFromBlacklist (entry: VideoBlacklist) {
const confirmMessage = this.i18n(
'Do you really want to remove this video from the blacklist? It will be available again in the videos list.'
<span i18n *ngIf="user.blocked" class="banned-info">(banned)</span>
</a>
</td>
+
<td *ngIf="!requiresEmailVerification || user.blocked; else emailWithVerificationStatus">{{ user.email }}</td>
+
<ng-template #emailWithVerificationStatus>
<td *ngIf="user.emailVerified === false; else emailVerifiedNotFalse" i18n-title title="User's email must be verified to login">
<em>? {{ user.email }}</em>
</td>
</ng-template>
</ng-template>
+
<td>{{ user.videoQuotaUsed }} / {{ user.videoQuota }}</td>
<td>{{ user.roleLabel }}</td>
<td>{{ user.createdAt }}</td>
)
}
- blacklistVideo (videoId: number, reason?: string) {
- const body = reason ? { reason } : {}
+ blacklistVideo (videoId: number, reason: string, unfederate: boolean) {
+ const body = {
+ unfederate,
+ reason
+ }
return this.authHttp.post(VideoBlacklistService.BASE_VIDEOS_URL + videoId + '/blacklist', body)
.pipe(
</div>
</div>
+ <div class="form-group" *ngIf="video.isLocal">
+ <my-peertube-checkbox
+ inputName="unfederate" formControlName="unfederate"
+ i18n-labelText labelText="Unfederate the video (ask for its deletion from the remote instances)"
+ ></my-peertube-checkbox>
+ </div>
+
<div class="form-group inputs">
<span i18n class="action-button action-button-cancel" (click)="hide()">
Cancel
}
ngOnInit () {
+ const defaultValues = { unfederate: 'true' }
+
this.buildForm({
- reason: this.videoBlacklistValidatorsService.VIDEO_BLACKLIST_REASON
- })
+ reason: this.videoBlacklistValidatorsService.VIDEO_BLACKLIST_REASON,
+ unfederate: null
+ }, defaultValues)
}
show () {
blacklist () {
const reason = this.form.value[ 'reason' ] || undefined
+ const unfederate = this.video.isLocal ? this.form.value[ 'unfederate' ] : undefined
- this.videoBlacklistService.blacklistVideo(this.video.id, reason)
+ this.videoBlacklistService.blacklistVideo(this.video.id, reason, unfederate)
.subscribe(
() => {
this.notifier.success(this.i18n('Video blacklisted.'))
import { sequelizeTypescript } from '../../../initializers'
import { Notifier } from '../../../lib/notifier'
import { VideoModel } from '../../../models/video/video'
+import { sendCreateVideo, sendDeleteVideo, sendUpdateVideo } from '../../../lib/activitypub/send'
+import { federateVideoIfNeeded } from '../../../lib/activitypub'
const blacklistRouter = express.Router()
const toCreate = {
videoId: videoInstance.id,
+ unfederated: body.unfederate === true,
reason: body.reason
}
const blacklist = await VideoBlacklistModel.create(toCreate)
blacklist.Video = videoInstance
+ if (body.unfederate === true) {
+ await sendDeleteVideo(videoInstance, undefined)
+ }
+
Notifier.Instance.notifyOnVideoBlacklist(blacklist)
logger.info('Video %s blacklisted.', res.locals.video.uuid)
const videoBlacklist = res.locals.videoBlacklist as VideoBlacklistModel
const video: VideoModel = res.locals.video
- await sequelizeTypescript.transaction(t => {
- return videoBlacklist.destroy({ transaction: t })
+ await sequelizeTypescript.transaction(async t => {
+ const unfederated = videoBlacklist.unfederated
+ await videoBlacklist.destroy({ transaction: t })
+
+ // Re federate the video
+ if (unfederated === true) {
+ await federateVideoIfNeeded(video, true, t)
+ }
})
Notifier.Instance.notifyOnVideoUnblacklist(video)
}
const isNewVideo = wasPrivateVideo && videoInstanceUpdated.privacy !== VideoPrivacy.PRIVATE
- await federateVideoIfNeeded(videoInstanceUpdated, isNewVideo, t)
+
+ // Don't send update if the video was unfederated
+ if (!videoInstanceUpdated.VideoBlacklist || videoInstanceUpdated.VideoBlacklist.unfederated === false) {
+ await federateVideoIfNeeded(videoInstanceUpdated, isNewVideo, t)
+ }
auditLogger.update(
getAuditIdFromRes(res),
// ---------------------------------------------------------------------------
-const LAST_MIGRATION_VERSION = 315
+const LAST_MIGRATION_VERSION = 320
// ---------------------------------------------------------------------------
--- /dev/null
+import * as Sequelize from 'sequelize'
+
+async function up (utils: {
+ transaction: Sequelize.Transaction,
+ queryInterface: Sequelize.QueryInterface,
+ sequelize: Sequelize.Sequelize
+}): Promise<void> {
+
+ {
+ const data = {
+ type: Sequelize.BOOLEAN,
+ allowNull: false,
+ defaultValue: false
+ }
+
+ await utils.queryInterface.addColumn('videoBlacklist', 'unfederated', data)
+ }
+}
+
+function down (options) {
+ throw new Error('Not implemented.')
+}
+
+export {
+ up,
+ down
+}
const serverActor = await getServerActor()
const serverShareUrl = getVideoAnnounceActivityPubUrl(serverActor, video)
- return VideoShareModel.findOrCreate({
+ const [ serverShare ] = await VideoShareModel.findOrCreate({
defaults: {
actorId: serverActor.id,
videoId: video.id,
url: serverShareUrl
},
transaction: t
- }).then(([ serverShare, created ]) => {
- if (created) return sendVideoAnnounce(serverActor, serverShare, video, t)
-
- return undefined
})
+
+ return sendVideoAnnounce(serverActor, serverShare, video, t)
}
async function shareByVideoChannel (video: VideoModel, t: Transaction) {
const videoChannelShareUrl = getVideoAnnounceActivityPubUrl(video.VideoChannel.Actor, video)
- return VideoShareModel.findOrCreate({
+ const [ videoChannelShare ] = await VideoShareModel.findOrCreate({
defaults: {
actorId: video.VideoChannel.actorId,
videoId: video.id,
url: videoChannelShareUrl
},
transaction: t
- }).then(([ videoChannelShare, created ]) => {
- if (created) return sendVideoAnnounce(video.VideoChannel.Actor, videoChannelShare, video, t)
-
- return undefined
})
+
+ return sendVideoAnnounce(video.VideoChannel.Actor, videoChannelShare, video, t)
}
async function undoShareByVideoChannel (video: VideoModel, oldVideoChannel: VideoChannelModel, t: Transaction) {
import * as express from 'express'
import { body, param } from 'express-validator/check'
-import { isIdOrUUIDValid } from '../../../helpers/custom-validators/misc'
+import { isBooleanValid, isIdOrUUIDValid } from '../../../helpers/custom-validators/misc'
import { isVideoExist } from '../../../helpers/custom-validators/videos'
import { logger } from '../../../helpers/logger'
import { areValidationErrors } from '../utils'
import { isVideoBlacklistExist, isVideoBlacklistReasonValid } from '../../../helpers/custom-validators/video-blacklist'
+import { VideoModel } from '../../../models/video/video'
const videosBlacklistRemoveValidator = [
param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
const videosBlacklistAddValidator = [
param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
+ body('unfederate')
+ .optional()
+ .toBoolean()
+ .custom(isBooleanValid).withMessage('Should have a valid unfederate boolean'),
body('reason')
.optional()
.custom(isVideoBlacklistReasonValid).withMessage('Should have a valid reason'),
if (areValidationErrors(req, res)) return
if (!await isVideoExist(req.params.videoId, res)) return
+ const video: VideoModel = res.locals.video
+ if (req.body.unfederate === true && video.remote === true) {
+ return res
+ .status(409)
+ .send({ error: 'You cannot unfederate a remote video.' })
+ .end()
+ }
+
return next()
}
]
-import {
- AfterCreate,
- AfterDestroy,
- AllowNull,
- BelongsTo,
- Column,
- CreatedAt,
- DataType,
- ForeignKey,
- Is,
- Model,
- Table,
- UpdatedAt
-} from 'sequelize-typescript'
+import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { getSortOnModel, SortType, throwIfNotValid } from '../utils'
import { VideoModel } from './video'
import { isVideoBlacklistReasonValid } from '../../helpers/custom-validators/video-blacklist'
-import { Emailer } from '../../lib/emailer'
import { VideoBlacklist } from '../../../shared/models/videos'
import { CONSTRAINTS_FIELDS } from '../../initializers'
@Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_BLACKLIST.REASON.max))
reason: string
+ @AllowNull(false)
+ @Column
+ unfederated: boolean
+
@CreatedAt
createdAt: Date
createdAt: this.createdAt,
updatedAt: this.updatedAt,
reason: this.reason,
+ unfederated: this.unfederated,
video: {
id: video.id,
import {
createUser,
+ doubleFollow,
+ flushAndRunMultipleServers,
flushTests,
- getBlacklistedVideosList, getVideo, getVideoWithToken,
+ getBlacklistedVideosList,
+ getVideo,
+ getVideoWithToken,
killallServers,
makePostBodyRequest,
makePutBodyRequest,
removeVideoFromBlacklist,
- runServer,
ServerInfo,
setAccessTokensToServers,
uploadVideo,
- userLogin
+ userLogin, waitJobs
} from '../../../../shared/utils'
import {
checkBadCountPagination,
import { expect } from 'chai'
describe('Test video blacklist API validators', function () {
- let server: ServerInfo
+ let servers: ServerInfo[]
let notBlacklistedVideoId: number
+ let remoteVideoUUID: string
let userAccessToken1 = ''
let userAccessToken2 = ''
this.timeout(120000)
await flushTests()
+ servers = await flushAndRunMultipleServers(2)
- server = await runServer(1)
-
- await setAccessTokensToServers([ server ])
+ await setAccessTokensToServers(servers)
+ await doubleFollow(servers[0], servers[1])
{
const username = 'user1'
const password = 'my super password'
- await createUser(server.url, server.accessToken, username, password)
- userAccessToken1 = await userLogin(server, { username, password })
+ await createUser(servers[0].url, servers[0].accessToken, username, password)
+ userAccessToken1 = await userLogin(servers[0], { username, password })
}
{
const username = 'user2'
const password = 'my super password'
- await createUser(server.url, server.accessToken, username, password)
- userAccessToken2 = await userLogin(server, { username, password })
+ await createUser(servers[0].url, servers[0].accessToken, username, password)
+ userAccessToken2 = await userLogin(servers[0], { username, password })
}
{
- const res = await uploadVideo(server.url, userAccessToken1, {})
- server.video = res.body.video
+ const res = await uploadVideo(servers[0].url, userAccessToken1, {})
+ servers[0].video = res.body.video
}
{
- const res = await uploadVideo(server.url, server.accessToken, {})
+ const res = await uploadVideo(servers[0].url, servers[0].accessToken, {})
notBlacklistedVideoId = res.body.video.uuid
}
+
+ {
+ const res = await uploadVideo(servers[1].url, servers[1].accessToken, {})
+ remoteVideoUUID = res.body.video.uuid
+ }
+
+ await waitJobs(servers)
})
describe('When adding a video in blacklist', function () {
const basePath = '/api/v1/videos/'
it('Should fail with nothing', async function () {
- const path = basePath + server.video + '/blacklist'
+ const path = basePath + servers[0].video + '/blacklist'
const fields = {}
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
+ await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
})
it('Should fail with a wrong video', async function () {
const wrongPath = '/api/v1/videos/blabla/blacklist'
const fields = {}
- await makePostBodyRequest({ url: server.url, path: wrongPath, token: server.accessToken, fields })
+ await makePostBodyRequest({ url: servers[0].url, path: wrongPath, token: servers[0].accessToken, fields })
})
it('Should fail with a non authenticated user', async function () {
- const path = basePath + server.video + '/blacklist'
+ const path = basePath + servers[0].video + '/blacklist'
const fields = {}
- await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: 401 })
+ await makePostBodyRequest({ url: servers[0].url, path, token: 'hello', fields, statusCodeExpected: 401 })
})
it('Should fail with a non admin user', async function () {
- const path = basePath + server.video + '/blacklist'
+ const path = basePath + servers[0].video + '/blacklist'
const fields = {}
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken2, fields, statusCodeExpected: 403 })
+ await makePostBodyRequest({ url: servers[0].url, path, token: userAccessToken2, fields, statusCodeExpected: 403 })
})
it('Should fail with an invalid reason', async function () {
- const path = basePath + server.video.uuid + '/blacklist'
+ const path = basePath + servers[0].video.uuid + '/blacklist'
const fields = { reason: 'a'.repeat(305) }
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
+ await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
+ })
+
+ it('Should fail to unfederate a remote video', async function () {
+ const path = basePath + remoteVideoUUID + '/blacklist'
+ const fields = { unfederate: true }
+
+ await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 409 })
})
it('Should succeed with the correct params', async function () {
- const path = basePath + server.video.uuid + '/blacklist'
+ const path = basePath + servers[0].video.uuid + '/blacklist'
const fields = { }
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
+ await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 204 })
})
})
it('Should fail with a wrong video', async function () {
const wrongPath = '/api/v1/videos/blabla/blacklist'
const fields = {}
- await makePutBodyRequest({ url: server.url, path: wrongPath, token: server.accessToken, fields })
+ await makePutBodyRequest({ url: servers[0].url, path: wrongPath, token: servers[0].accessToken, fields })
})
it('Should fail with a video not blacklisted', async function () {
const path = '/api/v1/videos/' + notBlacklistedVideoId + '/blacklist'
const fields = {}
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 404 })
+ await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 404 })
})
it('Should fail with a non authenticated user', async function () {
- const path = basePath + server.video + '/blacklist'
+ const path = basePath + servers[0].video + '/blacklist'
const fields = {}
- await makePutBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: 401 })
+ await makePutBodyRequest({ url: servers[0].url, path, token: 'hello', fields, statusCodeExpected: 401 })
})
it('Should fail with a non admin user', async function () {
- const path = basePath + server.video + '/blacklist'
+ const path = basePath + servers[0].video + '/blacklist'
const fields = {}
- await makePutBodyRequest({ url: server.url, path, token: userAccessToken2, fields, statusCodeExpected: 403 })
+ await makePutBodyRequest({ url: servers[0].url, path, token: userAccessToken2, fields, statusCodeExpected: 403 })
})
it('Should fail with an invalid reason', async function () {
- const path = basePath + server.video.uuid + '/blacklist'
+ const path = basePath + servers[0].video.uuid + '/blacklist'
const fields = { reason: 'a'.repeat(305) }
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
+ await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
})
it('Should succeed with the correct params', async function () {
- const path = basePath + server.video.uuid + '/blacklist'
+ const path = basePath + servers[0].video.uuid + '/blacklist'
const fields = { reason: 'hello' }
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
+ await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 204 })
})
})
describe('When getting blacklisted video', function () {
it('Should fail with a non authenticated user', async function () {
- await getVideo(server.url, server.video.uuid, 401)
+ await getVideo(servers[0].url, servers[0].video.uuid, 401)
})
it('Should fail with another user', async function () {
- await getVideoWithToken(server.url, userAccessToken2, server.video.uuid, 403)
+ await getVideoWithToken(servers[0].url, userAccessToken2, servers[0].video.uuid, 403)
})
it('Should succeed with the owner authenticated user', async function () {
- const res = await getVideoWithToken(server.url, userAccessToken1, server.video.uuid, 200)
+ const res = await getVideoWithToken(servers[0].url, userAccessToken1, servers[0].video.uuid, 200)
const video: VideoDetails = res.body
expect(video.blacklisted).to.be.true
})
it('Should succeed with an admin', async function () {
- const res = await getVideoWithToken(server.url, server.accessToken, server.video.uuid, 200)
+ const res = await getVideoWithToken(servers[0].url, servers[0].accessToken, servers[0].video.uuid, 200)
const video: VideoDetails = res.body
expect(video.blacklisted).to.be.true
describe('When removing a video in blacklist', function () {
it('Should fail with a non authenticated user', async function () {
- await removeVideoFromBlacklist(server.url, 'fake token', server.video.uuid, 401)
+ await removeVideoFromBlacklist(servers[0].url, 'fake token', servers[0].video.uuid, 401)
})
it('Should fail with a non admin user', async function () {
- await removeVideoFromBlacklist(server.url, userAccessToken2, server.video.uuid, 403)
+ await removeVideoFromBlacklist(servers[0].url, userAccessToken2, servers[0].video.uuid, 403)
})
it('Should fail with an incorrect id', async function () {
- await removeVideoFromBlacklist(server.url, server.accessToken, 'hello', 400)
+ await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, 'hello', 400)
})
it('Should fail with a not blacklisted video', async function () {
// The video was not added to the blacklist so it should fail
- await removeVideoFromBlacklist(server.url, server.accessToken, notBlacklistedVideoId, 404)
+ await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, notBlacklistedVideoId, 404)
})
it('Should succeed with the correct params', async function () {
- await removeVideoFromBlacklist(server.url, server.accessToken, server.video.uuid, 204)
+ await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, servers[0].video.uuid, 204)
})
})
const basePath = '/api/v1/videos/blacklist/'
it('Should fail with a non authenticated user', async function () {
- await getBlacklistedVideosList(server.url, 'fake token', 401)
+ await getBlacklistedVideosList(servers[0].url, 'fake token', 401)
})
it('Should fail with a non admin user', async function () {
- await getBlacklistedVideosList(server.url, userAccessToken2, 403)
+ await getBlacklistedVideosList(servers[0].url, userAccessToken2, 403)
})
it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, basePath, server.accessToken)
+ await checkBadStartPagination(servers[0].url, basePath, servers[0].accessToken)
})
it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, basePath, server.accessToken)
+ await checkBadCountPagination(servers[0].url, basePath, servers[0].accessToken)
})
it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, basePath, server.accessToken)
+ await checkBadSortPagination(servers[0].url, basePath, servers[0].accessToken)
})
})
after(async function () {
- killallServers([ server ])
+ killallServers(servers)
// Keep the logs if the test failed
if (this['ok']) {
import './single-server'
import './video-abuse'
import './video-blacklist'
-import './video-blacklist-management'
import './video-captions'
import './video-change-ownership'
import './video-channels'
+++ /dev/null
-/* tslint:disable:no-unused-expression */
-
-import * as chai from 'chai'
-import { orderBy } from 'lodash'
-import 'mocha'
-import {
- addVideoToBlacklist,
- flushAndRunMultipleServers,
- getBlacklistedVideosList,
- getMyVideos,
- getSortedBlacklistedVideosList,
- getVideosList,
- killallServers,
- removeVideoFromBlacklist,
- ServerInfo,
- setAccessTokensToServers,
- updateVideoBlacklist,
- uploadVideo
-} from '../../../../shared/utils/index'
-import { doubleFollow } from '../../../../shared/utils/server/follows'
-import { waitJobs } from '../../../../shared/utils/server/jobs'
-import { VideoAbuse } from '../../../../shared/models/videos'
-
-const expect = chai.expect
-
-describe('Test video blacklist management', function () {
- let servers: ServerInfo[] = []
- let videoId: number
-
- async function blacklistVideosOnServer (server: ServerInfo) {
- const res = await getVideosList(server.url)
-
- const videos = res.body.data
- for (let video of videos) {
- await addVideoToBlacklist(server.url, server.accessToken, video.id, 'super reason')
- }
- }
-
- before(async function () {
- this.timeout(50000)
-
- // Run servers
- servers = await flushAndRunMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
-
- // Upload 2 videos on server 2
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 1st video', description: 'A video on server 2' })
- await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 2nd video', description: 'A video on server 2' })
-
- // Wait videos propagation, server 2 has transcoding enabled
- await waitJobs(servers)
-
- // Blacklist the two videos on server 1
- await blacklistVideosOnServer(servers[0])
- })
-
- describe('When listing blacklisted videos', function () {
- it('Should display all the blacklisted videos', async function () {
- const res = await getBlacklistedVideosList(servers[0].url, servers[0].accessToken)
-
- expect(res.body.total).to.equal(2)
-
- const blacklistedVideos = res.body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- for (const blacklistedVideo of blacklistedVideos) {
- expect(blacklistedVideo.reason).to.equal('super reason')
- videoId = blacklistedVideo.video.id
- }
- })
-
- it('Should get the correct sort when sorting by descending id', async function () {
- const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-id')
- expect(res.body.total).to.equal(2)
-
- const blacklistedVideos = res.body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- const result = orderBy(res.body.data, [ 'id' ], [ 'desc' ])
-
- expect(blacklistedVideos).to.deep.equal(result)
- })
-
- it('Should get the correct sort when sorting by descending video name', async function () {
- const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
- expect(res.body.total).to.equal(2)
-
- const blacklistedVideos = res.body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- const result = orderBy(res.body.data, [ 'name' ], [ 'desc' ])
-
- expect(blacklistedVideos).to.deep.equal(result)
- })
-
- it('Should get the correct sort when sorting by ascending creation date', async function () {
- const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, 'createdAt')
- expect(res.body.total).to.equal(2)
-
- const blacklistedVideos = res.body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- const result = orderBy(res.body.data, [ 'createdAt' ])
-
- expect(blacklistedVideos).to.deep.equal(result)
- })
- })
-
- describe('When updating blacklisted videos', function () {
- it('Should change the reason', async function () {
- await updateVideoBlacklist(servers[0].url, servers[0].accessToken, videoId, 'my super reason updated')
-
- const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
- const video = res.body.data.find(b => b.video.id === videoId)
-
- expect(video.reason).to.equal('my super reason updated')
- })
- })
-
- describe('When listing my videos', function () {
- it('Should display blacklisted videos', async function () {
- await blacklistVideosOnServer(servers[1])
-
- const res = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 5)
-
- expect(res.body.total).to.equal(2)
- expect(res.body.data).to.have.lengthOf(2)
-
- for (const video of res.body.data) {
- expect(video.blacklisted).to.be.true
- expect(video.blacklistedReason).to.equal('super reason')
- }
- })
- })
-
- describe('When removing a blacklisted video', function () {
- let videoToRemove: VideoAbuse
- let blacklist = []
-
- it('Should not have any video in videos list on server 1', async function () {
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
- })
-
- it('Should remove a video from the blacklist on server 1', async function () {
- // Get one video in the blacklist
- const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
- videoToRemove = res.body.data[0]
- blacklist = res.body.data.slice(1)
-
- // Remove it
- await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, videoToRemove.video.id)
- })
-
- it('Should have the ex-blacklisted video in videos list on server 1', async function () {
- const res = await getVideosList(servers[0].url)
- expect(res.body.total).to.equal(1)
-
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(1)
-
- expect(videos[0].name).to.equal(videoToRemove.video.name)
- expect(videos[0].id).to.equal(videoToRemove.video.id)
- })
-
- it('Should not have the ex-blacklisted video in videos blacklist list on server 1', async function () {
- const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
- expect(res.body.total).to.equal(1)
-
- const videos = res.body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(1)
- expect(videos).to.deep.equal(blacklist)
- })
- })
-
- after(async function () {
- killallServers(servers)
- })
-})
/* tslint:disable:no-unused-expression */
import * as chai from 'chai'
+import { orderBy } from 'lodash'
import 'mocha'
import {
addVideoToBlacklist,
flushAndRunMultipleServers,
+ getBlacklistedVideosList,
+ getMyVideos,
+ getSortedBlacklistedVideosList,
getVideosList,
killallServers,
+ removeVideoFromBlacklist,
searchVideo,
ServerInfo,
setAccessTokensToServers,
- uploadVideo
+ updateVideo,
+ updateVideoBlacklist,
+ uploadVideo,
+ viewVideo
} from '../../../../shared/utils/index'
import { doubleFollow } from '../../../../shared/utils/server/follows'
import { waitJobs } from '../../../../shared/utils/server/jobs'
+import { VideoBlacklist } from '../../../../shared/models/videos'
const expect = chai.expect
-describe('Test video blacklists', function () {
+describe('Test video blacklist management', function () {
let servers: ServerInfo[] = []
+ let videoId: number
+
+ async function blacklistVideosOnServer (server: ServerInfo) {
+ const res = await getVideosList(server.url)
+
+ const videos = res.body.data
+ for (let video of videos) {
+ await addVideoToBlacklist(server.url, server.accessToken, video.id, 'super reason')
+ }
+ }
before(async function () {
this.timeout(50000)
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
- // Upload a video on server 2
- const videoAttributes = {
- name: 'my super name for server 2',
- description: 'my super description for server 2'
- }
- await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
+ // Upload 2 videos on server 2
+ await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 1st video', description: 'A video on server 2' })
+ await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 2nd video', description: 'A video on server 2' })
// Wait videos propagation, server 2 has transcoding enabled
await waitJobs(servers)
- const res = await getVideosList(servers[0].url)
- const videos = res.body.data
+ // Blacklist the two videos on server 1
+ await blacklistVideosOnServer(servers[0])
+ })
+
+ describe('When listing/searching videos', function () {
- expect(videos.length).to.equal(1)
+ it('Should not have the video blacklisted in videos list/search on server 1', async function () {
+ {
+ const res = await getVideosList(servers[ 0 ].url)
- servers[0].remoteVideo = videos.find(video => video.name === 'my super name for server 2')
+ expect(res.body.total).to.equal(0)
+ expect(res.body.data).to.be.an('array')
+ expect(res.body.data.length).to.equal(0)
+ }
+
+ {
+ const res = await searchVideo(servers[ 0 ].url, 'name')
+
+ expect(res.body.total).to.equal(0)
+ expect(res.body.data).to.be.an('array')
+ expect(res.body.data.length).to.equal(0)
+ }
+ })
+
+ it('Should have the blacklisted video in videos list/search on server 2', async function () {
+ {
+ const res = await getVideosList(servers[ 1 ].url)
+
+ expect(res.body.total).to.equal(2)
+ expect(res.body.data).to.be.an('array')
+ expect(res.body.data.length).to.equal(2)
+ }
+
+ {
+ const res = await searchVideo(servers[ 1 ].url, 'video')
+
+ expect(res.body.total).to.equal(2)
+ expect(res.body.data).to.be.an('array')
+ expect(res.body.data.length).to.equal(2)
+ }
+ })
})
- it('Should blacklist a remote video on server 1', async function () {
- await addVideoToBlacklist(servers[0].url, servers[0].accessToken, servers[0].remoteVideo.id)
+ describe('When listing blacklisted videos', function () {
+ it('Should display all the blacklisted videos', async function () {
+ const res = await getBlacklistedVideosList(servers[0].url, servers[0].accessToken)
+
+ expect(res.body.total).to.equal(2)
+
+ const blacklistedVideos = res.body.data
+ expect(blacklistedVideos).to.be.an('array')
+ expect(blacklistedVideos.length).to.equal(2)
+
+ for (const blacklistedVideo of blacklistedVideos) {
+ expect(blacklistedVideo.reason).to.equal('super reason')
+ videoId = blacklistedVideo.video.id
+ }
+ })
+
+ it('Should get the correct sort when sorting by descending id', async function () {
+ const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-id')
+ expect(res.body.total).to.equal(2)
+
+ const blacklistedVideos = res.body.data
+ expect(blacklistedVideos).to.be.an('array')
+ expect(blacklistedVideos.length).to.equal(2)
+
+ const result = orderBy(res.body.data, [ 'id' ], [ 'desc' ])
+
+ expect(blacklistedVideos).to.deep.equal(result)
+ })
+
+ it('Should get the correct sort when sorting by descending video name', async function () {
+ const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
+ expect(res.body.total).to.equal(2)
+
+ const blacklistedVideos = res.body.data
+ expect(blacklistedVideos).to.be.an('array')
+ expect(blacklistedVideos.length).to.equal(2)
+
+ const result = orderBy(res.body.data, [ 'name' ], [ 'desc' ])
+
+ expect(blacklistedVideos).to.deep.equal(result)
+ })
+
+ it('Should get the correct sort when sorting by ascending creation date', async function () {
+ const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, 'createdAt')
+ expect(res.body.total).to.equal(2)
+
+ const blacklistedVideos = res.body.data
+ expect(blacklistedVideos).to.be.an('array')
+ expect(blacklistedVideos.length).to.equal(2)
+
+ const result = orderBy(res.body.data, [ 'createdAt' ])
+
+ expect(blacklistedVideos).to.deep.equal(result)
+ })
})
- it('Should not have the video blacklisted in videos list on server 1', async function () {
- const res = await getVideosList(servers[0].url)
+ describe('When updating blacklisted videos', function () {
+ it('Should change the reason', async function () {
+ await updateVideoBlacklist(servers[0].url, servers[0].accessToken, videoId, 'my super reason updated')
+
+ const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
+ const video = res.body.data.find(b => b.video.id === videoId)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
+ expect(video.reason).to.equal('my super reason updated')
+ })
})
- it('Should not have the video blacklisted in videos search on server 1', async function () {
- const res = await searchVideo(servers[0].url, 'name')
+ describe('When listing my videos', function () {
+ it('Should display blacklisted videos', async function () {
+ await blacklistVideosOnServer(servers[1])
+
+ const res = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 5)
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(0)
+ expect(res.body.total).to.equal(2)
+ expect(res.body.data).to.have.lengthOf(2)
+
+ for (const video of res.body.data) {
+ expect(video.blacklisted).to.be.true
+ expect(video.blacklistedReason).to.equal('super reason')
+ }
+ })
})
- it('Should have the blacklisted video in videos list on server 2', async function () {
- const res = await getVideosList(servers[1].url)
+ describe('When removing a blacklisted video', function () {
+ let videoToRemove: VideoBlacklist
+ let blacklist = []
+
+ it('Should not have any video in videos list on server 1', async function () {
+ const res = await getVideosList(servers[0].url)
+ expect(res.body.total).to.equal(0)
+ expect(res.body.data).to.be.an('array')
+ expect(res.body.data.length).to.equal(0)
+ })
+
+ it('Should remove a video from the blacklist on server 1', async function () {
+ // Get one video in the blacklist
+ const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
+ videoToRemove = res.body.data[0]
+ blacklist = res.body.data.slice(1)
+
+ // Remove it
+ await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, videoToRemove.video.id)
+ })
+
+ it('Should have the ex-blacklisted video in videos list on server 1', async function () {
+ const res = await getVideosList(servers[0].url)
+ expect(res.body.total).to.equal(1)
+
+ const videos = res.body.data
+ expect(videos).to.be.an('array')
+ expect(videos.length).to.equal(1)
+
+ expect(videos[0].name).to.equal(videoToRemove.video.name)
+ expect(videos[0].id).to.equal(videoToRemove.video.id)
+ })
+
+ it('Should not have the ex-blacklisted video in videos blacklist list on server 1', async function () {
+ const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name')
+ expect(res.body.total).to.equal(1)
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(1)
+ const videos = res.body.data
+ expect(videos).to.be.an('array')
+ expect(videos.length).to.equal(1)
+ expect(videos).to.deep.equal(blacklist)
+ })
})
- it('Should have the video blacklisted in videos search on server 2', async function () {
- const res = await searchVideo(servers[1].url, 'name')
+ describe('When blacklisting local videos', function () {
+ let video3UUID: string
+ let video4UUID: string
+
+ before(async function () {
+ this.timeout(10000)
+
+ {
+ const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'Video 3' })
+ video3UUID = res.body.video.uuid
+ }
+ {
+ const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'Video 4' })
+ video4UUID = res.body.video.uuid
+ }
+
+ await waitJobs(servers)
+ })
+
+ it('Should blacklist video 3 and keep it federated', async function () {
+ this.timeout(10000)
+
+ await addVideoToBlacklist(servers[ 0 ].url, servers[ 0 ].accessToken, video3UUID, 'super reason', false)
+
+ await waitJobs(servers)
+
+ {
+ const res = await getVideosList(servers[ 0 ].url)
+ expect(res.body.data.find(v => v.uuid === video3UUID)).to.be.undefined
+ }
+
+ {
+ const res = await getVideosList(servers[ 1 ].url)
+ expect(res.body.data.find(v => v.uuid === video3UUID)).to.not.be.undefined
+ }
+ })
+
+ it('Should unfederate the video', async function () {
+ this.timeout(10000)
+
+ await addVideoToBlacklist(servers[ 0 ].url, servers[ 0 ].accessToken, video4UUID, 'super reason', true)
+
+ await waitJobs(servers)
+
+ for (const server of servers) {
+ const res = await getVideosList(server.url)
+ expect(res.body.data.find(v => v.uuid === video4UUID)).to.be.undefined
+ }
+ })
+
+ it('Should have the video unfederated even after an Update AP message', async function () {
+ this.timeout(10000)
+
+ await updateVideo(servers[ 0 ].url, servers[ 0 ].accessToken, video4UUID, { description: 'super description' })
+
+ await waitJobs(servers)
+
+ for (const server of servers) {
+ const res = await getVideosList(server.url)
+ expect(res.body.data.find(v => v.uuid === video4UUID)).to.be.undefined
+ }
+ })
+
+ it('Should have the correct video blacklist unfederate attribute', async function () {
+ const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, 'createdAt')
+
+ const blacklistedVideos: VideoBlacklist[] = res.body.data
+ const video3Blacklisted = blacklistedVideos.find(b => b.video.uuid === video3UUID)
+ const video4Blacklisted = blacklistedVideos.find(b => b.video.uuid === video4UUID)
+
+ expect(video3Blacklisted.unfederated).to.be.false
+ expect(video4Blacklisted.unfederated).to.be.true
+ })
+
+ it('Should remove the video from blacklist and refederate the video', async function () {
+ this.timeout(10000)
+
+ await removeVideoFromBlacklist(servers[ 0 ].url, servers[ 0 ].accessToken, video4UUID)
+
+ await waitJobs(servers)
+
+ for (const server of servers) {
+ const res = await getVideosList(server.url)
+ expect(res.body.data.find(v => v.uuid === video4UUID)).to.not.be.undefined
+ }
+ })
- expect(res.body.total).to.equal(1)
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(1)
})
after(async function () {
export interface VideoBlacklistCreate {
reason?: string
+ unfederate?: boolean
}
id: number
createdAt: Date
updatedAt: Date
+ unfederated: boolean
reason?: string
video: {
if (dontContinue === true) return
server.app.stdout.removeListener('data', onStdout)
+
+ process.on('exit', () => process.kill(server.app.pid))
+
res(server)
})
+
})
}
import * as request from 'supertest'
-function addVideoToBlacklist (url: string, token: string, videoId: number | string, reason?: string, specialStatus = 204) {
+function addVideoToBlacklist (
+ url: string,
+ token: string,
+ videoId: number | string,
+ reason?: string,
+ unfederate?: boolean,
+ specialStatus = 204
+) {
const path = '/api/v1/videos/' + videoId + '/blacklist'
return request(url)
.post(path)
- .send({ reason })
+ .send({ reason, unfederate })
.set('Accept', 'application/json')
.set('Authorization', 'Bearer ' + token)
.expect(specialStatus)