1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-04 02:09:37 +02:00

Merge branch 'develop' into pr/1285

This commit is contained in:
Chocobozzz 2019-02-11 14:09:23 +01:00
commit b718fd2237
No known key found for this signature in database
GPG key ID: 583A612D890159BE
387 changed files with 18290 additions and 10001 deletions

View file

@ -14,6 +14,8 @@ import { AccountModel } from '../../models/account/account'
import { VideoModel } from '../../models/video/video'
import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
import { VideoChannelModel } from '../../models/video/video-channel'
import { JobQueue } from '../../lib/job-queue'
import { logger } from '../../helpers/logger'
const accountsRouter = express.Router()
@ -57,6 +59,11 @@ export {
function getAccount (req: express.Request, res: express.Response, next: express.NextFunction) {
const account: AccountModel = res.locals.account
if (account.isOutdated()) {
JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'actor', url: account.Actor.url } })
.catch(err => logger.error('Cannot create AP refresher job for actor %s.', account.Actor.url, { err }))
}
return res.json(account.toFormattedJSON())
}

View file

@ -1,5 +1,5 @@
import * as express from 'express'
import { omit, snakeCase } from 'lodash'
import { snakeCase } from 'lodash'
import { ServerConfig, UserRight } from '../../../shared'
import { About } from '../../../shared/models/server/about.model'
import { CustomConfig } from '../../../shared/models/server/custom-config.model'
@ -78,6 +78,9 @@ async function getConfig (req: express.Request, res: express.Response) {
requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION
},
transcoding: {
hls: {
enabled: CONFIG.TRANSCODING.HLS.ENABLED
},
enabledResolutions
},
import: {
@ -120,6 +123,11 @@ async function getConfig (req: express.Request, res: express.Response) {
user: {
videoQuota: CONFIG.USER.VIDEO_QUOTA,
videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY
},
trending: {
videos: {
intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS
}
}
}
@ -241,6 +249,9 @@ function customConfig (): CustomConfig {
'480p': CONFIG.TRANSCODING.RESOLUTIONS[ '480p' ],
'720p': CONFIG.TRANSCODING.RESOLUTIONS[ '720p' ],
'1080p': CONFIG.TRANSCODING.RESOLUTIONS[ '1080p' ]
},
hls: {
enabled: CONFIG.TRANSCODING.HLS.ENABLED
}
},
import: {

View file

@ -8,6 +8,7 @@ import { VideoCommentModel } from '../../../models/video/video-comment'
import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../../initializers/constants'
import { cacheRoute } from '../../../middlewares/cache'
import { VideoFileModel } from '../../../models/video/video-file'
const statsRouter = express.Router()
@ -16,11 +17,12 @@ statsRouter.get('/stats',
asyncMiddleware(getStats)
)
async function getStats (req: express.Request, res: express.Response, next: express.NextFunction) {
async function getStats (req: express.Request, res: express.Response) {
const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
const { totalUsers } = await UserModel.getStats()
const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
const videosRedundancyStats = await Promise.all(
CONFIG.REDUNDANCY.VIDEOS.STRATEGIES.map(r => {
@ -32,8 +34,9 @@ async function getStats (req: express.Request, res: express.Response, next: expr
const data: ServerStats = {
totalLocalVideos,
totalLocalVideoViews,
totalVideos,
totalLocalVideoFilesSize,
totalLocalVideoComments,
totalVideos,
totalVideoComments,
totalUsers,
totalInstanceFollowers,

View file

@ -41,6 +41,7 @@ import { myBlocklistRouter } from './my-blocklist'
import { myVideosHistoryRouter } from './my-history'
import { myNotificationsRouter } from './my-notifications'
import { Notifier } from '../../../lib/notifier'
import { mySubscriptionsRouter } from './my-subscriptions'
const auditLogger = auditLoggerFactory('users')
@ -58,6 +59,7 @@ const askSendEmailLimiter = new RateLimit({
const usersRouter = express.Router()
usersRouter.use('/', myNotificationsRouter)
usersRouter.use('/', mySubscriptionsRouter)
usersRouter.use('/', myBlocklistRouter)
usersRouter.use('/', myVideosHistoryRouter)
usersRouter.use('/', meRouter)
@ -227,7 +229,7 @@ async function unblockUser (req: express.Request, res: express.Response, next: e
return res.status(204).end()
}
async function blockUser (req: express.Request, res: express.Response, next: express.NextFunction) {
async function blockUser (req: express.Request, res: express.Response) {
const user: UserModel = res.locals.user
const reason = req.body.reason
@ -236,23 +238,23 @@ async function blockUser (req: express.Request, res: express.Response, next: exp
return res.status(204).end()
}
function getUser (req: express.Request, res: express.Response, next: express.NextFunction) {
function getUser (req: express.Request, res: express.Response) {
return res.json((res.locals.user as UserModel).toFormattedJSON())
}
async function autocompleteUsers (req: express.Request, res: express.Response, next: express.NextFunction) {
async function autocompleteUsers (req: express.Request, res: express.Response) {
const resultList = await UserModel.autoComplete(req.query.search as string)
return res.json(resultList)
}
async function listUsers (req: express.Request, res: express.Response, next: express.NextFunction) {
async function listUsers (req: express.Request, res: express.Response) {
const resultList = await UserModel.listForApi(req.query.start, req.query.count, req.query.sort, req.query.search)
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
async function removeUser (req: express.Request, res: express.Response, next: express.NextFunction) {
async function removeUser (req: express.Request, res: express.Response) {
const user: UserModel = res.locals.user
await user.destroy()
@ -262,12 +264,13 @@ async function removeUser (req: express.Request, res: express.Response, next: ex
return res.sendStatus(204)
}
async function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) {
async function updateUser (req: express.Request, res: express.Response) {
const body: UserUpdate = req.body
const userToUpdate = res.locals.user as UserModel
const oldUserAuditView = new UserAuditView(userToUpdate.toFormattedJSON())
const roleChanged = body.role !== undefined && body.role !== userToUpdate.role
if (body.password !== undefined) userToUpdate.password = body.password
if (body.email !== undefined) userToUpdate.email = body.email
if (body.emailVerified !== undefined) userToUpdate.emailVerified = body.emailVerified
if (body.videoQuota !== undefined) userToUpdate.videoQuota = body.videoQuota
@ -277,11 +280,11 @@ async function updateUser (req: express.Request, res: express.Response, next: ex
const user = await userToUpdate.save()
// Destroy user token to refresh rights
if (roleChanged) await deleteUserToken(userToUpdate.id)
if (roleChanged || body.password !== undefined) await deleteUserToken(userToUpdate.id)
auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
// Don't need to send this update to followers, these attributes are not propagated
// Don't need to send this update to followers, these attributes are not federated
return res.sendStatus(204)
}
@ -291,7 +294,7 @@ async function askResetUserPassword (req: express.Request, res: express.Response
const verificationString = await Redis.Instance.setResetPasswordVerificationString(user.id)
const url = CONFIG.WEBSERVER.URL + '/reset-password?userId=' + user.id + '&verificationString=' + verificationString
await Emailer.Instance.addForgetPasswordEmailJob(user.email, url)
await Emailer.Instance.addPasswordResetEmailJob(user.email, url)
return res.status(204).end()
}

View file

@ -8,36 +8,23 @@ import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
authenticate,
commonVideosFiltersValidator,
paginationValidator,
setDefaultPagination,
setDefaultSort,
userSubscriptionAddValidator,
userSubscriptionGetValidator,
usersUpdateMeValidator,
usersVideoRatingValidator
} from '../../../middlewares'
import {
areSubscriptionsExistValidator,
deleteMeValidator,
userSubscriptionsSortValidator,
videoImportsSortValidator,
videosSortValidator
} from '../../../middlewares/validators'
import { deleteMeValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
import { UserModel } from '../../../models/account/user'
import { VideoModel } from '../../../models/video/video'
import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type'
import { buildNSFWFilter, createReqFiles } from '../../../helpers/express-utils'
import { createReqFiles } from '../../../helpers/express-utils'
import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model'
import { updateAvatarValidator } from '../../../middlewares/validators/avatar'
import { updateActorAvatarFile } from '../../../lib/avatar'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
import { VideoImportModel } from '../../../models/video/video-import'
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { JobQueue } from '../../../lib/job-queue'
import { logger } from '../../../helpers/logger'
import { AccountModel } from '../../../models/account/account'
const auditLogger = auditLoggerFactory('users-me')
@ -98,51 +85,6 @@ meRouter.post('/me/avatar/pick',
asyncRetryTransactionMiddleware(updateMyAvatar)
)
// ##### Subscriptions part #####
meRouter.get('/me/subscriptions/videos',
authenticate,
paginationValidator,
videosSortValidator,
setDefaultSort,
setDefaultPagination,
commonVideosFiltersValidator,
asyncMiddleware(getUserSubscriptionVideos)
)
meRouter.get('/me/subscriptions/exist',
authenticate,
areSubscriptionsExistValidator,
asyncMiddleware(areSubscriptionsExist)
)
meRouter.get('/me/subscriptions',
authenticate,
paginationValidator,
userSubscriptionsSortValidator,
setDefaultSort,
setDefaultPagination,
asyncMiddleware(getUserSubscriptions)
)
meRouter.post('/me/subscriptions',
authenticate,
userSubscriptionAddValidator,
asyncMiddleware(addUserSubscription)
)
meRouter.get('/me/subscriptions/:uri',
authenticate,
userSubscriptionGetValidator,
getUserSubscription
)
meRouter.delete('/me/subscriptions/:uri',
authenticate,
userSubscriptionGetValidator,
asyncRetryTransactionMiddleware(deleteUserSubscription)
)
// ---------------------------------------------------------------------------
export {
@ -151,100 +93,6 @@ export {
// ---------------------------------------------------------------------------
async function areSubscriptionsExist (req: express.Request, res: express.Response) {
const uris = req.query.uris as string[]
const user = res.locals.oauth.token.User as UserModel
const handles = uris.map(u => {
let [ name, host ] = u.split('@')
if (host === CONFIG.WEBSERVER.HOST) host = null
return { name, host, uri: u }
})
const results = await ActorFollowModel.listSubscribedIn(user.Account.Actor.id, handles)
const existObject: { [id: string ]: boolean } = {}
for (const handle of handles) {
const obj = results.find(r => {
const server = r.ActorFollowing.Server
return r.ActorFollowing.preferredUsername === handle.name &&
(
(!server && !handle.host) ||
(server.host === handle.host)
)
})
existObject[handle.uri] = obj !== undefined
}
return res.json(existObject)
}
async function addUserSubscription (req: express.Request, res: express.Response) {
const user = res.locals.oauth.token.User as UserModel
const [ name, host ] = req.body.uri.split('@')
const payload = {
name,
host,
followerActorId: user.Account.Actor.id
}
JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
.catch(err => logger.error('Cannot create follow job for subscription %s.', req.body.uri, err))
return res.status(204).end()
}
function getUserSubscription (req: express.Request, res: express.Response) {
const subscription: ActorFollowModel = res.locals.subscription
return res.json(subscription.ActorFollowing.VideoChannel.toFormattedJSON())
}
async function deleteUserSubscription (req: express.Request, res: express.Response) {
const subscription: ActorFollowModel = res.locals.subscription
await sequelizeTypescript.transaction(async t => {
return subscription.destroy({ transaction: t })
})
return res.type('json').status(204).end()
}
async function getUserSubscriptions (req: express.Request, res: express.Response) {
const user = res.locals.oauth.token.User as UserModel
const actorId = user.Account.Actor.id
const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort)
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
async function getUserSubscriptionVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
const user = res.locals.oauth.token.User as UserModel
const resultList = await VideoModel.listForApi({
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
includeLocalVideos: false,
categoryOneOf: req.query.categoryOneOf,
licenceOneOf: req.query.licenceOneOf,
languageOneOf: req.query.languageOneOf,
tagsOneOf: req.query.tagsOneOf,
tagsAllOf: req.query.tagsAllOf,
nsfw: buildNSFWFilter(res, req.query.nsfw),
filter: req.query.filter as VideoFilter,
withFiles: false,
followerActorId: user.Account.Actor.id,
user
})
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
const user = res.locals.oauth.token.User as UserModel
const resultList = await VideoModel.listUserVideosForApi(
@ -319,7 +167,7 @@ async function deleteMe (req: express.Request, res: express.Response) {
return res.sendStatus(204)
}
async function updateMe (req: express.Request, res: express.Response, next: express.NextFunction) {
async function updateMe (req: express.Request, res: express.Response) {
const body: UserUpdateMe = req.body
const user: UserModel = res.locals.oauth.token.user

View file

@ -0,0 +1,170 @@
import * as express from 'express'
import 'multer'
import { getFormattedObjects } from '../../../helpers/utils'
import { CONFIG, sequelizeTypescript } from '../../../initializers'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
authenticate,
commonVideosFiltersValidator,
paginationValidator,
setDefaultPagination,
setDefaultSort,
userSubscriptionAddValidator,
userSubscriptionGetValidator
} from '../../../middlewares'
import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators'
import { UserModel } from '../../../models/account/user'
import { VideoModel } from '../../../models/video/video'
import { buildNSFWFilter } from '../../../helpers/express-utils'
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { JobQueue } from '../../../lib/job-queue'
import { logger } from '../../../helpers/logger'
const mySubscriptionsRouter = express.Router()
mySubscriptionsRouter.get('/me/subscriptions/videos',
authenticate,
paginationValidator,
videosSortValidator,
setDefaultSort,
setDefaultPagination,
commonVideosFiltersValidator,
asyncMiddleware(getUserSubscriptionVideos)
)
mySubscriptionsRouter.get('/me/subscriptions/exist',
authenticate,
areSubscriptionsExistValidator,
asyncMiddleware(areSubscriptionsExist)
)
mySubscriptionsRouter.get('/me/subscriptions',
authenticate,
paginationValidator,
userSubscriptionsSortValidator,
setDefaultSort,
setDefaultPagination,
asyncMiddleware(getUserSubscriptions)
)
mySubscriptionsRouter.post('/me/subscriptions',
authenticate,
userSubscriptionAddValidator,
asyncMiddleware(addUserSubscription)
)
mySubscriptionsRouter.get('/me/subscriptions/:uri',
authenticate,
userSubscriptionGetValidator,
getUserSubscription
)
mySubscriptionsRouter.delete('/me/subscriptions/:uri',
authenticate,
userSubscriptionGetValidator,
asyncRetryTransactionMiddleware(deleteUserSubscription)
)
// ---------------------------------------------------------------------------
export {
mySubscriptionsRouter
}
// ---------------------------------------------------------------------------
async function areSubscriptionsExist (req: express.Request, res: express.Response) {
const uris = req.query.uris as string[]
const user = res.locals.oauth.token.User as UserModel
const handles = uris.map(u => {
let [ name, host ] = u.split('@')
if (host === CONFIG.WEBSERVER.HOST) host = null
return { name, host, uri: u }
})
const results = await ActorFollowModel.listSubscribedIn(user.Account.Actor.id, handles)
const existObject: { [id: string ]: boolean } = {}
for (const handle of handles) {
const obj = results.find(r => {
const server = r.ActorFollowing.Server
return r.ActorFollowing.preferredUsername === handle.name &&
(
(!server && !handle.host) ||
(server.host === handle.host)
)
})
existObject[handle.uri] = obj !== undefined
}
return res.json(existObject)
}
async function addUserSubscription (req: express.Request, res: express.Response) {
const user = res.locals.oauth.token.User as UserModel
const [ name, host ] = req.body.uri.split('@')
const payload = {
name,
host,
followerActorId: user.Account.Actor.id
}
JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
.catch(err => logger.error('Cannot create follow job for subscription %s.', req.body.uri, err))
return res.status(204).end()
}
function getUserSubscription (req: express.Request, res: express.Response) {
const subscription: ActorFollowModel = res.locals.subscription
return res.json(subscription.ActorFollowing.VideoChannel.toFormattedJSON())
}
async function deleteUserSubscription (req: express.Request, res: express.Response) {
const subscription: ActorFollowModel = res.locals.subscription
await sequelizeTypescript.transaction(async t => {
return subscription.destroy({ transaction: t })
})
return res.type('json').status(204).end()
}
async function getUserSubscriptions (req: express.Request, res: express.Response) {
const user = res.locals.oauth.token.User as UserModel
const actorId = user.Account.Actor.id
const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort)
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
async function getUserSubscriptionVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
const user = res.locals.oauth.token.User as UserModel
const resultList = await VideoModel.listForApi({
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
includeLocalVideos: false,
categoryOneOf: req.query.categoryOneOf,
licenceOneOf: req.query.licenceOneOf,
languageOneOf: req.query.languageOneOf,
tagsOneOf: req.query.tagsOneOf,
tagsAllOf: req.query.tagsAllOf,
nsfw: buildNSFWFilter(res, req.query.nsfw),
filter: req.query.filter as VideoFilter,
withFiles: false,
followerActorId: user.Account.Actor.id,
user
})
return res.json(getFormattedObjects(resultList.data, resultList.total))
}

View file

@ -30,6 +30,7 @@ import { updateActorAvatarFile } from '../../lib/avatar'
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger'
import { resetSequelizeInstance } from '../../helpers/database-utils'
import { UserModel } from '../../models/account/user'
import { JobQueue } from '../../lib/job-queue'
const auditLogger = auditLoggerFactory('channels')
const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR })
@ -197,6 +198,11 @@ async function removeVideoChannel (req: express.Request, res: express.Response)
async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id)
if (videoChannelWithVideos.isOutdated()) {
JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'actor', url: videoChannelWithVideos.Actor.url } })
.catch(err => logger.error('Cannot create AP refresher job for actor %s.', videoChannelWithVideos.Actor.url, { err }))
}
return res.json(videoChannelWithVideos.toFormattedJSON())
}

View file

@ -3,7 +3,6 @@ import { UserRight, VideoAbuseCreate, VideoAbuseState } from '../../../../shared
import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers'
import { sendVideoAbuse } from '../../../lib/activitypub/send'
import {
asyncMiddleware,
asyncRetryTransactionMiddleware,
@ -23,6 +22,7 @@ import { VideoAbuseModel } from '../../../models/video/video-abuse'
import { auditLoggerFactory, VideoAbuseAuditView } from '../../../helpers/audit-logger'
import { UserModel } from '../../../models/account/user'
import { Notifier } from '../../../lib/notifier'
import { sendVideoAbuse } from '../../../lib/activitypub/send/send-flag'
const auditLogger = auditLoggerFactory('abuse')
const abuseVideoRouter = express.Router()

View file

@ -18,6 +18,8 @@ import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
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()
@ -66,12 +68,17 @@ async function addVideoToBlacklist (req: express.Request, res: express.Response)
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)
@ -101,8 +108,14 @@ async function removeVideoFromBlacklistController (req: express.Request, res: ex
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)

View file

@ -164,6 +164,7 @@ function buildVideo (channelId: number, body: VideoImportCreate, importData: You
licence: body.licence || importData.licence,
language: body.language || undefined,
commentsEnabled: body.commentsEnabled || true,
downloadEnabled: body.downloadEnabled || true,
waitTranscoding: body.waitTranscoding || false,
state: VideoState.TO_IMPORT,
nsfw: body.nsfw || importData.nsfw || false,

View file

@ -23,7 +23,6 @@ import {
fetchRemoteVideoDescription,
getVideoActivityPubUrl
} from '../../../lib/activitypub'
import { sendCreateView } from '../../../lib/activitypub/send'
import { JobQueue } from '../../../lib/job-queue'
import { Redis } from '../../../lib/redis'
import {
@ -37,6 +36,7 @@ import {
setDefaultPagination,
setDefaultSort,
videosAddValidator,
videosCustomGetValidator,
videosGetValidator,
videosRemoveValidator,
videosSortValidator,
@ -59,6 +59,7 @@ import { resetSequelizeInstance } from '../../../helpers/database-utils'
import { move } from 'fs-extra'
import { watchingRouter } from './watching'
import { Notifier } from '../../../lib/notifier'
import { sendView } from '../../../lib/activitypub/send/send-view'
const auditLogger = auditLoggerFactory('videos')
const videosRouter = express.Router()
@ -123,9 +124,9 @@ videosRouter.get('/:id/description',
)
videosRouter.get('/:id',
optionalAuthenticate,
asyncMiddleware(videosGetValidator),
asyncMiddleware(videosCustomGetValidator('only-video-with-rights')),
asyncMiddleware(checkVideoFollowConstraints),
getVideo
asyncMiddleware(getVideo)
)
videosRouter.post('/:id/views',
asyncMiddleware(videosGetValidator),
@ -181,6 +182,7 @@ async function addVideo (req: express.Request, res: express.Response) {
licence: videoInfo.licence,
language: videoInfo.language,
commentsEnabled: videoInfo.commentsEnabled || false,
downloadEnabled: videoInfo.downloadEnabled || true,
waitTranscoding: videoInfo.waitTranscoding || false,
state: CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED,
nsfw: videoInfo.nsfw || false,
@ -326,8 +328,9 @@ async function updateVideo (req: express.Request, res: express.Response) {
if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support)
if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description)
if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled)
if (videoInfoToUpdate.originallyPublishedAt !== undefined &&
videoInfoToUpdate.originallyPublishedAt !== null) {
if (videoInfoToUpdate.downloadEnabled !== undefined) videoInstance.set('downloadEnabled', videoInfoToUpdate.downloadEnabled)
if (videoInfoToUpdate.originallyPublishedAt !== undefined && videoInfoToUpdate.originallyPublishedAt !== null) {
videoInstance.set('originallyPublishedAt', videoInfoToUpdate.originallyPublishedAt)
}
@ -370,7 +373,11 @@ async function updateVideo (req: express.Request, res: express.Response) {
}
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),
@ -397,15 +404,17 @@ async function updateVideo (req: express.Request, res: express.Response) {
return res.type('json').status(204).end()
}
function getVideo (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video
async function getVideo (req: express.Request, res: express.Response) {
// We need more attributes
const userId: number = res.locals.oauth ? res.locals.oauth.token.User.id : null
const video: VideoModel = await VideoModel.loadForGetAPI(res.locals.video.id, undefined, userId)
if (videoInstance.isOutdated()) {
JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', videoUrl: videoInstance.url } })
.catch(err => logger.error('Cannot create AP refresher job for video %s.', videoInstance.url, { err }))
if (video.isOutdated()) {
JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', url: video.url } })
.catch(err => logger.error('Cannot create AP refresher job for video %s.', video.url, { err }))
}
return res.json(videoInstance.toFormattedDetailsJSON())
return res.json(video.toFormattedDetailsJSON())
}
async function viewVideo (req: express.Request, res: express.Response) {
@ -424,7 +433,7 @@ async function viewVideo (req: express.Request, res: express.Response) {
])
const serverActor = await getServerActor()
await sendCreateView(serverActor, videoInstance, undefined)
await sendView(serverActor, videoInstance, undefined)
return res.status(204).end()
}