From 191764f30b0a812bf3a9dbdc7daf1d5afe25e12a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 14 Aug 2018 09:08:47 +0200 Subject: Improve blacklist management --- server/controllers/api/videos/blacklist.ts | 4 ++-- server/middlewares/validators/videos.ts | 33 ++++++++++++++++++---------- server/models/video/video-abuse.ts | 1 - server/models/video/video-blacklist.ts | 11 +++++++--- server/models/video/video.ts | 31 ++++++++++++++++++++++---- server/tests/utils/videos/video-blacklist.ts | 3 ++- 6 files changed, 60 insertions(+), 23 deletions(-) (limited to 'server') diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts index 358f339ed..7f803c8e9 100644 --- a/server/controllers/api/videos/blacklist.ts +++ b/server/controllers/api/videos/blacklist.ts @@ -1,5 +1,5 @@ import * as express from 'express' -import { BlacklistedVideo, UserRight, VideoBlacklistCreate } from '../../../../shared' +import { VideoBlacklist, UserRight, VideoBlacklistCreate } from '../../../../shared' import { logger } from '../../../helpers/logger' import { getFormattedObjects } from '../../../helpers/utils' import { @@ -87,7 +87,7 @@ async function updateVideoBlacklistController (req: express.Request, res: expres async function listBlacklist (req: express.Request, res: express.Response, next: express.NextFunction) { const resultList = await VideoBlacklistModel.listForApi(req.query.start, req.query.count, req.query.sort) - return res.json(getFormattedObjects(resultList.data, resultList.total)) + return res.json(getFormattedObjects(resultList.data, resultList.total)) } async function removeVideoFromBlacklistController (req: express.Request, res: express.Response, next: express.NextFunction) { diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index 203a00876..77d601a4d 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -35,6 +35,8 @@ import { VideoShareModel } from '../../models/video/video-share' import { authenticate } from '../oauth' import { areValidationErrors } from './utils' import { cleanUpReqFiles } from '../../helpers/utils' +import { VideoModel } from '../../models/video/video' +import { UserModel } from '../../models/account/user' const videosAddValidator = getCommonVideoAttributes().concat([ body('videofile') @@ -131,7 +133,25 @@ const videosGetValidator = [ if (areValidationErrors(req, res)) return if (!await isVideoExist(req.params.id, res)) return - const video = res.locals.video + const video: VideoModel = res.locals.video + + // Video private or blacklisted + if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) { + authenticate(req, res, () => { + const user: UserModel = res.locals.oauth.token.User + + // Only the owner or a user that have blacklist rights can see the video + if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) { + return res.status(403) + .json({ error: 'Cannot get this private or blacklisted video.' }) + .end() + } + + return next() + }) + + return + } // Video is public, anyone can access it if (video.privacy === VideoPrivacy.PUBLIC) return next() @@ -143,17 +163,6 @@ const videosGetValidator = [ // Don't leak this unlisted video return res.status(404).end() } - - // Video is private, check the user - authenticate(req, res, () => { - if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { - return res.status(403) - .json({ error: 'Cannot get this private video of another user' }) - .end() - } - - return next() - }) } ] diff --git a/server/models/video/video-abuse.ts b/server/models/video/video-abuse.ts index 10a191372..dbb88ca45 100644 --- a/server/models/video/video-abuse.ts +++ b/server/models/video/video-abuse.ts @@ -137,7 +137,6 @@ export class VideoAbuseModel extends Model { video: { id: this.Video.id, uuid: this.Video.uuid, - url: this.Video.url, name: this.Video.name }, createdAt: this.createdAt diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts index 1b8a338cb..eabc37ef0 100644 --- a/server/models/video/video-blacklist.ts +++ b/server/models/video/video-blacklist.ts @@ -16,7 +16,7 @@ import { getSortOnModel, throwIfNotValid } from '../utils' import { VideoModel } from './video' import { isVideoBlacklistReasonValid } from '../../helpers/custom-validators/video-blacklist' import { Emailer } from '../../lib/emailer' -import { BlacklistedVideo } from '../../../shared/models/videos' +import { VideoBlacklist } from '../../../shared/models/videos' import { CONSTRAINTS_FIELDS } from '../../initializers' @Table({ @@ -68,7 +68,12 @@ export class VideoBlacklistModel extends Model { offset: start, limit: count, order: getSortOnModel(sort.sortModel, sort.sortValue), - include: [ { model: VideoModel } ] + include: [ + { + model: VideoModel, + required: true + } + ] } return VideoBlacklistModel.findAndCountAll(query) @@ -90,7 +95,7 @@ export class VideoBlacklistModel extends Model { return VideoBlacklistModel.findOne(query) } - toFormattedJSON (): BlacklistedVideo { + toFormattedJSON (): VideoBlacklist { const video = this.Video return { diff --git a/server/models/video/video.ts b/server/models/video/video.ts index f3a900bc9..b13dee403 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -127,7 +127,8 @@ export enum ScopeNames { WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS', WITH_TAGS = 'WITH_TAGS', WITH_FILES = 'WITH_FILES', - WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE' + WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE', + WITH_BLACKLISTED = 'WITH_BLACKLISTED' } type AvailableForListOptions = { @@ -374,6 +375,15 @@ type AvailableForListOptions = { [ScopeNames.WITH_TAGS]: { include: [ () => TagModel ] }, + [ScopeNames.WITH_BLACKLISTED]: { + include: [ + { + attributes: [ 'id', 'reason' ], + model: () => VideoBlacklistModel, + required: false + } + ] + }, [ScopeNames.WITH_FILES]: { include: [ { @@ -1004,7 +1014,13 @@ export class VideoModel extends Model { } return VideoModel - .scope([ ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT_DETAILS, ScopeNames.WITH_SCHEDULED_UPDATE ]) + .scope([ + ScopeNames.WITH_TAGS, + ScopeNames.WITH_BLACKLISTED, + ScopeNames.WITH_FILES, + ScopeNames.WITH_ACCOUNT_DETAILS, + ScopeNames.WITH_SCHEDULED_UPDATE + ]) .findById(id, options) } @@ -1030,7 +1046,13 @@ export class VideoModel extends Model { } return VideoModel - .scope([ ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT_DETAILS, ScopeNames.WITH_SCHEDULED_UPDATE ]) + .scope([ + ScopeNames.WITH_TAGS, + ScopeNames.WITH_BLACKLISTED, + ScopeNames.WITH_FILES, + ScopeNames.WITH_ACCOUNT_DETAILS, + ScopeNames.WITH_SCHEDULED_UPDATE + ]) .findOne(options) } @@ -1276,7 +1298,8 @@ export class VideoModel extends Model { toFormattedDetailsJSON (): VideoDetails { const formattedJson = this.toFormattedJSON({ additionalAttributes: { - scheduledUpdate: true + scheduledUpdate: true, + blacklistInfo: true } }) diff --git a/server/tests/utils/videos/video-blacklist.ts b/server/tests/utils/videos/video-blacklist.ts index 7819f4b25..2c176fde0 100644 --- a/server/tests/utils/videos/video-blacklist.ts +++ b/server/tests/utils/videos/video-blacklist.ts @@ -19,7 +19,8 @@ function updateVideoBlacklist (url: string, token: string, videoId: number, reas .send({ reason }) .set('Accept', 'application/json') .set('Authorization', 'Bearer ' + token) - .expect(specialStatus)} + .expect(specialStatus) +} function removeVideoFromBlacklist (url: string, token: string, videoId: number | string, specialStatus = 204) { const path = '/api/v1/videos/' + videoId + '/blacklist' -- cgit v1.2.3