import { UsersRoutes } from './users'
import { VideoAbusesRoutes } from './video-abuses'
import { AdminGuard } from './admin-guard.service'
+import { BlacklistRoutes } from './blacklist'
const adminRoutes: Routes = [
{
...FriendsRoutes,
...RequestSchedulersRoutes,
...UsersRoutes,
- ...VideoAbusesRoutes
+ ...VideoAbusesRoutes,
+ ...BlacklistRoutes
]
}
]
import { RequestSchedulersComponent, RequestSchedulersStatsComponent, RequestSchedulersService } from './request-schedulers'
import { UsersComponent, UserAddComponent, UserUpdateComponent, UserListComponent, UserService } from './users'
import { VideoAbusesComponent, VideoAbuseListComponent } from './video-abuses'
+import { BlacklistComponent, BlacklistListComponent, BlacklistService } from './blacklist'
import { SharedModule } from '../shared'
import { AdminGuard } from './admin-guard.service'
UserUpdateComponent,
UserListComponent,
+ BlacklistComponent,
+ BlacklistListComponent,
+
VideoAbusesComponent,
VideoAbuseListComponent
],
FriendService,
RequestSchedulersService,
UserService,
- AdminGuard
+ AdminGuard,
+ BlacklistService
]
})
export class AdminModule { }
--- /dev/null
+<div class="row">
+ <div class="content-padding">
+ <h3>Blacklisted videos</h3>
+
+ <p-dataTable
+ [value]="blacklist" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
+ sortField="id" (onLazyLoad)="loadLazy($event)"
+ >
+ <p-column field="id" header="ID" [sortable]="true"></p-column>
+ <p-column field="name" header="Name" [sortable]="true"></p-column>
+ <p-column field="description" header="Description"></p-column>
+ <p-column field="duration" header="Duration" [sortable]="true"></p-column>
+ <p-column field="views" header="Views" [sortable]="true"></p-column>
+ <p-column field="likes" header="Likes" [sortable]="true"></p-column>
+ <p-column field="dislikes" header="Dislikes" [sortable]="true"></p-column>
+ <p-column field="nsfw" header="NSFW"></p-column>
+ <p-column field="uuid" header="UUID" [sortable]="true"></p-column>
+ <p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
+ <p-column header="Delete" styleClass="action-cell">
+ <ng-template pTemplate="body" let-entry="rowData">
+ <span (click)="removeVideoFromBlacklist(entry)" class="glyphicon glyphicon-remove glyphicon-black" title="Remove this video"></span>
+ </ng-template>
+ </p-column>
+ </p-dataTable>
+ </div>
+</div>
--- /dev/null
+import { Component, OnInit } from '@angular/core'
+import { SortMeta } from 'primeng/components/common/sortmeta'
+
+import { NotificationsService } from 'angular2-notifications'
+
+import { ConfirmService } from '../../../core'
+import { RestTable, RestPagination } from '../../../shared'
+import { BlacklistService } from '../shared'
+import { BlacklistedVideo } from '../../../../../../shared'
+
+@Component({
+ selector: 'my-blacklist-list',
+ templateUrl: './blacklist-list.component.html',
+ styleUrls: []
+})
+export class BlacklistListComponent extends RestTable implements OnInit {
+ blacklist: BlacklistedVideo[] = []
+ totalRecords = 0
+ rowsPerPage = 10
+ sort: SortMeta = { field: 'id', order: 1 }
+ pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
+
+ constructor (
+ private notificationsService: NotificationsService,
+ private confirmService: ConfirmService,
+ private blacklistService: BlacklistService
+ ) {
+ super()
+ }
+
+ ngOnInit () {
+ this.loadData()
+ }
+
+ removeVideoFromBlacklist (entry: BlacklistedVideo) {
+ const confirmMessage = 'Do you really want to remove this video from the blacklist ? It will be available again in the video list.'
+
+ this.confirmService.confirm(confirmMessage, 'Remove').subscribe(
+ res => {
+ if (res === false) return
+
+ this.blacklistService.removeVideoFromBlacklist(entry).subscribe(
+ status => {
+ this.notificationsService.success('Success', `Video ${entry.name} removed from the blacklist.`)
+ this.loadData()
+ },
+
+ err => this.notificationsService.error('Error', err.message)
+ )
+ }
+ )
+ }
+
+ protected loadData () {
+ this.blacklistService.getBlacklist(this.pagination, this.sort)
+ .subscribe(
+ resultList => {
+ this.blacklist = resultList.data
+ this.totalRecords = resultList.total
+ },
+
+ err => this.notificationsService.error('Error', err.message)
+ )
+ }
+}
--- /dev/null
+export * from './blacklist-list.component'
--- /dev/null
+import { Component } from '@angular/core'
+
+@Component({
+ template: '<router-outlet></router-outlet>'
+})
+
+export class BlacklistComponent {
+}
--- /dev/null
+import { Routes } from '@angular/router'
+
+import { BlacklistComponent } from './blacklist.component'
+import { BlacklistListComponent } from './blacklist-list'
+
+export const BlacklistRoutes: Routes = [
+ {
+ path: 'blacklist',
+ component: BlacklistComponent,
+ children: [
+ {
+ path: '',
+ redirectTo: 'list',
+ pathMatch: 'full'
+ },
+ {
+ path: 'list',
+ component: BlacklistListComponent,
+ data: {
+ meta: {
+ title: 'Blacklisted videos'
+ }
+ }
+ }
+ ]
+ }
+]
--- /dev/null
+export * from './shared'
+export * from './blacklist-list'
+export * from './blacklist.component'
+export * from './blacklist.routes'
--- /dev/null
+import { Injectable } from '@angular/core'
+import { HttpClient, HttpParams } from '@angular/common/http'
+import { Observable } from 'rxjs/Observable'
+import 'rxjs/add/operator/catch'
+import 'rxjs/add/operator/map'
+
+import { SortMeta } from 'primeng/components/common/sortmeta'
+
+import { RestExtractor, RestPagination, RestService } from '../../../shared'
+import { Utils } from '../../../shared'
+import { BlacklistedVideo, ResultList } from '../../../../../../shared'
+
+@Injectable()
+export class BlacklistService {
+ private static BASE_BLACKLISTS_URL = '/api/v1/blacklist/'
+
+ constructor (
+ private authHttp: HttpClient,
+ private restService: RestService,
+ private restExtractor: RestExtractor
+ ) {}
+
+ getBlacklist (pagination: RestPagination, sort: SortMeta): Observable<ResultList<BlacklistedVideo>> {
+ let params = new HttpParams()
+ params = this.restService.addRestGetParams(params, pagination, sort)
+
+ return this.authHttp.get<ResultList<BlacklistedVideo>>(BlacklistService.BASE_BLACKLISTS_URL, { params })
+ .map(res => this.restExtractor.convertResultListDateToHuman(res))
+ .map(res => this.restExtractor.applyToResultListData(res, this.formatBlacklistedVideo.bind(this)))
+ .catch(res => this.restExtractor.handleError(res))
+ }
+
+ removeVideoFromBlacklist (entry: BlacklistedVideo) {
+ return this.authHttp.delete(BlacklistService.BASE_BLACKLISTS_URL + entry.id)
+ .map(this.restExtractor.extractDataBool)
+ .catch(res => this.restExtractor.handleError(res))
+ }
+
+ private formatBlacklistedVideo (blacklistedVideo: BlacklistedVideo) {
+ return Object.assign(blacklistedVideo, {
+ createdAt: Utils.dateToHuman(blacklistedVideo.createdAt)
+ })
+ }
+}
--- /dev/null
+export * from './blacklist.service'
<span class="hidden-xs glyphicon glyphicon-alert"></span>
Video abuses
</a>
+
+ <a routerLink="/admin/blacklist/list" routerLinkActive="active">
+ <span class="hidden-xs glyphicon glyphicon-eye-close"></span>
+ Video blacklist
+ </a>
</div>
<div class="panel-block">
--- /dev/null
+import * as express from 'express'
+
+import { database } from '../../initializers'
+import { getFormattedObjects } from '../../helpers'
+import { BlacklistedVideo } from '../../../shared'
+import { BlacklistedVideoInstance } from '../../models'
+
+import {
+ removeVideoFromBlacklist
+} from '../../lib'
+import {
+ authenticate,
+ ensureIsAdmin,
+ paginationValidator,
+ blacklistSortValidator,
+ setBlacklistSort,
+ setPagination,
+ blacklistRemoveValidator
+} from '../../middlewares'
+
+const blacklistRouter = express.Router()
+
+blacklistRouter.get('/',
+ authenticate,
+ ensureIsAdmin,
+ paginationValidator,
+ blacklistSortValidator,
+ setBlacklistSort,
+ setPagination,
+ listBlacklist
+)
+
+blacklistRouter.delete('/:id',
+ authenticate,
+ ensureIsAdmin,
+ blacklistRemoveValidator,
+ removeVideoFromBlacklistController
+)
+
+// ---------------------------------------------------------------------------
+
+export {
+ blacklistRouter
+}
+
+// ---------------------------------------------------------------------------
+
+function listBlacklist (req: express.Request, res: express.Response, next: express.NextFunction) {
+ database.BlacklistedVideo.listForApi(req.query.start, req.query.count, req.query.sort)
+ .then(resultList => res.json(getFormattedObjects<BlacklistedVideo, BlacklistedVideoInstance>(resultList.data, resultList.total)))
+ .catch(err => next(err))
+}
+
+function removeVideoFromBlacklistController (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const entry = res.locals.blacklistEntryToRemove as BlacklistedVideoInstance
+
+ removeVideoFromBlacklist(entry)
+ .then(() => res.sendStatus(204))
+ .catch(err => next(err))
+}
import { requestSchedulerRouter } from './request-schedulers'
import { usersRouter } from './users'
import { videosRouter } from './videos'
+import { blacklistRouter } from './blacklist'
const apiRouter = express.Router()
apiRouter.use('/request-schedulers', requestSchedulerRouter)
apiRouter.use('/users', usersRouter)
apiRouter.use('/videos', videosRouter)
+apiRouter.use('/blacklist', blacklistRouter)
apiRouter.use('/ping', pong)
apiRouter.use('/*', badRequest)
})
}
+type SortType = { sortModel: any, sortValue: string }
+
// ---------------------------------------------------------------------------
export {
badRequest,
generateRandomString,
getFormattedObjects,
- isSignupAllowed
+ isSignupAllowed,
+ SortType
}
const SORTABLE_COLUMNS = {
USERS: [ 'id', 'username', 'createdAt' ],
VIDEO_ABUSES: [ 'id', 'createdAt' ],
- VIDEOS: [ 'name', 'duration', 'createdAt', 'views', 'likes' ]
+ VIDEOS: [ 'name', 'duration', 'createdAt', 'views', 'likes' ],
+ BLACKLISTS: [ 'id', 'name', 'duration', 'views', 'likes', 'dislikes', 'uuid', 'createdAt' ]
}
const OAUTH_LIFETIME = {
--- /dev/null
+import { logger } from '../helpers'
+import { BlacklistedVideoInstance } from '../models'
+
+function removeVideoFromBlacklist (entry: BlacklistedVideoInstance) {
+ return entry.destroy()
+ .then(() => {
+ logger.info('Video removed from the blacklist')
+ })
+ .catch(err => {
+ logger.error('Some error while removing video from the blacklist.', err)
+ })
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+ removeVideoFromBlacklist
+}
+
+// ---------------------------------------------------------------------------
export * from './request'
export * from './friends'
export * from './oauth-model'
+export * from './blacklist'
import 'express-validator'
import * as express from 'express'
+import { SortType } from '../helpers'
+import { database } from '../initializers'
+
function setUsersSort (req: express.Request, res: express.Response, next: express.NextFunction) {
if (!req.query.sort) req.query.sort = '-createdAt'
return next()
}
+function setBlacklistSort (req: express.Request, res: express.Response, next: express.NextFunction) {
+ let newSort: SortType = { sortModel: undefined, sortValue: undefined }
+
+ if (!req.query.sort) req.query.sort = '-createdAt'
+
+ // Set model we want to sort onto
+ if (req.query.sort === '-createdAt' || req.query.sort === 'createdAt' ||
+ req.query.sort === '-id' || req.query.sort === 'id') {
+ // If we want to sort onto the BlacklistedVideos relation, we won't specify it in the query parameter ...
+ newSort.sortModel = undefined
+ } else {
+ newSort.sortModel = database.Video
+ }
+
+ newSort.sortValue = req.query.sort
+
+ req.query.sort = newSort
+
+ return next()
+}
+
// ---------------------------------------------------------------------------
export {
setUsersSort,
setVideoAbusesSort,
- setVideosSort
+ setVideosSort,
+ setBlacklistSort
}
--- /dev/null
+import { param } from 'express-validator/check'
+import * as express from 'express'
+
+import { database as db } from '../../initializers/database'
+import { checkErrors } from './utils'
+import { logger } from '../../helpers'
+
+const blacklistRemoveValidator = [
+ param('id').isNumeric().not().isEmpty().withMessage('Should have a valid id'),
+
+ (req: express.Request, res: express.Response, next: express.NextFunction) => {
+ logger.debug('Checking blacklistRemove parameters.', { parameters: req.params })
+
+ checkErrors(req, res, () => {
+ db.BlacklistedVideo.loadById(req.params.id)
+ .then(entry => {
+ if (!entry) return res.status(404).send('Blacklisted video not found')
+
+ res.locals.blacklistEntryToRemove = entry
+
+ next()
+ })
+ .catch(err => {
+ logger.error('Error in blacklistRemove request validator', { error: err })
+ return res.sendStatus(500)
+ })
+ })
+ }
+]
+
+// ---------------------------------------------------------------------------
+
+export {
+ blacklistRemoveValidator
+}
export * from './sort'
export * from './users'
export * from './videos'
+export * from './blacklist'
const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS)
const SORTABLE_VIDEO_ABUSES_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_ABUSES)
const SORTABLE_VIDEOS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEOS)
+const SORTABLE_BLACKLISTS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.BLACKLISTS)
const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS)
const videoAbusesSortValidator = checkSort(SORTABLE_VIDEO_ABUSES_COLUMNS)
const videosSortValidator = checkSort(SORTABLE_VIDEOS_COLUMNS)
+const blacklistSortValidator = checkSort(SORTABLE_BLACKLISTS_COLUMNS)
// ---------------------------------------------------------------------------
export {
usersSortValidator,
videoAbusesSortValidator,
- videosSortValidator
+ videosSortValidator,
+ blacklistSortValidator
}
// ---------------------------------------------------------------------------
instanceMethods.forEach(m => model.prototype[m.name] = m)
}
+function getSortOnModel (model: any, value: string) {
+ let sort = getSort(value)
+
+ if (model) return [ { model: model }, sort[0], sort[1] ]
+ return sort
+}
+
// ---------------------------------------------------------------------------
export {
addMethodsToModel,
- getSort
+ getSort,
+ getSortOnModel
}
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
+import { SortType } from '../../helpers'
import { ResultList } from '../../../shared'
+import { VideoInstance } from './video-interface'
// Don't use barrel, import just what we need
import { BlacklistedVideo as FormattedBlacklistedVideo } from '../../../shared/models/videos/video-blacklist.model'
export type List = () => Promise<BlacklistedVideoInstance[]>
- export type ListForApi = (start: number, count: number, sort: string) => Promise< ResultList<BlacklistedVideoInstance> >
+ export type ListForApi = (start: number, count: number, sort: SortType) => Promise< ResultList<BlacklistedVideoInstance> >
export type LoadById = (id: number) => Promise<BlacklistedVideoInstance>
export interface BlacklistedVideoAttributes {
videoId: number
+
+ Video?: VideoInstance
}
export interface BlacklistedVideoInstance
import * as Sequelize from 'sequelize'
-import { addMethodsToModel, getSort } from '../utils'
+import { SortType } from '../../helpers'
+import { addMethodsToModel, getSortOnModel } from '../utils'
+import { VideoInstance } from './video-interface'
import {
BlacklistedVideoInstance,
BlacklistedVideoAttributes,
// ------------------------------ METHODS ------------------------------
toFormattedJSON = function (this: BlacklistedVideoInstance) {
+ let video: VideoInstance
+
+ video = this.Video
+
return {
id: this.id,
videoId: this.videoId,
- createdAt: this.createdAt
+ createdAt: this.createdAt,
+ updatedAt: this.updatedAt,
+ name: video.name,
+ uuid: video.uuid,
+ description: video.description,
+ duration: video.duration,
+ views: video.views,
+ likes: video.likes,
+ dislikes: video.dislikes,
+ nsfw: video.nsfw
}
}
return BlacklistedVideo.findAll()
}
-listForApi = function (start: number, count: number, sort: string) {
+listForApi = function (start: number, count: number, sort: SortType) {
const query = {
offset: start,
limit: count,
- order: [ getSort(sort) ]
+ order: [ getSortOnModel(sort.sortModel, sort.sortValue) ],
+ include: [ { model: BlacklistedVideo['sequelize'].models.Video } ]
}
return BlacklistedVideo.findAndCountAll(query).then(({ rows, count }) => {
import './request-schedulers'
import './videos'
import './video-abuses'
-import './video-blacklists'
+import './video-blacklist'
// ---------------------------------------------------------------
before(async function () {
- this.timeout(20000)
+ this.timeout(60000)
await flushTests()
// ---------------------------------------------------------------
before(async function () {
- this.timeout(20000)
+ this.timeout(60000)
await flushTests()
--- /dev/null
+/* tslint:disable:no-unused-expression */
+
+import 'mocha'
+import * as request from 'supertest'
+
+import {
+ ServerInfo,
+ flushTests,
+ runServer,
+ uploadVideo,
+ getVideosList,
+ createUser,
+ setAccessTokensToServers,
+ killallServers,
+ makePostBodyRequest,
+ getUserAccessToken
+} from '../../utils'
+
+describe('Test video blacklist API validators', function () {
+ let server: ServerInfo
+ let userAccessToken = ''
+
+ // ---------------------------------------------------------------
+
+ before(async function () {
+ this.timeout(120000)
+
+ await flushTests()
+
+ server = await runServer(1)
+
+ await setAccessTokensToServers([ server ])
+
+ const username = 'user1'
+ const password = 'my super password'
+ await createUser(server.url, server.accessToken, username, password)
+ userAccessToken = await getUserAccessToken(server, { username, password })
+
+ // Upload a video
+ const videoAttributes = {}
+ await uploadVideo(server.url, server.accessToken, videoAttributes)
+
+ const res = await getVideosList(server.url)
+
+ const videos = res.body.data
+ server.video = videos[0]
+ })
+
+ 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 fields = {}
+ await makePostBodyRequest({ url: server.url, path, token: server.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 })
+ })
+
+ it('Should fail with a non authenticated user', async function () {
+ const fields = {}
+ const path = basePath + server.video + '/blacklist'
+ await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: 401 })
+ })
+
+ it('Should fail with a non admin user', async function () {
+ const fields = {}
+ const path = basePath + server.video + '/blacklist'
+ await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 403 })
+ })
+
+ it('Should fail with a local video', async function () {
+ const fields = {}
+ const path = basePath + server.video.id + '/blacklist'
+ await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 403 })
+ })
+ })
+
+ describe('When removing a video in blacklist', function () {
+ const basePath = '/api/v1/blacklist/'
+
+ it('Should fail with a non authenticated user', async function () {
+ const path = basePath + server.video.id
+
+ await request(server.url)
+ .delete(path)
+ .set('Authorization', 'Bearer ' + 'fake token')
+ .set('Accept', 'application/json')
+ .expect(401)
+ })
+
+ it('Should fail with a non admin user', async function () {
+ const path = basePath + server.video.id
+
+ await request(server.url)
+ .delete(path)
+ .set('Authorization', 'Bearer ' + userAccessToken)
+ .set('Accept', 'application/json')
+ .expect(403)
+ })
+
+ it('Should fail with an incorrect id', async function () {
+ const path = basePath + 'foobar'
+
+ await request(server.url)
+ .delete(path)
+ .set('Authorization', 'Bearer ' + server.accessToken)
+ .set('Accept', 'application/json')
+ .expect(400)
+ })
+
+ it('Should fail with a not blacklisted video', async function () {
+ // The video was not added to the blacklist so it should fail
+ const path = basePath + server.video.id
+
+ await request(server.url)
+ .delete(path)
+ .set('Authorization', 'Bearer ' + server.accessToken)
+ .set('Accept', 'application/json')
+ .expect(404)
+ })
+ })
+
+ describe('When listing videos in blacklist', function () {
+ const basePath = '/api/v1/blacklist/'
+
+ it('Should fail with a non authenticated user', async function () {
+ const path = basePath
+
+ await request(server.url)
+ .get(path)
+ .query({ sort: 'createdAt' })
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + 'fake token')
+ .expect(401)
+ })
+
+ it('Should fail with a non admin user', async function () {
+ const path = basePath
+
+ await request(server.url)
+ .get(path)
+ .query({ sort: 'createdAt' })
+ .set('Authorization', 'Bearer ' + userAccessToken)
+ .set('Accept', 'application/json')
+ .expect(403)
+ })
+
+ it('Should fail with a bad start pagination', async function () {
+ const path = basePath
+
+ await request(server.url)
+ .get(path)
+ .query({ start: 'foobar' })
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + server.accessToken)
+ .expect(400)
+ })
+
+ it('Should fail with a bad count pagination', async function () {
+ const path = basePath
+
+ await request(server.url)
+ .get(path)
+ .query({ count: 'foobar' })
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + server.accessToken)
+ .expect(400)
+ })
+
+ it('Should fail with an incorrect sort', async function () {
+ const path = basePath
+
+ await request(server.url)
+ .get(path)
+ .query({ sort: 'foobar' })
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + server.accessToken)
+ .expect(400)
+ })
+ })
+
+ after(async function () {
+ killallServers([ server ])
+
+ // Keep the logs if the test failed
+ if (this['ok']) {
+ await flushTests()
+ }
+ })
+})
+++ /dev/null
-/* tslint:disable:no-unused-expression */
-
-import 'mocha'
-
-import {
- ServerInfo,
- flushTests,
- runServer,
- uploadVideo,
- getVideosList,
- createUser,
- setAccessTokensToServers,
- killallServers,
- makePostBodyRequest,
- getUserAccessToken
-} from '../../utils'
-
-describe('Test video blacklists API validators', function () {
- let server: ServerInfo
- let userAccessToken = ''
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- await flushTests()
-
- server = await runServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const username = 'user1'
- const password = 'my super password'
- await createUser(server.url, server.accessToken, username, password)
- userAccessToken = await getUserAccessToken(server, { username, password })
-
- // Upload a video
- const videoAttributes = {}
- await uploadVideo(server.url, server.accessToken, videoAttributes)
-
- const res = await getVideosList(server.url)
-
- const videos = res.body.data
- server.video = videos[0]
- })
-
- 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 fields = {}
- await makePostBodyRequest({ url: server.url, path, token: server.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 })
- })
-
- it('Should fail with a non authenticated user', async function () {
- const fields = {}
- const path = basePath + server.video + '/blacklist'
- await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: 401 })
- })
-
- it('Should fail with a non admin user', async function () {
- const fields = {}
- const path = basePath + server.video + '/blacklist'
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 403 })
- })
-
- it('Should fail with a local video', async function () {
- const fields = {}
- const path = basePath + server.video.id + '/blacklist'
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 403 })
- })
- })
-
- after(async function () {
- killallServers([ server ])
-
- // Keep the logs if the test failed
- if (this['ok']) {
- await flushTests()
- }
- })
-})
import './single-pod'
import './video-abuse'
import './video-blacklist'
+import './video-blacklist-management'
import './multiple-pods'
import './request-schedulers'
import './friends-advanced'
--- /dev/null
+/* tslint:disable:no-unused-expressions */
+
+import 'mocha'
+import * as chai from 'chai'
+const expect = chai.expect
+import * as lodash from 'lodash'
+const orderBy = lodash.orderBy
+
+import {
+ ServerInfo,
+ flushTests,
+ wait,
+ setAccessTokensToServers,
+ flushAndRunMultipleServers,
+ killallServers,
+ makeFriends,
+ getVideosList,
+ uploadVideo,
+ addVideoToBlacklist,
+ removeVideoFromBlacklist,
+ getBlacklistedVideosList,
+ getSortedBlacklistedVideosList
+} from '../utils'
+
+describe('Test video blacklist management', function () {
+ let servers: ServerInfo[] = []
+
+ async function blacklistVideosOnPod (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)
+ }
+ }
+
+ before(async function () {
+ this.timeout(120000)
+
+ // Run servers
+ servers = await flushAndRunMultipleServers(2)
+
+ // Get the access tokens
+ await setAccessTokensToServers(servers)
+
+ // Pod 1 makes friend with pod 2
+ await makeFriends(servers[0].url, servers[0].accessToken)
+
+ // Upload 2 videos on pod 2
+ await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 1st video', description: 'A video on pod 2' })
+ await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 2nd video', description: 'A video on pod 2' })
+
+ // Wait videos propagation
+ await wait(22000)
+
+ // Blacklist the two videos on pod 1
+ await blacklistVideosOnPod(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 videos = res.body.data
+ expect(videos).to.be.an('array')
+ expect(videos.length).to.equal(2)
+ })
+
+ 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 videos = res.body.data
+ expect(videos).to.be.an('array')
+ expect(videos.length).to.equal(2)
+
+ const result = orderBy(res.body.data, [ 'id' ], [ 'desc' ])
+
+ expect(videos).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 videos = res.body.data
+ expect(videos).to.be.an('array')
+ expect(videos.length).to.equal(2)
+
+ const result = orderBy(res.body.data, [ 'name' ], [ 'desc' ])
+
+ expect(videos).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 videos = res.body.data
+ expect(videos).to.be.an('array')
+ expect(videos.length).to.equal(2)
+
+ const result = orderBy(res.body.data, [ 'createdAt' ])
+
+ expect(videos).to.deep.equal(result)
+ })
+ })
+
+ describe('When removing a blacklisted video', function () {
+ let videoToRemove
+ let blacklist = []
+
+ it('Should not have any video in videos list on pod 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 pod 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.videoId)
+ })
+
+ it('Should have the ex-blacklisted video in videos list on pod 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.name)
+ expect(videos[0].id).to.equal(videoToRemove.videoId)
+ })
+
+ it('Should not have the ex-blacklisted video in videos blacklist list on pod 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)
+
+ if (this['ok']) {
+ await flushTests()
+ }
+ })
+})
let servers: ServerInfo[] = []
before(async function () {
- this.timeout(30000)
+ this.timeout(60000)
// Run servers
servers = await flushAndRunMultipleServers(2)
export * from './servers'
export * from './users'
export * from './video-abuses'
-export * from './video-blacklists'
+export * from './video-blacklist'
export * from './videos'
--- /dev/null
+import * as request from 'supertest'
+
+function addVideoToBlacklist (url: string, token: string, videoId: number, specialStatus = 204) {
+ const path = '/api/v1/videos/' + videoId + '/blacklist'
+
+ return request(url)
+ .post(path)
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + token)
+ .expect(specialStatus)
+}
+
+function removeVideoFromBlacklist (url: string, token: string, videoId: number, specialStatus = 204) {
+ const path = '/api/v1/blacklist/' + videoId
+
+ return request(url)
+ .delete(path)
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + token)
+ .expect(specialStatus)
+}
+
+function getBlacklistedVideosList (url: string, token: string, specialStatus = 200) {
+ const path = '/api/v1/blacklist/'
+
+ return request(url)
+ .get(path)
+ .query({ sort: 'createdAt' })
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + token)
+ .expect(specialStatus)
+ .expect('Content-Type', /json/)
+}
+
+function getSortedBlacklistedVideosList (url: string, token: string, sort: string, specialStatus = 200) {
+ const path = '/api/v1/blacklist/'
+
+ return request(url)
+ .get(path)
+ .query({ sort: sort })
+ .set('Accept', 'application/json')
+ .set('Authorization', 'Bearer ' + token)
+ .expect(specialStatus)
+ .expect('Content-Type', /json/)
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+ addVideoToBlacklist,
+ removeVideoFromBlacklist,
+ getBlacklistedVideosList,
+ getSortedBlacklistedVideosList
+}
+++ /dev/null
-import * as request from 'supertest'
-
-function addVideoToBlacklist (url: string, token: string, videoId: number, specialStatus = 204) {
- const path = '/api/v1/videos/' + videoId + '/blacklist'
-
- return request(url)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(specialStatus)
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- addVideoToBlacklist
-}
id: number
videoId: number
createdAt: Date
+ updatedAt: Date
+ name: string
+ uuid: string
+ description: string
+ duration: number
+ views: number
+ likes: number
+ dislikes: number
+ nsfw: boolean
}