aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/activitypub/pods.ts69
-rw-r--r--server/controllers/activitypub/videos.ts278
-rw-r--r--server/controllers/api/index.ts2
-rw-r--r--server/controllers/api/server/follows.ts (renamed from server/controllers/api/application/follows.ts)4
-rw-r--r--server/controllers/api/server/index.ts (renamed from server/controllers/api/application/index.ts)0
-rw-r--r--server/controllers/api/videos/abuse.ts6
-rw-r--r--server/controllers/api/videos/index.ts6
-rw-r--r--server/controllers/api/videos/rate.ts2
-rw-r--r--server/controllers/client.ts4
-rw-r--r--server/controllers/static.ts2
-rw-r--r--server/helpers/activitypub.ts16
-rw-r--r--server/helpers/custom-validators/accounts.ts2
-rw-r--r--server/helpers/custom-validators/index.ts4
-rw-r--r--server/helpers/custom-validators/servers.ts (renamed from server/helpers/custom-validators/pods.ts)0
-rw-r--r--server/helpers/custom-validators/videos.ts4
-rw-r--r--server/helpers/webfinger.ts6
-rw-r--r--server/initializers/constants.ts10
-rw-r--r--server/initializers/database.ts4
-rw-r--r--server/lib/cache/videos-preview-cache.ts2
-rw-r--r--server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts4
-rw-r--r--server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts4
-rw-r--r--server/lib/user.ts2
-rw-r--r--server/lib/video-channel.ts6
-rw-r--r--server/middlewares/activitypub.ts4
-rw-r--r--server/middlewares/index.ts2
-rw-r--r--server/middlewares/servers.ts (renamed from server/middlewares/pods.ts)0
-rw-r--r--server/middlewares/sort.ts7
-rw-r--r--server/middlewares/validators/index.ts2
-rw-r--r--server/middlewares/validators/servers.ts (renamed from server/middlewares/validators/pods.ts)2
-rw-r--r--server/middlewares/validators/video-channels.ts4
-rw-r--r--server/middlewares/validators/videos.ts4
-rw-r--r--server/models/account/account-follow.ts4
-rw-r--r--server/models/account/account-interface.ts11
-rw-r--r--server/models/account/account.ts37
-rw-r--r--server/models/index.ts2
-rw-r--r--server/models/pod/index.ts1
-rw-r--r--server/models/pod/pod-interface.ts61
-rw-r--r--server/models/pod/pod.ts248
-rw-r--r--server/models/server/index.ts1
-rw-r--r--server/models/server/server-interface.ts56
-rw-r--r--server/models/server/server.ts233
-rw-r--r--server/models/video/video-abuse-interface.ts4
-rw-r--r--server/models/video/video-abuse.ts18
-rw-r--r--server/models/video/video-channel-interface.ts2
-rw-r--r--server/models/video/video-channel.ts14
-rw-r--r--server/models/video/video-interface.ts12
-rw-r--r--server/models/video/video.ts58
47 files changed, 427 insertions, 797 deletions
diff --git a/server/controllers/activitypub/pods.ts b/server/controllers/activitypub/pods.ts
deleted file mode 100644
index 6cce57c1c..000000000
--- a/server/controllers/activitypub/pods.ts
+++ /dev/null
@@ -1,69 +0,0 @@
1// import * as express from 'express'
2//
3// import { database as db } from '../../../initializers/database'
4// import {
5// checkSignature,
6// signatureValidator,
7// setBodyHostPort,
8// remotePodsAddValidator,
9// asyncMiddleware
10// } from '../../../middlewares'
11// import { sendOwnedDataToPod } from '../../../lib'
12// import { getMyPublicCert, getFormattedObjects } from '../../../helpers'
13// import { CONFIG } from '../../../initializers'
14// import { PodInstance } from '../../../models'
15// import { PodSignature, Pod as FormattedPod } from '../../../../shared'
16//
17// const remotePodsRouter = express.Router()
18//
19// remotePodsRouter.post('/remove',
20// signatureValidator,
21// checkSignature,
22// asyncMiddleware(removePods)
23// )
24//
25// remotePodsRouter.post('/list',
26// asyncMiddleware(remotePodsList)
27// )
28//
29// remotePodsRouter.post('/add',
30// setBodyHostPort, // We need to modify the host before running the validator!
31// remotePodsAddValidator,
32// asyncMiddleware(addPods)
33// )
34//
35// // ---------------------------------------------------------------------------
36//
37// export {
38// remotePodsRouter
39// }
40//
41// // ---------------------------------------------------------------------------
42//
43// async function addPods (req: express.Request, res: express.Response, next: express.NextFunction) {
44// const information = req.body
45//
46// const pod = db.Pod.build(information)
47// const podCreated = await pod.save()
48//
49// await sendOwnedDataToPod(podCreated.id)
50//
51// const cert = await getMyPublicCert()
52// return res.json({ cert, email: CONFIG.ADMIN.EMAIL })
53// }
54//
55// async function remotePodsList (req: express.Request, res: express.Response, next: express.NextFunction) {
56// const pods = await db.Pod.list()
57//
58// return res.json(getFormattedObjects<FormattedPod, PodInstance>(pods, pods.length))
59// }
60//
61// async function removePods (req: express.Request, res: express.Response, next: express.NextFunction) {
62// const signature: PodSignature = req.body.signature
63// const host = signature.host
64//
65// const pod = await db.Pod.loadByHost(host)
66// await pod.destroy()
67//
68// return res.type('json').status(204).end()
69// }
diff --git a/server/controllers/activitypub/videos.ts b/server/controllers/activitypub/videos.ts
deleted file mode 100644
index 98894379f..000000000
--- a/server/controllers/activitypub/videos.ts
+++ /dev/null
@@ -1,278 +0,0 @@
1// import * as express from 'express'
2// import * as Bluebird from 'bluebird'
3// import * as Sequelize from 'sequelize'
4//
5// import { database as db } from '../../../initializers/database'
6// import {
7// REQUEST_ENDPOINT_ACTIONS,
8// REQUEST_ENDPOINTS,
9// REQUEST_VIDEO_EVENT_TYPES,
10// REQUEST_VIDEO_QADU_TYPES
11// } from '../../../initializers'
12// import {
13// checkSignature,
14// signatureValidator,
15// remoteVideosValidator,
16// remoteQaduVideosValidator,
17// remoteEventsVideosValidator
18// } from '../../../middlewares'
19// import { logger, retryTransactionWrapper, resetSequelizeInstance } from '../../../helpers'
20// import { quickAndDirtyUpdatesVideoToFriends, fetchVideoChannelByHostAndUUID } from '../../../lib'
21// import { PodInstance, VideoFileInstance } from '../../../models'
22// import {
23// RemoteVideoRequest,
24// RemoteVideoCreateData,
25// RemoteVideoUpdateData,
26// RemoteVideoRemoveData,
27// RemoteVideoReportAbuseData,
28// RemoteQaduVideoRequest,
29// RemoteQaduVideoData,
30// RemoteVideoEventRequest,
31// RemoteVideoEventData,
32// RemoteVideoChannelCreateData,
33// RemoteVideoChannelUpdateData,
34// RemoteVideoChannelRemoveData,
35// RemoteVideoAccountRemoveData,
36// RemoteVideoAccountCreateData
37// } from '../../../../shared'
38// import { VideoInstance } from '../../../models/video/video-interface'
39//
40// const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
41//
42// // Functions to call when processing a remote request
43// // FIXME: use RemoteVideoRequestType as id type
44// const functionsHash: { [ id: string ]: (...args) => Promise<any> } = {}
45// functionsHash[ENDPOINT_ACTIONS.ADD_VIDEO] = addRemoteVideoRetryWrapper
46// functionsHash[ENDPOINT_ACTIONS.UPDATE_VIDEO] = updateRemoteVideoRetryWrapper
47// functionsHash[ENDPOINT_ACTIONS.REMOVE_VIDEO] = removeRemoteVideoRetryWrapper
48// functionsHash[ENDPOINT_ACTIONS.ADD_CHANNEL] = addRemoteVideoChannelRetryWrapper
49// functionsHash[ENDPOINT_ACTIONS.UPDATE_CHANNEL] = updateRemoteVideoChannelRetryWrapper
50// functionsHash[ENDPOINT_ACTIONS.REMOVE_CHANNEL] = removeRemoteVideoChannelRetryWrapper
51// functionsHash[ENDPOINT_ACTIONS.REPORT_ABUSE] = reportAbuseRemoteVideoRetryWrapper
52// functionsHash[ENDPOINT_ACTIONS.ADD_ACCOUNT] = addRemoteVideoAccountRetryWrapper
53// functionsHash[ENDPOINT_ACTIONS.REMOVE_ACCOUNT] = removeRemoteVideoAccountRetryWrapper
54//
55// const remoteVideosRouter = express.Router()
56//
57// remoteVideosRouter.post('/',
58// signatureValidator,
59// checkSignature,
60// remoteVideosValidator,
61// remoteVideos
62// )
63//
64// remoteVideosRouter.post('/qadu',
65// signatureValidator,
66// checkSignature,
67// remoteQaduVideosValidator,
68// remoteVideosQadu
69// )
70//
71// remoteVideosRouter.post('/events',
72// signatureValidator,
73// checkSignature,
74// remoteEventsVideosValidator,
75// remoteVideosEvents
76// )
77//
78// // ---------------------------------------------------------------------------
79//
80// export {
81// remoteVideosRouter
82// }
83//
84// // ---------------------------------------------------------------------------
85//
86// function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
87// const requests: RemoteVideoRequest[] = req.body.data
88// const fromPod = res.locals.secure.pod
89//
90// // We need to process in the same order to keep consistency
91// Bluebird.each(requests, request => {
92// const data = request.data
93//
94// // Get the function we need to call in order to process the request
95// const fun = functionsHash[request.type]
96// if (fun === undefined) {
97// logger.error('Unknown remote request type %s.', request.type)
98// return
99// }
100//
101// return fun.call(this, data, fromPod)
102// })
103// .catch(err => logger.error('Error managing remote videos.', err))
104//
105// // Don't block the other pod
106// return res.type('json').status(204).end()
107// }
108//
109// function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) {
110// const requests: RemoteQaduVideoRequest[] = req.body.data
111// const fromPod = res.locals.secure.pod
112//
113// Bluebird.each(requests, request => {
114// const videoData = request.data
115//
116// return quickAndDirtyUpdateVideoRetryWrapper(videoData, fromPod)
117// })
118// .catch(err => logger.error('Error managing remote videos.', err))
119//
120// return res.type('json').status(204).end()
121// }
122//
123// function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) {
124// const requests: RemoteVideoEventRequest[] = req.body.data
125// const fromPod = res.locals.secure.pod
126//
127// Bluebird.each(requests, request => {
128// const eventData = request.data
129//
130// return processVideosEventsRetryWrapper(eventData, fromPod)
131// })
132// .catch(err => logger.error('Error managing remote videos.', err))
133//
134// return res.type('json').status(204).end()
135// }
136//
137// async function processVideosEventsRetryWrapper (eventData: RemoteVideoEventData, fromPod: PodInstance) {
138// const options = {
139// arguments: [ eventData, fromPod ],
140// errorMessage: 'Cannot process videos events with many retries.'
141// }
142//
143// await retryTransactionWrapper(processVideosEvents, options)
144// }
145//
146// async function processVideosEvents (eventData: RemoteVideoEventData, fromPod: PodInstance) {
147// await db.sequelize.transaction(async t => {
148// const sequelizeOptions = { transaction: t }
149// const videoInstance = await fetchLocalVideoByUUID(eventData.uuid, t)
150//
151// let columnToUpdate
152// let qaduType
153//
154// switch (eventData.eventType) {
155// case REQUEST_VIDEO_EVENT_TYPES.VIEWS:
156// columnToUpdate = 'views'
157// qaduType = REQUEST_VIDEO_QADU_TYPES.VIEWS
158// break
159//
160// case REQUEST_VIDEO_EVENT_TYPES.LIKES:
161// columnToUpdate = 'likes'
162// qaduType = REQUEST_VIDEO_QADU_TYPES.LIKES
163// break
164//
165// case REQUEST_VIDEO_EVENT_TYPES.DISLIKES:
166// columnToUpdate = 'dislikes'
167// qaduType = REQUEST_VIDEO_QADU_TYPES.DISLIKES
168// break
169//
170// default:
171// throw new Error('Unknown video event type.')
172// }
173//
174// const query = {}
175// query[columnToUpdate] = eventData.count
176//
177// await videoInstance.increment(query, sequelizeOptions)
178//
179// const qadusParams = [
180// {
181// videoId: videoInstance.id,
182// type: qaduType
183// }
184// ]
185// await quickAndDirtyUpdatesVideoToFriends(qadusParams, t)
186// })
187//
188// logger.info('Remote video event processed for video with uuid %s.', eventData.uuid)
189// }
190//
191// async function quickAndDirtyUpdateVideoRetryWrapper (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
192// const options = {
193// arguments: [ videoData, fromPod ],
194// errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
195// }
196//
197// await retryTransactionWrapper(quickAndDirtyUpdateVideo, options)
198// }
199//
200// async function quickAndDirtyUpdateVideo (videoData: RemoteQaduVideoData, fromPod: PodInstance) {
201// let videoUUID = ''
202//
203// await db.sequelize.transaction(async t => {
204// const videoInstance = await fetchVideoByHostAndUUID(fromPod.host, videoData.uuid, t)
205// const sequelizeOptions = { transaction: t }
206//
207// videoUUID = videoInstance.uuid
208//
209// if (videoData.views) {
210// videoInstance.set('views', videoData.views)
211// }
212//
213// if (videoData.likes) {
214// videoInstance.set('likes', videoData.likes)
215// }
216//
217// if (videoData.dislikes) {
218// videoInstance.set('dislikes', videoData.dislikes)
219// }
220//
221// await videoInstance.save(sequelizeOptions)
222// })
223//
224// logger.info('Remote video with uuid %s quick and dirty updated', videoUUID)
225// }
226//
227// async function reportAbuseRemoteVideoRetryWrapper (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
228// const options = {
229// arguments: [ reportData, fromPod ],
230// errorMessage: 'Cannot create remote abuse video with many retries.'
231// }
232//
233// await retryTransactionWrapper(reportAbuseRemoteVideo, options)
234// }
235//
236// async function reportAbuseRemoteVideo (reportData: RemoteVideoReportAbuseData, fromPod: PodInstance) {
237// logger.debug('Reporting remote abuse for video %s.', reportData.videoUUID)
238//
239// await db.sequelize.transaction(async t => {
240// const videoInstance = await fetchLocalVideoByUUID(reportData.videoUUID, t)
241// const videoAbuseData = {
242// reporterUsername: reportData.reporterUsername,
243// reason: reportData.reportReason,
244// reporterPodId: fromPod.id,
245// videoId: videoInstance.id
246// }
247//
248// await db.VideoAbuse.create(videoAbuseData)
249//
250// })
251//
252// logger.info('Remote abuse for video uuid %s created', reportData.videoUUID)
253// }
254//
255// async function fetchLocalVideoByUUID (id: string, t: Sequelize.Transaction) {
256// try {
257// const video = await db.Video.loadLocalVideoByUUID(id, t)
258//
259// if (!video) throw new Error('Video ' + id + ' not found')
260//
261// return video
262// } catch (err) {
263// logger.error('Cannot load owned video from id.', { error: err.stack, id })
264// throw err
265// }
266// }
267//
268// async function fetchVideoByHostAndUUID (podHost: string, uuid: string, t: Sequelize.Transaction) {
269// try {
270// const video = await db.Video.loadByHostAndUUID(podHost, uuid, t)
271// if (!video) throw new Error('Video not found')
272//
273// return video
274// } catch (err) {
275// logger.error('Cannot load video from host and uuid.', { error: err.stack, podHost, uuid })
276// throw err
277// }
278// }
diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts
index a22c78cce..876c911c7 100644
--- a/server/controllers/api/index.ts
+++ b/server/controllers/api/index.ts
@@ -4,7 +4,7 @@ import { badRequest } from '../../helpers'
4 4
5import { oauthClientsRouter } from './oauth-clients' 5import { oauthClientsRouter } from './oauth-clients'
6import { configRouter } from './config' 6import { configRouter } from './config'
7import { applicationRouter } from './application' 7import { applicationRouter } from './server'
8import { usersRouter } from './users' 8import { usersRouter } from './users'
9import { videosRouter } from './videos' 9import { videosRouter } from './videos'
10 10
diff --git a/server/controllers/api/application/follows.ts b/server/controllers/api/server/follows.ts
index 000bbd23e..c9775ad21 100644
--- a/server/controllers/api/application/follows.ts
+++ b/server/controllers/api/server/follows.ts
@@ -9,10 +9,10 @@ import { database as db } from '../../../initializers/database'
9import { sendFollow } from '../../../lib/activitypub/send-request' 9import { sendFollow } from '../../../lib/activitypub/send-request'
10import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../../middlewares' 10import { asyncMiddleware, paginationValidator, setFollowersSort, setPagination } from '../../../middlewares'
11import { authenticate } from '../../../middlewares/oauth' 11import { authenticate } from '../../../middlewares/oauth'
12import { setBodyHostsPort } from '../../../middlewares/pods' 12import { setBodyHostsPort } from '../../../middlewares/servers'
13import { setFollowingSort } from '../../../middlewares/sort' 13import { setFollowingSort } from '../../../middlewares/sort'
14import { ensureUserHasRight } from '../../../middlewares/user-right' 14import { ensureUserHasRight } from '../../../middlewares/user-right'
15import { followValidator } from '../../../middlewares/validators/pods' 15import { followValidator } from '../../../middlewares/validators/servers'
16import { followersSortValidator, followingSortValidator } from '../../../middlewares/validators/sort' 16import { followersSortValidator, followingSortValidator } from '../../../middlewares/validators/sort'
17 17
18const applicationFollowsRouter = express.Router() 18const applicationFollowsRouter = express.Router()
diff --git a/server/controllers/api/application/index.ts b/server/controllers/api/server/index.ts
index 011b971ed..011b971ed 100644
--- a/server/controllers/api/application/index.ts
+++ b/server/controllers/api/server/index.ts
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts
index 7a3471116..29f901f60 100644
--- a/server/controllers/api/videos/abuse.ts
+++ b/server/controllers/api/videos/abuse.ts
@@ -70,12 +70,12 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
70 reporterUsername, 70 reporterUsername,
71 reason: body.reason, 71 reason: body.reason,
72 videoId: videoInstance.id, 72 videoId: videoInstance.id,
73 reporterPodId: null // This is our pod that reported this abuse 73 reporterServerId: null // This is our server that reported this abuse
74 } 74 }
75 75
76 await db.sequelize.transaction(async t => { 76 await db.sequelize.transaction(async t => {
77 const abuse = await db.VideoAbuse.create(abuseToCreate, { transaction: t }) 77 const abuse = await db.VideoAbuse.create(abuseToCreate, { transaction: t })
78 // We send the information to the destination pod 78 // We send the information to the destination server
79 if (videoInstance.isOwned() === false) { 79 if (videoInstance.isOwned() === false) {
80 const reportData = { 80 const reportData = {
81 reporterUsername, 81 reporterUsername,
@@ -84,7 +84,7 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
84 } 84 }
85 85
86 // await friends.reportAbuseVideoToFriend(reportData, videoInstance, t) 86 // await friends.reportAbuseVideoToFriend(reportData, videoInstance, t)
87 // TODO: send abuse to origin pod 87 // TODO: send abuse to origin server
88 } 88 }
89 }) 89 })
90 90
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 063839223..ebc07e179 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -233,7 +233,7 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
233 233
234 // Let transcoding job send the video to friends because the video file extension might change 234 // Let transcoding job send the video to friends because the video file extension might change
235 if (CONFIG.TRANSCODING.ENABLED === true) return undefined 235 if (CONFIG.TRANSCODING.ENABLED === true) return undefined
236 // Don't send video to remote pods, it is private 236 // Don't send video to remote servers, it is private
237 if (video.privacy === VideoPrivacy.PRIVATE) return undefined 237 if (video.privacy === VideoPrivacy.PRIVATE) return undefined
238 238
239 await sendAddVideo(video, t) 239 await sendAddVideo(video, t)
@@ -287,7 +287,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
287 await sendUpdateVideoChannel(videoInstance, t) 287 await sendUpdateVideoChannel(videoInstance, t)
288 } 288 }
289 289
290 // Video is not private anymore, send a create action to remote pods 290 // Video is not private anymore, send a create action to remote servers
291 if (wasPrivateVideo === true && videoInstance.privacy !== VideoPrivacy.PRIVATE) { 291 if (wasPrivateVideo === true && videoInstance.privacy !== VideoPrivacy.PRIVATE) {
292 await sendAddVideo(videoInstance, t) 292 await sendAddVideo(videoInstance, t)
293 } 293 }
@@ -365,7 +365,7 @@ async function removeVideo (req: express.Request, res: express.Response) {
365} 365}
366 366
367async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) { 367async function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
368 const resultList = await db.Video.searchAndPopulateAccountAndPodAndTags( 368 const resultList = await db.Video.searchAndPopulateAccountAndServerAndTags(
369 req.params.value, 369 req.params.value,
370 req.query.field, 370 req.query.field,
371 req.query.start, 371 req.query.start,
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts
index 955277d25..8216dffd2 100644
--- a/server/controllers/api/videos/rate.ts
+++ b/server/controllers/api/videos/rate.ts
@@ -83,7 +83,7 @@ async function rateVideo (req: express.Request, res: express.Response) {
83 await videoInstance.increment(incrementQuery, sequelizeOptions) 83 await videoInstance.increment(incrementQuery, sequelizeOptions)
84 84
85 if (videoInstance.isOwned() === false) { 85 if (videoInstance.isOwned() === false) {
86 // TODO: Send a event to original pod 86 // TODO: Send a event to original server
87 } else { 87 } else {
88 // TODO: Send update to followers 88 // TODO: Send update to followers
89 } 89 }
diff --git a/server/controllers/client.ts b/server/controllers/client.ts
index 40dda7584..045a50ef0 100644
--- a/server/controllers/client.ts
+++ b/server/controllers/client.ts
@@ -110,9 +110,9 @@ async function generateWatchHtmlPage (req: express.Request, res: express.Respons
110 110
111 // Let Angular application handle errors 111 // Let Angular application handle errors
112 if (validator.isUUID(videoId, 4)) { 112 if (validator.isUUID(videoId, 4)) {
113 videoPromise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(videoId) 113 videoPromise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(videoId)
114 } else if (validator.isInt(videoId)) { 114 } else if (validator.isInt(videoId)) {
115 videoPromise = db.Video.loadAndPopulateAccountAndPodAndTags(+videoId) 115 videoPromise = db.Video.loadAndPopulateAccountAndServerAndTags(+videoId)
116 } else { 116 } else {
117 return res.sendFile(indexPath) 117 return res.sendFile(indexPath)
118 } 118 }
diff --git a/server/controllers/static.ts b/server/controllers/static.ts
index c7c952d6f..7425fd097 100644
--- a/server/controllers/static.ts
+++ b/server/controllers/static.ts
@@ -12,7 +12,7 @@ import { asyncMiddleware } from '../middlewares'
12const staticRouter = express.Router() 12const staticRouter = express.Router()
13 13
14/* 14/*
15 Cors is very important to let other pods access torrent and video files 15 Cors is very important to let other servers access torrent and video files
16*/ 16*/
17 17
18const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR 18const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
index b91490a0b..3e77e0581 100644
--- a/server/helpers/activitypub.ts
+++ b/server/helpers/activitypub.ts
@@ -35,7 +35,7 @@ async function getOrCreateAccount (accountUrl: string) {
35 35
36 // We don't have this account in our database, fetch it on remote 36 // We don't have this account in our database, fetch it on remote
37 if (!account) { 37 if (!account) {
38 const res = await fetchRemoteAccountAndCreatePod(accountUrl) 38 const res = await fetchRemoteAccountAndCreateServer(accountUrl)
39 if (res === undefined) throw new Error('Cannot fetch remote account.') 39 if (res === undefined) throw new Error('Cannot fetch remote account.')
40 40
41 // Save our new account in database 41 // Save our new account in database
@@ -46,7 +46,7 @@ async function getOrCreateAccount (accountUrl: string) {
46 return account 46 return account
47} 47}
48 48
49async function fetchRemoteAccountAndCreatePod (accountUrl: string) { 49async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
50 const options = { 50 const options = {
51 uri: accountUrl, 51 uri: accountUrl,
52 method: 'GET', 52 method: 'GET',
@@ -90,7 +90,7 @@ async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
90 }) 90 })
91 91
92 const accountHost = url.parse(account.url).host 92 const accountHost = url.parse(account.url).host
93 const podOptions = { 93 const serverOptions = {
94 where: { 94 where: {
95 host: accountHost 95 host: accountHost
96 }, 96 },
@@ -98,15 +98,15 @@ async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
98 host: accountHost 98 host: accountHost
99 } 99 }
100 } 100 }
101 const [ pod ] = await db.Pod.findOrCreate(podOptions) 101 const [ server ] = await db.Server.findOrCreate(serverOptions)
102 account.set('podId', pod.id) 102 account.set('serverId', server.id)
103 103
104 return { account, pod } 104 return { account, server }
105} 105}
106 106
107function fetchRemoteVideoPreview (video: VideoInstance) { 107function fetchRemoteVideoPreview (video: VideoInstance) {
108 // FIXME: use url 108 // FIXME: use url
109 const host = video.VideoChannel.Account.Pod.host 109 const host = video.VideoChannel.Account.Server.host
110 const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName()) 110 const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName())
111 111
112 return request.get(REMOTE_SCHEME.HTTP + '://' + host + path) 112 return request.get(REMOTE_SCHEME.HTTP + '://' + host + path)
@@ -163,7 +163,7 @@ function activityPubCollectionPagination (url: string, page: number, result: Res
163// --------------------------------------------------------------------------- 163// ---------------------------------------------------------------------------
164 164
165export { 165export {
166 fetchRemoteAccountAndCreatePod, 166 fetchRemoteAccountAndCreateServer,
167 activityPubContextify, 167 activityPubContextify,
168 activityPubCollectionPagination, 168 activityPubCollectionPagination,
169 getActivityPubUrl, 169 getActivityPubUrl,
diff --git a/server/helpers/custom-validators/accounts.ts b/server/helpers/custom-validators/accounts.ts
index 6d6219a95..088d5fc8f 100644
--- a/server/helpers/custom-validators/accounts.ts
+++ b/server/helpers/custom-validators/accounts.ts
@@ -8,7 +8,7 @@ import { AccountInstance } from '../../models'
8import { logger } from '../logger' 8import { logger } from '../logger'
9 9
10import { isUserUsernameValid } from './users' 10import { isUserUsernameValid } from './users'
11import { isHostValid } from './pods' 11import { isHostValid } from './servers'
12 12
13function isAccountNameValid (value: string) { 13function isAccountNameValid (value: string) {
14 return isUserUsernameValid(value) 14 return isUserUsernameValid(value)
diff --git a/server/helpers/custom-validators/index.ts b/server/helpers/custom-validators/index.ts
index 1c475e301..d3b2f5393 100644
--- a/server/helpers/custom-validators/index.ts
+++ b/server/helpers/custom-validators/index.ts
@@ -1,7 +1,7 @@
1export * from './activitypub' 1export * from './activitypub'
2export * from './misc' 2export * from './misc'
3export * from './pods' 3export * from './servers'
4export * from './pods' 4export * from './servers'
5export * from './users' 5export * from './users'
6export * from './accounts' 6export * from './accounts'
7export * from './video-channels' 7export * from './video-channels'
diff --git a/server/helpers/custom-validators/pods.ts b/server/helpers/custom-validators/servers.ts
index d5021bf38..d5021bf38 100644
--- a/server/helpers/custom-validators/pods.ts
+++ b/server/helpers/custom-validators/servers.ts
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
index 715119cf6..d68de6609 100644
--- a/server/helpers/custom-validators/videos.ts
+++ b/server/helpers/custom-validators/videos.ts
@@ -171,9 +171,9 @@ function isVideoFileInfoHashValid (value: string) {
171function checkVideoExists (id: string, res: express.Response, callback: () => void) { 171function checkVideoExists (id: string, res: express.Response, callback: () => void) {
172 let promise: Promise<VideoInstance> 172 let promise: Promise<VideoInstance>
173 if (validator.isInt(id)) { 173 if (validator.isInt(id)) {
174 promise = db.Video.loadAndPopulateAccountAndPodAndTags(+id) 174 promise = db.Video.loadAndPopulateAccountAndServerAndTags(+id)
175 } else { // UUID 175 } else { // UUID
176 promise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(id) 176 promise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(id)
177 } 177 }
178 178
179 promise.then(video => { 179 promise.then(video => {
diff --git a/server/helpers/webfinger.ts b/server/helpers/webfinger.ts
index 0155e5f3e..31417e728 100644
--- a/server/helpers/webfinger.ts
+++ b/server/helpers/webfinger.ts
@@ -3,7 +3,7 @@ import * as WebFinger from 'webfinger.js'
3import { isTestInstance } from './core-utils' 3import { isTestInstance } from './core-utils'
4import { isActivityPubUrlValid } from './custom-validators' 4import { isActivityPubUrlValid } from './custom-validators'
5import { WebFingerData } from '../../shared' 5import { WebFingerData } from '../../shared'
6import { fetchRemoteAccountAndCreatePod } from './activitypub' 6import { fetchRemoteAccountAndCreateServer } from './activitypub'
7 7
8const webfinger = new WebFinger({ 8const webfinger = new WebFinger({
9 webfist_fallback: false, 9 webfist_fallback: false,
@@ -22,8 +22,8 @@ async function getAccountFromWebfinger (nameWithHost: string) {
22 throw new Error('Cannot find self link or href is not a valid URL.') 22 throw new Error('Cannot find self link or href is not a valid URL.')
23 } 23 }
24 24
25 const res = await fetchRemoteAccountAndCreatePod(selfLink.href) 25 const res = await fetchRemoteAccountAndCreateServer(selfLink.href)
26 if (res === undefined) throw new Error('Cannot fetch and create pod of remote account ' + selfLink.href) 26 if (res === undefined) throw new Error('Cannot fetch and create server of remote account ' + selfLink.href)
27 27
28 return res.account 28 return res.account
29} 29}
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 4a49c1ab3..99da95ab9 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -6,10 +6,6 @@ import { root, isTestInstance } from '../helpers/core-utils'
6 6
7import { 7import {
8 VideoRateType, 8 VideoRateType,
9 RequestEndpoint,
10 RequestVideoEventType,
11 RequestVideoQaduType,
12 RemoteVideoRequestType,
13 JobState, 9 JobState,
14 JobCategory 10 JobCategory
15} from '../../shared/models' 11} from '../../shared/models'
@@ -220,7 +216,7 @@ const VIDEO_MIMETYPE_EXT = {
220 216
221// --------------------------------------------------------------------------- 217// ---------------------------------------------------------------------------
222 218
223// Score a pod has when we create it as a friend 219// Score a server has when we create it as a friend
224const FRIEND_SCORE = { 220const FRIEND_SCORE = {
225 BASE: 100, 221 BASE: 100,
226 MAX: 1000 222 MAX: 1000
@@ -243,7 +239,7 @@ const ACTIVITY_PUB = {
243// --------------------------------------------------------------------------- 239// ---------------------------------------------------------------------------
244 240
245// Number of points we add/remove from a friend after a successful/bad request 241// Number of points we add/remove from a friend after a successful/bad request
246const PODS_SCORE = { 242const SERVERS_SCORE = {
247 PENALTY: -10, 243 PENALTY: -10,
248 BONUS: 10 244 BONUS: 10
249} 245}
@@ -352,7 +348,7 @@ export {
352 OAUTH_LIFETIME, 348 OAUTH_LIFETIME,
353 OPENGRAPH_AND_OEMBED_COMMENT, 349 OPENGRAPH_AND_OEMBED_COMMENT,
354 PAGINATION_COUNT_DEFAULT, 350 PAGINATION_COUNT_DEFAULT,
355 PODS_SCORE, 351 SERVERS_SCORE,
356 PREVIEWS_SIZE, 352 PREVIEWS_SIZE,
357 REMOTE_SCHEME, 353 REMOTE_SCHEME,
358 ACTIVITY_PUB_ACCEPT_HEADER, 354 ACTIVITY_PUB_ACCEPT_HEADER,
diff --git a/server/initializers/database.ts b/server/initializers/database.ts
index 1383bb33b..19b5a0466 100644
--- a/server/initializers/database.ts
+++ b/server/initializers/database.ts
@@ -18,7 +18,7 @@ import { UserModel } from '../models/account/user-interface'
18import { AccountVideoRateModel } from '../models/account/account-video-rate-interface' 18import { AccountVideoRateModel } from '../models/account/account-video-rate-interface'
19import { AccountFollowModel } from '../models/account/account-follow-interface' 19import { AccountFollowModel } from '../models/account/account-follow-interface'
20import { TagModel } from './../models/video/tag-interface' 20import { TagModel } from './../models/video/tag-interface'
21import { PodModel } from './../models/pod/pod-interface' 21import { ServerModel } from '../models/server/server-interface'
22import { OAuthTokenModel } from './../models/oauth/oauth-token-interface' 22import { OAuthTokenModel } from './../models/oauth/oauth-token-interface'
23import { OAuthClientModel } from './../models/oauth/oauth-client-interface' 23import { OAuthClientModel } from './../models/oauth/oauth-client-interface'
24import { JobModel } from './../models/job/job-interface' 24import { JobModel } from './../models/job/job-interface'
@@ -38,7 +38,7 @@ const database: {
38 Job?: JobModel, 38 Job?: JobModel,
39 OAuthClient?: OAuthClientModel, 39 OAuthClient?: OAuthClientModel,
40 OAuthToken?: OAuthTokenModel, 40 OAuthToken?: OAuthTokenModel,
41 Pod?: PodModel, 41 Server?: ServerModel,
42 Tag?: TagModel, 42 Tag?: TagModel,
43 AccountVideoRate?: AccountVideoRateModel, 43 AccountVideoRate?: AccountVideoRateModel,
44 AccountFollow?: AccountFollowModel, 44 AccountFollow?: AccountFollowModel,
diff --git a/server/lib/cache/videos-preview-cache.ts b/server/lib/cache/videos-preview-cache.ts
index 776f647a0..0570f51e8 100644
--- a/server/lib/cache/videos-preview-cache.ts
+++ b/server/lib/cache/videos-preview-cache.ts
@@ -42,7 +42,7 @@ class VideosPreviewCache {
42 } 42 }
43 43
44 private async loadPreviews (key: string) { 44 private async loadPreviews (key: string) {
45 const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(key) 45 const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(key)
46 if (!video) return undefined 46 if (!video) return undefined
47 47
48 if (video.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName()) 48 if (video.isOwned()) return join(CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName())
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 47603a66c..d3ee886e7 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
@@ -8,7 +8,7 @@ import { JobScheduler } from '../job-scheduler'
8import { TranscodingJobPayload } from './transcoding-job-scheduler' 8import { TranscodingJobPayload } from './transcoding-job-scheduler'
9 9
10async function process (data: TranscodingJobPayload, jobId: number) { 10async function process (data: TranscodingJobPayload, jobId: number) {
11 const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(data.videoUUID) 11 const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(data.videoUUID)
12 // No video, maybe deleted? 12 // No video, maybe deleted?
13 if (!video) { 13 if (!video) {
14 logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid }) 14 logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid })
@@ -31,7 +31,7 @@ async function onSuccess (jobId: number, video: VideoInstance, jobScheduler: Job
31 logger.info('Job %d is a success.', jobId) 31 logger.info('Job %d is a success.', jobId)
32 32
33 // Maybe the video changed in database, refresh it 33 // Maybe the video changed in database, refresh it
34 const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(video.uuid) 34 const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(video.uuid)
35 // Video does not exist anymore 35 // Video does not exist anymore
36 if (!videoDatabase) return undefined 36 if (!videoDatabase) return undefined
37 37
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 77e5d9f7f..4f2ce3d24 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'
5import { sendUpdateVideo } from '../../activitypub/send-request' 5import { sendUpdateVideo } from '../../activitypub/send-request'
6 6
7async function process (data: { videoUUID: string, resolution: VideoResolution }, jobId: number) { 7async function process (data: { videoUUID: string, resolution: VideoResolution }, jobId: number) {
8 const video = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(data.videoUUID) 8 const video = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(data.videoUUID)
9 // No video, maybe deleted? 9 // No video, maybe deleted?
10 if (!video) { 10 if (!video) {
11 logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid }) 11 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) {
28 logger.info('Job %d is a success.', jobId) 28 logger.info('Job %d is a success.', jobId)
29 29
30 // Maybe the video changed in database, refresh it 30 // Maybe the video changed in database, refresh it
31 const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(video.uuid) 31 const videoDatabase = await db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(video.uuid)
32 // Video does not exist anymore 32 // Video does not exist anymore
33 if (!videoDatabase) return undefined 33 if (!videoDatabase) return undefined
34 34
diff --git a/server/lib/user.ts b/server/lib/user.ts
index d2d599dfd..9884e566f 100644
--- a/server/lib/user.ts
+++ b/server/lib/user.ts
@@ -46,7 +46,7 @@ async function createLocalAccount (name: string, userId: number, applicationId:
46 followingUrl: url + '/following', 46 followingUrl: url + '/following',
47 userId, 47 userId,
48 applicationId, 48 applicationId,
49 podId: null // It is our pod 49 serverId: null // It is our server
50 }) 50 })
51 51
52 return accountInstance.save({ transaction: t }) 52 return accountInstance.save({ transaction: t })
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts
index 13841ea33..80303fb83 100644
--- a/server/lib/video-channel.ts
+++ b/server/lib/video-channel.ts
@@ -30,14 +30,14 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account
30 return videoChannelCreated 30 return videoChannelCreated
31} 31}
32 32
33async function fetchVideoChannelByHostAndUUID (podHost: string, uuid: string, t: Sequelize.Transaction) { 33async function fetchVideoChannelByHostAndUUID (serverHost: string, uuid: string, t: Sequelize.Transaction) {
34 try { 34 try {
35 const videoChannel = await db.VideoChannel.loadByHostAndUUID(podHost, uuid, t) 35 const videoChannel = await db.VideoChannel.loadByHostAndUUID(serverHost, uuid, t)
36 if (!videoChannel) throw new Error('Video channel not found') 36 if (!videoChannel) throw new Error('Video channel not found')
37 37
38 return videoChannel 38 return videoChannel
39 } catch (err) { 39 } catch (err) {
40 logger.error('Cannot load video channel from host and uuid.', { error: err.stack, podHost, uuid }) 40 logger.error('Cannot load video channel from host and uuid.', { error: err.stack, serverHost, uuid })
41 throw err 41 throw err
42 } 42 }
43} 43}
diff --git a/server/middlewares/activitypub.ts b/server/middlewares/activitypub.ts
index bed2bfeab..0ea522e5c 100644
--- a/server/middlewares/activitypub.ts
+++ b/server/middlewares/activitypub.ts
@@ -1,7 +1,7 @@
1import { NextFunction, Request, Response, RequestHandler } from 'express' 1import { NextFunction, Request, Response, RequestHandler } from 'express'
2import { ActivityPubSignature } from '../../shared' 2import { ActivityPubSignature } from '../../shared'
3import { isSignatureVerified, logger } from '../helpers' 3import { isSignatureVerified, logger } from '../helpers'
4import { fetchRemoteAccountAndCreatePod } from '../helpers/activitypub' 4import { fetchRemoteAccountAndCreateServer } from '../helpers/activitypub'
5import { database as db, ACTIVITY_PUB_ACCEPT_HEADER } from '../initializers' 5import { database as db, ACTIVITY_PUB_ACCEPT_HEADER } from '../initializers'
6import { each, eachSeries, waterfall } from 'async' 6import { each, eachSeries, waterfall } from 'async'
7 7
@@ -14,7 +14,7 @@ async function checkSignature (req: Request, res: Response, next: NextFunction)
14 14
15 // We don't have this account in our database, fetch it on remote 15 // We don't have this account in our database, fetch it on remote
16 if (!account) { 16 if (!account) {
17 const accountResult = await fetchRemoteAccountAndCreatePod(signatureObject.creator) 17 const accountResult = await fetchRemoteAccountAndCreateServer(signatureObject.creator)
18 18
19 if (!accountResult) { 19 if (!accountResult) {
20 return res.sendStatus(403) 20 return res.sendStatus(403)
diff --git a/server/middlewares/index.ts b/server/middlewares/index.ts
index 40480450b..aafcad2d9 100644
--- a/server/middlewares/index.ts
+++ b/server/middlewares/index.ts
@@ -3,7 +3,7 @@ export * from './activitypub'
3export * from './async' 3export * from './async'
4export * from './oauth' 4export * from './oauth'
5export * from './pagination' 5export * from './pagination'
6export * from './pods' 6export * from './servers'
7export * from './search' 7export * from './search'
8export * from './sort' 8export * from './sort'
9export * from './user-right' 9export * from './user-right'
diff --git a/server/middlewares/pods.ts b/server/middlewares/servers.ts
index eaf9aa144..eaf9aa144 100644
--- a/server/middlewares/pods.ts
+++ b/server/middlewares/servers.ts
diff --git a/server/middlewares/sort.ts b/server/middlewares/sort.ts
index 20ae341f0..279b29e65 100644
--- a/server/middlewares/sort.ts
+++ b/server/middlewares/sort.ts
@@ -4,12 +4,6 @@ import * as express from 'express'
4import { SortType } from '../helpers' 4import { SortType } from '../helpers'
5import { database } from '../initializers' 5import { database } from '../initializers'
6 6
7function setPodsSort (req: express.Request, res: express.Response, next: express.NextFunction) {
8 if (!req.query.sort) req.query.sort = '-createdAt'
9
10 return next()
11}
12
13function setUsersSort (req: express.Request, res: express.Response, next: express.NextFunction) { 7function setUsersSort (req: express.Request, res: express.Response, next: express.NextFunction) {
14 if (!req.query.sort) req.query.sort = '-createdAt' 8 if (!req.query.sort) req.query.sort = '-createdAt'
15 9
@@ -70,7 +64,6 @@ function setBlacklistSort (req: express.Request, res: express.Response, next: ex
70// --------------------------------------------------------------------------- 64// ---------------------------------------------------------------------------
71 65
72export { 66export {
73 setPodsSort,
74 setUsersSort, 67 setUsersSort,
75 setVideoAbusesSort, 68 setVideoAbusesSort,
76 setVideoChannelsSort, 69 setVideoChannelsSort,
diff --git a/server/middlewares/validators/index.ts b/server/middlewares/validators/index.ts
index 92a4bad28..3f5afe5b3 100644
--- a/server/middlewares/validators/index.ts
+++ b/server/middlewares/validators/index.ts
@@ -2,7 +2,7 @@ export * from './account'
2export * from './oembed' 2export * from './oembed'
3export * from './activitypub' 3export * from './activitypub'
4export * from './pagination' 4export * from './pagination'
5export * from './pods' 5export * from './servers'
6export * from './sort' 6export * from './sort'
7export * from './users' 7export * from './users'
8export * from './videos' 8export * from './videos'
diff --git a/server/middlewares/validators/pods.ts b/server/middlewares/validators/servers.ts
index e17369a6f..95b69b789 100644
--- a/server/middlewares/validators/pods.ts
+++ b/server/middlewares/validators/servers.ts
@@ -1,6 +1,6 @@
1import * as express from 'express' 1import * as express from 'express'
2import { body } from 'express-validator/check' 2import { body } from 'express-validator/check'
3import { isEachUniqueHostValid } from '../../helpers/custom-validators/pods' 3import { isEachUniqueHostValid } from '../../helpers/custom-validators/servers'
4import { isTestInstance } from '../../helpers/core-utils' 4import { isTestInstance } from '../../helpers/core-utils'
5import { CONFIG } from '../../initializers/constants' 5import { CONFIG } from '../../initializers/constants'
6import { logger } from '../../helpers/logger' 6import { logger } from '../../helpers/logger'
diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts
index 53416a857..f0ead24e3 100644
--- a/server/middlewares/validators/video-channels.ts
+++ b/server/middlewares/validators/video-channels.ts
@@ -50,7 +50,7 @@ const videoChannelsUpdateValidator = [
50 // We need to make additional checks 50 // We need to make additional checks
51 if (res.locals.videoChannel.isOwned() === false) { 51 if (res.locals.videoChannel.isOwned() === false) {
52 return res.status(403) 52 return res.status(403)
53 .json({ error: 'Cannot update video channel of another pod' }) 53 .json({ error: 'Cannot update video channel of another server' })
54 .end() 54 .end()
55 } 55 }
56 56
@@ -113,7 +113,7 @@ function checkUserCanDeleteVideoChannel (res: express.Response, callback: () =>
113 // Retrieve the user who did the request 113 // Retrieve the user who did the request
114 if (res.locals.videoChannel.isOwned() === false) { 114 if (res.locals.videoChannel.isOwned() === false) {
115 return res.status(403) 115 return res.status(403)
116 .json({ error: 'Cannot remove video channel of another pod.' }) 116 .json({ error: 'Cannot remove video channel of another server.' })
117 .end() 117 .end()
118 } 118 }
119 119
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index 10b426df3..158b475e3 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -127,7 +127,7 @@ const videosUpdateValidator = [
127 // We need to make additional checks 127 // We need to make additional checks
128 if (video.isOwned() === false) { 128 if (video.isOwned() === false) {
129 return res.status(403) 129 return res.status(403)
130 .json({ error: 'Cannot update video of another pod' }) 130 .json({ error: 'Cannot update video of another server' })
131 .end() 131 .end()
132 } 132 }
133 133
@@ -250,7 +250,7 @@ function checkUserCanDeleteVideo (userId: number, res: express.Response, callbac
250 // Retrieve the user who did the request 250 // Retrieve the user who did the request
251 if (res.locals.video.isOwned() === false) { 251 if (res.locals.video.isOwned() === false) {
252 return res.status(403) 252 return res.status(403)
253 .json({ error: 'Cannot remove video of another pod, blacklist it' }) 253 .json({ error: 'Cannot remove video of another server, blacklist it' })
254 .end() 254 .end()
255 } 255 }
256 256
diff --git a/server/models/account/account-follow.ts b/server/models/account/account-follow.ts
index 6d7592326..c940d7cd4 100644
--- a/server/models/account/account-follow.ts
+++ b/server/models/account/account-follow.ts
@@ -101,7 +101,7 @@ listFollowingForApi = function (id: number, start: number, count: number, sort:
101 model: AccountFollow['sequelize'].models.Account, 101 model: AccountFollow['sequelize'].models.Account,
102 as: 'AccountFollowing', 102 as: 'AccountFollowing',
103 required: true, 103 required: true,
104 include: [ AccountFollow['sequelize'].models.Pod ] 104 include: [ AccountFollow['sequelize'].models.Server ]
105 } 105 }
106 ] 106 ]
107 } 107 }
@@ -125,7 +125,7 @@ listFollowersForApi = function (id: number, start: number, count: number, sort:
125 model: AccountFollow[ 'sequelize' ].models.Account, 125 model: AccountFollow[ 'sequelize' ].models.Account,
126 required: true, 126 required: true,
127 as: 'AccountFollower', 127 as: 'AccountFollower',
128 include: [ AccountFollow['sequelize'].models.Pod ] 128 include: [ AccountFollow['sequelize'].models.Server ]
129 }, 129 },
130 { 130 {
131 model: AccountFollow['sequelize'].models.Account, 131 model: AccountFollow['sequelize'].models.Account,
diff --git a/server/models/account/account-interface.ts b/server/models/account/account-interface.ts
index ce1afec02..1a567fb7a 100644
--- a/server/models/account/account-interface.ts
+++ b/server/models/account/account-interface.ts
@@ -1,8 +1,7 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import * as Sequelize from 'sequelize' 2import * as Sequelize from 'sequelize'
3import { Account as FormattedAccount, ActivityPubActor } from '../../../shared' 3import { Account as FormattedAccount, ActivityPubActor } from '../../../shared'
4import { ResultList } from '../../../shared/models/result-list.model' 4import { ServerInstance } from '../server/server-interface'
5import { PodInstance } from '../pod/pod-interface'
6import { VideoChannelInstance } from '../video/video-channel-interface' 5import { VideoChannelInstance } from '../video/video-channel-interface'
7 6
8export namespace AccountMethods { 7export namespace AccountMethods {
@@ -11,7 +10,7 @@ export namespace AccountMethods {
11 export type Load = (id: number) => Bluebird<AccountInstance> 10 export type Load = (id: number) => Bluebird<AccountInstance>
12 export type LoadByUUID = (uuid: string) => Bluebird<AccountInstance> 11 export type LoadByUUID = (uuid: string) => Bluebird<AccountInstance>
13 export type LoadByUrl = (url: string, transaction?: Sequelize.Transaction) => Bluebird<AccountInstance> 12 export type LoadByUrl = (url: string, transaction?: Sequelize.Transaction) => Bluebird<AccountInstance>
14 export type LoadAccountByPodAndUUID = (uuid: string, podId: number, transaction: Sequelize.Transaction) => Bluebird<AccountInstance> 13 export type LoadAccountByServerAndUUID = (uuid: string, serverId: number, transaction: Sequelize.Transaction) => Bluebird<AccountInstance>
15 export type LoadLocalByName = (name: string) => Bluebird<AccountInstance> 14 export type LoadLocalByName = (name: string) => Bluebird<AccountInstance>
16 export type LoadByNameAndHost = (name: string, host: string) => Bluebird<AccountInstance> 15 export type LoadByNameAndHost = (name: string, host: string) => Bluebird<AccountInstance>
17 export type ListOwned = () => Bluebird<AccountInstance[]> 16 export type ListOwned = () => Bluebird<AccountInstance[]>
@@ -27,7 +26,7 @@ export namespace AccountMethods {
27 26
28export interface AccountClass { 27export interface AccountClass {
29 loadApplication: AccountMethods.LoadApplication 28 loadApplication: AccountMethods.LoadApplication
30 loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID 29 loadAccountByServerAndUUID: AccountMethods.LoadAccountByServerAndUUID
31 load: AccountMethods.Load 30 load: AccountMethods.Load
32 loadByUUID: AccountMethods.LoadByUUID 31 loadByUUID: AccountMethods.LoadByUUID
33 loadByUrl: AccountMethods.LoadByUrl 32 loadByUrl: AccountMethods.LoadByUrl
@@ -51,7 +50,7 @@ export interface AccountAttributes {
51 50
52 uuid?: string 51 uuid?: string
53 52
54 podId?: number 53 serverId?: number
55 userId?: number 54 userId?: number
56 applicationId?: number 55 applicationId?: number
57} 56}
@@ -69,7 +68,7 @@ export interface AccountInstance extends AccountClass, AccountAttributes, Sequel
69 createdAt: Date 68 createdAt: Date
70 updatedAt: Date 69 updatedAt: Date
71 70
72 Pod: PodInstance 71 Server: ServerInstance
73 VideoChannels: VideoChannelInstance[] 72 VideoChannels: VideoChannelInstance[]
74} 73}
75 74
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index e90eaae5e..ee00c5aef 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -26,7 +26,7 @@ import { sendDeleteAccount } from '../../lib/activitypub/send-request'
26import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants' 26import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants'
27 27
28let Account: Sequelize.Model<AccountInstance, AccountAttributes> 28let Account: Sequelize.Model<AccountInstance, AccountAttributes>
29let loadAccountByPodAndUUID: AccountMethods.LoadAccountByPodAndUUID 29let loadAccountByServerAndUUID: AccountMethods.LoadAccountByServerAndUUID
30let load: AccountMethods.Load 30let load: AccountMethods.Load
31let loadApplication: AccountMethods.LoadApplication 31let loadApplication: AccountMethods.LoadApplication
32let loadByUUID: AccountMethods.LoadByUUID 32let loadByUUID: AccountMethods.LoadByUUID
@@ -170,7 +170,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
170 fields: [ 'name' ] 170 fields: [ 'name' ]
171 }, 171 },
172 { 172 {
173 fields: [ 'podId' ] 173 fields: [ 'serverId' ]
174 }, 174 },
175 { 175 {
176 fields: [ 'userId' ], 176 fields: [ 'userId' ],
@@ -181,7 +181,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
181 unique: true 181 unique: true
182 }, 182 },
183 { 183 {
184 fields: [ 'name', 'podId', 'applicationId' ], 184 fields: [ 'name', 'serverId', 'applicationId' ],
185 unique: true 185 unique: true
186 } 186 }
187 ], 187 ],
@@ -191,7 +191,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
191 191
192 const classMethods = [ 192 const classMethods = [
193 associate, 193 associate,
194 loadAccountByPodAndUUID, 194 loadAccountByServerAndUUID,
195 loadApplication, 195 loadApplication,
196 load, 196 load,
197 loadByUUID, 197 loadByUUID,
@@ -217,9 +217,9 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes
217// --------------------------------------------------------------------------- 217// ---------------------------------------------------------------------------
218 218
219function associate (models) { 219function associate (models) {
220 Account.belongsTo(models.Pod, { 220 Account.belongsTo(models.Server, {
221 foreignKey: { 221 foreignKey: {
222 name: 'podId', 222 name: 'serverId',
223 allowNull: true 223 allowNull: true
224 }, 224 },
225 onDelete: 'cascade' 225 onDelete: 'cascade'
@@ -278,19 +278,28 @@ function afterDestroy (account: AccountInstance) {
278} 278}
279 279
280toFormattedJSON = function (this: AccountInstance) { 280toFormattedJSON = function (this: AccountInstance) {
281 let host = this.Pod ? this.Pod.host : CONFIG.WEBSERVER.HOST 281 let host = CONFIG.WEBSERVER.HOST
282 let score: number
283
284 if (this.Server) {
285 host = this.Server.host
286 score = this.Server.score as number
287 }
282 288
283 const json = { 289 const json = {
284 id: this.id, 290 id: this.id,
285 host, 291 host,
286 name: this.name 292 score,
293 name: this.name,
294 createdAt: this.createdAt,
295 updatedAt: this.updatedAt
287 } 296 }
288 297
289 return json 298 return json
290} 299}
291 300
292toActivityPubObject = function (this: AccountInstance) { 301toActivityPubObject = function (this: AccountInstance) {
293 const type = this.podId ? 'Application' as 'Application' : 'Person' as 'Person' 302 const type = this.serverId ? 'Application' as 'Application' : 'Person' as 'Person'
294 303
295 const json = { 304 const json = {
296 type, 305 type,
@@ -317,7 +326,7 @@ toActivityPubObject = function (this: AccountInstance) {
317} 326}
318 327
319isOwned = function (this: AccountInstance) { 328isOwned = function (this: AccountInstance) {
320 return this.podId === null 329 return this.serverId === null
321} 330}
322 331
323getFollowerSharedInboxUrls = function (this: AccountInstance) { 332getFollowerSharedInboxUrls = function (this: AccountInstance) {
@@ -356,7 +365,7 @@ getPublicKeyUrl = function (this: AccountInstance) {
356listOwned = function () { 365listOwned = function () {
357 const query: Sequelize.FindOptions<AccountAttributes> = { 366 const query: Sequelize.FindOptions<AccountAttributes> = {
358 where: { 367 where: {
359 podId: null 368 serverId: null
360 } 369 }
361 } 370 }
362 371
@@ -417,7 +426,7 @@ loadByNameAndHost = function (name: string, host: string) {
417 }, 426 },
418 include: [ 427 include: [
419 { 428 {
420 model: Account['sequelize'].models.Pod, 429 model: Account['sequelize'].models.Server,
421 required: true, 430 required: true,
422 where: { 431 where: {
423 host 432 host
@@ -440,10 +449,10 @@ loadByUrl = function (url: string, transaction?: Sequelize.Transaction) {
440 return Account.findOne(query) 449 return Account.findOne(query)
441} 450}
442 451
443loadAccountByPodAndUUID = function (uuid: string, podId: number, transaction: Sequelize.Transaction) { 452loadAccountByServerAndUUID = function (uuid: string, serverId: number, transaction: Sequelize.Transaction) {
444 const query: Sequelize.FindOptions<AccountAttributes> = { 453 const query: Sequelize.FindOptions<AccountAttributes> = {
445 where: { 454 where: {
446 podId, 455 serverId,
447 uuid 456 uuid
448 }, 457 },
449 transaction 458 transaction
diff --git a/server/models/index.ts b/server/models/index.ts
index 0aec2d3b1..65faa5294 100644
--- a/server/models/index.ts
+++ b/server/models/index.ts
@@ -1,6 +1,6 @@
1export * from './application' 1export * from './application'
2export * from './job' 2export * from './job'
3export * from './oauth' 3export * from './oauth'
4export * from './pod' 4export * from './server'
5export * from './account' 5export * from './account'
6export * from './video' 6export * from './video'
diff --git a/server/models/pod/index.ts b/server/models/pod/index.ts
deleted file mode 100644
index d2bf50d4d..000000000
--- a/server/models/pod/index.ts
+++ /dev/null
@@ -1 +0,0 @@
1export * from './pod-interface'
diff --git a/server/models/pod/pod-interface.ts b/server/models/pod/pod-interface.ts
deleted file mode 100644
index 6c5aab3fa..000000000
--- a/server/models/pod/pod-interface.ts
+++ /dev/null
@@ -1,61 +0,0 @@
1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3
4// Don't use barrel, import just what we need
5import { Pod as FormattedPod } from '../../../shared/models/pods/pod.model'
6import { ResultList } from '../../../shared/models/result-list.model'
7
8export namespace PodMethods {
9 export type ToFormattedJSON = (this: PodInstance) => FormattedPod
10
11 export type CountAll = () => Promise<number>
12
13 export type IncrementScores = (ids: number[], value: number) => Promise<[ number, PodInstance[] ]>
14
15 export type List = () => Promise<PodInstance[]>
16
17 export type ListForApi = (start: number, count: number, sort: string) => Promise< ResultList<PodInstance> >
18
19 export type ListAllIds = (transaction: Sequelize.Transaction) => Promise<number[]>
20
21 export type ListRandomPodIdsWithRequest = (limit: number, tableWithPods: string, tableWithPodsJoins: string) => Promise<number[]>
22
23 export type ListBadPods = () => Promise<PodInstance[]>
24
25 export type Load = (id: number) => Promise<PodInstance>
26
27 export type LoadByHost = (host: string) => Promise<PodInstance>
28
29 export type RemoveAll = () => Promise<number>
30
31 export type UpdatePodsScore = (goodPods: number[], badPods: number[]) => void
32}
33
34export interface PodClass {
35 countAll: PodMethods.CountAll
36 incrementScores: PodMethods.IncrementScores
37 list: PodMethods.List
38 listForApi: PodMethods.ListForApi
39 listAllIds: PodMethods.ListAllIds
40 listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
41 listBadPods: PodMethods.ListBadPods
42 load: PodMethods.Load
43 loadByHost: PodMethods.LoadByHost
44 removeAll: PodMethods.RemoveAll
45 updatePodsScore: PodMethods.UpdatePodsScore
46}
47
48export interface PodAttributes {
49 id?: number
50 host?: string
51 score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
52}
53
54export interface PodInstance extends PodClass, PodAttributes, Sequelize.Instance<PodAttributes> {
55 createdAt: Date
56 updatedAt: Date
57
58 toFormattedJSON: PodMethods.ToFormattedJSON,
59}
60
61export interface PodModel extends PodClass, Sequelize.Model<PodInstance, PodAttributes> {}
diff --git a/server/models/pod/pod.ts b/server/models/pod/pod.ts
deleted file mode 100644
index 6d270ad7f..000000000
--- a/server/models/pod/pod.ts
+++ /dev/null
@@ -1,248 +0,0 @@
1import { map } from 'lodash'
2import * as Sequelize from 'sequelize'
3
4import { FRIEND_SCORE, PODS_SCORE } from '../../initializers'
5import { logger, isHostValid } from '../../helpers'
6
7import { addMethodsToModel, getSort } from '../utils'
8import {
9 PodInstance,
10 PodAttributes,
11
12 PodMethods
13} from './pod-interface'
14
15let Pod: Sequelize.Model<PodInstance, PodAttributes>
16let toFormattedJSON: PodMethods.ToFormattedJSON
17let countAll: PodMethods.CountAll
18let incrementScores: PodMethods.IncrementScores
19let list: PodMethods.List
20let listForApi: PodMethods.ListForApi
21let listAllIds: PodMethods.ListAllIds
22let listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
23let listBadPods: PodMethods.ListBadPods
24let load: PodMethods.Load
25let loadByHost: PodMethods.LoadByHost
26let removeAll: PodMethods.RemoveAll
27let updatePodsScore: PodMethods.UpdatePodsScore
28
29export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
30 Pod = sequelize.define<PodInstance, PodAttributes>('Pod',
31 {
32 host: {
33 type: DataTypes.STRING,
34 allowNull: false,
35 validate: {
36 isHost: value => {
37 const res = isHostValid(value)
38 if (res === false) throw new Error('Host not valid.')
39 }
40 }
41 },
42 score: {
43 type: DataTypes.INTEGER,
44 defaultValue: FRIEND_SCORE.BASE,
45 allowNull: false,
46 validate: {
47 isInt: true,
48 max: FRIEND_SCORE.MAX
49 }
50 }
51 },
52 {
53 indexes: [
54 {
55 fields: [ 'host' ],
56 unique: true
57 },
58 {
59 fields: [ 'score' ]
60 }
61 ]
62 }
63 )
64
65 const classMethods = [
66 countAll,
67 incrementScores,
68 list,
69 listForApi,
70 listAllIds,
71 listRandomPodIdsWithRequest,
72 listBadPods,
73 load,
74 loadByHost,
75 updatePodsScore,
76 removeAll
77 ]
78 const instanceMethods = [ toFormattedJSON ]
79 addMethodsToModel(Pod, classMethods, instanceMethods)
80
81 return Pod
82}
83
84// ------------------------------ METHODS ------------------------------
85
86toFormattedJSON = function (this: PodInstance) {
87 const json = {
88 id: this.id,
89 host: this.host,
90 score: this.score as number,
91 createdAt: this.createdAt
92 }
93
94 return json
95}
96
97// ------------------------------ Statics ------------------------------
98
99countAll = function () {
100 return Pod.count()
101}
102
103incrementScores = function (ids: number[], value: number) {
104 const update = {
105 score: Sequelize.literal('score +' + value)
106 }
107
108 const options = {
109 where: {
110 id: {
111 [Sequelize.Op.in]: ids
112 }
113 },
114 // In this case score is a literal and not an integer so we do not validate it
115 validate: false
116 }
117
118 return Pod.update(update, options)
119}
120
121list = function () {
122 return Pod.findAll()
123}
124
125listForApi = function (start: number, count: number, sort: string) {
126 const query = {
127 offset: start,
128 limit: count,
129 order: [ getSort(sort) ]
130 }
131
132 return Pod.findAndCountAll(query).then(({ rows, count }) => {
133 return {
134 data: rows,
135 total: count
136 }
137 })
138}
139
140listAllIds = function (transaction: Sequelize.Transaction) {
141 const query = {
142 attributes: [ 'id' ],
143 transaction
144 }
145
146 return Pod.findAll(query).then(pods => {
147 return map(pods, 'id')
148 })
149}
150
151listRandomPodIdsWithRequest = function (limit: number, tableWithPods: string, tableWithPodsJoins: string) {
152 return Pod.count().then(count => {
153 // Optimization...
154 if (count === 0) return []
155
156 let start = Math.floor(Math.random() * count) - limit
157 if (start < 0) start = 0
158
159 const subQuery = `(SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins})`
160 const query = {
161 attributes: [ 'id' ],
162 order: [
163 [ 'id', 'ASC' ]
164 ],
165 offset: start,
166 limit: limit,
167 where: {
168 id: {
169 [Sequelize.Op.in]: Sequelize.literal(subQuery)
170 }
171 }
172 }
173
174 return Pod.findAll(query).then(pods => {
175 return map(pods, 'id')
176 })
177 })
178}
179
180listBadPods = function () {
181 const query = {
182 where: {
183 score: {
184 [Sequelize.Op.lte]: 0
185 }
186 }
187 }
188
189 return Pod.findAll(query)
190}
191
192load = function (id: number) {
193 return Pod.findById(id)
194}
195
196loadByHost = function (host: string) {
197 const query = {
198 where: {
199 host: host
200 }
201 }
202
203 return Pod.findOne(query)
204}
205
206removeAll = function () {
207 return Pod.destroy()
208}
209
210updatePodsScore = function (goodPods: number[], badPods: number[]) {
211 logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
212
213 if (goodPods.length !== 0) {
214 incrementScores(goodPods, PODS_SCORE.BONUS).catch(err => {
215 logger.error('Cannot increment scores of good pods.', err)
216 })
217 }
218
219 if (badPods.length !== 0) {
220 incrementScores(badPods, PODS_SCORE.PENALTY)
221 .then(() => removeBadPods())
222 .catch(err => {
223 if (err) logger.error('Cannot decrement scores of bad pods.', err)
224 })
225 }
226}
227
228// ---------------------------------------------------------------------------
229
230// Remove pods with a score of 0 (too many requests where they were unreachable)
231async function removeBadPods () {
232 try {
233 const pods = await listBadPods()
234
235 const podsRemovePromises = pods.map(pod => pod.destroy())
236 await Promise.all(podsRemovePromises)
237
238 const numberOfPodsRemoved = pods.length
239
240 if (numberOfPodsRemoved) {
241 logger.info('Removed %d pods.', numberOfPodsRemoved)
242 } else {
243 logger.info('No need to remove bad pods.')
244 }
245 } catch (err) {
246 logger.error('Cannot remove bad pods.', err)
247 }
248}
diff --git a/server/models/server/index.ts b/server/models/server/index.ts
new file mode 100644
index 000000000..4cb2994aa
--- /dev/null
+++ b/server/models/server/index.ts
@@ -0,0 +1 @@
export * from './server-interface'
diff --git a/server/models/server/server-interface.ts b/server/models/server/server-interface.ts
new file mode 100644
index 000000000..806d052cb
--- /dev/null
+++ b/server/models/server/server-interface.ts
@@ -0,0 +1,56 @@
1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird'
3
4// Don't use barrel, import just what we need
5import { ResultList } from '../../../shared/models/result-list.model'
6
7export namespace ServerMethods {
8 export type CountAll = () => Promise<number>
9
10 export type IncrementScores = (ids: number[], value: number) => Promise<[ number, ServerInstance[] ]>
11
12 export type List = () => Promise<ServerInstance[]>
13
14 export type ListForApi = (start: number, count: number, sort: string) => Promise< ResultList<ServerInstance> >
15
16 export type ListAllIds = (transaction: Sequelize.Transaction) => Promise<number[]>
17
18 export type ListRandomServerIdsWithRequest = (limit: number, tableWithServers: string, tableWithServersJoins: string) => Promise<number[]>
19
20 export type ListBadServers = () => Promise<ServerInstance[]>
21
22 export type Load = (id: number) => Promise<ServerInstance>
23
24 export type LoadByHost = (host: string) => Promise<ServerInstance>
25
26 export type RemoveAll = () => Promise<number>
27
28 export type UpdateServersScore = (goodServers: number[], badServers: number[]) => void
29}
30
31export interface ServerClass {
32 countAll: ServerMethods.CountAll
33 incrementScores: ServerMethods.IncrementScores
34 list: ServerMethods.List
35 listForApi: ServerMethods.ListForApi
36 listAllIds: ServerMethods.ListAllIds
37 listRandomServerIdsWithRequest: ServerMethods.ListRandomServerIdsWithRequest
38 listBadServers: ServerMethods.ListBadServers
39 load: ServerMethods.Load
40 loadByHost: ServerMethods.LoadByHost
41 removeAll: ServerMethods.RemoveAll
42 updateServersScore: ServerMethods.UpdateServersScore
43}
44
45export interface ServerAttributes {
46 id?: number
47 host?: string
48 score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
49}
50
51export interface ServerInstance extends ServerClass, ServerAttributes, Sequelize.Instance<ServerAttributes> {
52 createdAt: Date
53 updatedAt: Date
54}
55
56export interface ServerModel extends ServerClass, Sequelize.Model<ServerInstance, ServerAttributes> {}
diff --git a/server/models/server/server.ts b/server/models/server/server.ts
new file mode 100644
index 000000000..26fa87550
--- /dev/null
+++ b/server/models/server/server.ts
@@ -0,0 +1,233 @@
1import { map } from 'lodash'
2import * as Sequelize from 'sequelize'
3
4import { FRIEND_SCORE, SERVERS_SCORE } from '../../initializers'
5import { logger, isHostValid } from '../../helpers'
6
7import { addMethodsToModel, getSort } from '../utils'
8import {
9 ServerInstance,
10 ServerAttributes,
11
12 ServerMethods
13} from './server-interface'
14
15let Server: Sequelize.Model<ServerInstance, ServerAttributes>
16let countAll: ServerMethods.CountAll
17let incrementScores: ServerMethods.IncrementScores
18let list: ServerMethods.List
19let listForApi: ServerMethods.ListForApi
20let listAllIds: ServerMethods.ListAllIds
21let listRandomServerIdsWithRequest: ServerMethods.ListRandomServerIdsWithRequest
22let listBadServers: ServerMethods.ListBadServers
23let load: ServerMethods.Load
24let loadByHost: ServerMethods.LoadByHost
25let removeAll: ServerMethods.RemoveAll
26let updateServersScore: ServerMethods.UpdateServersScore
27
28export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
29 Server = sequelize.define<ServerInstance, ServerAttributes>('Server',
30 {
31 host: {
32 type: DataTypes.STRING,
33 allowNull: false,
34 validate: {
35 isHost: value => {
36 const res = isHostValid(value)
37 if (res === false) throw new Error('Host not valid.')
38 }
39 }
40 },
41 score: {
42 type: DataTypes.INTEGER,
43 defaultValue: FRIEND_SCORE.BASE,
44 allowNull: false,
45 validate: {
46 isInt: true,
47 max: FRIEND_SCORE.MAX
48 }
49 }
50 },
51 {
52 indexes: [
53 {
54 fields: [ 'host' ],
55 unique: true
56 },
57 {
58 fields: [ 'score' ]
59 }
60 ]
61 }
62 )
63
64 const classMethods = [
65 countAll,
66 incrementScores,
67 list,
68 listForApi,
69 listAllIds,
70 listRandomServerIdsWithRequest,
71 listBadServers,
72 load,
73 loadByHost,
74 updateServersScore,
75 removeAll
76 ]
77 addMethodsToModel(Server, classMethods)
78
79 return Server
80}
81
82// ------------------------------ Statics ------------------------------
83
84countAll = function () {
85 return Server.count()
86}
87
88incrementScores = function (ids: number[], value: number) {
89 const update = {
90 score: Sequelize.literal('score +' + value)
91 }
92
93 const options = {
94 where: {
95 id: {
96 [Sequelize.Op.in]: ids
97 }
98 },
99 // In this case score is a literal and not an integer so we do not validate it
100 validate: false
101 }
102
103 return Server.update(update, options)
104}
105
106list = function () {
107 return Server.findAll()
108}
109
110listForApi = function (start: number, count: number, sort: string) {
111 const query = {
112 offset: start,
113 limit: count,
114 order: [ getSort(sort) ]
115 }
116
117 return Server.findAndCountAll(query).then(({ rows, count }) => {
118 return {
119 data: rows,
120 total: count
121 }
122 })
123}
124
125listAllIds = function (transaction: Sequelize.Transaction) {
126 const query = {
127 attributes: [ 'id' ],
128 transaction
129 }
130
131 return Server.findAll(query).then(servers => {
132 return map(servers, 'id')
133 })
134}
135
136listRandomServerIdsWithRequest = function (limit: number, tableWithServers: string, tableWithServersJoins: string) {
137 return Server.count().then(count => {
138 // Optimization...
139 if (count === 0) return []
140
141 let start = Math.floor(Math.random() * count) - limit
142 if (start < 0) start = 0
143
144 const subQuery = `(SELECT DISTINCT "${tableWithServers}"."serverId" FROM "${tableWithServers}" ${tableWithServersJoins})`
145 const query = {
146 attributes: [ 'id' ],
147 order: [
148 [ 'id', 'ASC' ]
149 ],
150 offset: start,
151 limit: limit,
152 where: {
153 id: {
154 [Sequelize.Op.in]: Sequelize.literal(subQuery)
155 }
156 }
157 }
158
159 return Server.findAll(query).then(servers => {
160 return map(servers, 'id')
161 })
162 })
163}
164
165listBadServers = function () {
166 const query = {
167 where: {
168 score: {
169 [Sequelize.Op.lte]: 0
170 }
171 }
172 }
173
174 return Server.findAll(query)
175}
176
177load = function (id: number) {
178 return Server.findById(id)
179}
180
181loadByHost = function (host: string) {
182 const query = {
183 where: {
184 host: host
185 }
186 }
187
188 return Server.findOne(query)
189}
190
191removeAll = function () {
192 return Server.destroy()
193}
194
195updateServersScore = function (goodServers: number[], badServers: number[]) {
196 logger.info('Updating %d good servers and %d bad servers scores.', goodServers.length, badServers.length)
197
198 if (goodServers.length !== 0) {
199 incrementScores(goodServers, SERVERS_SCORE.BONUS).catch(err => {
200 logger.error('Cannot increment scores of good servers.', err)
201 })
202 }
203
204 if (badServers.length !== 0) {
205 incrementScores(badServers, SERVERS_SCORE.PENALTY)
206 .then(() => removeBadServers())
207 .catch(err => {
208 if (err) logger.error('Cannot decrement scores of bad servers.', err)
209 })
210 }
211}
212
213// ---------------------------------------------------------------------------
214
215// Remove servers with a score of 0 (too many requests where they were unreachable)
216async function removeBadServers () {
217 try {
218 const servers = await listBadServers()
219
220 const serversRemovePromises = servers.map(server => server.destroy())
221 await Promise.all(serversRemovePromises)
222
223 const numberOfServersRemoved = servers.length
224
225 if (numberOfServersRemoved) {
226 logger.info('Removed %d servers.', numberOfServersRemoved)
227 } else {
228 logger.info('No need to remove bad servers.')
229 }
230 } catch (err) {
231 logger.error('Cannot remove bad servers.', err)
232 }
233}
diff --git a/server/models/video/video-abuse-interface.ts b/server/models/video/video-abuse-interface.ts
index 978268926..16806cae2 100644
--- a/server/models/video/video-abuse-interface.ts
+++ b/server/models/video/video-abuse-interface.ts
@@ -1,7 +1,7 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import * as Promise from 'bluebird' 2import * as Promise from 'bluebird'
3 3
4import { PodInstance } from '../pod/pod-interface' 4import { ServerInstance } from '../server/server-interface'
5import { ResultList } from '../../../shared' 5import { ResultList } from '../../../shared'
6 6
7// Don't use barrel, import just what we need 7// Don't use barrel, import just what we need
@@ -28,7 +28,7 @@ export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttribute
28 createdAt: Date 28 createdAt: Date
29 updatedAt: Date 29 updatedAt: Date
30 30
31 Pod: PodInstance 31 Server: ServerInstance
32 32
33 toFormattedJSON: VideoAbuseMethods.ToFormattedJSON 33 toFormattedJSON: VideoAbuseMethods.ToFormattedJSON
34} 34}
diff --git a/server/models/video/video-abuse.ts b/server/models/video/video-abuse.ts
index ebc63e7a0..c1d070ec0 100644
--- a/server/models/video/video-abuse.ts
+++ b/server/models/video/video-abuse.ts
@@ -45,7 +45,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
45 fields: [ 'videoId' ] 45 fields: [ 'videoId' ]
46 }, 46 },
47 { 47 {
48 fields: [ 'reporterPodId' ] 48 fields: [ 'reporterServerId' ]
49 } 49 }
50 ] 50 ]
51 } 51 }
@@ -67,18 +67,18 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
67// ------------------------------ METHODS ------------------------------ 67// ------------------------------ METHODS ------------------------------
68 68
69toFormattedJSON = function (this: VideoAbuseInstance) { 69toFormattedJSON = function (this: VideoAbuseInstance) {
70 let reporterPodHost 70 let reporterServerHost
71 71
72 if (this.Pod) { 72 if (this.Server) {
73 reporterPodHost = this.Pod.host 73 reporterServerHost = this.Server.host
74 } else { 74 } else {
75 // It means it's our video 75 // It means it's our video
76 reporterPodHost = CONFIG.WEBSERVER.HOST 76 reporterServerHost = CONFIG.WEBSERVER.HOST
77 } 77 }
78 78
79 const json = { 79 const json = {
80 id: this.id, 80 id: this.id,
81 reporterPodHost, 81 reporterServerHost,
82 reason: this.reason, 82 reason: this.reason,
83 reporterUsername: this.reporterUsername, 83 reporterUsername: this.reporterUsername,
84 videoId: this.videoId, 84 videoId: this.videoId,
@@ -91,9 +91,9 @@ toFormattedJSON = function (this: VideoAbuseInstance) {
91// ------------------------------ STATICS ------------------------------ 91// ------------------------------ STATICS ------------------------------
92 92
93function associate (models) { 93function associate (models) {
94 VideoAbuse.belongsTo(models.Pod, { 94 VideoAbuse.belongsTo(models.Server, {
95 foreignKey: { 95 foreignKey: {
96 name: 'reporterPodId', 96 name: 'reporterServerId',
97 allowNull: true 97 allowNull: true
98 }, 98 },
99 onDelete: 'CASCADE' 99 onDelete: 'CASCADE'
@@ -115,7 +115,7 @@ listForApi = function (start: number, count: number, sort: string) {
115 order: [ getSort(sort) ], 115 order: [ getSort(sort) ],
116 include: [ 116 include: [
117 { 117 {
118 model: VideoAbuse['sequelize'].models.Pod, 118 model: VideoAbuse['sequelize'].models.Server,
119 required: false 119 required: false
120 } 120 }
121 ] 121 ]
diff --git a/server/models/video/video-channel-interface.ts b/server/models/video/video-channel-interface.ts
index 55e772063..8ad3e5cb7 100644
--- a/server/models/video/video-channel-interface.ts
+++ b/server/models/video/video-channel-interface.ts
@@ -22,7 +22,7 @@ export namespace VideoChannelMethods {
22 export type LoadAndPopulateAccount = (id: number) => Promise<VideoChannelInstance> 22 export type LoadAndPopulateAccount = (id: number) => Promise<VideoChannelInstance>
23 export type LoadByUUIDAndPopulateAccount = (uuid: string) => Promise<VideoChannelInstance> 23 export type LoadByUUIDAndPopulateAccount = (uuid: string) => Promise<VideoChannelInstance>
24 export type LoadByUUID = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance> 24 export type LoadByUUID = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
25 export type LoadByHostAndUUID = (uuid: string, podHost: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance> 25 export type LoadByHostAndUUID = (uuid: string, serverHost: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
26 export type LoadAndPopulateAccountAndVideos = (id: number) => Promise<VideoChannelInstance> 26 export type LoadAndPopulateAccountAndVideos = (id: number) => Promise<VideoChannelInstance>
27 export type LoadByUrl = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance> 27 export type LoadByUrl = (uuid: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
28 export type LoadByUUIDOrUrl = (uuid: string, url: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance> 28 export type LoadByUUIDOrUrl = (uuid: string, url: string, t?: Sequelize.Transaction) => Promise<VideoChannelInstance>
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts
index 6d70f2aa2..3cb4a33b9 100644
--- a/server/models/video/video-channel.ts
+++ b/server/models/video/video-channel.ts
@@ -218,7 +218,7 @@ listForApi = function (start: number, count: number, sort: string) {
218 { 218 {
219 model: VideoChannel['sequelize'].models.Account, 219 model: VideoChannel['sequelize'].models.Account,
220 required: true, 220 required: true,
221 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] 221 include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
222 } 222 }
223 ] 223 ]
224 } 224 }
@@ -238,7 +238,7 @@ listByAccount = function (accountId: number) {
238 id: accountId 238 id: accountId
239 }, 239 },
240 required: true, 240 required: true,
241 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] 241 include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
242 } 242 }
243 ] 243 ]
244 } 244 }
@@ -297,7 +297,7 @@ loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Tran
297 model: VideoChannel['sequelize'].models.Account, 297 model: VideoChannel['sequelize'].models.Account,
298 include: [ 298 include: [
299 { 299 {
300 model: VideoChannel['sequelize'].models.Pod, 300 model: VideoChannel['sequelize'].models.Server,
301 required: true, 301 required: true,
302 where: { 302 where: {
303 host: fromHost 303 host: fromHost
@@ -322,7 +322,7 @@ loadByIdAndAccount = function (id: number, accountId: number) {
322 include: [ 322 include: [
323 { 323 {
324 model: VideoChannel['sequelize'].models.Account, 324 model: VideoChannel['sequelize'].models.Account,
325 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] 325 include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
326 } 326 }
327 ] 327 ]
328 } 328 }
@@ -335,7 +335,7 @@ loadAndPopulateAccount = function (id: number) {
335 include: [ 335 include: [
336 { 336 {
337 model: VideoChannel['sequelize'].models.Account, 337 model: VideoChannel['sequelize'].models.Account,
338 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] 338 include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
339 } 339 }
340 ] 340 ]
341 } 341 }
@@ -351,7 +351,7 @@ loadByUUIDAndPopulateAccount = function (uuid: string) {
351 include: [ 351 include: [
352 { 352 {
353 model: VideoChannel['sequelize'].models.Account, 353 model: VideoChannel['sequelize'].models.Account,
354 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] 354 include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
355 } 355 }
356 ] 356 ]
357 } 357 }
@@ -364,7 +364,7 @@ loadAndPopulateAccountAndVideos = function (id: number) {
364 include: [ 364 include: [
365 { 365 {
366 model: VideoChannel['sequelize'].models.Account, 366 model: VideoChannel['sequelize'].models.Account,
367 include: [ { model: VideoChannel['sequelize'].models.Pod, required: false } ] 367 include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ]
368 }, 368 },
369 VideoChannel['sequelize'].models.Video 369 VideoChannel['sequelize'].models.Video
370 ] 370 ]
diff --git a/server/models/video/video-interface.ts b/server/models/video/video-interface.ts
index 7243756d2..4df33f801 100644
--- a/server/models/video/video-interface.ts
+++ b/server/models/video/video-interface.ts
@@ -46,7 +46,7 @@ export namespace VideoMethods {
46 46
47 export type ListForApi = (start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> > 47 export type ListForApi = (start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
48 export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> > 48 export type ListUserVideosForApi = (userId: number, start: number, count: number, sort: string) => Bluebird< ResultList<VideoInstance> >
49 export type SearchAndPopulateAccountAndPodAndTags = ( 49 export type SearchAndPopulateAccountAndServerAndTags = (
50 value: string, 50 value: string,
51 field: string, 51 field: string,
52 start: number, 52 start: number,
@@ -60,8 +60,8 @@ export namespace VideoMethods {
60 export type LoadLocalVideoByUUID = (uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance> 60 export type LoadLocalVideoByUUID = (uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
61 export type LoadByHostAndUUID = (fromHost: string, uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance> 61 export type LoadByHostAndUUID = (fromHost: string, uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
62 export type LoadAndPopulateAccount = (id: number) => Bluebird<VideoInstance> 62 export type LoadAndPopulateAccount = (id: number) => Bluebird<VideoInstance>
63 export type LoadAndPopulateAccountAndPodAndTags = (id: number) => Bluebird<VideoInstance> 63 export type LoadAndPopulateAccountAndServerAndTags = (id: number) => Bluebird<VideoInstance>
64 export type LoadByUUIDAndPopulateAccountAndPodAndTags = (uuid: string) => Bluebird<VideoInstance> 64 export type LoadByUUIDAndPopulateAccountAndServerAndTags = (uuid: string) => Bluebird<VideoInstance>
65 export type LoadByUUIDOrURL = (uuid: string, url: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance> 65 export type LoadByUUIDOrURL = (uuid: string, url: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
66 66
67 export type RemoveThumbnail = (this: VideoInstance) => Promise<void> 67 export type RemoveThumbnail = (this: VideoInstance) => Promise<void>
@@ -79,14 +79,14 @@ export interface VideoClass {
79 listOwnedByAccount: VideoMethods.ListOwnedByAccount 79 listOwnedByAccount: VideoMethods.ListOwnedByAccount
80 load: VideoMethods.Load 80 load: VideoMethods.Load
81 loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount 81 loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
82 loadAndPopulateAccountAndPodAndTags: VideoMethods.LoadAndPopulateAccountAndPodAndTags 82 loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
83 loadByHostAndUUID: VideoMethods.LoadByHostAndUUID 83 loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
84 loadByUUID: VideoMethods.LoadByUUID 84 loadByUUID: VideoMethods.LoadByUUID
85 loadByUrl: VideoMethods.LoadByUrl 85 loadByUrl: VideoMethods.LoadByUrl
86 loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL 86 loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
87 loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID 87 loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
88 loadByUUIDAndPopulateAccountAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndPodAndTags 88 loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
89 searchAndPopulateAccountAndPodAndTags: VideoMethods.SearchAndPopulateAccountAndPodAndTags 89 searchAndPopulateAccountAndServerAndTags: VideoMethods.SearchAndPopulateAccountAndServerAndTags
90} 90}
91 91
92export interface VideoAttributes { 92export interface VideoAttributes {
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index dd73dd7ca..86800fb88 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -88,9 +88,9 @@ let loadByUUID: VideoMethods.LoadByUUID
88let loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL 88let loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
89let loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID 89let loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
90let loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount 90let loadAndPopulateAccount: VideoMethods.LoadAndPopulateAccount
91let loadAndPopulateAccountAndPodAndTags: VideoMethods.LoadAndPopulateAccountAndPodAndTags 91let loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
92let loadByUUIDAndPopulateAccountAndPodAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndPodAndTags 92let loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
93let searchAndPopulateAccountAndPodAndTags: VideoMethods.SearchAndPopulateAccountAndPodAndTags 93let searchAndPopulateAccountAndServerAndTags: VideoMethods.SearchAndPopulateAccountAndServerAndTags
94let removeThumbnail: VideoMethods.RemoveThumbnail 94let removeThumbnail: VideoMethods.RemoveThumbnail
95let removePreview: VideoMethods.RemovePreview 95let removePreview: VideoMethods.RemovePreview
96let removeFile: VideoMethods.RemoveFile 96let removeFile: VideoMethods.RemoveFile
@@ -275,13 +275,13 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
275 listOwnedByAccount, 275 listOwnedByAccount,
276 load, 276 load,
277 loadAndPopulateAccount, 277 loadAndPopulateAccount,
278 loadAndPopulateAccountAndPodAndTags, 278 loadAndPopulateAccountAndServerAndTags,
279 loadByHostAndUUID, 279 loadByHostAndUUID,
280 loadByUUIDOrURL, 280 loadByUUIDOrURL,
281 loadByUUID, 281 loadByUUID,
282 loadLocalVideoByUUID, 282 loadLocalVideoByUUID,
283 loadByUUIDAndPopulateAccountAndPodAndTags, 283 loadByUUIDAndPopulateAccountAndServerAndTags,
284 searchAndPopulateAccountAndPodAndTags 284 searchAndPopulateAccountAndServerAndTags
285 ] 285 ]
286 const instanceMethods = [ 286 const instanceMethods = [
287 createPreview, 287 createPreview,
@@ -477,13 +477,13 @@ getPreviewPath = function (this: VideoInstance) {
477} 477}
478 478
479toFormattedJSON = function (this: VideoInstance) { 479toFormattedJSON = function (this: VideoInstance) {
480 let podHost 480 let serverHost
481 481
482 if (this.VideoChannel.Account.Pod) { 482 if (this.VideoChannel.Account.Server) {
483 podHost = this.VideoChannel.Account.Pod.host 483 serverHost = this.VideoChannel.Account.Server.host
484 } else { 484 } else {
485 // It means it's our video 485 // It means it's our video
486 podHost = CONFIG.WEBSERVER.HOST 486 serverHost = CONFIG.WEBSERVER.HOST
487 } 487 }
488 488
489 const json = { 489 const json = {
@@ -498,7 +498,7 @@ toFormattedJSON = function (this: VideoInstance) {
498 languageLabel: this.getLanguageLabel(), 498 languageLabel: this.getLanguageLabel(),
499 nsfw: this.nsfw, 499 nsfw: this.nsfw,
500 description: this.getTruncatedDescription(), 500 description: this.getTruncatedDescription(),
501 podHost, 501 serverHost,
502 isLocal: this.isOwned(), 502 isLocal: this.isOwned(),
503 account: this.VideoChannel.Account.name, 503 account: this.VideoChannel.Account.name,
504 duration: this.duration, 504 duration: this.duration,
@@ -519,7 +519,7 @@ toFormattedJSON = function (this: VideoInstance) {
519toFormattedDetailsJSON = function (this: VideoInstance) { 519toFormattedDetailsJSON = function (this: VideoInstance) {
520 const formattedJson = this.toFormattedJSON() 520 const formattedJson = this.toFormattedJSON()
521 521
522 // Maybe our pod is not up to date and there are new privacy settings since our version 522 // Maybe our server is not up to date and there are new privacy settings since our version
523 let privacyLabel = VIDEO_PRIVACIES[this.privacy] 523 let privacyLabel = VIDEO_PRIVACIES[this.privacy]
524 if (!privacyLabel) privacyLabel = 'Unknown' 524 if (!privacyLabel) privacyLabel = 'Unknown'
525 525
@@ -721,7 +721,7 @@ getDescriptionPath = function (this: VideoInstance) {
721getCategoryLabel = function (this: VideoInstance) { 721getCategoryLabel = function (this: VideoInstance) {
722 let categoryLabel = VIDEO_CATEGORIES[this.category] 722 let categoryLabel = VIDEO_CATEGORIES[this.category]
723 723
724 // Maybe our pod is not up to date and there are new categories since our version 724 // Maybe our server is not up to date and there are new categories since our version
725 if (!categoryLabel) categoryLabel = 'Misc' 725 if (!categoryLabel) categoryLabel = 'Misc'
726 726
727 return categoryLabel 727 return categoryLabel
@@ -730,7 +730,7 @@ getCategoryLabel = function (this: VideoInstance) {
730getLicenceLabel = function (this: VideoInstance) { 730getLicenceLabel = function (this: VideoInstance) {
731 let licenceLabel = VIDEO_LICENCES[this.licence] 731 let licenceLabel = VIDEO_LICENCES[this.licence]
732 732
733 // Maybe our pod is not up to date and there are new licences since our version 733 // Maybe our server is not up to date and there are new licences since our version
734 if (!licenceLabel) licenceLabel = 'Unknown' 734 if (!licenceLabel) licenceLabel = 'Unknown'
735 735
736 return licenceLabel 736 return licenceLabel
@@ -830,7 +830,7 @@ listForApi = function (start: number, count: number, sort: string) {
830 model: Video['sequelize'].models.Account, 830 model: Video['sequelize'].models.Account,
831 include: [ 831 include: [
832 { 832 {
833 model: Video['sequelize'].models.Pod, 833 model: Video['sequelize'].models.Server,
834 required: false 834 required: false
835 } 835 }
836 ] 836 ]
@@ -866,7 +866,7 @@ loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Tran
866 model: Video['sequelize'].models.Account, 866 model: Video['sequelize'].models.Account,
867 include: [ 867 include: [
868 { 868 {
869 model: Video['sequelize'].models.Pod, 869 model: Video['sequelize'].models.Server,
870 required: true, 870 required: true,
871 where: { 871 where: {
872 host: fromHost 872 host: fromHost
@@ -989,7 +989,7 @@ loadAndPopulateAccount = function (id: number) {
989 return Video.findById(id, options) 989 return Video.findById(id, options)
990} 990}
991 991
992loadAndPopulateAccountAndPodAndTags = function (id: number) { 992loadAndPopulateAccountAndServerAndTags = function (id: number) {
993 const options = { 993 const options = {
994 include: [ 994 include: [
995 { 995 {
@@ -997,7 +997,7 @@ loadAndPopulateAccountAndPodAndTags = function (id: number) {
997 include: [ 997 include: [
998 { 998 {
999 model: Video['sequelize'].models.Account, 999 model: Video['sequelize'].models.Account,
1000 include: [ { model: Video['sequelize'].models.Pod, required: false } ] 1000 include: [ { model: Video['sequelize'].models.Server, required: false } ]
1001 } 1001 }
1002 ] 1002 ]
1003 }, 1003 },
@@ -1009,7 +1009,7 @@ loadAndPopulateAccountAndPodAndTags = function (id: number) {
1009 return Video.findById(id, options) 1009 return Video.findById(id, options)
1010} 1010}
1011 1011
1012loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) { 1012loadByUUIDAndPopulateAccountAndServerAndTags = function (uuid: string) {
1013 const options = { 1013 const options = {
1014 where: { 1014 where: {
1015 uuid 1015 uuid
@@ -1020,7 +1020,7 @@ loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) {
1020 include: [ 1020 include: [
1021 { 1021 {
1022 model: Video['sequelize'].models.Account, 1022 model: Video['sequelize'].models.Account,
1023 include: [ { model: Video['sequelize'].models.Pod, required: false } ] 1023 include: [ { model: Video['sequelize'].models.Server, required: false } ]
1024 } 1024 }
1025 ] 1025 ]
1026 }, 1026 },
@@ -1032,15 +1032,15 @@ loadByUUIDAndPopulateAccountAndPodAndTags = function (uuid: string) {
1032 return Video.findOne(options) 1032 return Video.findOne(options)
1033} 1033}
1034 1034
1035searchAndPopulateAccountAndPodAndTags = function (value: string, field: string, start: number, count: number, sort: string) { 1035searchAndPopulateAccountAndServerAndTags = function (value: string, field: string, start: number, count: number, sort: string) {
1036 const podInclude: Sequelize.IncludeOptions = { 1036 const serverInclude: Sequelize.IncludeOptions = {
1037 model: Video['sequelize'].models.Pod, 1037 model: Video['sequelize'].models.Server,
1038 required: false 1038 required: false
1039 } 1039 }
1040 1040
1041 const accountInclude: Sequelize.IncludeOptions = { 1041 const accountInclude: Sequelize.IncludeOptions = {
1042 model: Video['sequelize'].models.Account, 1042 model: Video['sequelize'].models.Account,
1043 include: [ podInclude ] 1043 include: [ serverInclude ]
1044 } 1044 }
1045 1045
1046 const videoChannelInclude: Sequelize.IncludeOptions = { 1046 const videoChannelInclude: Sequelize.IncludeOptions = {
@@ -1071,13 +1071,13 @@ searchAndPopulateAccountAndPodAndTags = function (value: string, field: string,
1071 )` 1071 )`
1072 ) 1072 )
1073 } else if (field === 'host') { 1073 } else if (field === 'host') {
1074 // FIXME: Include our pod? (not stored in the database) 1074 // FIXME: Include our server? (not stored in the database)
1075 podInclude.where = { 1075 serverInclude.where = {
1076 host: { 1076 host: {
1077 [Sequelize.Op.iLike]: '%' + value + '%' 1077 [Sequelize.Op.iLike]: '%' + value + '%'
1078 } 1078 }
1079 } 1079 }
1080 podInclude.required = true 1080 serverInclude.required = true
1081 } else if (field === 'account') { 1081 } else if (field === 'account') {
1082 accountInclude.where = { 1082 accountInclude.where = {
1083 name: { 1083 name: {
@@ -1123,8 +1123,8 @@ function getBaseUrls (video: VideoInstance) {
1123 baseUrlHttp = CONFIG.WEBSERVER.URL 1123 baseUrlHttp = CONFIG.WEBSERVER.URL
1124 baseUrlWs = CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT 1124 baseUrlWs = CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
1125 } else { 1125 } else {
1126 baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.VideoChannel.Account.Pod.host 1126 baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.VideoChannel.Account.Server.host
1127 baseUrlWs = REMOTE_SCHEME.WS + '://' + video.VideoChannel.Account.Pod.host 1127 baseUrlWs = REMOTE_SCHEME.WS + '://' + video.VideoChannel.Account.Server.host
1128 } 1128 }
1129 1129
1130 return { baseUrlHttp, baseUrlWs } 1130 return { baseUrlHttp, baseUrlWs }