aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/video-channel.ts26
-rw-r--r--server/lib/activitypub/process/process-create.ts1
-rw-r--r--server/lib/video-channel.ts16
-rw-r--r--server/middlewares/validators/videos/video-channels.ts16
-rw-r--r--server/models/video/video.ts23
-rw-r--r--server/tests/api/check-params/video-channels.ts12
-rw-r--r--server/tests/api/videos/video-channels.ts42
7 files changed, 118 insertions, 18 deletions
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts
index c98a39be2..81a03a62b 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 } from '../../lib/video-channel' 22import { createVideoChannel, 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'
@@ -160,6 +160,7 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
160 const videoChannelFieldsSave = videoChannelInstance.toJSON() 160 const videoChannelFieldsSave = videoChannelInstance.toJSON()
161 const oldVideoChannelAuditKeys = new VideoChannelAuditView(videoChannelInstance.toFormattedJSON()) 161 const oldVideoChannelAuditKeys = new VideoChannelAuditView(videoChannelInstance.toFormattedJSON())
162 const videoChannelInfoToUpdate = req.body as VideoChannelUpdate 162 const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
163 let doBulkVideoUpdate = false
163 164
164 try { 165 try {
165 await sequelizeTypescript.transaction(async t => { 166 await sequelizeTypescript.transaction(async t => {
@@ -167,9 +168,18 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
167 transaction: t 168 transaction: t
168 } 169 }
169 170
170 if (videoChannelInfoToUpdate.displayName !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.displayName) 171 if (videoChannelInfoToUpdate.displayName !== undefined) videoChannelInstance.name = videoChannelInfoToUpdate.displayName
171 if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description) 172 if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.description = videoChannelInfoToUpdate.description
172 if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support) 173
174 if (videoChannelInfoToUpdate.support !== undefined) {
175 const oldSupportField = videoChannelInstance.support
176 videoChannelInstance.support = videoChannelInfoToUpdate.support
177
178 if (videoChannelInfoToUpdate.bulkVideosSupportUpdate === true && oldSupportField !== videoChannelInfoToUpdate.support) {
179 doBulkVideoUpdate = true
180 await VideoModel.bulkUpdateSupportField(videoChannelInstance, t)
181 }
182 }
173 183
174 const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) 184 const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
175 await sendUpdateActor(videoChannelInstanceUpdated, t) 185 await sendUpdateActor(videoChannelInstanceUpdated, t)
@@ -179,6 +189,7 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
179 new VideoChannelAuditView(videoChannelInstanceUpdated.toFormattedJSON()), 189 new VideoChannelAuditView(videoChannelInstanceUpdated.toFormattedJSON()),
180 oldVideoChannelAuditKeys 190 oldVideoChannelAuditKeys
181 ) 191 )
192
182 logger.info('Video channel %s updated.', videoChannelInstance.Actor.url) 193 logger.info('Video channel %s updated.', videoChannelInstance.Actor.url)
183 }) 194 })
184 } catch (err) { 195 } catch (err) {
@@ -192,7 +203,12 @@ async function updateVideoChannel (req: express.Request, res: express.Response)
192 throw err 203 throw err
193 } 204 }
194 205
195 return res.type('json').status(204).end() 206 res.type('json').status(204).end()
207
208 // Don't process in a transaction, and after the response because it could be long
209 if (doBulkVideoUpdate) {
210 await federateAllVideosOfChannel(videoChannelInstance)
211 }
196} 212}
197 213
198async function removeVideoChannel (req: express.Request, res: express.Response) { 214async function removeVideoChannel (req: express.Request, res: express.Response) {
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts
index 3b6eb45c4..daf846513 100644
--- a/server/lib/activitypub/process/process-create.ts
+++ b/server/lib/activitypub/process/process-create.ts
@@ -87,6 +87,7 @@ async function processCreateVideoComment (activity: ActivityCreate, byActor: Act
87 commentObject.inReplyTo, 87 commentObject.inReplyTo,
88 { err } 88 { err }
89 ) 89 )
90 return
90 } 91 }
91 92
92 const { comment, created } = await addVideoComment(video, commentObject.id) 93 const { comment, created } = await addVideoComment(video, commentObject.id)
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts
index 0fe95ca09..ee0482c36 100644
--- a/server/lib/video-channel.ts
+++ b/server/lib/video-channel.ts
@@ -3,7 +3,8 @@ import * as uuidv4 from 'uuid/v4'
3import { VideoChannelCreate } from '../../shared/models' 3import { VideoChannelCreate } from '../../shared/models'
4import { AccountModel } from '../models/account/account' 4import { AccountModel } from '../models/account/account'
5import { VideoChannelModel } from '../models/video/video-channel' 5import { VideoChannelModel } from '../models/video/video-channel'
6import { buildActorInstance, getVideoChannelActivityPubUrl } from './activitypub' 6import { buildActorInstance, federateVideoIfNeeded, getVideoChannelActivityPubUrl } from './activitypub'
7import { VideoModel } from '../models/video/video'
7 8
8async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountModel, t: Sequelize.Transaction) { 9async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountModel, t: Sequelize.Transaction) {
9 const uuid = uuidv4() 10 const uuid = uuidv4()
@@ -33,8 +34,19 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account
33 return videoChannelCreated 34 return videoChannelCreated
34} 35}
35 36
37async function federateAllVideosOfChannel (videoChannel: VideoChannelModel) {
38 const videoIds = await VideoModel.getAllIdsFromChannel(videoChannel)
39
40 for (const videoId of videoIds) {
41 const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId)
42
43 await federateVideoIfNeeded(video, false)
44 }
45}
46
36// --------------------------------------------------------------------------- 47// ---------------------------------------------------------------------------
37 48
38export { 49export {
39 createVideoChannel 50 createVideoChannel,
51 federateAllVideosOfChannel
40} 52}
diff --git a/server/middlewares/validators/videos/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts
index 4b26f0bc4..f5a59cacb 100644
--- a/server/middlewares/validators/videos/video-channels.ts
+++ b/server/middlewares/validators/videos/video-channels.ts
@@ -14,6 +14,7 @@ import { VideoChannelModel } from '../../../models/video/video-channel'
14import { areValidationErrors } from '../utils' 14import { areValidationErrors } from '../utils'
15import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor' 15import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor'
16import { ActorModel } from '../../../models/activitypub/actor' 16import { ActorModel } from '../../../models/activitypub/actor'
17import { isBooleanValid } from '../../../helpers/custom-validators/misc'
17 18
18const videoChannelsAddValidator = [ 19const videoChannelsAddValidator = [
19 body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'), 20 body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'),
@@ -40,9 +41,18 @@ const videoChannelsAddValidator = [
40 41
41const videoChannelsUpdateValidator = [ 42const videoChannelsUpdateValidator = [
42 param('nameWithHost').exists().withMessage('Should have an video channel name with host'), 43 param('nameWithHost').exists().withMessage('Should have an video channel name with host'),
43 body('displayName').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid display name'), 44 body('displayName')
44 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), 45 .optional()
45 body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), 46 .custom(isVideoChannelNameValid).withMessage('Should have a valid display name'),
47 body('description')
48 .optional()
49 .custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
50 body('support')
51 .optional()
52 .custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
53 body('bulkVideosSupportUpdate')
54 .optional()
55 .custom(isBooleanValid).withMessage('Should have a valid bulkVideosSupportUpdate boolean field'),
46 56
47 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 57 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
48 logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) 58 logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index c0a7892a4..eccf0a4fa 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -1515,6 +1515,29 @@ export class VideoModel extends Model<VideoModel> {
1515 .then(results => results.length === 1) 1515 .then(results => results.length === 1)
1516 } 1516 }
1517 1517
1518 static bulkUpdateSupportField (videoChannel: VideoChannelModel, t: Transaction) {
1519 const options = {
1520 where: {
1521 channelId: videoChannel.id
1522 },
1523 transaction: t
1524 }
1525
1526 return VideoModel.update({ support: videoChannel.support }, options)
1527 }
1528
1529 static getAllIdsFromChannel (videoChannel: VideoChannelModel) {
1530 const query = {
1531 attributes: [ 'id' ],
1532 where: {
1533 channelId: videoChannel.id
1534 }
1535 }
1536
1537 return VideoModel.findAll(query)
1538 .then(videos => videos.map(v => v.id))
1539 }
1540
1518 // threshold corresponds to how many video the field should have to be returned 1541 // threshold corresponds to how many video the field should have to be returned
1519 static async getRandomFieldSamples (field: 'category' | 'channelId', threshold: number, count: number) { 1542 static async getRandomFieldSamples (field: 'category' | 'channelId', threshold: number, count: number) {
1520 const serverActor = await getServerActor() 1543 const serverActor = await getServerActor()
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts
index ff04f6b03..de88298d1 100644
--- a/server/tests/api/check-params/video-channels.ts
+++ b/server/tests/api/check-params/video-channels.ts
@@ -24,6 +24,7 @@ import {
24 checkBadStartPagination 24 checkBadStartPagination
25} from '../../../../shared/extra-utils/requests/check-api-params' 25} from '../../../../shared/extra-utils/requests/check-api-params'
26import { join } from 'path' 26import { join } from 'path'
27import { VideoChannelUpdate } from '../../../../shared/models/videos'
27 28
28const expect = chai.expect 29const expect = chai.expect
29 30
@@ -169,9 +170,11 @@ describe('Test video channels API validator', function () {
169 }) 170 })
170 171
171 describe('When updating a video channel', function () { 172 describe('When updating a video channel', function () {
172 const baseCorrectParams = { 173 const baseCorrectParams: VideoChannelUpdate = {
173 displayName: 'hello', 174 displayName: 'hello',
174 description: 'super description' 175 description: 'super description',
176 support: 'toto',
177 bulkVideosSupportUpdate: false
175 } 178 }
176 let path: string 179 let path: string
177 180
@@ -214,6 +217,11 @@ describe('Test video channels API validator', function () {
214 await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) 217 await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
215 }) 218 })
216 219
220 it('Should fail with a bad bulkVideosSupportUpdate field', async function () {
221 const fields = immutableAssign(baseCorrectParams, { bulkVideosSupportUpdate: 'super' })
222 await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
223 })
224
217 it('Should succeed with the correct parameters', async function () { 225 it('Should succeed with the correct parameters', async function () {
218 await makePutBodyRequest({ 226 await makePutBodyRequest({
219 url: server.url, 227 url: server.url,
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts
index 2d298dd3f..4f600cae8 100644
--- a/server/tests/api/videos/video-channels.ts
+++ b/server/tests/api/videos/video-channels.ts
@@ -2,12 +2,12 @@
2 2
3import * as chai from 'chai' 3import * as chai from 'chai'
4import 'mocha' 4import 'mocha'
5import { User, Video, VideoChannel } from '../../../../shared/index' 5import { User, Video, VideoChannel, VideoDetails } from '../../../../shared/index'
6import { 6import {
7 cleanupTests, 7 cleanupTests,
8 createUser, 8 createUser,
9 doubleFollow, 9 doubleFollow,
10 flushAndRunMultipleServers, 10 flushAndRunMultipleServers, getVideo,
11 getVideoChannelVideos, 11 getVideoChannelVideos,
12 testImage, 12 testImage,
13 updateVideo, 13 updateVideo,
@@ -79,7 +79,8 @@ describe('Test video channels', function () {
79 79
80 // The channel is 1 is propagated to servers 2 80 // The channel is 1 is propagated to servers 2
81 { 81 {
82 const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'my video name', channelId: secondVideoChannelId }) 82 const videoAttributesArg = { name: 'my video name', channelId: secondVideoChannelId, support: 'video support field' }
83 const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, videoAttributesArg)
83 videoUUID = res.body.video.uuid 84 videoUUID = res.body.video.uuid
84 } 85 }
85 86
@@ -201,12 +202,12 @@ describe('Test video channels', function () {
201 }) 202 })
202 203
203 it('Should update video channel', async function () { 204 it('Should update video channel', async function () {
204 this.timeout(5000) 205 this.timeout(15000)
205 206
206 const videoChannelAttributes = { 207 const videoChannelAttributes = {
207 displayName: 'video channel updated', 208 displayName: 'video channel updated',
208 description: 'video channel description updated', 209 description: 'video channel description updated',
209 support: 'video channel support text updated' 210 support: 'support updated'
210 } 211 }
211 212
212 await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes) 213 await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes)
@@ -224,7 +225,36 @@ describe('Test video channels', function () {
224 expect(res.body.data[0].name).to.equal('second_video_channel') 225 expect(res.body.data[0].name).to.equal('second_video_channel')
225 expect(res.body.data[0].displayName).to.equal('video channel updated') 226 expect(res.body.data[0].displayName).to.equal('video channel updated')
226 expect(res.body.data[0].description).to.equal('video channel description updated') 227 expect(res.body.data[0].description).to.equal('video channel description updated')
227 expect(res.body.data[0].support).to.equal('video channel support text updated') 228 expect(res.body.data[0].support).to.equal('support updated')
229 }
230 })
231
232 it('Should not have updated the video support field', async function () {
233 for (const server of servers) {
234 const res = await getVideo(server.url, videoUUID)
235 const video: VideoDetails = res.body
236
237 expect(video.support).to.equal('video support field')
238 }
239 })
240
241 it('Should update the channel support field and update videos too', async function () {
242 this.timeout(35000)
243
244 const videoChannelAttributes = {
245 support: 'video channel support text updated',
246 bulkVideosSupportUpdate: true
247 }
248
249 await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes)
250
251 await waitJobs(servers)
252
253 for (const server of servers) {
254 const res = await getVideo(server.url, videoUUID)
255 const video: VideoDetails = res.body
256
257 expect(video.support).to.equal(videoChannelAttributes.support)
228 } 258 }
229 }) 259 })
230 260