From 38fa2065831b5f55be0d7f30f19a62c967397208 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 10 Nov 2017 14:48:08 +0100 Subject: [PATCH] Remove references to author --- server/controllers/activitypub/videos.ts | 26 +- server/controllers/api/users.ts | 8 +- server/controllers/api/videos/channel.ts | 20 +- server/controllers/api/videos/index.ts | 2 +- server/controllers/client.ts | 4 +- server/controllers/services.ts | 2 +- server/helpers/custom-validators/index.ts | 1 + .../custom-validators/video-accounts.ts | 45 ++ .../custom-validators/video-channels.ts | 4 +- server/helpers/custom-validators/videos.ts | 4 +- server/initializers/constants.ts | 2 +- server/initializers/database.ts | 4 - server/initializers/installer.ts | 4 +- server/lib/cache/videos-preview-cache.ts | 2 +- server/lib/friends.ts | 567 ------------------ .../video-file-optimizer-handler.ts | 4 +- .../video-file-transcoder-handler.ts | 4 +- server/lib/video-channel.ts | 2 +- .../middlewares/validators/video-channels.ts | 20 +- server/middlewares/validators/videos.ts | 14 +- server/models/account/user.ts | 4 +- server/models/index.ts | 1 - server/models/oauth/oauth-token.ts | 4 +- .../request/abstract-request-interface.ts | 12 - server/models/request/index.ts | 5 - server/models/request/request-interface.ts | 46 -- .../request/request-to-pod-interface.ts | 23 - server/models/request/request-to-pod.ts | 51 -- .../request/request-video-event-interface.ts | 50 -- server/models/request/request-video-event.ts | 191 ------ .../request/request-video-qadu-interface.ts | 48 -- server/models/request/request-video-qadu.ts | 159 ----- server/models/request/request.ts | 144 ----- server/models/video/index.ts | 1 - 34 files changed, 111 insertions(+), 1367 deletions(-) create mode 100644 server/helpers/custom-validators/video-accounts.ts delete mode 100644 server/lib/friends.ts delete mode 100644 server/models/request/abstract-request-interface.ts delete mode 100644 server/models/request/index.ts delete mode 100644 server/models/request/request-interface.ts delete mode 100644 server/models/request/request-to-pod-interface.ts delete mode 100644 server/models/request/request-to-pod.ts delete mode 100644 server/models/request/request-video-event-interface.ts delete mode 100644 server/models/request/request-video-event.ts delete mode 100644 server/models/request/request-video-qadu-interface.ts delete mode 100644 server/models/request/request-video-qadu.ts delete mode 100644 server/models/request/request.ts diff --git a/server/controllers/activitypub/videos.ts b/server/controllers/activitypub/videos.ts index 9a1868ff7..a9b31bf75 100644 --- a/server/controllers/activitypub/videos.ts +++ b/server/controllers/activitypub/videos.ts @@ -32,8 +32,8 @@ // RemoteVideoChannelCreateData, // RemoteVideoChannelUpdateData, // RemoteVideoChannelRemoveData, -// RemoteVideoAuthorRemoveData, -// RemoteVideoAuthorCreateData +// RemoteVideoAccountRemoveData, +// RemoteVideoAccountCreateData // } from '../../../../shared' // import { VideoInstance } from '../../../models/video/video-interface' // @@ -49,8 +49,8 @@ // functionsHash[ENDPOINT_ACTIONS.UPDATE_CHANNEL] = updateRemoteVideoChannelRetryWrapper // functionsHash[ENDPOINT_ACTIONS.REMOVE_CHANNEL] = removeRemoteVideoChannelRetryWrapper // functionsHash[ENDPOINT_ACTIONS.REPORT_ABUSE] = reportAbuseRemoteVideoRetryWrapper -// functionsHash[ENDPOINT_ACTIONS.ADD_AUTHOR] = addRemoteVideoAuthorRetryWrapper -// functionsHash[ENDPOINT_ACTIONS.REMOVE_AUTHOR] = removeRemoteVideoAuthorRetryWrapper +// functionsHash[ENDPOINT_ACTIONS.ADD_ACCOUNT] = addRemoteVideoAccountRetryWrapper +// functionsHash[ENDPOINT_ACTIONS.REMOVE_ACCOUNT] = removeRemoteVideoAccountRetryWrapper // // const remoteVideosRouter = express.Router() // @@ -245,24 +245,24 @@ // logger.info('Remote video with uuid %s removed.', videoToRemoveData.uuid) // } // -// async function removeRemoteVideoAuthorRetryWrapper (authorAttributesToRemove: RemoteVideoAuthorRemoveData, fromPod: PodInstance) { +// async function removeRemoteVideoAccountRetryWrapper (accountAttributesToRemove: RemoteVideoAccountRemoveData, fromPod: PodInstance) { // const options = { -// arguments: [ authorAttributesToRemove, fromPod ], -// errorMessage: 'Cannot remove the remote video author with many retries.' +// arguments: [ accountAttributesToRemove, fromPod ], +// errorMessage: 'Cannot remove the remote video account with many retries.' // } // -// await retryTransactionWrapper(removeRemoteVideoAuthor, options) +// await retryTransactionWrapper(removeRemoteVideoAccount, options) // } // -// async function removeRemoteVideoAuthor (authorAttributesToRemove: RemoteVideoAuthorRemoveData, fromPod: PodInstance) { -// logger.debug('Removing remote video author "%s".', authorAttributesToRemove.uuid) +// async function removeRemoteVideoAccount (accountAttributesToRemove: RemoteVideoAccountRemoveData, fromPod: PodInstance) { +// logger.debug('Removing remote video account "%s".', accountAttributesToRemove.uuid) // // await db.sequelize.transaction(async t => { -// const videoAuthor = await db.Author.loadAuthorByPodAndUUID(authorAttributesToRemove.uuid, fromPod.id, t) -// await videoAuthor.destroy({ transaction: t }) +// const videoAccount = await db.Account.loadAccountByPodAndUUID(accountAttributesToRemove.uuid, fromPod.id, t) +// await videoAccount.destroy({ transaction: t }) // }) // -// logger.info('Remote video author with uuid %s removed.', authorAttributesToRemove.uuid) +// logger.info('Remote video account with uuid %s removed.', accountAttributesToRemove.uuid) // } // // async function removeRemoteVideoChannelRetryWrapper (videoChannelAttributesToRemove: RemoteVideoChannelRemoveData, fromPod: PodInstance) { diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index bacfc4552..9ec6feb57 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts @@ -28,7 +28,7 @@ import { UserRole, UserRight } from '../../../shared' -import { createUserAuthorAndChannel } from '../../lib' +import { createUserAccountAndChannel } from '../../lib' import { UserInstance } from '../../models' import { videosSortValidator } from '../../middlewares/validators/sort' import { setVideosSort } from '../../middlewares/sort' @@ -142,9 +142,9 @@ async function createUser (req: express.Request, res: express.Response, next: ex videoQuota: body.videoQuota }) - await createUserAuthorAndChannel(user) + await createUserAccountAndChannel(user) - logger.info('User %s with its channel and author created.', body.username) + logger.info('User %s with its channel and account created.', body.username) } async function registerUser (req: express.Request, res: express.Response, next: express.NextFunction) { @@ -159,7 +159,7 @@ async function registerUser (req: express.Request, res: express.Response, next: videoQuota: CONFIG.USER.VIDEO_QUOTA }) - await createUserAuthorAndChannel(user) + await createUserAccountAndChannel(user) return res.type('json').status(204).end() } diff --git a/server/controllers/api/videos/channel.ts b/server/controllers/api/videos/channel.ts index ab54eedee..4d1f03903 100644 --- a/server/controllers/api/videos/channel.ts +++ b/server/controllers/api/videos/channel.ts @@ -17,14 +17,14 @@ import { videoChannelsRemoveValidator, videoChannelGetValidator, videoChannelsUpdateValidator, - listVideoAuthorChannelsValidator, + listVideoAccountChannelsValidator, asyncMiddleware } from '../../../middlewares' import { createVideoChannel, updateVideoChannelToFriends } from '../../../lib' -import { VideoChannelInstance, AuthorInstance } from '../../../models' +import { VideoChannelInstance, AccountInstance } from '../../../models' import { VideoChannelCreate, VideoChannelUpdate } from '../../../../shared' const videoChannelRouter = express.Router() @@ -37,9 +37,9 @@ videoChannelRouter.get('/channels', asyncMiddleware(listVideoChannels) ) -videoChannelRouter.get('/authors/:authorId/channels', - listVideoAuthorChannelsValidator, - asyncMiddleware(listVideoAuthorChannels) +videoChannelRouter.get('/accounts/:accountId/channels', + listVideoAccountChannelsValidator, + asyncMiddleware(listVideoAccountChannels) ) videoChannelRouter.post('/channels', @@ -79,8 +79,8 @@ async function listVideoChannels (req: express.Request, res: express.Response, n return res.json(getFormattedObjects(resultList.data, resultList.total)) } -async function listVideoAuthorChannels (req: express.Request, res: express.Response, next: express.NextFunction) { - const resultList = await db.VideoChannel.listByAuthor(res.locals.author.id) +async function listVideoAccountChannels (req: express.Request, res: express.Response, next: express.NextFunction) { + const resultList = await db.VideoChannel.listByAccount(res.locals.account.id) return res.json(getFormattedObjects(resultList.data, resultList.total)) } @@ -101,11 +101,11 @@ async function addVideoChannelRetryWrapper (req: express.Request, res: express.R async function addVideoChannel (req: express.Request, res: express.Response) { const videoChannelInfo: VideoChannelCreate = req.body - const author: AuthorInstance = res.locals.oauth.token.User.Author + const account: AccountInstance = res.locals.oauth.token.User.Account let videoChannelCreated: VideoChannelInstance await db.sequelize.transaction(async t => { - videoChannelCreated = await createVideoChannel(videoChannelInfo, author, t) + videoChannelCreated = await createVideoChannel(videoChannelInfo, account, t) }) logger.info('Video channel with uuid %s created.', videoChannelCreated.uuid) @@ -179,7 +179,7 @@ async function removeVideoChannel (req: express.Request, res: express.Response) } async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) { - const videoChannelWithVideos = await db.VideoChannel.loadAndPopulateAuthorAndVideos(res.locals.videoChannel.id) + const videoChannelWithVideos = await db.VideoChannel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id) return res.json(videoChannelWithVideos.toFormattedJSON()) } diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 964db151d..9ad84609f 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -395,7 +395,7 @@ async function removeVideo (req: express.Request, res: express.Response) { } async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { - const resultList = await db.Video.searchAndPopulateAuthorAndPodAndTags( + const resultList = await db.Video.searchAndPopulateAccountAndPodAndTags( req.params.value, req.query.field, req.query.start, diff --git a/server/controllers/client.ts b/server/controllers/client.ts index 67ebfcf1d..40dda7584 100644 --- a/server/controllers/client.ts +++ b/server/controllers/client.ts @@ -110,9 +110,9 @@ async function generateWatchHtmlPage (req: express.Request, res: express.Respons // Let Angular application handle errors if (validator.isUUID(videoId, 4)) { - videoPromise = db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(videoId) + videoPromise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(videoId) } else if (validator.isInt(videoId)) { - videoPromise = db.Video.loadAndPopulateAuthorAndPodAndTags(+videoId) + videoPromise = db.Video.loadAndPopulateAccountAndPodAndTags(+videoId) } else { return res.sendFile(indexPath) } diff --git a/server/controllers/services.ts b/server/controllers/services.ts index 99a33a716..0db6e5498 100644 --- a/server/controllers/services.ts +++ b/server/controllers/services.ts @@ -47,7 +47,7 @@ function generateOEmbed (req: express.Request, res: express.Response, next: expr width: embedWidth, height: embedHeight, title: video.name, - author_name: video.VideoChannel.Author.name, + author_name: video.VideoChannel.Account.name, provider_name: 'PeerTube', provider_url: webserverUrl } diff --git a/server/helpers/custom-validators/index.ts b/server/helpers/custom-validators/index.ts index 58a40249b..33922b8fe 100644 --- a/server/helpers/custom-validators/index.ts +++ b/server/helpers/custom-validators/index.ts @@ -3,5 +3,6 @@ export * from './misc' export * from './pods' export * from './pods' export * from './users' +export * from './video-accounts' export * from './video-channels' export * from './videos' diff --git a/server/helpers/custom-validators/video-accounts.ts b/server/helpers/custom-validators/video-accounts.ts new file mode 100644 index 000000000..3f3e9edd1 --- /dev/null +++ b/server/helpers/custom-validators/video-accounts.ts @@ -0,0 +1,45 @@ +import * as Promise from 'bluebird' +import * as validator from 'validator' +import * as express from 'express' +import 'express-validator' + +import { database as db } from '../../initializers' +import { AccountInstance } from '../../models' +import { logger } from '../logger' + +import { isUserUsernameValid } from './users' + +function isVideoAccountNameValid (value: string) { + return isUserUsernameValid(value) +} + +function checkVideoAccountExists (id: string, res: express.Response, callback: () => void) { + let promise: Promise + if (validator.isInt(id)) { + promise = db.Account.load(+id) + } else { // UUID + promise = db.Account.loadByUUID(id) + } + + promise.then(account => { + if (!account) { + return res.status(404) + .json({ error: 'Video account not found' }) + .end() + } + + res.locals.account = account + callback() + }) + .catch(err => { + logger.error('Error in video account request validator.', err) + return res.sendStatus(500) + }) +} + +// --------------------------------------------------------------------------- + +export { + checkVideoAccountExists, + isVideoAccountNameValid +} diff --git a/server/helpers/custom-validators/video-channels.ts b/server/helpers/custom-validators/video-channels.ts index b6be557e6..acc42f4a4 100644 --- a/server/helpers/custom-validators/video-channels.ts +++ b/server/helpers/custom-validators/video-channels.ts @@ -26,9 +26,9 @@ function isVideoChannelUUIDValid (value: string) { function checkVideoChannelExists (id: string, res: express.Response, callback: () => void) { let promise: Promise if (validator.isInt(id)) { - promise = db.VideoChannel.loadAndPopulateAuthor(+id) + promise = db.VideoChannel.loadAndPopulateAccount(+id) } else { // UUID - promise = db.VideoChannel.loadByUUIDAndPopulateAuthor(id) + promise = db.VideoChannel.loadByUUIDAndPopulateAccount(id) } promise.then(videoChannel => { diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index 83407f17b..487b3d646 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts @@ -166,9 +166,9 @@ function isVideoFileInfoHashValid (value: string) { function checkVideoExists (id: string, res: express.Response, callback: () => void) { let promise: Promise if (validator.isInt(id)) { - promise = db.Video.loadAndPopulateAuthorAndPodAndTags(+id) + promise = db.Video.loadAndPopulateAccountAndPodAndTags(+id) } else { // UUID - promise = db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(id) + promise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(id) } promise.then(video => { diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index e1f877e80..e6fda88c2 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -29,7 +29,7 @@ const PAGINATION_COUNT_DEFAULT = 15 // Sortable columns per schema const SEARCHABLE_COLUMNS = { - VIDEOS: [ 'name', 'magnetUri', 'host', 'author', 'tags' ] + VIDEOS: [ 'name', 'magnetUri', 'host', 'account', 'tags' ] } // Sortable columns per schema diff --git a/server/initializers/database.ts b/server/initializers/database.ts index 52e766394..aefb6da3a 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts @@ -44,10 +44,6 @@ const database: { OAuthClient?: OAuthClientModel, OAuthToken?: OAuthTokenModel, Pod?: PodModel, - RequestToPod?: RequestToPodModel, - RequestVideoEvent?: RequestVideoEventModel, - RequestVideoQadu?: RequestVideoQaduModel, - Request?: RequestModel, Tag?: TagModel, AccountVideoRate?: AccountVideoRateModel, AccountFollow?: AccountFollowModel, diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index 077472341..c8f6b3bc2 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts @@ -5,7 +5,7 @@ import { database as db } from './database' import { CONFIG, LAST_MIGRATION_VERSION, CACHE } from './constants' import { clientsExist, usersExist } from './checker' import { logger, createCertsIfNotExist, mkdirpPromise, rimrafPromise } from '../helpers' -import { createUserAuthorAndChannel } from '../lib' +import { createUserAccountAndChannel } from '../lib' import { UserRole } from '../../shared' async function installApplication () { @@ -117,7 +117,7 @@ async function createOAuthAdminIfNotExist () { } const user = db.User.build(userData) - await createUserAuthorAndChannel(user, validatePassword) + await createUserAccountAndChannel(user, validatePassword) logger.info('Username: ' + username) logger.info('User password: ' + password) diff --git a/server/lib/cache/videos-preview-cache.ts b/server/lib/cache/videos-preview-cache.ts index 0fe4d2f78..791ad1cbf 100644 --- a/server/lib/cache/videos-preview-cache.ts +++ b/server/lib/cache/videos-preview-cache.ts @@ -43,7 +43,7 @@ class VideosPreviewCache { } private async loadPreviews (key: string) { - const video = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(key) + const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(key) if (!video) return undefined if (video.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName()) diff --git a/server/lib/friends.ts b/server/lib/friends.ts deleted file mode 100644 index 5c9baef47..000000000 --- a/server/lib/friends.ts +++ /dev/null @@ -1,567 +0,0 @@ -import * as request from 'request' -import * as Sequelize from 'sequelize' -import * as Bluebird from 'bluebird' -import { join } from 'path' - -import { database as db } from '../initializers/database' -import { - API_VERSION, - CONFIG, - REQUESTS_IN_PARALLEL, - REQUEST_ENDPOINTS, - REQUEST_ENDPOINT_ACTIONS, - REMOTE_SCHEME, - STATIC_PATHS -} from '../initializers' -import { - logger, - getMyPublicCert, - makeSecureRequest, - makeRetryRequest -} from '../helpers' -import { - RequestScheduler, - RequestSchedulerOptions, - - RequestVideoQaduScheduler, - RequestVideoQaduSchedulerOptions, - - RequestVideoEventScheduler, - RequestVideoEventSchedulerOptions -} from './request' -import { - PodInstance, - VideoInstance -} from '../models' -import { - RequestEndpoint, - RequestVideoEventType, - RequestVideoQaduType, - RemoteVideoCreateData, - RemoteVideoUpdateData, - RemoteVideoRemoveData, - RemoteVideoReportAbuseData, - ResultList, - RemoteVideoRequestType, - Pod as FormattedPod, - RemoteVideoChannelCreateData, - RemoteVideoChannelUpdateData, - RemoteVideoChannelRemoveData, - RemoteVideoAuthorCreateData, - RemoteVideoAuthorRemoveData -} from '../../shared' - -type QaduParam = { videoId: number, type: RequestVideoQaduType } -type EventParam = { videoId: number, type: RequestVideoEventType } - -const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] - -const requestScheduler = new RequestScheduler() -const requestVideoQaduScheduler = new RequestVideoQaduScheduler() -const requestVideoEventScheduler = new RequestVideoEventScheduler() - -function activateSchedulers () { - requestScheduler.activate() - requestVideoQaduScheduler.activate() - requestVideoEventScheduler.activate() -} - -function addVideoToFriends (videoData: RemoteVideoCreateData, transaction: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.ADD_VIDEO, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: videoData, - transaction - } - return createRequest(options) -} - -function updateVideoToFriends (videoData: RemoteVideoUpdateData, transaction: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.UPDATE_VIDEO, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: videoData, - transaction - } - return createRequest(options) -} - -function removeVideoToFriends (videoParams: RemoteVideoRemoveData, transaction?: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.REMOVE_VIDEO, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: videoParams, - transaction - } - return createRequest(options) -} - -function addVideoAuthorToFriends (authorData: RemoteVideoAuthorCreateData, transaction: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.ADD_AUTHOR, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: authorData, - transaction - } - return createRequest(options) -} - -function removeVideoAuthorToFriends (authorData: RemoteVideoAuthorRemoveData, transaction?: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.REMOVE_AUTHOR, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: authorData, - transaction - } - return createRequest(options) -} - -function addVideoChannelToFriends (videoChannelData: RemoteVideoChannelCreateData, transaction: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.ADD_CHANNEL, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: videoChannelData, - transaction - } - return createRequest(options) -} - -function updateVideoChannelToFriends (videoChannelData: RemoteVideoChannelUpdateData, transaction: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.UPDATE_CHANNEL, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: videoChannelData, - transaction - } - return createRequest(options) -} - -function removeVideoChannelToFriends (videoChannelParams: RemoteVideoChannelRemoveData, transaction?: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.REMOVE_CHANNEL, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: videoChannelParams, - transaction - } - return createRequest(options) -} - -function reportAbuseVideoToFriend (reportData: RemoteVideoReportAbuseData, video: VideoInstance, transaction: Sequelize.Transaction) { - const options = { - type: ENDPOINT_ACTIONS.REPORT_ABUSE, - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: reportData, - toIds: [ video.VideoChannel.Author.podId ], - transaction - } - return createRequest(options) -} - -function quickAndDirtyUpdateVideoToFriends (qaduParam: QaduParam, transaction?: Sequelize.Transaction) { - const options = { - videoId: qaduParam.videoId, - type: qaduParam.type, - transaction - } - return createVideoQaduRequest(options) -} - -function quickAndDirtyUpdatesVideoToFriends (qadusParams: QaduParam[], transaction: Sequelize.Transaction) { - const tasks = [] - - qadusParams.forEach(qaduParams => { - tasks.push(quickAndDirtyUpdateVideoToFriends(qaduParams, transaction)) - }) - - return Promise.all(tasks) -} - -function addEventToRemoteVideo (eventParam: EventParam, transaction?: Sequelize.Transaction) { - const options = { - videoId: eventParam.videoId, - type: eventParam.type, - transaction - } - return createVideoEventRequest(options) -} - -function addEventsToRemoteVideo (eventsParams: EventParam[], transaction: Sequelize.Transaction) { - const tasks = [] - - for (const eventParams of eventsParams) { - tasks.push(addEventToRemoteVideo(eventParams, transaction)) - } - - return Promise.all(tasks) -} - -async function hasFriends () { - const count = await db.Pod.countAll() - - return count !== 0 -} - -async function makeFriends (hosts: string[]) { - const podsScore = {} - - logger.info('Make friends!') - const cert = await getMyPublicCert() - - for (const host of hosts) { - await computeForeignPodsList(host, podsScore) - } - - logger.debug('Pods scores computed.', { podsScore: podsScore }) - - const podsList = computeWinningPods(hosts, podsScore) - logger.debug('Pods that we keep.', { podsToKeep: podsList }) - - return makeRequestsToWinningPods(cert, podsList) -} - -async function quitFriends () { - // Stop pool requests - requestScheduler.deactivate() - - try { - await requestScheduler.flush() - - await requestVideoQaduScheduler.flush() - - const pods = await db.Pod.list() - const requestParams = { - method: 'POST' as 'POST', - path: '/api/' + API_VERSION + '/remote/pods/remove', - toPod: null - } - - // Announce we quit them - // We don't care if the request fails - // The other pod will exclude us automatically after a while - try { - await Bluebird.map(pods, pod => { - requestParams.toPod = pod - - return makeSecureRequest(requestParams) - }, { concurrency: REQUESTS_IN_PARALLEL }) - } catch (err) { // Don't stop the process - logger.error('Some errors while quitting friends.', err) - } - - const tasks = [] - for (const pod of pods) { - tasks.push(pod.destroy()) - } - await Promise.all(pods) - - logger.info('Removed all remote videos.') - - requestScheduler.activate() - } catch (err) { - // Don't forget to re activate the scheduler, even if there was an error - requestScheduler.activate() - - throw err - } -} - -async function sendOwnedDataToPod (podId: number) { - // First send authors - await sendOwnedAuthorsToPod(podId) - await sendOwnedChannelsToPod(podId) - await sendOwnedVideosToPod(podId) -} - -async function sendOwnedChannelsToPod (podId: number) { - const videoChannels = await db.VideoChannel.listOwned() - - const tasks: Promise[] = [] - for (const videoChannel of videoChannels) { - const remoteVideoChannel = videoChannel.toAddRemoteJSON() - const options = { - type: 'add-channel' as 'add-channel', - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: remoteVideoChannel, - toIds: [ podId ], - transaction: null - } - - const p = createRequest(options) - tasks.push(p) - } - - await Promise.all(tasks) -} - -async function sendOwnedAuthorsToPod (podId: number) { - const authors = await db.Author.listOwned() - const tasks: Promise[] = [] - - for (const author of authors) { - const remoteAuthor = author.toAddRemoteJSON() - const options = { - type: 'add-author' as 'add-author', - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: remoteAuthor, - toIds: [ podId ], - transaction: null - } - - const p = createRequest(options) - tasks.push(p) - } - - await Promise.all(tasks) -} - -async function sendOwnedVideosToPod (podId: number) { - const videosList = await db.Video.listOwnedAndPopulateAuthorAndTags() - const tasks: Bluebird[] = [] - - for (const video of videosList) { - const promise = video.toAddRemoteJSON() - .then(remoteVideo => { - const options = { - type: 'add-video' as 'add-video', - endpoint: REQUEST_ENDPOINTS.VIDEOS, - data: remoteVideo, - toIds: [ podId ], - transaction: null - } - return createRequest(options) - }) - .catch(err => { - logger.error('Cannot convert video to remote.', err) - // Don't break the process - return undefined - }) - - tasks.push(promise) - } - - await Promise.all(tasks) -} - -function fetchRemotePreview (video: VideoInstance) { - const host = video.VideoChannel.Author.Pod.host - const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName()) - - return request.get(REMOTE_SCHEME.HTTP + '://' + host + path) -} - -function fetchRemoteDescription (video: VideoInstance) { - const host = video.VideoChannel.Author.Pod.host - const path = video.getDescriptionPath() - - const requestOptions = { - url: REMOTE_SCHEME.HTTP + '://' + host + path, - json: true - } - - return new Promise((res, rej) => { - request.get(requestOptions, (err, response, body) => { - if (err) return rej(err) - - return res(body.description ? body.description : '') - }) - }) -} - -async function removeFriend (pod: PodInstance) { - const requestParams = { - method: 'POST' as 'POST', - path: '/api/' + API_VERSION + '/remote/pods/remove', - toPod: pod - } - - try { - await makeSecureRequest(requestParams) - } catch (err) { - logger.warn('Cannot notify friends %s we are quitting him.', pod.host, err) - } - - try { - await pod.destroy() - - logger.info('Removed friend %s.', pod.host) - } catch (err) { - logger.error('Cannot destroy friend %s.', pod.host, err) - } -} - -function getRequestScheduler () { - return requestScheduler -} - -function getRequestVideoQaduScheduler () { - return requestVideoQaduScheduler -} - -function getRequestVideoEventScheduler () { - return requestVideoEventScheduler -} - -// --------------------------------------------------------------------------- - -export { - activateSchedulers, - addVideoToFriends, - removeVideoAuthorToFriends, - updateVideoToFriends, - addVideoAuthorToFriends, - reportAbuseVideoToFriend, - quickAndDirtyUpdateVideoToFriends, - quickAndDirtyUpdatesVideoToFriends, - addEventToRemoteVideo, - addEventsToRemoteVideo, - hasFriends, - makeFriends, - quitFriends, - removeFriend, - removeVideoToFriends, - sendOwnedDataToPod, - getRequestScheduler, - getRequestVideoQaduScheduler, - getRequestVideoEventScheduler, - fetchRemotePreview, - addVideoChannelToFriends, - fetchRemoteDescription, - updateVideoChannelToFriends, - removeVideoChannelToFriends -} - -// --------------------------------------------------------------------------- - -async function computeForeignPodsList (host: string, podsScore: { [ host: string ]: number }) { - const result = await getForeignPodsList(host) - const foreignPodsList: { host: string }[] = result.data - - // Let's give 1 point to the pod we ask the friends list - foreignPodsList.push({ host }) - - for (const foreignPod of foreignPodsList) { - const foreignPodHost = foreignPod.host - - if (podsScore[foreignPodHost]) podsScore[foreignPodHost]++ - else podsScore[foreignPodHost] = 1 - } - - return undefined -} - -function computeWinningPods (hosts: string[], podsScore: { [ host: string ]: number }) { - // Build the list of pods to add - // Only add a pod if it exists in more than a half base pods - const podsList = [] - const baseScore = hosts.length / 2 - - for (const podHost of Object.keys(podsScore)) { - // If the pod is not me and with a good score we add it - if (isMe(podHost) === false && podsScore[podHost] > baseScore) { - podsList.push({ host: podHost }) - } - } - - return podsList -} - -function getForeignPodsList (host: string) { - return new Promise< ResultList >((res, rej) => { - const path = '/api/' + API_VERSION + '/remote/pods/list' - - request.post(REMOTE_SCHEME.HTTP + '://' + host + path, (err, response, body) => { - if (err) return rej(err) - - try { - const json: ResultList = JSON.parse(body) - return res(json) - } catch (err) { - return rej(err) - } - }) - }) -} - -async function makeRequestsToWinningPods (cert: string, podsList: PodInstance[]) { - // Stop pool requests - requestScheduler.deactivate() - // Flush pool requests - requestScheduler.forceSend() - - try { - await Bluebird.map(podsList, async pod => { - const params = { - url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/remote/pods/add', - method: 'POST' as 'POST', - json: { - host: CONFIG.WEBSERVER.HOST, - email: CONFIG.ADMIN.EMAIL, - publicKey: cert - } - } - - const { response, body } = await makeRetryRequest(params) - const typedBody = body as { cert: string, email: string } - - if (response.statusCode === 200) { - const podObj = db.Pod.build({ host: pod.host, publicKey: typedBody.cert, email: typedBody.email }) - - let podCreated: PodInstance - try { - podCreated = await podObj.save() - } catch (err) { - logger.error('Cannot add friend %s pod.', pod.host, err) - } - - // Add our videos to the request scheduler - sendOwnedDataToPod(podCreated.id) - .catch(err => logger.warn('Cannot send owned data to pod %d.', podCreated.id, err)) - } else { - logger.error('Status not 200 for %s pod.', pod.host) - } - }, { concurrency: REQUESTS_IN_PARALLEL }) - - logger.debug('makeRequestsToWinningPods finished.') - - requestScheduler.activate() - } catch (err) { - // Final callback, we've ended all the requests - // Now we made new friends, we can re activate the pool of requests - requestScheduler.activate() - } -} - -// Wrapper that populate "toIds" argument with all our friends if it is not specified -type CreateRequestOptions = { - type: RemoteVideoRequestType - endpoint: RequestEndpoint - data: Object - toIds?: number[] - transaction: Sequelize.Transaction -} -async function createRequest (options: CreateRequestOptions) { - if (options.toIds !== undefined) { - await requestScheduler.createRequest(options as RequestSchedulerOptions) - return undefined - } - - // If the "toIds" pods is not specified, we send the request to all our friends - const podIds = await db.Pod.listAllIds(options.transaction) - - const newOptions = Object.assign(options, { toIds: podIds }) - await requestScheduler.createRequest(newOptions) - - return undefined -} - -function createVideoQaduRequest (options: RequestVideoQaduSchedulerOptions) { - return requestVideoQaduScheduler.createRequest(options) -} - -function createVideoEventRequest (options: RequestVideoEventSchedulerOptions) { - return requestVideoEventScheduler.createRequest(options) -} - -function isMe (host: string) { - return host === CONFIG.WEBSERVER.HOST -} diff --git a/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts b/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts index ccded4721..f019c28bc 100644 --- a/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts +++ b/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts @@ -7,7 +7,7 @@ import { addVideoToFriends } from '../../friends' import { JobScheduler } from '../job-scheduler' async function process (data: { videoUUID: string }, jobId: number) { - const video = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(data.videoUUID) + const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(data.videoUUID) // No video, maybe deleted? if (!video) { logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid }) @@ -30,7 +30,7 @@ async function onSuccess (jobId: number, video: VideoInstance) { logger.info('Job %d is a success.', jobId) // Maybe the video changed in database, refresh it - const videoDatabase = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(video.uuid) + const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(video.uuid) // Video does not exist anymore if (!videoDatabase) return undefined diff --git a/server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts b/server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts index 853645510..397b95795 100644 --- a/server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts +++ b/server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts @@ -5,7 +5,7 @@ import { VideoInstance } from '../../../models' import { VideoResolution } from '../../../../shared' async function process (data: { videoUUID: string, resolution: VideoResolution }, jobId: number) { - const video = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(data.videoUUID) + const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(data.videoUUID) // No video, maybe deleted? if (!video) { logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid }) @@ -28,7 +28,7 @@ async function onSuccess (jobId: number, video: VideoInstance) { logger.info('Job %d is a success.', jobId) // Maybe the video changed in database, refresh it - const videoDatabase = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(video.uuid) + const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(video.uuid) // Video does not exist anymore if (!videoDatabase) return undefined diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index a6dd4d061..f81383ce8 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts @@ -11,7 +11,7 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account name: videoChannelInfo.name, description: videoChannelInfo.description, remote: false, - authorId: account.id + accountId: account.id } const videoChannel = db.VideoChannel.build(videoChannelData) diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts index 7d611728b..53416a857 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/video-channels.ts @@ -9,19 +9,19 @@ import { isVideoChannelDescriptionValid, isVideoChannelNameValid, checkVideoChannelExists, - checkVideoAuthorExists + checkVideoAccountExists } from '../../helpers' import { UserInstance } from '../../models' import { UserRight } from '../../../shared' -const listVideoAuthorChannelsValidator = [ - param('authorId').custom(isIdOrUUIDValid).withMessage('Should have a valid author id'), +const listVideoAccountChannelsValidator = [ + param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'), (req: express.Request, res: express.Response, next: express.NextFunction) => { - logger.debug('Checking listVideoAuthorChannelsValidator parameters', { parameters: req.body }) + logger.debug('Checking listVideoAccountChannelsValidator parameters', { parameters: req.body }) checkErrors(req, res, () => { - checkVideoAuthorExists(req.params.authorId, res, next) + checkVideoAccountExists(req.params.accountId, res, next) }) } ] @@ -54,7 +54,7 @@ const videoChannelsUpdateValidator = [ .end() } - if (res.locals.videoChannel.Author.userId !== res.locals.oauth.token.User.id) { + if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) { return res.status(403) .json({ error: 'Cannot update video channel of another user' }) .end() @@ -98,7 +98,7 @@ const videoChannelGetValidator = [ // --------------------------------------------------------------------------- export { - listVideoAuthorChannelsValidator, + listVideoAccountChannelsValidator, videoChannelsAddValidator, videoChannelsUpdateValidator, videoChannelsRemoveValidator, @@ -119,8 +119,8 @@ function checkUserCanDeleteVideoChannel (res: express.Response, callback: () => // Check if the user can delete the video channel // The user can delete it if s/he is an admin - // Or if s/he is the video channel's author - if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && res.locals.videoChannel.Author.userId !== user.id) { + // Or if s/he is the video channel's account + if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && res.locals.videoChannel.Account.userId !== user.id) { return res.status(403) .json({ error: 'Cannot remove video channel of another user' }) .end() @@ -131,7 +131,7 @@ function checkUserCanDeleteVideoChannel (res: express.Response, callback: () => } function checkVideoChannelIsNotTheLastOne (res: express.Response, callback: () => void) { - db.VideoChannel.countByAuthor(res.locals.oauth.token.User.Author.id) + db.VideoChannel.countByAccount(res.locals.oauth.token.User.Account.id) .then(count => { if (count <= 1) { return res.status(409) diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index 15b4629c1..10b426df3 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -48,11 +48,11 @@ const videosAddValidator = [ const videoFile: Express.Multer.File = req.files['videofile'][0] const user = res.locals.oauth.token.User - return db.VideoChannel.loadByIdAndAuthor(req.body.channelId, user.Author.id) + return db.VideoChannel.loadByIdAndAccount(req.body.channelId, user.Account.id) .then(videoChannel => { if (!videoChannel) { res.status(400) - .json({ error: 'Unknown video video channel for this author.' }) + .json({ error: 'Unknown video video channel for this account.' }) .end() return undefined @@ -131,7 +131,7 @@ const videosUpdateValidator = [ .end() } - if (video.VideoChannel.Author.userId !== res.locals.oauth.token.User.id) { + if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { return res.status(403) .json({ error: 'Cannot update video of another user' }) .end() @@ -163,7 +163,7 @@ const videosGetValidator = [ if (video.privacy !== VideoPrivacy.PRIVATE) return next() authenticate(req, res, () => { - if (video.VideoChannel.Author.userId !== res.locals.oauth.token.User.id) { + 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() @@ -256,10 +256,10 @@ function checkUserCanDeleteVideo (userId: number, res: express.Response, callbac // 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 - const author = res.locals.video.VideoChannel.Author + // Or if s/he is the video's account + const account = res.locals.video.VideoChannel.Account const user = res.locals.oauth.token.User - if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && author.userId !== user.id) { + if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && account.userId !== user.id) { return res.status(403) .json({ error: 'Cannot remove video of another user' }) .end() diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 1401762c5..7390baf91 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts @@ -164,7 +164,7 @@ toFormattedJSON = function (this: UserInstance) { roleLabel: USER_ROLE_LABELS[this.role], videoQuota: this.videoQuota, createdAt: this.createdAt, - author: { + account: { id: this.Account.id, uuid: this.Account.uuid } @@ -295,7 +295,7 @@ function getOriginalVideoFileTotalFromUser (user: UserInstance) { '(SELECT MAX("VideoFiles"."size") AS "size" FROM "VideoFiles" ' + 'INNER JOIN "Videos" ON "VideoFiles"."videoId" = "Videos"."id" ' + 'INNER JOIN "VideoChannels" ON "VideoChannels"."id" = "Videos"."channelId" ' + - 'INNER JOIN "Accounts" ON "VideoChannels"."authorId" = "Accounts"."id" ' + + 'INNER JOIN "Accounts" ON "VideoChannels"."accountId" = "Accounts"."id" ' + 'INNER JOIN "Users" ON "Accounts"."userId" = "Users"."id" ' + 'WHERE "Users"."id" = $userId GROUP BY "Videos"."id") t' diff --git a/server/models/index.ts b/server/models/index.ts index 29479e067..0aec2d3b1 100644 --- a/server/models/index.ts +++ b/server/models/index.ts @@ -2,6 +2,5 @@ export * from './application' export * from './job' export * from './oauth' export * from './pod' -export * from './request' export * from './account' export * from './video' diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts index dc8bcd872..c7afcc38c 100644 --- a/server/models/oauth/oauth-token.ts +++ b/server/models/oauth/oauth-token.ts @@ -131,7 +131,7 @@ getByTokenAndPopulateUser = function (bearerToken: string) { model: OAuthToken['sequelize'].models.User, include: [ { - model: OAuthToken['sequelize'].models.Author, + model: OAuthToken['sequelize'].models.Account, required: true } ] @@ -156,7 +156,7 @@ getByRefreshTokenAndPopulateUser = function (refreshToken: string) { model: OAuthToken['sequelize'].models.User, include: [ { - model: OAuthToken['sequelize'].models.Author, + model: OAuthToken['sequelize'].models.Account, required: true } ] diff --git a/server/models/request/abstract-request-interface.ts b/server/models/request/abstract-request-interface.ts deleted file mode 100644 index a384f4d27..000000000 --- a/server/models/request/abstract-request-interface.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as Promise from 'bluebird' - -export interface AbstractRequestClass { - countTotalRequests: () => Promise - listWithLimitAndRandom: (limitPods: number, limitRequestsPerPod: number) => Promise - removeWithEmptyTo: () => Promise - removeAll: () => Promise -} - -export interface AbstractRequestToPodClass { - removeByRequestIdsAndPod: (ids: number[], podId: number) => Promise -} diff --git a/server/models/request/index.ts b/server/models/request/index.ts deleted file mode 100644 index 3dd6aedc2..000000000 --- a/server/models/request/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './abstract-request-interface' -export * from './request-interface' -export * from './request-to-pod-interface' -export * from './request-video-event-interface' -export * from './request-video-qadu-interface' diff --git a/server/models/request/request-interface.ts b/server/models/request/request-interface.ts deleted file mode 100644 index dae35651b..000000000 --- a/server/models/request/request-interface.ts +++ /dev/null @@ -1,46 +0,0 @@ -import * as Sequelize from 'sequelize' -import * as Promise from 'bluebird' - -import { AbstractRequestClass } from './abstract-request-interface' -import { PodInstance, PodAttributes } from '../pod/pod-interface' -import { RequestEndpoint } from '../../../shared/models/request-scheduler.model' - -export type RequestsGrouped = { - [ podId: number ]: { - request: RequestInstance, - pod: PodInstance - }[] -} - -export namespace RequestMethods { - export type CountTotalRequests = () => Promise - - export type ListWithLimitAndRandom = (limitPods: number, limitRequestsPerPod: number) => Promise - - export type RemoveWithEmptyTo = () => Promise - - export type RemoveAll = () => Promise -} - -export interface RequestClass extends AbstractRequestClass { - countTotalRequests: RequestMethods.CountTotalRequests - listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom - removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo - removeAll: RequestMethods.RemoveAll -} - -export interface RequestAttributes { - request: object - endpoint: RequestEndpoint -} - -export interface RequestInstance extends RequestClass, RequestAttributes, Sequelize.Instance { - id: number - createdAt: Date - updatedAt: Date - - setPods: Sequelize.HasManySetAssociationsMixin - Pods: PodInstance[] -} - -export interface RequestModel extends RequestClass, Sequelize.Model {} diff --git a/server/models/request/request-to-pod-interface.ts b/server/models/request/request-to-pod-interface.ts deleted file mode 100644 index 7ca99f4d4..000000000 --- a/server/models/request/request-to-pod-interface.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as Sequelize from 'sequelize' -import * as Promise from 'bluebird' - -import { AbstractRequestToPodClass } from './abstract-request-interface' - -export namespace RequestToPodMethods { - export type RemoveByRequestIdsAndPod = (requestsIds: number[], podId: number) => Promise -} - -export interface RequestToPodClass extends AbstractRequestToPodClass { - removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod -} - -export interface RequestToPodAttributes { -} - -export interface RequestToPodInstance extends RequestToPodClass, RequestToPodAttributes, Sequelize.Instance { - id: number - createdAt: Date - updatedAt: Date -} - -export interface RequestToPodModel extends RequestToPodClass, Sequelize.Model {} diff --git a/server/models/request/request-to-pod.ts b/server/models/request/request-to-pod.ts deleted file mode 100644 index 4e14e918b..000000000 --- a/server/models/request/request-to-pod.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as Sequelize from 'sequelize' - -import { addMethodsToModel } from '../utils' -import { - RequestToPodInstance, - RequestToPodAttributes, - - RequestToPodMethods -} from './request-to-pod-interface' - -let RequestToPod: Sequelize.Model -let removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod - -export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { - RequestToPod = sequelize.define('RequestToPod', {}, { - indexes: [ - { - fields: [ 'requestId' ] - }, - { - fields: [ 'podId' ] - }, - { - fields: [ 'requestId', 'podId' ], - unique: true - } - ] - }) - - const classMethods = [ - removeByRequestIdsAndPod - ] - addMethodsToModel(RequestToPod, classMethods) - - return RequestToPod -} - -// --------------------------------------------------------------------------- - -removeByRequestIdsAndPod = function (requestsIds: number[], podId: number) { - const query = { - where: { - requestId: { - [Sequelize.Op.in]: requestsIds - }, - podId: podId - } - } - - return RequestToPod.destroy(query) -} diff --git a/server/models/request/request-video-event-interface.ts b/server/models/request/request-video-event-interface.ts deleted file mode 100644 index 26cabe3ba..000000000 --- a/server/models/request/request-video-event-interface.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as Sequelize from 'sequelize' -import * as Promise from 'bluebird' - -import { AbstractRequestClass, AbstractRequestToPodClass } from './abstract-request-interface' -import { VideoInstance } from '../video/video-interface' -import { PodInstance } from '../pod/pod-interface' - -import { RequestVideoEventType } from '../../../shared/models/request-scheduler.model' - -export type RequestsVideoEventGrouped = { - [ podId: number ]: { - id: number - type: RequestVideoEventType - count: number - video: VideoInstance - pod: PodInstance - }[] -} - -export namespace RequestVideoEventMethods { - export type CountTotalRequests = () => Promise - - export type ListWithLimitAndRandom = (limitPods: number, limitRequestsPerPod: number) => Promise - - export type RemoveByRequestIdsAndPod = (ids: number[], podId: number) => Promise - - export type RemoveAll = () => Promise -} - -export interface RequestVideoEventClass extends AbstractRequestClass, AbstractRequestToPodClass { - countTotalRequests: RequestVideoEventMethods.CountTotalRequests - listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom - removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod - removeAll: RequestVideoEventMethods.RemoveAll -} - -export interface RequestVideoEventAttributes { - type: RequestVideoEventType - count: number -} - -export interface RequestVideoEventInstance - extends RequestVideoEventClass, RequestVideoEventAttributes, Sequelize.Instance { - id: number - - Video: VideoInstance -} - -export interface RequestVideoEventModel - extends RequestVideoEventClass, Sequelize.Model {} diff --git a/server/models/request/request-video-event.ts b/server/models/request/request-video-event.ts deleted file mode 100644 index 8954407e1..000000000 --- a/server/models/request/request-video-event.ts +++ /dev/null @@ -1,191 +0,0 @@ -/* - Request Video events (likes, dislikes, views...) -*/ - -import { values } from 'lodash' -import * as Sequelize from 'sequelize' - -import { database as db } from '../../initializers/database' -import { REQUEST_VIDEO_EVENT_TYPES } from '../../initializers' -import { isVideoEventCountValid } from '../../helpers' -import { addMethodsToModel } from '../utils' -import { - RequestVideoEventInstance, - RequestVideoEventAttributes, - - RequestVideoEventMethods, - RequestsVideoEventGrouped -} from './request-video-event-interface' - -let RequestVideoEvent: Sequelize.Model -let countTotalRequests: RequestVideoEventMethods.CountTotalRequests -let listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom -let removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod -let removeAll: RequestVideoEventMethods.RemoveAll - -export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { - RequestVideoEvent = sequelize.define('RequestVideoEvent', - { - type: { - type: DataTypes.ENUM(values(REQUEST_VIDEO_EVENT_TYPES)), - allowNull: false - }, - count: { - type: DataTypes.INTEGER, - allowNull: false, - validate: { - countValid: function (value) { - const res = isVideoEventCountValid(value) - if (res === false) throw new Error('Video event count is not valid.') - } - } - } - }, - { - updatedAt: false, - indexes: [ - { - fields: [ 'videoId' ] - } - ] - } - ) - - const classMethods = [ - associate, - - listWithLimitAndRandom, - countTotalRequests, - removeAll, - removeByRequestIdsAndPod - ] - addMethodsToModel(RequestVideoEvent, classMethods) - - return RequestVideoEvent -} - -// ------------------------------ STATICS ------------------------------ - -function associate (models) { - RequestVideoEvent.belongsTo(models.Video, { - foreignKey: { - name: 'videoId', - allowNull: false - }, - onDelete: 'CASCADE' - }) -} - -countTotalRequests = function () { - const query = {} - return RequestVideoEvent.count(query) -} - -listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number) { - const Pod = db.Pod - - // We make a join between videos and authors to find the podId of our video event requests - const podJoins = 'INNER JOIN "VideoChannels" ON "VideoChannels"."authorId" = "Authors"."id" ' + - 'INNER JOIN "Videos" ON "Videos"."channelId" = "VideoChannels"."id" ' + - 'INNER JOIN "RequestVideoEvents" ON "RequestVideoEvents"."videoId" = "Videos"."id"' - - return Pod.listRandomPodIdsWithRequest(limitPods, 'Authors', podJoins).then(podIds => { - // We don't have friends that have requests - if (podIds.length === 0) return [] - - const query = { - order: [ - [ 'id', 'ASC' ] - ], - include: [ - { - model: RequestVideoEvent['sequelize'].models.Video, - include: [ - { - model: RequestVideoEvent['sequelize'].models.VideoChannel, - include: [ - { - model: RequestVideoEvent['sequelize'].models.Author, - include: [ - { - model: RequestVideoEvent['sequelize'].models.Pod, - where: { - id: { - [Sequelize.Op.in]: podIds - } - } - } - ] - } - ] - } - ] - } - ] - } - - return RequestVideoEvent.findAll(query).then(requests => { - const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod) - return requestsGrouped - }) - }) -} - -removeByRequestIdsAndPod = function (ids: number[], podId: number) { - const query = { - where: { - id: { - [Sequelize.Op.in]: ids - } - }, - include: [ - { - model: RequestVideoEvent['sequelize'].models.Video, - include: [ - { - model: RequestVideoEvent['sequelize'].models.VideoChannel, - include: [ - { - model: RequestVideoEvent['sequelize'].models.Author, - where: { - podId - } - } - ] - } - ] - } - ] - } - - return RequestVideoEvent.destroy(query) -} - -removeAll = function () { - // Delete all requests - return RequestVideoEvent.truncate({ cascade: true }) -} - -// --------------------------------------------------------------------------- - -function groupAndTruncateRequests (events: RequestVideoEventInstance[], limitRequestsPerPod: number) { - const eventsGrouped: RequestsVideoEventGrouped = {} - - events.forEach(event => { - const pod = event.Video.VideoChannel.Author.Pod - - if (!eventsGrouped[pod.id]) eventsGrouped[pod.id] = [] - - if (eventsGrouped[pod.id].length < limitRequestsPerPod) { - eventsGrouped[pod.id].push({ - id: event.id, - type: event.type, - count: event.count, - video: event.Video, - pod - }) - } - }) - - return eventsGrouped -} diff --git a/server/models/request/request-video-qadu-interface.ts b/server/models/request/request-video-qadu-interface.ts deleted file mode 100644 index b7b7b1ecc..000000000 --- a/server/models/request/request-video-qadu-interface.ts +++ /dev/null @@ -1,48 +0,0 @@ -import * as Sequelize from 'sequelize' -import * as Promise from 'bluebird' - -import { AbstractRequestClass, AbstractRequestToPodClass } from './abstract-request-interface' -import { VideoInstance } from '../video/video-interface' -import { PodInstance } from '../pod/pod-interface' - -import { RequestVideoQaduType } from '../../../shared/models/request-scheduler.model' - -export type RequestsVideoQaduGrouped = { - [ podId: number ]: { - request: RequestVideoQaduInstance - video: VideoInstance - pod: PodInstance - } -} - -export namespace RequestVideoQaduMethods { - export type CountTotalRequests = () => Promise - - export type ListWithLimitAndRandom = (limitPods: number, limitRequestsPerPod: number) => Promise - - export type RemoveByRequestIdsAndPod = (ids: number[], podId: number) => Promise - - export type RemoveAll = () => Promise -} - -export interface RequestVideoQaduClass extends AbstractRequestClass, AbstractRequestToPodClass { - countTotalRequests: RequestVideoQaduMethods.CountTotalRequests - listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom - removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod - removeAll: RequestVideoQaduMethods.RemoveAll -} - -export interface RequestVideoQaduAttributes { - type: RequestVideoQaduType -} - -export interface RequestVideoQaduInstance - extends RequestVideoQaduClass, RequestVideoQaduAttributes, Sequelize.Instance { - id: number - - Pod: PodInstance - Video: VideoInstance -} - -export interface RequestVideoQaduModel - extends RequestVideoQaduClass, Sequelize.Model {} diff --git a/server/models/request/request-video-qadu.ts b/server/models/request/request-video-qadu.ts deleted file mode 100644 index 93cf249b3..000000000 --- a/server/models/request/request-video-qadu.ts +++ /dev/null @@ -1,159 +0,0 @@ -/* - Request Video for Quick And Dirty Updates like: - - views - - likes - - dislikes - - We can't put it in the same system than basic requests for efficiency. - Moreover we don't want to slow down the basic requests with a lot of views/likes/dislikes requests. - So we put it an independant request scheduler. -*/ - -import { values } from 'lodash' -import * as Sequelize from 'sequelize' - -import { database as db } from '../../initializers/database' -import { REQUEST_VIDEO_QADU_TYPES } from '../../initializers' -import { addMethodsToModel } from '../utils' -import { - RequestVideoQaduInstance, - RequestVideoQaduAttributes, - - RequestVideoQaduMethods -} from './request-video-qadu-interface' - -let RequestVideoQadu: Sequelize.Model -let countTotalRequests: RequestVideoQaduMethods.CountTotalRequests -let listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom -let removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod -let removeAll: RequestVideoQaduMethods.RemoveAll - -export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { - RequestVideoQadu = sequelize.define('RequestVideoQadu', - { - type: { - type: DataTypes.ENUM(values(REQUEST_VIDEO_QADU_TYPES)), - allowNull: false - } - }, - { - timestamps: false, - indexes: [ - { - fields: [ 'podId' ] - }, - { - fields: [ 'videoId' ] - } - ] - } - ) - - const classMethods = [ - associate, - - listWithLimitAndRandom, - countTotalRequests, - removeAll, - removeByRequestIdsAndPod - ] - addMethodsToModel(RequestVideoQadu, classMethods) - - return RequestVideoQadu -} - -// ------------------------------ STATICS ------------------------------ - -function associate (models) { - RequestVideoQadu.belongsTo(models.Pod, { - foreignKey: { - name: 'podId', - allowNull: false - }, - onDelete: 'CASCADE' - }) - - RequestVideoQadu.belongsTo(models.Video, { - foreignKey: { - name: 'videoId', - allowNull: false - }, - onDelete: 'CASCADE' - }) -} - -countTotalRequests = function () { - const query = {} - return RequestVideoQadu.count(query) -} - -listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number) { - const Pod = db.Pod - const tableJoin = '' - - return Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', tableJoin).then(podIds => { - // We don't have friends that have requests - if (podIds.length === 0) return [] - - const query = { - include: [ - { - model: RequestVideoQadu['sequelize'].models.Pod, - where: { - id: { - [Sequelize.Op.in]: podIds - } - } - }, - { - model: RequestVideoQadu['sequelize'].models.Video - } - ] - } - - return RequestVideoQadu.findAll(query).then(requests => { - const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod) - return requestsGrouped - }) - }) -} - -removeByRequestIdsAndPod = function (ids: number[], podId: number) { - const query = { - where: { - id: { - [Sequelize.Op.in]: ids - }, - podId - } - } - - return RequestVideoQadu.destroy(query) -} - -removeAll = function () { - // Delete all requests - return RequestVideoQadu.truncate({ cascade: true }) -} - -// --------------------------------------------------------------------------- - -function groupAndTruncateRequests (requests: RequestVideoQaduInstance[], limitRequestsPerPod: number) { - const requestsGrouped = {} - - requests.forEach(request => { - const pod = request.Pod - - if (!requestsGrouped[pod.id]) requestsGrouped[pod.id] = [] - - if (requestsGrouped[pod.id].length < limitRequestsPerPod) { - requestsGrouped[pod.id].push({ - request: request, - video: request.Video, - pod - }) - } - }) - - return requestsGrouped -} diff --git a/server/models/request/request.ts b/server/models/request/request.ts deleted file mode 100644 index 71118a947..000000000 --- a/server/models/request/request.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { values } from 'lodash' -import * as Sequelize from 'sequelize' - -import { database as db } from '../../initializers/database' -import { REQUEST_ENDPOINTS } from '../../initializers' -import { addMethodsToModel } from '../utils' -import { - RequestInstance, - RequestAttributes, - - RequestMethods, - RequestsGrouped -} from './request-interface' - -let Request: Sequelize.Model -let countTotalRequests: RequestMethods.CountTotalRequests -let listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom -let removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo -let removeAll: RequestMethods.RemoveAll - -export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { - Request = sequelize.define('Request', - { - request: { - type: DataTypes.JSON, - allowNull: false - }, - endpoint: { - type: DataTypes.ENUM(values(REQUEST_ENDPOINTS)), - allowNull: false - } - } - ) - - const classMethods = [ - associate, - - listWithLimitAndRandom, - - countTotalRequests, - removeAll, - removeWithEmptyTo - ] - addMethodsToModel(Request, classMethods) - - return Request -} - -// ------------------------------ STATICS ------------------------------ - -function associate (models) { - Request.belongsToMany(models.Pod, { - foreignKey: { - name: 'requestId', - allowNull: false - }, - through: models.RequestToPod, - onDelete: 'CASCADE' - }) -} - -countTotalRequests = function () { - // We need to include Pod because there are no cascade delete when a pod is removed - // So we could count requests that do not have existing pod anymore - const query = { - include: [ Request['sequelize'].models.Pod ] - } - - return Request.count(query) -} - -listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number) { - const Pod = db.Pod - const tableJoin = '' - - return Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', tableJoin).then(podIds => { - // We don't have friends that have requests - if (podIds.length === 0) return [] - - // The first x requests of these pods - // It is very important to sort by id ASC to keep the requests order! - const query = { - order: [ - [ 'id', 'ASC' ] - ], - include: [ - { - model: Request['sequelize'].models.Pod, - where: { - id: { - [Sequelize.Op.in]: podIds - } - } - } - ] - } - - return Request.findAll(query).then(requests => { - - const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod) - return requestsGrouped - }) - }) -} - -removeAll = function () { - // Delete all requests - return Request.truncate({ cascade: true }) -} - -removeWithEmptyTo = function () { - const query = { - where: { - id: { - [Sequelize.Op.notIn]: [ - Sequelize.literal('SELECT "requestId" FROM "RequestToPods"') - ] - } - } - } - - return Request.destroy(query) -} - -// --------------------------------------------------------------------------- - -function groupAndTruncateRequests (requests: RequestInstance[], limitRequestsPerPod: number) { - const requestsGrouped: RequestsGrouped = {} - - requests.forEach(request => { - request.Pods.forEach(pod => { - if (!requestsGrouped[pod.id]) requestsGrouped[pod.id] = [] - - if (requestsGrouped[pod.id].length < limitRequestsPerPod) { - requestsGrouped[pod.id].push({ - request, - pod - }) - } - }) - }) - - return requestsGrouped -} diff --git a/server/models/video/index.ts b/server/models/video/index.ts index dba6a5590..20d97931f 100644 --- a/server/models/video/index.ts +++ b/server/models/video/index.ts @@ -1,4 +1,3 @@ -export * from './author-interface' export * from './tag-interface' export * from './video-abuse-interface' export * from './video-blacklist-interface'