aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers')
-rw-r--r--server/controllers/activitypub/client.ts39
-rw-r--r--server/controllers/activitypub/inbox.ts5
-rw-r--r--server/controllers/activitypub/outbox.ts10
-rw-r--r--server/controllers/api/config.ts38
-rw-r--r--server/controllers/api/search.ts5
-rw-r--r--server/controllers/api/server/follows.ts3
-rw-r--r--server/controllers/api/users/index.ts5
-rw-r--r--server/controllers/api/users/me.ts29
-rw-r--r--server/controllers/api/users/my-history.ts1
-rw-r--r--server/controllers/api/users/my-notifications.ts3
-rw-r--r--server/controllers/api/video-channel.ts9
-rw-r--r--server/controllers/api/video-playlist.ts36
-rw-r--r--server/controllers/api/videos/abuse.ts20
-rw-r--r--server/controllers/api/videos/blacklist.ts17
-rw-r--r--server/controllers/api/videos/captions.ts9
-rw-r--r--server/controllers/api/videos/comment.ts17
-rw-r--r--server/controllers/api/videos/import.ts38
-rw-r--r--server/controllers/api/videos/index.ts19
-rw-r--r--server/controllers/api/videos/ownership.ts5
-rw-r--r--server/controllers/api/videos/rate.ts2
-rw-r--r--server/controllers/api/videos/watching.ts2
-rw-r--r--server/controllers/feeds.ts2
-rw-r--r--server/controllers/services.ts2
-rw-r--r--server/controllers/static.ts6
-rw-r--r--server/controllers/webfinger.ts2
25 files changed, 186 insertions, 138 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts
index 11504b354..453ced8bf 100644
--- a/server/controllers/activitypub/client.ts
+++ b/server/controllers/activitypub/client.ts
@@ -16,7 +16,6 @@ import {
16} from '../../middlewares' 16} from '../../middlewares'
17import { getAccountVideoRateValidator, videoCommentGetValidator } from '../../middlewares/validators' 17import { getAccountVideoRateValidator, videoCommentGetValidator } from '../../middlewares/validators'
18import { AccountModel } from '../../models/account/account' 18import { AccountModel } from '../../models/account/account'
19import { ActorModel } from '../../models/activitypub/actor'
20import { ActorFollowModel } from '../../models/activitypub/actor-follow' 19import { ActorFollowModel } from '../../models/activitypub/actor-follow'
21import { VideoModel } from '../../models/video/video' 20import { VideoModel } from '../../models/video/video'
22import { VideoCommentModel } from '../../models/video/video-comment' 21import { VideoCommentModel } from '../../models/video/video-comment'
@@ -38,6 +37,7 @@ import { buildDislikeActivity } from '../../lib/activitypub/send/send-dislike'
38import { videoPlaylistElementAPGetValidator, videoPlaylistsGetValidator } from '../../middlewares/validators/videos/video-playlists' 37import { videoPlaylistElementAPGetValidator, videoPlaylistsGetValidator } from '../../middlewares/validators/videos/video-playlists'
39import { VideoPlaylistModel } from '../../models/video/video-playlist' 38import { VideoPlaylistModel } from '../../models/video/video-playlist'
40import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' 39import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
40import { MAccountId, MActorId, MVideo, MVideoAPWithoutCaption } from '@server/typings/models'
41 41
42const activityPubClientRouter = express.Router() 42const activityPubClientRouter = express.Router()
43 43
@@ -148,7 +148,7 @@ activityPubClientRouter.get('/redundancy/streaming-playlists/:streamingPlaylistT
148 148
149activityPubClientRouter.get('/video-playlists/:playlistId', 149activityPubClientRouter.get('/video-playlists/:playlistId',
150 executeIfActivityPub, 150 executeIfActivityPub,
151 asyncMiddleware(videoPlaylistsGetValidator), 151 asyncMiddleware(videoPlaylistsGetValidator('all')),
152 asyncMiddleware(videoPlaylistController) 152 asyncMiddleware(videoPlaylistController)
153) 153)
154activityPubClientRouter.get('/video-playlists/:playlistId/:videoId', 154activityPubClientRouter.get('/video-playlists/:playlistId/:videoId',
@@ -208,18 +208,19 @@ function getAccountVideoRate (rateType: VideoRateType) {
208 208
209async function videoController (req: express.Request, res: express.Response) { 209async function videoController (req: express.Request, res: express.Response) {
210 // We need more attributes 210 // We need more attributes
211 const video = await VideoModel.loadForGetAPI({ id: res.locals.video.id }) 211 const video = await VideoModel.loadForGetAPI({ id: res.locals.onlyVideoWithRights.id }) as MVideoAPWithoutCaption
212 212
213 if (video.url.startsWith(WEBSERVER.URL) === false) return res.redirect(video.url) 213 if (video.url.startsWith(WEBSERVER.URL) === false) return res.redirect(video.url)
214 214
215 // We need captions to render AP object 215 // We need captions to render AP object
216 video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id) 216 const captions = await VideoCaptionModel.listVideoCaptions(video.id)
217 const videoWithCaptions = Object.assign(video, { VideoCaptions: captions })
217 218
218 const audience = getAudience(video.VideoChannel.Account.Actor, video.privacy === VideoPrivacy.PUBLIC) 219 const audience = getAudience(videoWithCaptions.VideoChannel.Account.Actor, videoWithCaptions.privacy === VideoPrivacy.PUBLIC)
219 const videoObject = audiencify(video.toActivityPubObject(), audience) 220 const videoObject = audiencify(videoWithCaptions.toActivityPubObject(), audience)
220 221
221 if (req.path.endsWith('/activity')) { 222 if (req.path.endsWith('/activity')) {
222 const data = buildCreateActivity(video.url, video.VideoChannel.Account.Actor, videoObject, audience) 223 const data = buildCreateActivity(videoWithCaptions.url, video.VideoChannel.Account.Actor, videoObject, audience)
223 return activityPubResponse(activityPubContextify(data), res) 224 return activityPubResponse(activityPubContextify(data), res)
224 } 225 }
225 226
@@ -231,13 +232,13 @@ async function videoAnnounceController (req: express.Request, res: express.Respo
231 232
232 if (share.url.startsWith(WEBSERVER.URL) === false) return res.redirect(share.url) 233 if (share.url.startsWith(WEBSERVER.URL) === false) return res.redirect(share.url)
233 234
234 const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined) 235 const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.videoAll, undefined)
235 236
236 return activityPubResponse(activityPubContextify(activity), res) 237 return activityPubResponse(activityPubContextify(activity), res)
237} 238}
238 239
239async function videoAnnouncesController (req: express.Request, res: express.Response) { 240async function videoAnnouncesController (req: express.Request, res: express.Response) {
240 const video = res.locals.video 241 const video = res.locals.onlyVideo
241 242
242 const handler = async (start: number, count: number) => { 243 const handler = async (start: number, count: number) => {
243 const result = await VideoShareModel.listAndCountByVideoId(video.id, start, count) 244 const result = await VideoShareModel.listAndCountByVideoId(video.id, start, count)
@@ -252,21 +253,21 @@ async function videoAnnouncesController (req: express.Request, res: express.Resp
252} 253}
253 254
254async function videoLikesController (req: express.Request, res: express.Response) { 255async function videoLikesController (req: express.Request, res: express.Response) {
255 const video = res.locals.video 256 const video = res.locals.onlyVideo
256 const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video)) 257 const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video))
257 258
258 return activityPubResponse(activityPubContextify(json), res) 259 return activityPubResponse(activityPubContextify(json), res)
259} 260}
260 261
261async function videoDislikesController (req: express.Request, res: express.Response) { 262async function videoDislikesController (req: express.Request, res: express.Response) {
262 const video = res.locals.video 263 const video = res.locals.onlyVideo
263 const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video)) 264 const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video))
264 265
265 return activityPubResponse(activityPubContextify(json), res) 266 return activityPubResponse(activityPubContextify(json), res)
266} 267}
267 268
268async function videoCommentsController (req: express.Request, res: express.Response) { 269async function videoCommentsController (req: express.Request, res: express.Response) {
269 const video = res.locals.video 270 const video = res.locals.onlyVideo
270 271
271 const handler = async (start: number, count: number) => { 272 const handler = async (start: number, count: number) => {
272 const result = await VideoCommentModel.listAndCountByVideoId(video.id, start, count) 273 const result = await VideoCommentModel.listAndCountByVideoId(video.id, start, count)
@@ -301,7 +302,7 @@ async function videoChannelFollowingController (req: express.Request, res: expre
301} 302}
302 303
303async function videoCommentController (req: express.Request, res: express.Response) { 304async function videoCommentController (req: express.Request, res: express.Response) {
304 const videoComment = res.locals.videoComment 305 const videoComment = res.locals.videoCommentFull
305 306
306 if (videoComment.url.startsWith(WEBSERVER.URL) === false) return res.redirect(videoComment.url) 307 if (videoComment.url.startsWith(WEBSERVER.URL) === false) return res.redirect(videoComment.url)
307 308
@@ -337,7 +338,7 @@ async function videoRedundancyController (req: express.Request, res: express.Res
337} 338}
338 339
339async function videoPlaylistController (req: express.Request, res: express.Response) { 340async function videoPlaylistController (req: express.Request, res: express.Response) {
340 const playlist = res.locals.videoPlaylist 341 const playlist = res.locals.videoPlaylistFull
341 342
342 // We need more attributes 343 // We need more attributes
343 playlist.OwnerAccount = await AccountModel.load(playlist.ownerAccountId) 344 playlist.OwnerAccount = await AccountModel.load(playlist.ownerAccountId)
@@ -350,7 +351,7 @@ async function videoPlaylistController (req: express.Request, res: express.Respo
350} 351}
351 352
352async function videoPlaylistElementController (req: express.Request, res: express.Response) { 353async function videoPlaylistElementController (req: express.Request, res: express.Response) {
353 const videoPlaylistElement = res.locals.videoPlaylistElement 354 const videoPlaylistElement = res.locals.videoPlaylistElementAP
354 355
355 const json = videoPlaylistElement.toActivityPubObject() 356 const json = videoPlaylistElement.toActivityPubObject()
356 return activityPubResponse(activityPubContextify(json), res) 357 return activityPubResponse(activityPubContextify(json), res)
@@ -358,7 +359,7 @@ async function videoPlaylistElementController (req: express.Request, res: expres
358 359
359// --------------------------------------------------------------------------- 360// ---------------------------------------------------------------------------
360 361
361async function actorFollowing (req: express.Request, actor: ActorModel) { 362async function actorFollowing (req: express.Request, actor: MActorId) {
362 const handler = (start: number, count: number) => { 363 const handler = (start: number, count: number) => {
363 return ActorFollowModel.listAcceptedFollowingUrlsForApi([ actor.id ], undefined, start, count) 364 return ActorFollowModel.listAcceptedFollowingUrlsForApi([ actor.id ], undefined, start, count)
364 } 365 }
@@ -366,7 +367,7 @@ async function actorFollowing (req: express.Request, actor: ActorModel) {
366 return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page) 367 return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
367} 368}
368 369
369async function actorFollowers (req: express.Request, actor: ActorModel) { 370async function actorFollowers (req: express.Request, actor: MActorId) {
370 const handler = (start: number, count: number) => { 371 const handler = (start: number, count: number) => {
371 return ActorFollowModel.listAcceptedFollowerUrlsForAP([ actor.id ], undefined, start, count) 372 return ActorFollowModel.listAcceptedFollowerUrlsForAP([ actor.id ], undefined, start, count)
372 } 373 }
@@ -374,7 +375,7 @@ async function actorFollowers (req: express.Request, actor: ActorModel) {
374 return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page) 375 return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
375} 376}
376 377
377async function actorPlaylists (req: express.Request, account: AccountModel) { 378async function actorPlaylists (req: express.Request, account: MAccountId) {
378 const handler = (start: number, count: number) => { 379 const handler = (start: number, count: number) => {
379 return VideoPlaylistModel.listPublicUrlsOfForAP(account.id, start, count) 380 return VideoPlaylistModel.listPublicUrlsOfForAP(account.id, start, count)
380 } 381 }
@@ -382,7 +383,7 @@ async function actorPlaylists (req: express.Request, account: AccountModel) {
382 return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page) 383 return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
383} 384}
384 385
385function videoRates (req: express.Request, rateType: VideoRateType, video: VideoModel, url: string) { 386function videoRates (req: express.Request, rateType: VideoRateType, video: MVideo, url: string) {
386 const handler = async (start: number, count: number) => { 387 const handler = async (start: number, count: number) => {
387 const result = await AccountVideoRateModel.listAndCountAccountUrlsByVideoId(rateType, video.id, start, count) 388 const result = await AccountVideoRateModel.listAndCountAccountUrlsByVideoId(rateType, video.id, start, count)
388 return { 389 return {
diff --git a/server/controllers/activitypub/inbox.ts b/server/controllers/activitypub/inbox.ts
index 2d3eef222..d9df253aa 100644
--- a/server/controllers/activitypub/inbox.ts
+++ b/server/controllers/activitypub/inbox.ts
@@ -7,7 +7,7 @@ import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChann
7import { activityPubValidator } from '../../middlewares/validators/activitypub/activity' 7import { activityPubValidator } from '../../middlewares/validators/activitypub/activity'
8import { queue } from 'async' 8import { queue } from 'async'
9import { ActorModel } from '../../models/activitypub/actor' 9import { ActorModel } from '../../models/activitypub/actor'
10import { SignatureActorModel } from '../../typings/models' 10import { MActorDefault, MActorSignature } from '../../typings/models'
11 11
12const inboxRouter = express.Router() 12const inboxRouter = express.Router()
13 13
@@ -41,7 +41,8 @@ export {
41 41
42// --------------------------------------------------------------------------- 42// ---------------------------------------------------------------------------
43 43
44const inboxQueue = queue<{ activities: Activity[], signatureActor?: SignatureActorModel, inboxActor?: ActorModel }, Error>((task, cb) => { 44type QueueParam = { activities: Activity[], signatureActor?: MActorSignature, inboxActor?: MActorDefault }
45const inboxQueue = queue<QueueParam, Error>((task, cb) => {
45 const options = { signatureActor: task.signatureActor, inboxActor: task.inboxActor } 46 const options = { signatureActor: task.signatureActor, inboxActor: task.inboxActor }
46 47
47 processActivities(task.activities, options) 48 processActivities(task.activities, options)
diff --git a/server/controllers/activitypub/outbox.ts b/server/controllers/activitypub/outbox.ts
index 38b6ec976..f3dd2ad7d 100644
--- a/server/controllers/activitypub/outbox.ts
+++ b/server/controllers/activitypub/outbox.ts
@@ -6,11 +6,9 @@ import { logger } from '../../helpers/logger'
6import { buildAnnounceActivity, buildCreateActivity } from '../../lib/activitypub/send' 6import { buildAnnounceActivity, buildCreateActivity } from '../../lib/activitypub/send'
7import { buildAudience } from '../../lib/activitypub/audience' 7import { buildAudience } from '../../lib/activitypub/audience'
8import { asyncMiddleware, localAccountValidator, localVideoChannelValidator } from '../../middlewares' 8import { asyncMiddleware, localAccountValidator, localVideoChannelValidator } from '../../middlewares'
9import { AccountModel } from '../../models/account/account'
10import { ActorModel } from '../../models/activitypub/actor'
11import { VideoModel } from '../../models/video/video' 9import { VideoModel } from '../../models/video/video'
12import { activityPubResponse } from './utils' 10import { activityPubResponse } from './utils'
13import { VideoChannelModel } from '../../models/video/video-channel' 11import { MActorLight } from '@server/typings/models'
14 12
15const outboxRouter = express.Router() 13const outboxRouter = express.Router()
16 14
@@ -45,14 +43,10 @@ async function outboxController (req: express.Request, res: express.Response) {
45 return activityPubResponse(activityPubContextify(json), res) 43 return activityPubResponse(activityPubContextify(json), res)
46} 44}
47 45
48async function buildActivities (actor: ActorModel, start: number, count: number) { 46async function buildActivities (actor: MActorLight, start: number, count: number) {
49 const data = await VideoModel.listAllAndSharedByActorForOutbox(actor.id, start, count) 47 const data = await VideoModel.listAllAndSharedByActorForOutbox(actor.id, start, count)
50 const activities: Activity[] = [] 48 const activities: Activity[] = []
51 49
52 // Avoid too many SQL requests
53 const actors = data.data.map(v => v.VideoChannel.Account.Actor)
54 actors.push(actor)
55
56 for (const video of data.data) { 50 for (const video of data.data) {
57 const byActor = video.VideoChannel.Account.Actor 51 const byActor = video.VideoChannel.Account.Actor
58 const createActivityAudience = buildAudience([ byActor.followersUrl ], video.privacy === VideoPrivacy.PUBLIC) 52 const createActivityAudience = buildAudience([ byActor.followersUrl ], video.privacy === VideoPrivacy.PUBLIC)
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 21fa85a08..39a124fc5 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -158,7 +158,19 @@ function getAbout (req: express.Request, res: express.Response) {
158 name: CONFIG.INSTANCE.NAME, 158 name: CONFIG.INSTANCE.NAME,
159 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, 159 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
160 description: CONFIG.INSTANCE.DESCRIPTION, 160 description: CONFIG.INSTANCE.DESCRIPTION,
161 terms: CONFIG.INSTANCE.TERMS 161 terms: CONFIG.INSTANCE.TERMS,
162 codeOfConduct: CONFIG.INSTANCE.CODE_OF_CONDUCT,
163
164 hardwareInformation: CONFIG.INSTANCE.HARDWARE_INFORMATION,
165
166 creationReason: CONFIG.INSTANCE.CREATION_REASON,
167 moderationInformation: CONFIG.INSTANCE.MODERATION_INFORMATION,
168 administrator: CONFIG.INSTANCE.ADMINISTRATOR,
169 maintenanceLifetime: CONFIG.INSTANCE.MAINTENANCE_LIFETIME,
170 businessModel: CONFIG.INSTANCE.BUSINESS_MODEL,
171
172 languages: CONFIG.INSTANCE.LANGUAGES,
173 categories: CONFIG.INSTANCE.CATEGORIES
162 } 174 }
163 } 175 }
164 176
@@ -221,6 +233,18 @@ function customConfig (): CustomConfig {
221 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, 233 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
222 description: CONFIG.INSTANCE.DESCRIPTION, 234 description: CONFIG.INSTANCE.DESCRIPTION,
223 terms: CONFIG.INSTANCE.TERMS, 235 terms: CONFIG.INSTANCE.TERMS,
236 codeOfConduct: CONFIG.INSTANCE.CODE_OF_CONDUCT,
237
238 creationReason: CONFIG.INSTANCE.CREATION_REASON,
239 moderationInformation: CONFIG.INSTANCE.MODERATION_INFORMATION,
240 administrator: CONFIG.INSTANCE.ADMINISTRATOR,
241 maintenanceLifetime: CONFIG.INSTANCE.MAINTENANCE_LIFETIME,
242 businessModel: CONFIG.INSTANCE.BUSINESS_MODEL,
243 hardwareInformation: CONFIG.INSTANCE.HARDWARE_INFORMATION,
244
245 languages: CONFIG.INSTANCE.LANGUAGES,
246 categories: CONFIG.INSTANCE.CATEGORIES,
247
224 isNSFW: CONFIG.INSTANCE.IS_NSFW, 248 isNSFW: CONFIG.INSTANCE.IS_NSFW,
225 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE, 249 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
226 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY, 250 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
@@ -300,6 +324,18 @@ function customConfig (): CustomConfig {
300 enabled: CONFIG.FOLLOWERS.INSTANCE.ENABLED, 324 enabled: CONFIG.FOLLOWERS.INSTANCE.ENABLED,
301 manualApproval: CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL 325 manualApproval: CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL
302 } 326 }
327 },
328 followings: {
329 instance: {
330 autoFollowBack: {
331 enabled: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_BACK.ENABLED
332 },
333
334 autoFollowIndex: {
335 enabled: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_INDEX.ENABLED,
336 indexUrl: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_INDEX.INDEX_URL
337 }
338 }
303 } 339 }
304 } 340 }
305} 341}
diff --git a/server/controllers/api/search.ts b/server/controllers/api/search.ts
index 9a1e30b83..349650aca 100644
--- a/server/controllers/api/search.ts
+++ b/server/controllers/api/search.ts
@@ -19,6 +19,7 @@ import { getOrCreateActorAndServerAndModel, getOrCreateVideoAndAccountAndChannel
19import { logger } from '../../helpers/logger' 19import { logger } from '../../helpers/logger'
20import { VideoChannelModel } from '../../models/video/video-channel' 20import { VideoChannelModel } from '../../models/video/video-channel'
21import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger' 21import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger'
22import { MChannelAccountDefault, MVideoAccountLightBlacklistAllFiles } from '../../typings/models'
22 23
23const searchRouter = express.Router() 24const searchRouter = express.Router()
24 25
@@ -84,7 +85,7 @@ async function searchVideoChannelsDB (query: VideoChannelsSearchQuery, res: expr
84} 85}
85 86
86async function searchVideoChannelURI (search: string, isWebfingerSearch: boolean, res: express.Response) { 87async function searchVideoChannelURI (search: string, isWebfingerSearch: boolean, res: express.Response) {
87 let videoChannel: VideoChannelModel 88 let videoChannel: MChannelAccountDefault
88 let uri = search 89 let uri = search
89 90
90 if (isWebfingerSearch) { 91 if (isWebfingerSearch) {
@@ -137,7 +138,7 @@ async function searchVideosDB (query: VideosSearchQuery, res: express.Response)
137} 138}
138 139
139async function searchVideoURI (url: string, res: express.Response) { 140async function searchVideoURI (url: string, res: express.Response) {
140 let video: VideoModel 141 let video: MVideoAccountLightBlacklistAllFiles
141 142
142 // Check if we can fetch a remote video with the URL 143 // Check if we can fetch a remote video with the URL
143 if (isUserAbleToSearchRemoteURI(res)) { 144 if (isUserAbleToSearchRemoteURI(res)) {
diff --git a/server/controllers/api/server/follows.ts b/server/controllers/api/server/follows.ts
index d38ce91de..37647622b 100644
--- a/server/controllers/api/server/follows.ts
+++ b/server/controllers/api/server/follows.ts
@@ -25,6 +25,7 @@ import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
25import { JobQueue } from '../../../lib/job-queue' 25import { JobQueue } from '../../../lib/job-queue'
26import { removeRedundancyOf } from '../../../lib/redundancy' 26import { removeRedundancyOf } from '../../../lib/redundancy'
27import { sequelizeTypescript } from '../../../initializers/database' 27import { sequelizeTypescript } from '../../../initializers/database'
28import { autoFollowBackIfNeeded } from '../../../lib/activitypub/follow'
28 29
29const serverFollowsRouter = express.Router() 30const serverFollowsRouter = express.Router()
30serverFollowsRouter.get('/following', 31serverFollowsRouter.get('/following',
@@ -172,5 +173,7 @@ async function acceptFollower (req: express.Request, res: express.Response) {
172 follow.state = 'accepted' 173 follow.state = 'accepted'
173 await follow.save() 174 await follow.save()
174 175
176 await autoFollowBackIfNeeded(follow)
177
175 return res.status(204).end() 178 return res.status(204).end()
176} 179}
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts
index ae40e86f8..27351c1a9 100644
--- a/server/controllers/api/users/index.ts
+++ b/server/controllers/api/users/index.ts
@@ -48,6 +48,7 @@ import { CONFIG } from '../../../initializers/config'
48import { sequelizeTypescript } from '../../../initializers/database' 48import { sequelizeTypescript } from '../../../initializers/database'
49import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' 49import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
50import { UserRegister } from '../../../../shared/models/users/user-register.model' 50import { UserRegister } from '../../../../shared/models/users/user-register.model'
51import { MUser, MUserAccountDefault } from '@server/typings/models'
51 52
52const auditLogger = auditLoggerFactory('users') 53const auditLogger = auditLoggerFactory('users')
53 54
@@ -195,7 +196,7 @@ async function createUser (req: express.Request, res: express.Response) {
195 videoQuota: body.videoQuota, 196 videoQuota: body.videoQuota,
196 videoQuotaDaily: body.videoQuotaDaily, 197 videoQuotaDaily: body.videoQuotaDaily,
197 adminFlags: body.adminFlags || UserAdminFlag.NONE 198 adminFlags: body.adminFlags || UserAdminFlag.NONE
198 }) 199 }) as MUser
199 200
200 const { user, account } = await createUserAccountAndChannelAndPlaylist({ userToCreate: userToCreate }) 201 const { user, account } = await createUserAccountAndChannelAndPlaylist({ userToCreate: userToCreate })
201 202
@@ -359,7 +360,7 @@ function success (req: express.Request, res: express.Response) {
359 res.end() 360 res.end()
360} 361}
361 362
362async function changeUserBlock (res: express.Response, user: UserModel, block: boolean, reason?: string) { 363async function changeUserBlock (res: express.Response, user: MUserAccountDefault, block: boolean, reason?: string) {
363 const oldUserAuditView = new UserAuditView(user.toFormattedJSON()) 364 const oldUserAuditView = new UserAuditView(user.toFormattedJSON())
364 365
365 user.blocked = block 366 user.blocked = block
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts
index e7ed3de64..bf872ca52 100644
--- a/server/controllers/api/users/me.ts
+++ b/server/controllers/api/users/me.ts
@@ -23,15 +23,12 @@ import { createReqFiles } from '../../../helpers/express-utils'
23import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model' 23import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model'
24import { updateAvatarValidator } from '../../../middlewares/validators/avatar' 24import { updateAvatarValidator } from '../../../middlewares/validators/avatar'
25import { updateActorAvatarFile } from '../../../lib/avatar' 25import { updateActorAvatarFile } from '../../../lib/avatar'
26import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
27import { VideoImportModel } from '../../../models/video/video-import' 26import { VideoImportModel } from '../../../models/video/video-import'
28import { AccountModel } from '../../../models/account/account' 27import { AccountModel } from '../../../models/account/account'
29import { CONFIG } from '../../../initializers/config' 28import { CONFIG } from '../../../initializers/config'
30import { sequelizeTypescript } from '../../../initializers/database' 29import { sequelizeTypescript } from '../../../initializers/database'
31import { sendVerifyUserEmail } from '../../../lib/user' 30import { sendVerifyUserEmail } from '../../../lib/user'
32 31
33const auditLogger = auditLoggerFactory('users-me')
34
35const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR }) 32const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR })
36 33
37const meRouter = express.Router() 34const meRouter = express.Router()
@@ -130,7 +127,7 @@ async function getUserInformation (req: express.Request, res: express.Response)
130 // We did not load channels in res.locals.user 127 // We did not load channels in res.locals.user
131 const user = await UserModel.loadByUsernameAndPopulateChannels(res.locals.oauth.token.user.username) 128 const user = await UserModel.loadByUsernameAndPopulateChannels(res.locals.oauth.token.user.username)
132 129
133 return res.json(user.toFormattedJSON({})) 130 return res.json(user.toFormattedJSON())
134} 131}
135 132
136async function getUserVideoQuotaUsed (req: express.Request, res: express.Response) { 133async function getUserVideoQuotaUsed (req: express.Request, res: express.Response) {
@@ -147,7 +144,7 @@ async function getUserVideoQuotaUsed (req: express.Request, res: express.Respons
147} 144}
148 145
149async function getUserVideoRating (req: express.Request, res: express.Response) { 146async function getUserVideoRating (req: express.Request, res: express.Response) {
150 const videoId = res.locals.video.id 147 const videoId = res.locals.videoId.id
151 const accountId = +res.locals.oauth.token.User.Account.id 148 const accountId = +res.locals.oauth.token.User.Account.id
152 149
153 const ratingObj = await AccountVideoRateModel.load(accountId, videoId, null) 150 const ratingObj = await AccountVideoRateModel.load(accountId, videoId, null)
@@ -165,8 +162,6 @@ async function deleteMe (req: express.Request, res: express.Response) {
165 162
166 await user.destroy() 163 await user.destroy()
167 164
168 auditLogger.delete(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON({})))
169
170 return res.sendStatus(204) 165 return res.sendStatus(204)
171} 166}
172 167
@@ -175,7 +170,6 @@ async function updateMe (req: express.Request, res: express.Response) {
175 let sendVerificationEmail = false 170 let sendVerificationEmail = false
176 171
177 const user = res.locals.oauth.token.user 172 const user = res.locals.oauth.token.user
178 const oldUserAuditView = new UserAuditView(user.toFormattedJSON({}))
179 173
180 if (body.password !== undefined) user.password = body.password 174 if (body.password !== undefined) user.password = body.password
181 if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy 175 if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy
@@ -184,6 +178,8 @@ async function updateMe (req: express.Request, res: express.Response) {
184 if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled 178 if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled
185 if (body.videoLanguages !== undefined) user.videoLanguages = body.videoLanguages 179 if (body.videoLanguages !== undefined) user.videoLanguages = body.videoLanguages
186 if (body.theme !== undefined) user.theme = body.theme 180 if (body.theme !== undefined) user.theme = body.theme
181 if (body.noInstanceConfigWarningModal !== undefined) user.noInstanceConfigWarningModal = body.noInstanceConfigWarningModal
182 if (body.noWelcomeModal !== undefined) user.noWelcomeModal = body.noWelcomeModal
187 183
188 if (body.email !== undefined) { 184 if (body.email !== undefined) {
189 if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) { 185 if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) {
@@ -195,17 +191,17 @@ async function updateMe (req: express.Request, res: express.Response) {
195 } 191 }
196 192
197 await sequelizeTypescript.transaction(async t => { 193 await sequelizeTypescript.transaction(async t => {
198 const userAccount = await AccountModel.load(user.Account.id)
199
200 await user.save({ transaction: t }) 194 await user.save({ transaction: t })
201 195
202 if (body.displayName !== undefined) userAccount.name = body.displayName 196 if (body.displayName !== undefined || body.description !== undefined) {
203 if (body.description !== undefined) userAccount.description = body.description 197 const userAccount = await AccountModel.load(user.Account.id, t)
204 await userAccount.save({ transaction: t })
205 198
206 await sendUpdateActor(userAccount, t) 199 if (body.displayName !== undefined) userAccount.name = body.displayName
200 if (body.description !== undefined) userAccount.description = body.description
201 await userAccount.save({ transaction: t })
207 202
208 auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON({})), oldUserAuditView) 203 await sendUpdateActor(userAccount, t)
204 }
209 }) 205 })
210 206
211 if (sendVerificationEmail === true) { 207 if (sendVerificationEmail === true) {
@@ -218,13 +214,10 @@ async function updateMe (req: express.Request, res: express.Response) {
218async function updateMyAvatar (req: express.Request, res: express.Response) { 214async function updateMyAvatar (req: express.Request, res: express.Response) {
219 const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ] 215 const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ]
220 const user = res.locals.oauth.token.user 216 const user = res.locals.oauth.token.user
221 const oldUserAuditView = new UserAuditView(user.toFormattedJSON({}))
222 217
223 const userAccount = await AccountModel.load(user.Account.id) 218 const userAccount = await AccountModel.load(user.Account.id)
224 219
225 const avatar = await updateActorAvatarFile(avatarPhysicalFile, userAccount) 220 const avatar = await updateActorAvatarFile(avatarPhysicalFile, userAccount)
226 221
227 auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON({})), oldUserAuditView)
228
229 return res.json({ avatar: avatar.toFormattedJSON() }) 222 return res.json({ avatar: avatar.toFormattedJSON() })
230} 223}
diff --git a/server/controllers/api/users/my-history.ts b/server/controllers/api/users/my-history.ts
index 7025c0ff1..4da1f3496 100644
--- a/server/controllers/api/users/my-history.ts
+++ b/server/controllers/api/users/my-history.ts
@@ -7,7 +7,6 @@ import {
7 setDefaultPagination, 7 setDefaultPagination,
8 userHistoryRemoveValidator 8 userHistoryRemoveValidator
9} from '../../../middlewares' 9} from '../../../middlewares'
10import { UserModel } from '../../../models/account/user'
11import { getFormattedObjects } from '../../../helpers/utils' 10import { getFormattedObjects } from '../../../helpers/utils'
12import { UserVideoHistoryModel } from '../../../models/account/user-video-history' 11import { UserVideoHistoryModel } from '../../../models/account/user-video-history'
13import { sequelizeTypescript } from '../../../initializers' 12import { sequelizeTypescript } from '../../../initializers'
diff --git a/server/controllers/api/users/my-notifications.ts b/server/controllers/api/users/my-notifications.ts
index f146284e4..017f5219e 100644
--- a/server/controllers/api/users/my-notifications.ts
+++ b/server/controllers/api/users/my-notifications.ts
@@ -76,7 +76,8 @@ async function updateNotificationSettings (req: express.Request, res: express.Re
76 newFollow: body.newFollow, 76 newFollow: body.newFollow,
77 newUserRegistration: body.newUserRegistration, 77 newUserRegistration: body.newUserRegistration,
78 commentMention: body.commentMention, 78 commentMention: body.commentMention,
79 newInstanceFollower: body.newInstanceFollower 79 newInstanceFollower: body.newInstanceFollower,
80 autoInstanceFollowing: body.autoInstanceFollowing
80 } 81 }
81 82
82 await UserNotificationSettingModel.update(values, query) 83 await UserNotificationSettingModel.update(values, query)
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts
index 81a03a62b..acc5b2987 100644
--- a/server/controllers/api/video-channel.ts
+++ b/server/controllers/api/video-channel.ts
@@ -19,7 +19,7 @@ import { VideoChannelModel } from '../../models/video/video-channel'
19import { videoChannelsNameWithHostValidator, videosSortValidator } from '../../middlewares/validators' 19import { videoChannelsNameWithHostValidator, videosSortValidator } from '../../middlewares/validators'
20import { sendUpdateActor } from '../../lib/activitypub/send' 20import { sendUpdateActor } from '../../lib/activitypub/send'
21import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' 21import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
22import { createVideoChannel, federateAllVideosOfChannel } from '../../lib/video-channel' 22import { createLocalVideoChannel, federateAllVideosOfChannel } from '../../lib/video-channel'
23import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' 23import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
24import { setAsyncActorKeys } from '../../lib/activitypub' 24import { setAsyncActorKeys } from '../../lib/activitypub'
25import { AccountModel } from '../../models/account/account' 25import { AccountModel } from '../../models/account/account'
@@ -35,6 +35,7 @@ import { VideoPlaylistModel } from '../../models/video/video-playlist'
35import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists' 35import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists'
36import { CONFIG } from '../../initializers/config' 36import { CONFIG } from '../../initializers/config'
37import { sequelizeTypescript } from '../../initializers/database' 37import { sequelizeTypescript } from '../../initializers/database'
38import { MChannelAccountDefault } from '@server/typings/models'
38 39
39const auditLogger = auditLoggerFactory('channels') 40const auditLogger = auditLoggerFactory('channels')
40const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR }) 41const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR })
@@ -136,10 +137,10 @@ async function updateVideoChannelAvatar (req: express.Request, res: express.Resp
136async function addVideoChannel (req: express.Request, res: express.Response) { 137async function addVideoChannel (req: express.Request, res: express.Response) {
137 const videoChannelInfo: VideoChannelCreate = req.body 138 const videoChannelInfo: VideoChannelCreate = req.body
138 139
139 const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => { 140 const videoChannelCreated = await sequelizeTypescript.transaction(async t => {
140 const account = await AccountModel.load(res.locals.oauth.token.User.Account.id, t) 141 const account = await AccountModel.load(res.locals.oauth.token.User.Account.id, t)
141 142
142 return createVideoChannel(videoChannelInfo, account, t) 143 return createLocalVideoChannel(videoChannelInfo, account, t)
143 }) 144 })
144 145
145 setAsyncActorKeys(videoChannelCreated.Actor) 146 setAsyncActorKeys(videoChannelCreated.Actor)
@@ -181,7 +182,7 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
181 } 182 }
182 } 183 }
183 184
184 const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) 185 const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) as MChannelAccountDefault
185 await sendUpdateActor(videoChannelInstanceUpdated, t) 186 await sendUpdateActor(videoChannelInstanceUpdated, t)
186 187
187 auditLogger.update( 188 auditLogger.update(
diff --git a/server/controllers/api/video-playlist.ts b/server/controllers/api/video-playlist.ts
index bd454f553..d9f0ff925 100644
--- a/server/controllers/api/video-playlist.ts
+++ b/server/controllers/api/video-playlist.ts
@@ -40,7 +40,7 @@ import { JobQueue } from '../../lib/job-queue'
40import { CONFIG } from '../../initializers/config' 40import { CONFIG } from '../../initializers/config'
41import { sequelizeTypescript } from '../../initializers/database' 41import { sequelizeTypescript } from '../../initializers/database'
42import { createPlaylistMiniatureFromExisting } from '../../lib/thumbnail' 42import { createPlaylistMiniatureFromExisting } from '../../lib/thumbnail'
43import { VideoModel } from '../../models/video/video' 43import { MVideoPlaylistFull, MVideoPlaylistThumbnail, MVideoThumbnail } from '@server/typings/models'
44 44
45const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { thumbnailfile: CONFIG.STORAGE.TMP_DIR }) 45const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { thumbnailfile: CONFIG.STORAGE.TMP_DIR })
46 46
@@ -58,7 +58,7 @@ videoPlaylistRouter.get('/',
58) 58)
59 59
60videoPlaylistRouter.get('/:playlistId', 60videoPlaylistRouter.get('/:playlistId',
61 asyncMiddleware(videoPlaylistsGetValidator), 61 asyncMiddleware(videoPlaylistsGetValidator('summary')),
62 getVideoPlaylist 62 getVideoPlaylist
63) 63)
64 64
@@ -83,7 +83,7 @@ videoPlaylistRouter.delete('/:playlistId',
83) 83)
84 84
85videoPlaylistRouter.get('/:playlistId/videos', 85videoPlaylistRouter.get('/:playlistId/videos',
86 asyncMiddleware(videoPlaylistsGetValidator), 86 asyncMiddleware(videoPlaylistsGetValidator('summary')),
87 paginationValidator, 87 paginationValidator,
88 setDefaultPagination, 88 setDefaultPagination,
89 optionalAuthenticate, 89 optionalAuthenticate,
@@ -140,7 +140,7 @@ async function listVideoPlaylists (req: express.Request, res: express.Response)
140} 140}
141 141
142function getVideoPlaylist (req: express.Request, res: express.Response) { 142function getVideoPlaylist (req: express.Request, res: express.Response) {
143 const videoPlaylist = res.locals.videoPlaylist 143 const videoPlaylist = res.locals.videoPlaylistSummary
144 144
145 if (videoPlaylist.isOutdated()) { 145 if (videoPlaylist.isOutdated()) {
146 JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video-playlist', url: videoPlaylist.url } }) 146 JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video-playlist', url: videoPlaylist.url } })
@@ -159,7 +159,7 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
159 description: videoPlaylistInfo.description, 159 description: videoPlaylistInfo.description,
160 privacy: videoPlaylistInfo.privacy || VideoPlaylistPrivacy.PRIVATE, 160 privacy: videoPlaylistInfo.privacy || VideoPlaylistPrivacy.PRIVATE,
161 ownerAccountId: user.Account.id 161 ownerAccountId: user.Account.id
162 }) 162 }) as MVideoPlaylistFull
163 163
164 videoPlaylist.url = getVideoPlaylistActivityPubUrl(videoPlaylist) // We use the UUID, so set the URL after building the object 164 videoPlaylist.url = getVideoPlaylistActivityPubUrl(videoPlaylist) // We use the UUID, so set the URL after building the object
165 165
@@ -175,8 +175,8 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
175 ? await createPlaylistMiniatureFromExisting(thumbnailField[0].path, videoPlaylist, false) 175 ? await createPlaylistMiniatureFromExisting(thumbnailField[0].path, videoPlaylist, false)
176 : undefined 176 : undefined
177 177
178 const videoPlaylistCreated: VideoPlaylistModel = await sequelizeTypescript.transaction(async t => { 178 const videoPlaylistCreated = await sequelizeTypescript.transaction(async t => {
179 const videoPlaylistCreated = await videoPlaylist.save({ transaction: t }) 179 const videoPlaylistCreated = await videoPlaylist.save({ transaction: t }) as MVideoPlaylistFull
180 180
181 if (thumbnailModel) { 181 if (thumbnailModel) {
182 thumbnailModel.automaticallyGenerated = false 182 thumbnailModel.automaticallyGenerated = false
@@ -201,7 +201,7 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
201} 201}
202 202
203async function updateVideoPlaylist (req: express.Request, res: express.Response) { 203async function updateVideoPlaylist (req: express.Request, res: express.Response) {
204 const videoPlaylistInstance = res.locals.videoPlaylist 204 const videoPlaylistInstance = res.locals.videoPlaylistFull
205 const videoPlaylistFieldsSave = videoPlaylistInstance.toJSON() 205 const videoPlaylistFieldsSave = videoPlaylistInstance.toJSON()
206 const videoPlaylistInfoToUpdate = req.body as VideoPlaylistUpdate 206 const videoPlaylistInfoToUpdate = req.body as VideoPlaylistUpdate
207 207
@@ -275,7 +275,7 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response)
275} 275}
276 276
277async function removeVideoPlaylist (req: express.Request, res: express.Response) { 277async function removeVideoPlaylist (req: express.Request, res: express.Response) {
278 const videoPlaylistInstance = res.locals.videoPlaylist 278 const videoPlaylistInstance = res.locals.videoPlaylistSummary
279 279
280 await sequelizeTypescript.transaction(async t => { 280 await sequelizeTypescript.transaction(async t => {
281 await videoPlaylistInstance.destroy({ transaction: t }) 281 await videoPlaylistInstance.destroy({ transaction: t })
@@ -290,10 +290,10 @@ async function removeVideoPlaylist (req: express.Request, res: express.Response)
290 290
291async function addVideoInPlaylist (req: express.Request, res: express.Response) { 291async function addVideoInPlaylist (req: express.Request, res: express.Response) {
292 const body: VideoPlaylistElementCreate = req.body 292 const body: VideoPlaylistElementCreate = req.body
293 const videoPlaylist = res.locals.videoPlaylist 293 const videoPlaylist = res.locals.videoPlaylistFull
294 const video = res.locals.video 294 const video = res.locals.onlyVideo
295 295
296 const playlistElement: VideoPlaylistElementModel = await sequelizeTypescript.transaction(async t => { 296 const playlistElement = await sequelizeTypescript.transaction(async t => {
297 const position = await VideoPlaylistElementModel.getNextPositionOf(videoPlaylist.id, t) 297 const position = await VideoPlaylistElementModel.getNextPositionOf(videoPlaylist.id, t)
298 298
299 const playlistElement = await VideoPlaylistElementModel.create({ 299 const playlistElement = await VideoPlaylistElementModel.create({
@@ -330,7 +330,7 @@ async function addVideoInPlaylist (req: express.Request, res: express.Response)
330 330
331async function updateVideoPlaylistElement (req: express.Request, res: express.Response) { 331async function updateVideoPlaylistElement (req: express.Request, res: express.Response) {
332 const body: VideoPlaylistElementUpdate = req.body 332 const body: VideoPlaylistElementUpdate = req.body
333 const videoPlaylist = res.locals.videoPlaylist 333 const videoPlaylist = res.locals.videoPlaylistFull
334 const videoPlaylistElement = res.locals.videoPlaylistElement 334 const videoPlaylistElement = res.locals.videoPlaylistElement
335 335
336 const playlistElement: VideoPlaylistElementModel = await sequelizeTypescript.transaction(async t => { 336 const playlistElement: VideoPlaylistElementModel = await sequelizeTypescript.transaction(async t => {
@@ -354,7 +354,7 @@ async function updateVideoPlaylistElement (req: express.Request, res: express.Re
354 354
355async function removeVideoFromPlaylist (req: express.Request, res: express.Response) { 355async function removeVideoFromPlaylist (req: express.Request, res: express.Response) {
356 const videoPlaylistElement = res.locals.videoPlaylistElement 356 const videoPlaylistElement = res.locals.videoPlaylistElement
357 const videoPlaylist = res.locals.videoPlaylist 357 const videoPlaylist = res.locals.videoPlaylistFull
358 const positionToDelete = videoPlaylistElement.position 358 const positionToDelete = videoPlaylistElement.position
359 359
360 await sequelizeTypescript.transaction(async t => { 360 await sequelizeTypescript.transaction(async t => {
@@ -381,7 +381,7 @@ async function removeVideoFromPlaylist (req: express.Request, res: express.Respo
381} 381}
382 382
383async function reorderVideosPlaylist (req: express.Request, res: express.Response) { 383async function reorderVideosPlaylist (req: express.Request, res: express.Response) {
384 const videoPlaylist = res.locals.videoPlaylist 384 const videoPlaylist = res.locals.videoPlaylistFull
385 const body: VideoPlaylistReorder = req.body 385 const body: VideoPlaylistReorder = req.body
386 386
387 const start: number = body.startPosition 387 const start: number = body.startPosition
@@ -434,7 +434,7 @@ async function reorderVideosPlaylist (req: express.Request, res: express.Respons
434} 434}
435 435
436async function getVideoPlaylistVideos (req: express.Request, res: express.Response) { 436async function getVideoPlaylistVideos (req: express.Request, res: express.Response) {
437 const videoPlaylistInstance = res.locals.videoPlaylist 437 const videoPlaylistInstance = res.locals.videoPlaylistSummary
438 const user = res.locals.oauth ? res.locals.oauth.token.User : undefined 438 const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
439 const server = await getServerActor() 439 const server = await getServerActor()
440 440
@@ -453,7 +453,7 @@ async function getVideoPlaylistVideos (req: express.Request, res: express.Respon
453 return res.json(getFormattedObjects(resultList.data, resultList.total, options)) 453 return res.json(getFormattedObjects(resultList.data, resultList.total, options))
454} 454}
455 455
456async function regeneratePlaylistThumbnail (videoPlaylist: VideoPlaylistModel) { 456async function regeneratePlaylistThumbnail (videoPlaylist: MVideoPlaylistThumbnail) {
457 await videoPlaylist.Thumbnail.destroy() 457 await videoPlaylist.Thumbnail.destroy()
458 videoPlaylist.Thumbnail = null 458 videoPlaylist.Thumbnail = null
459 459
@@ -461,7 +461,7 @@ async function regeneratePlaylistThumbnail (videoPlaylist: VideoPlaylistModel) {
461 if (firstElement) await generateThumbnailForPlaylist(videoPlaylist, firstElement.Video) 461 if (firstElement) await generateThumbnailForPlaylist(videoPlaylist, firstElement.Video)
462} 462}
463 463
464async function generateThumbnailForPlaylist (videoPlaylist: VideoPlaylistModel, video: VideoModel) { 464async function generateThumbnailForPlaylist (videoPlaylist: MVideoPlaylistThumbnail, video: MVideoThumbnail) {
465 logger.info('Generating default thumbnail to playlist %s.', videoPlaylist.url) 465 logger.info('Generating default thumbnail to playlist %s.', videoPlaylist.url)
466 466
467 const inputPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getMiniature().filename) 467 const inputPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getMiniature().filename)
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts
index 77808466c..4ae899b7e 100644
--- a/server/controllers/api/videos/abuse.ts
+++ b/server/controllers/api/videos/abuse.ts
@@ -1,7 +1,7 @@
1import * as express from 'express' 1import * as express from 'express'
2import { UserRight, VideoAbuseCreate, VideoAbuseState } from '../../../../shared' 2import { UserRight, VideoAbuseCreate, VideoAbuseState } from '../../../../shared'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { getFormattedObjects } from '../../../helpers/utils' 4import { getFormattedObjects, getServerActor } from '../../../helpers/utils'
5import { sequelizeTypescript } from '../../../initializers' 5import { sequelizeTypescript } from '../../../initializers'
6import { 6import {
7 asyncMiddleware, 7 asyncMiddleware,
@@ -21,6 +21,7 @@ import { VideoAbuseModel } from '../../../models/video/video-abuse'
21import { auditLoggerFactory, VideoAbuseAuditView } from '../../../helpers/audit-logger' 21import { auditLoggerFactory, VideoAbuseAuditView } from '../../../helpers/audit-logger'
22import { Notifier } from '../../../lib/notifier' 22import { Notifier } from '../../../lib/notifier'
23import { sendVideoAbuse } from '../../../lib/activitypub/send/send-flag' 23import { sendVideoAbuse } from '../../../lib/activitypub/send/send-flag'
24import { MVideoAbuseAccountVideo } from '../../../typings/models/video'
24 25
25const auditLogger = auditLoggerFactory('abuse') 26const auditLogger = auditLoggerFactory('abuse')
26const abuseVideoRouter = express.Router() 27const abuseVideoRouter = express.Router()
@@ -61,7 +62,16 @@ export {
61// --------------------------------------------------------------------------- 62// ---------------------------------------------------------------------------
62 63
63async function listVideoAbuses (req: express.Request, res: express.Response) { 64async function listVideoAbuses (req: express.Request, res: express.Response) {
64 const resultList = await VideoAbuseModel.listForApi(req.query.start, req.query.count, req.query.sort) 65 const user = res.locals.oauth.token.user
66 const serverActor = await getServerActor()
67
68 const resultList = await VideoAbuseModel.listForApi({
69 start: req.query.start,
70 count: req.query.count,
71 sort: req.query.sort,
72 serverAccountId: serverActor.Account.id,
73 user
74 })
65 75
66 return res.json(getFormattedObjects(resultList.data, resultList.total)) 76 return res.json(getFormattedObjects(resultList.data, resultList.total))
67} 77}
@@ -94,10 +104,10 @@ async function deleteVideoAbuse (req: express.Request, res: express.Response) {
94} 104}
95 105
96async function reportVideoAbuse (req: express.Request, res: express.Response) { 106async function reportVideoAbuse (req: express.Request, res: express.Response) {
97 const videoInstance = res.locals.video 107 const videoInstance = res.locals.videoAll
98 const body: VideoAbuseCreate = req.body 108 const body: VideoAbuseCreate = req.body
99 109
100 const videoAbuse: VideoAbuseModel = await sequelizeTypescript.transaction(async t => { 110 const videoAbuse = await sequelizeTypescript.transaction(async t => {
101 const reporterAccount = await AccountModel.load(res.locals.oauth.token.User.Account.id, t) 111 const reporterAccount = await AccountModel.load(res.locals.oauth.token.User.Account.id, t)
102 112
103 const abuseToCreate = { 113 const abuseToCreate = {
@@ -107,7 +117,7 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
107 state: VideoAbuseState.PENDING 117 state: VideoAbuseState.PENDING
108 } 118 }
109 119
110 const videoAbuseInstance = await VideoAbuseModel.create(abuseToCreate, { transaction: t }) 120 const videoAbuseInstance: MVideoAbuseAccountVideo = await VideoAbuseModel.create(abuseToCreate, { transaction: t })
111 videoAbuseInstance.Video = videoInstance 121 videoAbuseInstance.Video = videoInstance
112 videoAbuseInstance.Account = reporterAccount 122 videoAbuseInstance.Account = reporterAccount
113 123
diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts
index 9ff494def..2a667480d 100644
--- a/server/controllers/api/videos/blacklist.ts
+++ b/server/controllers/api/videos/blacklist.ts
@@ -1,5 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import { VideoBlacklist, UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../../../shared' 2import { UserRight, VideoBlacklistCreate, VideoBlacklistType } from '../../../../shared'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { getFormattedObjects } from '../../../helpers/utils' 4import { getFormattedObjects } from '../../../helpers/utils'
5import { 5import {
@@ -11,15 +11,16 @@ import {
11 setBlacklistSort, 11 setBlacklistSort,
12 setDefaultPagination, 12 setDefaultPagination,
13 videosBlacklistAddValidator, 13 videosBlacklistAddValidator,
14 videosBlacklistFiltersValidator,
14 videosBlacklistRemoveValidator, 15 videosBlacklistRemoveValidator,
15 videosBlacklistUpdateValidator, 16 videosBlacklistUpdateValidator
16 videosBlacklistFiltersValidator
17} from '../../../middlewares' 17} from '../../../middlewares'
18import { VideoBlacklistModel } from '../../../models/video/video-blacklist' 18import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
19import { sequelizeTypescript } from '../../../initializers' 19import { sequelizeTypescript } from '../../../initializers'
20import { Notifier } from '../../../lib/notifier' 20import { Notifier } from '../../../lib/notifier'
21import { sendDeleteVideo } from '../../../lib/activitypub/send' 21import { sendDeleteVideo } from '../../../lib/activitypub/send'
22import { federateVideoIfNeeded } from '../../../lib/activitypub' 22import { federateVideoIfNeeded } from '../../../lib/activitypub'
23import { MVideoBlacklistVideo } from '@server/typings/models'
23 24
24const blacklistRouter = express.Router() 25const blacklistRouter = express.Router()
25 26
@@ -64,7 +65,7 @@ export {
64// --------------------------------------------------------------------------- 65// ---------------------------------------------------------------------------
65 66
66async function addVideoToBlacklist (req: express.Request, res: express.Response) { 67async function addVideoToBlacklist (req: express.Request, res: express.Response) {
67 const videoInstance = res.locals.video 68 const videoInstance = res.locals.videoAll
68 const body: VideoBlacklistCreate = req.body 69 const body: VideoBlacklistCreate = req.body
69 70
70 const toCreate = { 71 const toCreate = {
@@ -74,7 +75,7 @@ async function addVideoToBlacklist (req: express.Request, res: express.Response)
74 type: VideoBlacklistType.MANUAL 75 type: VideoBlacklistType.MANUAL
75 } 76 }
76 77
77 const blacklist = await VideoBlacklistModel.create(toCreate) 78 const blacklist: MVideoBlacklistVideo = await VideoBlacklistModel.create(toCreate)
78 blacklist.Video = videoInstance 79 blacklist.Video = videoInstance
79 80
80 if (body.unfederate === true) { 81 if (body.unfederate === true) {
@@ -83,7 +84,7 @@ async function addVideoToBlacklist (req: express.Request, res: express.Response)
83 84
84 Notifier.Instance.notifyOnVideoBlacklist(blacklist) 85 Notifier.Instance.notifyOnVideoBlacklist(blacklist)
85 86
86 logger.info('Video %s blacklisted.', res.locals.video.uuid) 87 logger.info('Video %s blacklisted.', videoInstance.uuid)
87 88
88 return res.type('json').status(204).end() 89 return res.type('json').status(204).end()
89} 90}
@@ -108,7 +109,7 @@ async function listBlacklist (req: express.Request, res: express.Response) {
108 109
109async function removeVideoFromBlacklistController (req: express.Request, res: express.Response) { 110async function removeVideoFromBlacklistController (req: express.Request, res: express.Response) {
110 const videoBlacklist = res.locals.videoBlacklist 111 const videoBlacklist = res.locals.videoBlacklist
111 const video = res.locals.video 112 const video = res.locals.videoAll
112 113
113 const videoBlacklistType = await sequelizeTypescript.transaction(async t => { 114 const videoBlacklistType = await sequelizeTypescript.transaction(async t => {
114 const unfederated = videoBlacklist.unfederated 115 const unfederated = videoBlacklist.unfederated
@@ -135,7 +136,7 @@ async function removeVideoFromBlacklistController (req: express.Request, res: ex
135 Notifier.Instance.notifyOnNewVideoIfNeeded(video) 136 Notifier.Instance.notifyOnNewVideoIfNeeded(video)
136 } 137 }
137 138
138 logger.info('Video %s removed from blacklist.', res.locals.video.uuid) 139 logger.info('Video %s removed from blacklist.', video.uuid)
139 140
140 return res.type('json').status(204).end() 141 return res.type('json').status(204).end()
141} 142}
diff --git a/server/controllers/api/videos/captions.ts b/server/controllers/api/videos/captions.ts
index 44c255232..37481d12f 100644
--- a/server/controllers/api/videos/captions.ts
+++ b/server/controllers/api/videos/captions.ts
@@ -10,6 +10,7 @@ import { federateVideoIfNeeded } from '../../../lib/activitypub'
10import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils' 10import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
11import { CONFIG } from '../../../initializers/config' 11import { CONFIG } from '../../../initializers/config'
12import { sequelizeTypescript } from '../../../initializers/database' 12import { sequelizeTypescript } from '../../../initializers/database'
13import { MVideoCaptionVideo } from '@server/typings/models'
13 14
14const reqVideoCaptionAdd = createReqFiles( 15const reqVideoCaptionAdd = createReqFiles(
15 [ 'captionfile' ], 16 [ 'captionfile' ],
@@ -46,19 +47,19 @@ export {
46// --------------------------------------------------------------------------- 47// ---------------------------------------------------------------------------
47 48
48async function listVideoCaptions (req: express.Request, res: express.Response) { 49async function listVideoCaptions (req: express.Request, res: express.Response) {
49 const data = await VideoCaptionModel.listVideoCaptions(res.locals.video.id) 50 const data = await VideoCaptionModel.listVideoCaptions(res.locals.videoId.id)
50 51
51 return res.json(getFormattedObjects(data, data.length)) 52 return res.json(getFormattedObjects(data, data.length))
52} 53}
53 54
54async function addVideoCaption (req: express.Request, res: express.Response) { 55async function addVideoCaption (req: express.Request, res: express.Response) {
55 const videoCaptionPhysicalFile = req.files['captionfile'][0] 56 const videoCaptionPhysicalFile = req.files['captionfile'][0]
56 const video = res.locals.video 57 const video = res.locals.videoAll
57 58
58 const videoCaption = new VideoCaptionModel({ 59 const videoCaption = new VideoCaptionModel({
59 videoId: video.id, 60 videoId: video.id,
60 language: req.params.captionLanguage 61 language: req.params.captionLanguage
61 }) 62 }) as MVideoCaptionVideo
62 videoCaption.Video = video 63 videoCaption.Video = video
63 64
64 // Move physical file 65 // Move physical file
@@ -75,7 +76,7 @@ async function addVideoCaption (req: express.Request, res: express.Response) {
75} 76}
76 77
77async function deleteVideoCaption (req: express.Request, res: express.Response) { 78async function deleteVideoCaption (req: express.Request, res: express.Response) {
78 const video = res.locals.video 79 const video = res.locals.videoAll
79 const videoCaption = res.locals.videoCaption 80 const videoCaption = res.locals.videoCaption
80 81
81 await sequelizeTypescript.transaction(async t => { 82 await sequelizeTypescript.transaction(async t => {
diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts
index bc6d81a7c..b2b06b170 100644
--- a/server/controllers/api/videos/comment.ts
+++ b/server/controllers/api/videos/comment.ts
@@ -27,9 +27,6 @@ import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../.
27import { AccountModel } from '../../../models/account/account' 27import { AccountModel } from '../../../models/account/account'
28import { Notifier } from '../../../lib/notifier' 28import { Notifier } from '../../../lib/notifier'
29import { Hooks } from '../../../lib/plugins/hooks' 29import { Hooks } from '../../../lib/plugins/hooks'
30import { ActorModel } from '../../../models/activitypub/actor'
31import { VideoChannelModel } from '../../../models/video/video-channel'
32import { VideoModel } from '../../../models/video/video'
33import { sendDeleteVideoComment } from '../../../lib/activitypub/send' 30import { sendDeleteVideoComment } from '../../../lib/activitypub/send'
34 31
35const auditLogger = auditLoggerFactory('comments') 32const auditLogger = auditLoggerFactory('comments')
@@ -75,7 +72,7 @@ export {
75// --------------------------------------------------------------------------- 72// ---------------------------------------------------------------------------
76 73
77async function listVideoThreads (req: express.Request, res: express.Response) { 74async function listVideoThreads (req: express.Request, res: express.Response) {
78 const video = res.locals.video 75 const video = res.locals.onlyVideo
79 const user = res.locals.oauth ? res.locals.oauth.token.User : undefined 76 const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
80 77
81 let resultList: ResultList<VideoCommentModel> 78 let resultList: ResultList<VideoCommentModel>
@@ -86,7 +83,7 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
86 start: req.query.start, 83 start: req.query.start,
87 count: req.query.count, 84 count: req.query.count,
88 sort: req.query.sort, 85 sort: req.query.sort,
89 user: user 86 user
90 }, 'filter:api.video-threads.list.params') 87 }, 'filter:api.video-threads.list.params')
91 88
92 resultList = await Hooks.wrapPromiseFun( 89 resultList = await Hooks.wrapPromiseFun(
@@ -105,7 +102,7 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
105} 102}
106 103
107async function listVideoThreadComments (req: express.Request, res: express.Response) { 104async function listVideoThreadComments (req: express.Request, res: express.Response) {
108 const video = res.locals.video 105 const video = res.locals.onlyVideo
109 const user = res.locals.oauth ? res.locals.oauth.token.User : undefined 106 const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
110 107
111 let resultList: ResultList<VideoCommentModel> 108 let resultList: ResultList<VideoCommentModel>
@@ -141,7 +138,7 @@ async function addVideoCommentThread (req: express.Request, res: express.Respons
141 return createVideoComment({ 138 return createVideoComment({
142 text: videoCommentInfo.text, 139 text: videoCommentInfo.text,
143 inReplyToComment: null, 140 inReplyToComment: null,
144 video: res.locals.video, 141 video: res.locals.videoAll,
145 account 142 account
146 }, t) 143 }, t)
147 }) 144 })
@@ -164,8 +161,8 @@ async function addVideoCommentReply (req: express.Request, res: express.Response
164 161
165 return createVideoComment({ 162 return createVideoComment({
166 text: videoCommentInfo.text, 163 text: videoCommentInfo.text,
167 inReplyToComment: res.locals.videoComment, 164 inReplyToComment: res.locals.videoCommentFull,
168 video: res.locals.video, 165 video: res.locals.videoAll,
169 account 166 account
170 }, t) 167 }, t)
171 }) 168 })
@@ -179,7 +176,7 @@ async function addVideoCommentReply (req: express.Request, res: express.Response
179} 176}
180 177
181async function removeVideoComment (req: express.Request, res: express.Response) { 178async function removeVideoComment (req: express.Request, res: express.Response) {
182 const videoCommentInstance = res.locals.videoComment 179 const videoCommentInstance = res.locals.videoCommentFull
183 180
184 await sequelizeTypescript.transaction(async t => { 181 await sequelizeTypescript.transaction(async t => {
185 await videoCommentInstance.destroy({ transaction: t }) 182 await videoCommentInstance.destroy({ transaction: t })
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts
index 04c9b547b..28ced5836 100644
--- a/server/controllers/api/videos/import.ts
+++ b/server/controllers/api/videos/import.ts
@@ -1,6 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as magnetUtil from 'magnet-uri' 2import * as magnetUtil from 'magnet-uri'
3import 'multer'
4import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger' 3import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger'
5import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoImportAddValidator } from '../../../middlewares' 4import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoImportAddValidator } from '../../../middlewares'
6import { MIMETYPES } from '../../../initializers/constants' 5import { MIMETYPES } from '../../../initializers/constants'
@@ -15,7 +14,6 @@ import { VideoImportModel } from '../../../models/video/video-import'
15import { JobQueue } from '../../../lib/job-queue/job-queue' 14import { JobQueue } from '../../../lib/job-queue/job-queue'
16import { join } from 'path' 15import { join } from 'path'
17import { isArray } from '../../../helpers/custom-validators/misc' 16import { isArray } from '../../../helpers/custom-validators/misc'
18import { VideoChannelModel } from '../../../models/video/video-channel'
19import * as Bluebird from 'bluebird' 17import * as Bluebird from 'bluebird'
20import * as parseTorrent from 'parse-torrent' 18import * as parseTorrent from 'parse-torrent'
21import { getSecureTorrentName } from '../../../helpers/utils' 19import { getSecureTorrentName } from '../../../helpers/utils'
@@ -25,8 +23,16 @@ import { CONFIG } from '../../../initializers/config'
25import { sequelizeTypescript } from '../../../initializers/database' 23import { sequelizeTypescript } from '../../../initializers/database'
26import { createVideoMiniatureFromExisting } from '../../../lib/thumbnail' 24import { createVideoMiniatureFromExisting } from '../../../lib/thumbnail'
27import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' 25import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
28import { ThumbnailModel } from '../../../models/video/thumbnail' 26import {
29import { UserModel } from '../../../models/account/user' 27 MChannelAccountDefault,
28 MThumbnail,
29 MUser,
30 MVideoAccountDefault,
31 MVideoTag,
32 MVideoThumbnailAccountDefault,
33 MVideoWithBlacklistLight
34} from '@server/typings/models'
35import { MVideoImport, MVideoImportFormattable } from '@server/typings/models/video/video-import'
30 36
31const auditLogger = auditLoggerFactory('video-imports') 37const auditLogger = auditLoggerFactory('video-imports')
32const videoImportsRouter = express.Router() 38const videoImportsRouter = express.Router()
@@ -184,8 +190,8 @@ function buildVideo (channelId: number, body: VideoImportCreate, importData: You
184 category: body.category || importData.category, 190 category: body.category || importData.category,
185 licence: body.licence || importData.licence, 191 licence: body.licence || importData.licence,
186 language: body.language || undefined, 192 language: body.language || undefined,
187 commentsEnabled: body.commentsEnabled || true, 193 commentsEnabled: body.commentsEnabled !== false, // If the value is not "false", the default is "true"
188 downloadEnabled: body.downloadEnabled || true, 194 downloadEnabled: body.downloadEnabled !== false,
189 waitTranscoding: body.waitTranscoding || false, 195 waitTranscoding: body.waitTranscoding || false,
190 state: VideoState.TO_IMPORT, 196 state: VideoState.TO_IMPORT,
191 nsfw: body.nsfw || importData.nsfw || false, 197 nsfw: body.nsfw || importData.nsfw || false,
@@ -225,28 +231,28 @@ async function processPreview (req: express.Request, video: VideoModel) {
225} 231}
226 232
227function insertIntoDB (parameters: { 233function insertIntoDB (parameters: {
228 video: VideoModel, 234 video: MVideoThumbnailAccountDefault,
229 thumbnailModel: ThumbnailModel, 235 thumbnailModel: MThumbnail,
230 previewModel: ThumbnailModel, 236 previewModel: MThumbnail,
231 videoChannel: VideoChannelModel, 237 videoChannel: MChannelAccountDefault,
232 tags: string[], 238 tags: string[],
233 videoImportAttributes: Partial<VideoImportModel>, 239 videoImportAttributes: Partial<MVideoImport>,
234 user: UserModel 240 user: MUser
235}): Bluebird<VideoImportModel> { 241}): Bluebird<MVideoImportFormattable> {
236 const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters 242 const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters
237 243
238 return sequelizeTypescript.transaction(async t => { 244 return sequelizeTypescript.transaction(async t => {
239 const sequelizeOptions = { transaction: t } 245 const sequelizeOptions = { transaction: t }
240 246
241 // Save video object in database 247 // Save video object in database
242 const videoCreated = await video.save(sequelizeOptions) 248 const videoCreated = await video.save(sequelizeOptions) as (MVideoAccountDefault & MVideoWithBlacklistLight & MVideoTag)
243 videoCreated.VideoChannel = videoChannel 249 videoCreated.VideoChannel = videoChannel
244 250
245 if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t) 251 if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
246 if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t) 252 if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t)
247 253
248 await autoBlacklistVideoIfNeeded({ 254 await autoBlacklistVideoIfNeeded({
249 video, 255 video: videoCreated,
250 user, 256 user,
251 notify: false, 257 notify: false,
252 isRemote: false, 258 isRemote: false,
@@ -268,7 +274,7 @@ function insertIntoDB (parameters: {
268 const videoImport = await VideoImportModel.create( 274 const videoImport = await VideoImportModel.create(
269 Object.assign({ videoId: videoCreated.id }, videoImportAttributes), 275 Object.assign({ videoId: videoCreated.id }, videoImportAttributes),
270 sequelizeOptions 276 sequelizeOptions
271 ) 277 ) as MVideoImportFormattable
272 videoImport.Video = videoCreated 278 videoImport.Video = videoCreated
273 279
274 return videoImport 280 return videoImport
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 155ca4678..19da504c7 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -63,6 +63,7 @@ import { createVideoMiniatureFromExisting, generateVideoMiniature } from '../../
63import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' 63import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
64import { VideoTranscodingPayload } from '../../../lib/job-queue/handlers/video-transcoding' 64import { VideoTranscodingPayload } from '../../../lib/job-queue/handlers/video-transcoding'
65import { Hooks } from '../../../lib/plugins/hooks' 65import { Hooks } from '../../../lib/plugins/hooks'
66import { MVideoDetails, MVideoFullLight } from '@server/typings/models'
66 67
67const auditLogger = auditLoggerFactory('videos') 68const auditLogger = auditLoggerFactory('videos')
68const videosRouter = express.Router() 69const videosRouter = express.Router()
@@ -185,7 +186,7 @@ async function addVideo (req: express.Request, res: express.Response) {
185 licence: videoInfo.licence, 186 licence: videoInfo.licence,
186 language: videoInfo.language, 187 language: videoInfo.language,
187 commentsEnabled: videoInfo.commentsEnabled || false, 188 commentsEnabled: videoInfo.commentsEnabled || false,
188 downloadEnabled: videoInfo.downloadEnabled || true, 189 downloadEnabled: videoInfo.downloadEnabled !== false, // If the value is not "false", the default is "true"
189 waitTranscoding: videoInfo.waitTranscoding || false, 190 waitTranscoding: videoInfo.waitTranscoding || false,
190 state: CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED, 191 state: CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED,
191 nsfw: videoInfo.nsfw || false, 192 nsfw: videoInfo.nsfw || false,
@@ -197,7 +198,7 @@ async function addVideo (req: express.Request, res: express.Response) {
197 originallyPublishedAt: videoInfo.originallyPublishedAt 198 originallyPublishedAt: videoInfo.originallyPublishedAt
198 } 199 }
199 200
200 const video = new VideoModel(videoData) 201 const video = new VideoModel(videoData) as MVideoDetails
201 video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object 202 video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object
202 203
203 const videoFile = new VideoFileModel({ 204 const videoFile = new VideoFileModel({
@@ -238,7 +239,7 @@ async function addVideo (req: express.Request, res: express.Response) {
238 const { videoCreated } = await sequelizeTypescript.transaction(async t => { 239 const { videoCreated } = await sequelizeTypescript.transaction(async t => {
239 const sequelizeOptions = { transaction: t } 240 const sequelizeOptions = { transaction: t }
240 241
241 const videoCreated = await video.save(sequelizeOptions) 242 const videoCreated = await video.save(sequelizeOptions) as MVideoFullLight
242 243
243 await videoCreated.addAndSaveThumbnail(thumbnailModel, t) 244 await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
244 await videoCreated.addAndSaveThumbnail(previewModel, t) 245 await videoCreated.addAndSaveThumbnail(previewModel, t)
@@ -318,7 +319,7 @@ async function addVideo (req: express.Request, res: express.Response) {
318} 319}
319 320
320async function updateVideo (req: express.Request, res: express.Response) { 321async function updateVideo (req: express.Request, res: express.Response) {
321 const videoInstance = res.locals.video 322 const videoInstance = res.locals.videoAll
322 const videoFieldsSave = videoInstance.toJSON() 323 const videoFieldsSave = videoInstance.toJSON()
323 const oldVideoAuditView = new VideoAuditView(videoInstance.toFormattedDetailsJSON()) 324 const oldVideoAuditView = new VideoAuditView(videoInstance.toFormattedDetailsJSON())
324 const videoInfoToUpdate: VideoUpdate = req.body 325 const videoInfoToUpdate: VideoUpdate = req.body
@@ -371,7 +372,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
371 } 372 }
372 } 373 }
373 374
374 const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) 375 const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) as MVideoFullLight
375 376
376 if (thumbnailModel) await videoInstanceUpdated.addAndSaveThumbnail(thumbnailModel, t) 377 if (thumbnailModel) await videoInstanceUpdated.addAndSaveThumbnail(thumbnailModel, t)
377 if (previewModel) await videoInstanceUpdated.addAndSaveThumbnail(previewModel, t) 378 if (previewModel) await videoInstanceUpdated.addAndSaveThumbnail(previewModel, t)
@@ -447,7 +448,7 @@ async function getVideo (req: express.Request, res: express.Response) {
447 448
448 const video = await Hooks.wrapPromiseFun( 449 const video = await Hooks.wrapPromiseFun(
449 VideoModel.loadForGetAPI, 450 VideoModel.loadForGetAPI,
450 { id: res.locals.video.id, userId }, 451 { id: res.locals.onlyVideoWithRights.id, userId },
451 'filter:api.video.get.result' 452 'filter:api.video.get.result'
452 ) 453 )
453 454
@@ -460,7 +461,7 @@ async function getVideo (req: express.Request, res: express.Response) {
460} 461}
461 462
462async function viewVideo (req: express.Request, res: express.Response) { 463async function viewVideo (req: express.Request, res: express.Response) {
463 const videoInstance = res.locals.video 464 const videoInstance = res.locals.videoAll
464 465
465 const ip = req.ip 466 const ip = req.ip
466 const exists = await Redis.Instance.doesVideoIPViewExist(ip, videoInstance.uuid) 467 const exists = await Redis.Instance.doesVideoIPViewExist(ip, videoInstance.uuid)
@@ -483,7 +484,7 @@ async function viewVideo (req: express.Request, res: express.Response) {
483} 484}
484 485
485async function getVideoDescription (req: express.Request, res: express.Response) { 486async function getVideoDescription (req: express.Request, res: express.Response) {
486 const videoInstance = res.locals.video 487 const videoInstance = res.locals.videoAll
487 let description = '' 488 let description = ''
488 489
489 if (videoInstance.isOwned()) { 490 if (videoInstance.isOwned()) {
@@ -522,7 +523,7 @@ async function listVideos (req: express.Request, res: express.Response) {
522} 523}
523 524
524async function removeVideo (req: express.Request, res: express.Response) { 525async function removeVideo (req: express.Request, res: express.Response) {
525 const videoInstance = res.locals.video 526 const videoInstance = res.locals.videoAll
526 527
527 await sequelizeTypescript.transaction(async t => { 528 await sequelizeTypescript.transaction(async t => {
528 await videoInstance.destroy({ transaction: t }) 529 await videoInstance.destroy({ transaction: t })
diff --git a/server/controllers/api/videos/ownership.ts b/server/controllers/api/videos/ownership.ts
index 5272c1385..abb34082e 100644
--- a/server/controllers/api/videos/ownership.ts
+++ b/server/controllers/api/videos/ownership.ts
@@ -18,6 +18,7 @@ import { getFormattedObjects } from '../../../helpers/utils'
18import { changeVideoChannelShare } from '../../../lib/activitypub' 18import { changeVideoChannelShare } from '../../../lib/activitypub'
19import { sendUpdateVideo } from '../../../lib/activitypub/send' 19import { sendUpdateVideo } from '../../../lib/activitypub/send'
20import { VideoModel } from '../../../models/video/video' 20import { VideoModel } from '../../../models/video/video'
21import { MVideoFullLight } from '@server/typings/models'
21 22
22const ownershipVideoRouter = express.Router() 23const ownershipVideoRouter = express.Router()
23 24
@@ -56,7 +57,7 @@ export {
56// --------------------------------------------------------------------------- 57// ---------------------------------------------------------------------------
57 58
58async function giveVideoOwnership (req: express.Request, res: express.Response) { 59async function giveVideoOwnership (req: express.Request, res: express.Response) {
59 const videoInstance = res.locals.video 60 const videoInstance = res.locals.videoAll
60 const initiatorAccountId = res.locals.oauth.token.User.Account.id 61 const initiatorAccountId = res.locals.oauth.token.User.Account.id
61 const nextOwner = res.locals.nextOwner 62 const nextOwner = res.locals.nextOwner
62 63
@@ -107,7 +108,7 @@ async function acceptOwnership (req: express.Request, res: express.Response) {
107 108
108 targetVideo.channelId = channel.id 109 targetVideo.channelId = channel.id
109 110
110 const targetVideoUpdated = await targetVideo.save({ transaction: t }) 111 const targetVideoUpdated = await targetVideo.save({ transaction: t }) as MVideoFullLight
111 targetVideoUpdated.VideoChannel = channel 112 targetVideoUpdated.VideoChannel = channel
112 113
113 if (targetVideoUpdated.privacy !== VideoPrivacy.PRIVATE && targetVideoUpdated.state === VideoState.PUBLISHED) { 114 if (targetVideoUpdated.privacy !== VideoPrivacy.PRIVATE && targetVideoUpdated.state === VideoState.PUBLISHED) {
diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts
index b65babedf..3d2f3d728 100644
--- a/server/controllers/api/videos/rate.ts
+++ b/server/controllers/api/videos/rate.ts
@@ -27,7 +27,7 @@ export {
27async function rateVideo (req: express.Request, res: express.Response) { 27async function rateVideo (req: express.Request, res: express.Response) {
28 const body: UserVideoRateUpdate = req.body 28 const body: UserVideoRateUpdate = req.body
29 const rateType = body.rating 29 const rateType = body.rating
30 const videoInstance = res.locals.video 30 const videoInstance = res.locals.videoAll
31 const userAccount = res.locals.oauth.token.User.Account 31 const userAccount = res.locals.oauth.token.User.Account
32 32
33 await sequelizeTypescript.transaction(async t => { 33 await sequelizeTypescript.transaction(async t => {
diff --git a/server/controllers/api/videos/watching.ts b/server/controllers/api/videos/watching.ts
index dcd1f070d..036e16f3a 100644
--- a/server/controllers/api/videos/watching.ts
+++ b/server/controllers/api/videos/watching.ts
@@ -23,7 +23,7 @@ async function userWatchVideo (req: express.Request, res: express.Response) {
23 const user = res.locals.oauth.token.User 23 const user = res.locals.oauth.token.User
24 24
25 const body: UserWatchingVideo = req.body 25 const body: UserWatchingVideo = req.body
26 const { id: videoId } = res.locals.video as { id: number } 26 const { id: videoId } = res.locals.videoId
27 27
28 await UserVideoHistoryModel.upsert({ 28 await UserVideoHistoryModel.upsert({
29 videoId, 29 videoId,
diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts
index d3f581615..468f7a668 100644
--- a/server/controllers/feeds.ts
+++ b/server/controllers/feeds.ts
@@ -43,7 +43,7 @@ export {
43async function generateVideoCommentsFeed (req: express.Request, res: express.Response) { 43async function generateVideoCommentsFeed (req: express.Request, res: express.Response) {
44 const start = 0 44 const start = 0
45 45
46 const video = res.locals.video 46 const video = res.locals.videoAll
47 const videoId: number = video ? video.id : undefined 47 const videoId: number = video ? video.id : undefined
48 48
49 const comments = await VideoCommentModel.listForFeed(start, FEEDS.COUNT, videoId) 49 const comments = await VideoCommentModel.listForFeed(start, FEEDS.COUNT, videoId)
diff --git a/server/controllers/services.ts b/server/controllers/services.ts
index c1c53c3fc..ec057235f 100644
--- a/server/controllers/services.ts
+++ b/server/controllers/services.ts
@@ -23,7 +23,7 @@ export {
23// --------------------------------------------------------------------------- 23// ---------------------------------------------------------------------------
24 24
25function generateOEmbed (req: express.Request, res: express.Response) { 25function generateOEmbed (req: express.Request, res: express.Response) {
26 const video = res.locals.video 26 const video = res.locals.videoAll
27 const webserverUrl = WEBSERVER.URL 27 const webserverUrl = WEBSERVER.URL
28 const maxHeight = parseInt(req.query.maxheight, 10) 28 const maxHeight = parseInt(req.query.maxheight, 10)
29 const maxWidth = parseInt(req.query.maxwidth, 10) 29 const maxWidth = parseInt(req.query.maxwidth, 10)
diff --git a/server/controllers/static.ts b/server/controllers/static.ts
index 8979ef5f3..0f4772310 100644
--- a/server/controllers/static.ts
+++ b/server/controllers/static.ts
@@ -226,14 +226,14 @@ async function generateNodeinfo (req: express.Request, res: express.Response) {
226 return res.send(json).end() 226 return res.send(json).end()
227} 227}
228 228
229async function downloadTorrent (req: express.Request, res: express.Response, next: express.NextFunction) { 229async function downloadTorrent (req: express.Request, res: express.Response) {
230 const { video, videoFile } = getVideoAndFile(req, res) 230 const { video, videoFile } = getVideoAndFile(req, res)
231 if (!videoFile) return res.status(404).end() 231 if (!videoFile) return res.status(404).end()
232 232
233 return res.download(video.getTorrentFilePath(videoFile), `${video.name}-${videoFile.resolution}p.torrent`) 233 return res.download(video.getTorrentFilePath(videoFile), `${video.name}-${videoFile.resolution}p.torrent`)
234} 234}
235 235
236async function downloadVideoFile (req: express.Request, res: express.Response, next: express.NextFunction) { 236async function downloadVideoFile (req: express.Request, res: express.Response) {
237 const { video, videoFile } = getVideoAndFile(req, res) 237 const { video, videoFile } = getVideoAndFile(req, res)
238 if (!videoFile) return res.status(404).end() 238 if (!videoFile) return res.status(404).end()
239 239
@@ -242,7 +242,7 @@ async function downloadVideoFile (req: express.Request, res: express.Response, n
242 242
243function getVideoAndFile (req: express.Request, res: express.Response) { 243function getVideoAndFile (req: express.Request, res: express.Response) {
244 const resolution = parseInt(req.params.resolution, 10) 244 const resolution = parseInt(req.params.resolution, 10)
245 const video = res.locals.video 245 const video = res.locals.videoAll
246 246
247 const videoFile = video.VideoFiles.find(f => f.resolution === resolution) 247 const videoFile = video.VideoFiles.find(f => f.resolution === resolution)
248 248
diff --git a/server/controllers/webfinger.ts b/server/controllers/webfinger.ts
index f2ba3c826..fc9575160 100644
--- a/server/controllers/webfinger.ts
+++ b/server/controllers/webfinger.ts
@@ -18,7 +18,7 @@ export {
18// --------------------------------------------------------------------------- 18// ---------------------------------------------------------------------------
19 19
20function webfingerController (req: express.Request, res: express.Response) { 20function webfingerController (req: express.Request, res: express.Response) {
21 const actor = res.locals.actor 21 const actor = res.locals.actorFull
22 22
23 const json = { 23 const json = {
24 subject: req.query.resource, 24 subject: req.query.resource,