author: string
by: string
createdAt: Date
+ updatedAt: Date
categoryLabel: string
category: number
licenceLabel: string
} from '../../../middlewares'
import { logger, retryTransactionWrapper } from '../../../helpers'
import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib'
-import { PodInstance } from '../../../models'
+import { PodInstance, VideoFileInstance } from '../../../models'
import {
RemoteVideoRequest,
RemoteVideoCreateData,
// Get the function we need to call in order to process the request
const fun = functionsHash[request.type]
if (fun === undefined) {
- logger.error('Unkown remote request type %s.', request.type)
+ logger.error('Unknown remote request type %s.', request.type)
return
}
return quickAndDirtyUpdatesVideoToFriends(qadusParams, t)
})
})
- .then(() => logger.info('Remote video event processed for video %s.', eventData.uuid))
+ .then(() => logger.info('Remote video event processed for video with uuid %s.', eventData.uuid))
.catch(err => {
logger.debug('Cannot process a video event.', err)
throw err
}
function quickAndDirtyUpdateVideo (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
- let videoName
+ let videoUUID = ''
return db.sequelize.transaction(t => {
return fetchVideoByHostAndUUID(fromPod.host, videoData.uuid)
.then(videoInstance => {
const options = { transaction: t }
- videoName = videoInstance.name
+ videoUUID = videoInstance.uuid
if (videoData.views) {
videoInstance.set('views', videoData.views)
return videoInstance.save(options)
})
})
- .then(() => logger.info('Remote video %s quick and dirty updated', videoName))
+ .then(() => logger.info('Remote video with uuid %s quick and dirty updated', videoUUID))
.catch(err => logger.debug('Cannot quick and dirty update the remote video.', err))
}
return videoCreated.setTags(tagInstances, options)
})
})
- .then(() => logger.info('Remote video %s inserted.', videoToCreateData.name))
+ .then(() => logger.info('Remote video with uuid %s inserted.', videoToCreateData.uuid))
.catch(err => {
logger.debug('Cannot insert the remote video.', err)
throw err
return videoInstance.save(options).then(() => ({ videoInstance, tagInstances }))
})
.then(({ tagInstances, videoInstance }) => {
- const tasks = []
+ const tasks: Promise<void>[] = []
+
+ // Remove old video files
+ videoInstance.VideoFiles.forEach(videoFile => {
+ tasks.push(videoFile.destroy())
+ })
+
+ return Promise.all(tasks).then(() => ({ tagInstances, videoInstance }))
+ })
+ .then(({ tagInstances, videoInstance }) => {
+ const tasks: Promise<VideoFileInstance>[] = []
const options = {
transaction: t
}
return videoInstance.setTags(tagInstances, options)
})
})
- .then(() => logger.info('Remote video %s updated', videoAttributesToUpdate.name))
+ .then(() => logger.info('Remote video with uuid %s updated', videoAttributesToUpdate.uuid))
.catch(err => {
// This is just a debug because we will retry the insert
logger.debug('Cannot update the remote video.', err)
// We need the instance because we have to remove some other stuffs (thumbnail etc)
return fetchVideoByHostAndUUID(fromPod.host, videoToRemoveData.uuid)
.then(video => {
- logger.debug('Removing remote video %s.', video.uuid)
+ logger.debug('Removing remote video with uuid %s.', video.uuid)
return video.destroy()
})
.catch(err => {
function addVideo (req: express.Request, res: express.Response, videoPhysicalFile: Express.Multer.File) {
const videoInfo: VideoCreate = req.body
+ let videoUUID = ''
return db.sequelize.transaction(t => {
const user = res.locals.oauth.token.User
.then(videoCreated => {
// Do not forget to add Author information to the created video
videoCreated.Author = author
+ videoUUID = videoCreated.uuid
return { tagInstances, video: videoCreated, videoFile }
})
})
})
})
- .then(() => logger.info('Video with name %s created.', videoInfo.name))
+ .then(() => logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoUUID))
.catch((err: Error) => {
logger.debug('Cannot insert the video.', err)
throw err
})
})
.then(() => {
- logger.info('Video with name %s updated.', videoInstance.name)
+ logger.info('Video with name %s and uuid %s updated.', videoInstance.name, videoInstance.uuid)
})
.catch(err => {
logger.debug('Cannot update the video.', err)
const videoInstance = res.locals.video
videoInstance.destroy()
- .then(() => res.type('json').status(204).end())
+ .then(() => {
+ logger.info('Video with name %s and uuid %s deleted.', videoInstance.name, videoInstance.uuid)
+ res.type('json').status(204).end()
+ })
.catch(err => {
logger.error('Errors when removed the video.', err)
return next(err)
checkErrors(req, res, () => {
checkVideoExists(req.params.id, res, () => {
- // We need to make additional checks
-
// Check if the user who did the request is able to delete the video
checkUserCanDeleteVideo(res.locals.oauth.token.User.id, res, () => {
next()
// Retrieve the user who did the request
db.User.loadById(userId)
.then(user => {
+ if (res.locals.video.isOwned() === false) {
+ return res.status(403).send('Cannot remove video of another pod, blacklist it')
+ }
+
// Check if the user can delete the video
// The user can delete it if s/he is an admin
// Or if s/he is the video's author
- if (user.isAdmin() === false) {
- if (res.locals.video.isOwned() === false) {
- return res.status(403).send('Cannot remove video of another pod')
- }
-
- if (res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
- return res.status(403).send('Cannot remove video of another user')
- }
+ if (user.isAdmin() === false && res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
+ return res.status(403).send('Cannot remove video of another user')
}
// If we reach this comment, we can delete the video
import * as program from 'commander'
-import { isEqual, differenceWith } from 'lodash'
// /!\ Before imports /!\
process.env.NODE_ENV = 'test'
import { REQUESTS_INTERVAL } from '../../initializers/constants'
-import { Video, VideoRateType } from '../../../shared'
+import { Video, VideoRateType, VideoFile } from '../../../shared'
import {
ServerInfo as DefaultServerInfo,
flushAndRunMultipleServers,
checking = true
const waitingInterval = setInterval(async () => {
- const awaitingRequests = await isThereAwaitingRequests(servers)
- if (awaitingRequests === true) {
- console.log('A server has awaiting requests, waiting...')
+ const pendingRequests = await isTherePendingRequests(servers)
+ if (pendingRequests === true) {
+ console.log('A server has pending requests, waiting...')
return
}
+ // Even if there are no pending request, wait some potential processes
+ await wait(2000)
await checkIntegrity(servers)
initializeRequestsPerServer(servers)
async function remove (servers: ServerInfo[], numServer: number) {
const res = await getVideosList(servers[numServer].url)
- const videos = res.body.data
+ const videos = res.body.data.filter(video => video.isLocal === true)
if (videos.length === 0) return undefined
const toRemove = videos[getRandomInt(0, videos.length)].id
// Fetch all videos and remove some fields that can differ between pods
for (const server of servers) {
- const p = getAllVideosListBy(server.url).then(res => {
- const serverVideos = res.body.data
- for (const serverVideo of serverVideos) {
- delete serverVideo.id
- delete serverVideo.isLocal
- delete serverVideo.thumbnailPath
- delete serverVideo.updatedAt
- delete serverVideo.views
- }
-
- videos.push(serverVideos)
- })
-
+ const p = getAllVideosListBy(server.url).then(res => videos.push(res.body.data))
tasks.push(p)
}
let i = 0
for (const video of videos) {
- if (!isEqual(video, videos[0])) {
+ const differences = areDifferences(video, videos[0])
+ if (differences !== undefined) {
console.error('Integrity not ok with server %d!', i + 1)
if (displayDiffOnFail) {
- console.log(differenceWith(videos[0], video, isEqual))
- console.log(differenceWith(video, videos[0], isEqual))
+ console.log(differences)
}
process.exit(-1)
console.log('Integrity ok.')
}
+function areDifferences (videos1: Video[], videos2: Video[]) {
+ // Remove some keys we don't want to compare
+ videos1.concat(videos2).forEach(video => {
+ delete video.id
+ delete video.isLocal
+ delete video.thumbnailPath
+ delete video.updatedAt
+ delete video.views
+ })
+
+ if (videos1.length !== videos2.length) {
+ return `Videos length are different (${videos1.length}/${videos2.length}).`
+ }
+
+ for (const video1 of videos1) {
+ const video2 = videos2.find(video => video.uuid === video1.uuid)
+
+ if (!video2) return 'Video ' + video1.uuid + ' is missing.'
+
+ for (const videoKey of Object.keys(video1)) {
+ const attribute1 = video1[videoKey]
+ const attribute2 = video2[videoKey]
+
+ if (videoKey === 'tags') {
+ if (attribute1.length !== attribute2.length) {
+ return 'Tags are different.'
+ }
+
+ attribute1.forEach(tag1 => {
+ if (attribute2.indexOf(tag1) === -1) {
+ return 'Tag ' + tag1 + ' is missing.'
+ }
+ })
+ } else if (videoKey === 'files') {
+ if (attribute1.length !== attribute2.length) {
+ return 'Video files are different.'
+ }
+
+ attribute1.forEach((videoFile1: VideoFile) => {
+ const videoFile2: VideoFile = attribute2.find(videoFile => videoFile.magnetUri === videoFile1.magnetUri)
+ if (!videoFile2) {
+ return `Video ${video1.uuid} has missing video file ${videoFile1.magnetUri}.`
+ }
+
+ if (videoFile1.size !== videoFile2.size || videoFile1.resolutionLabel !== videoFile2.resolutionLabel) {
+ return `Video ${video1.uuid} has different video file ${videoFile1.magnetUri}.`
+ }
+ })
+ } else {
+ if (attribute1 !== attribute2) {
+ return `Video ${video1.uuid} has different value for attribute ${videoKey}.`
+ }
+ }
+ }
+ }
+
+ return undefined
+}
+
function goodbye () {
return process.exit(-1)
}
-async function isThereAwaitingRequests (servers: ServerInfo[]) {
+async function isTherePendingRequests (servers: ServerInfo[]) {
const tasks: Promise<any>[] = []
- let awaitingRequests = false
+ let pendingRequests = false
- // Check if each server has awaiting request
+ // Check if each server has pending request
for (const server of servers) {
const p = getRequestsStats(server).then(res => {
const stats = res.body
stats.requestVideoEventScheduler.totalRequests !== 0 ||
stats.requestVideoQaduScheduler.totalRequests !== 0
) {
- awaitingRequests = true
+ pendingRequests = true
}
})
await Promise.all(tasks)
- return awaitingRequests
+ return pendingRequests
}
uuid: string
author: string
createdAt: Date
+ updatedAt: Date
categoryLabel: string
category: number
licenceLabel: string