aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/users/me.ts2
-rw-r--r--server/controllers/api/video-channel.ts2
-rw-r--r--server/helpers/custom-validators/actor-images.ts17
-rw-r--r--server/helpers/custom-validators/users.ts13
-rw-r--r--server/lib/activitypub/actor.ts72
-rw-r--r--server/lib/activitypub/process/process-update.ts9
-rw-r--r--server/lib/actor-image.ts3
-rw-r--r--server/middlewares/validators/actor-image.ts (renamed from server/middlewares/validators/avatar.ts)10
-rw-r--r--server/middlewares/validators/index.ts1
-rw-r--r--server/models/video/video-channel.ts9
-rw-r--r--server/tests/api/check-params/video-channels.ts70
-rw-r--r--server/tests/api/videos/video-channels.ts86
-rw-r--r--server/tests/fixtures/banner-resized.jpgbin0 -> 88780 bytes
-rw-r--r--server/tests/fixtures/banner.jpgbin0 -> 31648 bytes
-rw-r--r--server/typings/express/index.d.ts1
15 files changed, 181 insertions, 114 deletions
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts
index 25a18caa5..9f9d2d77f 100644
--- a/server/controllers/api/users/me.ts
+++ b/server/controllers/api/users/me.ts
@@ -25,7 +25,7 @@ import {
25 usersVideoRatingValidator 25 usersVideoRatingValidator
26} from '../../../middlewares' 26} from '../../../middlewares'
27import { deleteMeValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators' 27import { deleteMeValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators'
28import { updateAvatarValidator } from '../../../middlewares/validators/avatar' 28import { updateAvatarValidator } from '../../../middlewares/validators/actor-image'
29import { AccountModel } from '../../../models/account/account' 29import { AccountModel } from '../../../models/account/account'
30import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 30import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
31import { UserModel } from '../../../models/account/user' 31import { UserModel } from '../../../models/account/user'
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts
index 1c926722d..149d6cfb4 100644
--- a/server/controllers/api/video-channel.ts
+++ b/server/controllers/api/video-channel.ts
@@ -33,7 +33,7 @@ import {
33 videoPlaylistsSortValidator 33 videoPlaylistsSortValidator
34} from '../../middlewares' 34} from '../../middlewares'
35import { videoChannelsNameWithHostValidator, videoChannelsOwnSearchValidator, videosSortValidator } from '../../middlewares/validators' 35import { videoChannelsNameWithHostValidator, videoChannelsOwnSearchValidator, videosSortValidator } from '../../middlewares/validators'
36import { updateAvatarValidator, updateBannerValidator } from '../../middlewares/validators/avatar' 36import { updateAvatarValidator, updateBannerValidator } from '../../middlewares/validators/actor-image'
37import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists' 37import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists'
38import { AccountModel } from '../../models/account/account' 38import { AccountModel } from '../../models/account/account'
39import { VideoModel } from '../../models/video/video' 39import { VideoModel } from '../../models/video/video'
diff --git a/server/helpers/custom-validators/actor-images.ts b/server/helpers/custom-validators/actor-images.ts
new file mode 100644
index 000000000..4fb0b7c70
--- /dev/null
+++ b/server/helpers/custom-validators/actor-images.ts
@@ -0,0 +1,17 @@
1
2import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
3import { isFileValid } from './misc'
4
5const imageMimeTypes = CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME
6 .map(v => v.replace('.', ''))
7 .join('|')
8const imageMimeTypesRegex = `image/(${imageMimeTypes})`
9function isActorImageFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], fieldname: string) {
10 return isFileValid(files, imageMimeTypesRegex, fieldname, CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max)
11}
12
13// ---------------------------------------------------------------------------
14
15export {
16 isActorImageFile
17}
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts
index 85f3634c8..5b21c3529 100644
--- a/server/helpers/custom-validators/users.ts
+++ b/server/helpers/custom-validators/users.ts
@@ -3,7 +3,7 @@ import validator from 'validator'
3import { UserRole } from '../../../shared' 3import { UserRole } from '../../../shared'
4import { isEmailEnabled } from '../../initializers/config' 4import { isEmailEnabled } from '../../initializers/config'
5import { CONSTRAINTS_FIELDS, NSFW_POLICY_TYPES } from '../../initializers/constants' 5import { CONSTRAINTS_FIELDS, NSFW_POLICY_TYPES } from '../../initializers/constants'
6import { exists, isArray, isBooleanValid, isFileValid } from './misc' 6import { exists, isArray, isBooleanValid } from './misc'
7 7
8const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS 8const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS
9 9
@@ -97,14 +97,6 @@ function isUserRoleValid (value: any) {
97 return exists(value) && validator.isInt('' + value) && UserRole[value] !== undefined 97 return exists(value) && validator.isInt('' + value) && UserRole[value] !== undefined
98} 98}
99 99
100const avatarMimeTypes = CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME
101 .map(v => v.replace('.', ''))
102 .join('|')
103const avatarMimeTypesRegex = `image/(${avatarMimeTypes})`
104function isAvatarFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
105 return isFileValid(files, avatarMimeTypesRegex, 'avatarfile', CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max)
106}
107
108// --------------------------------------------------------------------------- 100// ---------------------------------------------------------------------------
109 101
110export { 102export {
@@ -128,6 +120,5 @@ export {
128 isUserDisplayNameValid, 120 isUserDisplayNameValid,
129 isUserDescriptionValid, 121 isUserDescriptionValid,
130 isNoInstanceConfigWarningModal, 122 isNoInstanceConfigWarningModal,
131 isNoWelcomeModal, 123 isNoWelcomeModal
132 isAvatarFile
133} 124}
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index fe4796a3d..917fed6ec 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -34,6 +34,7 @@ import {
34 MActorFull, 34 MActorFull,
35 MActorFullActor, 35 MActorFullActor,
36 MActorId, 36 MActorId,
37 MActorImage,
37 MActorImages, 38 MActorImages,
38 MChannel 39 MChannel
39} from '../../types/models' 40} from '../../types/models'
@@ -169,38 +170,34 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ
169 } 170 }
170} 171}
171 172
172type AvatarInfo = { name: string, onDisk: boolean, fileUrl: string, type: ActorImageType } 173type ImageInfo = { name: string, onDisk?: boolean, fileUrl: string }
173async function updateActorImageInstance (actor: MActorImages, info: AvatarInfo, t: Transaction) { 174async function updateActorImageInstance (actor: MActorImages, type: ActorImageType, imageInfo: ImageInfo | null, t: Transaction) {
174 if (!info.name) return actor 175 const oldImageModel = type === ActorImageType.AVATAR
175
176 const oldImageModel = info.type === ActorImageType.AVATAR
177 ? actor.Avatar 176 ? actor.Avatar
178 : actor.Banner 177 : actor.Banner
179 178
180 if (oldImageModel) { 179 if (oldImageModel) {
181 // Don't update the avatar if the file URL did not change 180 // Don't update the avatar if the file URL did not change
182 if (info.fileUrl && oldImageModel.fileUrl === info.fileUrl) return actor 181 if (imageInfo?.fileUrl && oldImageModel.fileUrl === imageInfo.fileUrl) return actor
183 182
184 try { 183 try {
185 await oldImageModel.destroy({ transaction: t }) 184 await oldImageModel.destroy({ transaction: t })
185
186 setActorImage(actor, type, null)
186 } catch (err) { 187 } catch (err) {
187 logger.error('Cannot remove old actor image of actor %s.', actor.url, { err }) 188 logger.error('Cannot remove old actor image of actor %s.', actor.url, { err })
188 } 189 }
189 } 190 }
190 191
191 const imageModel = await ActorImageModel.create({ 192 if (imageInfo) {
192 filename: info.name, 193 const imageModel = await ActorImageModel.create({
193 onDisk: info.onDisk, 194 filename: imageInfo.name,
194 fileUrl: info.fileUrl, 195 onDisk: imageInfo.onDisk ?? false,
195 type: info.type 196 fileUrl: imageInfo.fileUrl,
196 }, { transaction: t }) 197 type: type
198 }, { transaction: t })
197 199
198 if (info.type === ActorImageType.AVATAR) { 200 setActorImage(actor, type, imageModel)
199 actor.avatarId = imageModel.id
200 actor.Avatar = imageModel
201 } else {
202 actor.bannerId = imageModel.id
203 actor.Banner = imageModel
204 } 201 }
205 202
206 return actor 203 return actor
@@ -310,27 +307,8 @@ async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannel
310 return sequelizeTypescript.transaction(async t => { 307 return sequelizeTypescript.transaction(async t => {
311 updateInstanceWithAnother(actor, result.actor) 308 updateInstanceWithAnother(actor, result.actor)
312 309
313 if (result.avatar !== undefined) { 310 await updateActorImageInstance(actor, ActorImageType.AVATAR, result.avatar, t)
314 const avatarInfo = { 311 await updateActorImageInstance(actor, ActorImageType.BANNER, result.banner, t)
315 name: result.avatar.name,
316 fileUrl: result.avatar.fileUrl,
317 onDisk: false,
318 type: ActorImageType.AVATAR
319 }
320
321 await updateActorImageInstance(actor, avatarInfo, t)
322 }
323
324 if (result.banner !== undefined) {
325 const bannerInfo = {
326 name: result.banner.name,
327 fileUrl: result.banner.fileUrl,
328 onDisk: false,
329 type: ActorImageType.BANNER
330 }
331
332 await updateActorImageInstance(actor, bannerInfo, t)
333 }
334 312
335 // Force update 313 // Force update
336 actor.setDataValue('updatedAt', new Date()) 314 actor.setDataValue('updatedAt', new Date())
@@ -381,6 +359,22 @@ export {
381 359
382// --------------------------------------------------------------------------- 360// ---------------------------------------------------------------------------
383 361
362function setActorImage (actorModel: MActorImages, type: ActorImageType, imageModel: MActorImage) {
363 const id = imageModel
364 ? imageModel.id
365 : null
366
367 if (type === ActorImageType.AVATAR) {
368 actorModel.avatarId = id
369 actorModel.Avatar = imageModel
370 } else {
371 actorModel.bannerId = id
372 actorModel.Banner = imageModel
373 }
374
375 return actorModel
376}
377
384function saveActorAndServerAndModelIfNotExist ( 378function saveActorAndServerAndModelIfNotExist (
385 result: FetchRemoteActorResult, 379 result: FetchRemoteActorResult,
386 ownerActor?: MActorFullActor, 380 ownerActor?: MActorFullActor,
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts
index ad3bb392d..6df9b93b2 100644
--- a/server/lib/activitypub/process/process-update.ts
+++ b/server/lib/activitypub/process/process-update.ts
@@ -134,13 +134,8 @@ async function processUpdateActor (actor: ActorModel, activity: ActivityUpdate)
134 134
135 await updateActorInstance(actor, actorAttributesToUpdate) 135 await updateActorInstance(actor, actorAttributesToUpdate)
136 136
137 for (const imageInfo of [ avatarInfo, bannerInfo ]) { 137 await updateActorImageInstance(actor, ActorImageType.AVATAR, avatarInfo, t)
138 if (!imageInfo) continue 138 await updateActorImageInstance(actor, ActorImageType.BANNER, bannerInfo, t)
139
140 const imageOptions = Object.assign({}, imageInfo, { onDisk: false })
141
142 await updateActorImageInstance(actor, imageOptions, t)
143 }
144 139
145 await actor.save({ transaction: t }) 140 await actor.save({ transaction: t })
146 141
diff --git a/server/lib/actor-image.ts b/server/lib/actor-image.ts
index 59afa93bd..fa1a2a18a 100644
--- a/server/lib/actor-image.ts
+++ b/server/lib/actor-image.ts
@@ -34,11 +34,10 @@ async function updateLocalActorImageFile (
34 const actorImageInfo = { 34 const actorImageInfo = {
35 name: imageName, 35 name: imageName,
36 fileUrl: null, 36 fileUrl: null,
37 type,
38 onDisk: true 37 onDisk: true
39 } 38 }
40 39
41 const updatedActor = await updateActorImageInstance(accountOrChannel.Actor, actorImageInfo, t) 40 const updatedActor = await updateActorImageInstance(accountOrChannel.Actor, type, actorImageInfo, t)
42 await updatedActor.save({ transaction: t }) 41 await updatedActor.save({ transaction: t })
43 42
44 await sendUpdateActor(accountOrChannel, t) 43 await sendUpdateActor(accountOrChannel, t)
diff --git a/server/middlewares/validators/avatar.ts b/server/middlewares/validators/actor-image.ts
index f7eb367bd..961d7a7e5 100644
--- a/server/middlewares/validators/avatar.ts
+++ b/server/middlewares/validators/actor-image.ts
@@ -1,13 +1,13 @@
1import * as express from 'express' 1import * as express from 'express'
2import { body } from 'express-validator' 2import { body } from 'express-validator'
3import { isAvatarFile } from '../../helpers/custom-validators/users' 3import { isActorImageFile } from '@server/helpers/custom-validators/actor-images'
4import { areValidationErrors } from './utils'
5import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
6import { logger } from '../../helpers/logger'
7import { cleanUpReqFiles } from '../../helpers/express-utils' 4import { cleanUpReqFiles } from '../../helpers/express-utils'
5import { logger } from '../../helpers/logger'
6import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
7import { areValidationErrors } from './utils'
8 8
9const updateActorImageValidatorFactory = (fieldname: string) => ([ 9const updateActorImageValidatorFactory = (fieldname: string) => ([
10 body(fieldname).custom((value, { req }) => isAvatarFile(req.files)).withMessage( 10 body(fieldname).custom((value, { req }) => isActorImageFile(req.files, fieldname)).withMessage(
11 'This file is not supported or too large. Please, make sure it is of the following type : ' + 11 'This file is not supported or too large. Please, make sure it is of the following type : ' +
12 CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME.join(', ') 12 CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME.join(', ')
13 ), 13 ),
diff --git a/server/middlewares/validators/index.ts b/server/middlewares/validators/index.ts
index 4086d77aa..24faeea3e 100644
--- a/server/middlewares/validators/index.ts
+++ b/server/middlewares/validators/index.ts
@@ -1,5 +1,6 @@
1export * from './abuse' 1export * from './abuse'
2export * from './account' 2export * from './account'
3export * from './actor-image'
3export * from './blocklist' 4export * from './blocklist'
4export * from './oembed' 5export * from './oembed'
5export * from './activitypub' 6export * from './activitypub'
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts
index 74885edfb..d2a055f5b 100644
--- a/server/models/video/video-channel.ts
+++ b/server/models/video/video-channel.ts
@@ -99,7 +99,14 @@ export type SummaryOptions = {
99 } 99 }
100 } 100 }
101 ] 101 ]
102 } 102 },
103 include: [
104 {
105 model: ActorImageModel,
106 as: 'Banner',
107 required: false
108 }
109 ]
103 }, 110 },
104 { 111 {
105 model: AccountModel, 112 model: AccountModel,
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts
index 0dd436426..bc2e6192e 100644
--- a/server/tests/api/check-params/video-channels.ts
+++ b/server/tests/api/check-params/video-channels.ts
@@ -234,7 +234,8 @@ describe('Test video channels API validator', function () {
234 }) 234 })
235 }) 235 })
236 236
237 describe('When updating video channel avatar', function () { 237 describe('When updating video channel avatar/banner', function () {
238 const types = [ 'avatar', 'banner' ]
238 let path: string 239 let path: string
239 240
240 before(async function () { 241 before(async function () {
@@ -242,48 +243,57 @@ describe('Test video channels API validator', function () {
242 }) 243 })
243 244
244 it('Should fail with an incorrect input file', async function () { 245 it('Should fail with an incorrect input file', async function () {
245 const fields = {} 246 for (const type of types) {
246 const attaches = { 247 const fields = {}
247 avatarfile: join(__dirname, '..', '..', 'fixtures', 'video_short.mp4') 248 const attaches = {
249 [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
250 }
251
252 await makeUploadRequest({ url: server.url, path: `${path}/${type}/pick`, token: server.accessToken, fields, attaches })
248 } 253 }
249 await makeUploadRequest({ url: server.url, path: path + '/avatar/pick', token: server.accessToken, fields, attaches })
250 }) 254 })
251 255
252 it('Should fail with a big file', async function () { 256 it('Should fail with a big file', async function () {
253 const fields = {} 257 for (const type of types) {
254 const attaches = { 258 const fields = {}
255 avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar-big.png') 259 const attaches = {
260 [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
261 }
262 await makeUploadRequest({ url: server.url, path: `${path}/${type}/pick`, token: server.accessToken, fields, attaches })
256 } 263 }
257 await makeUploadRequest({ url: server.url, path: path + '/avatar/pick', token: server.accessToken, fields, attaches })
258 }) 264 })
259 265
260 it('Should fail with an unauthenticated user', async function () { 266 it('Should fail with an unauthenticated user', async function () {
261 const fields = {} 267 for (const type of types) {
262 const attaches = { 268 const fields = {}
263 avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png') 269 const attaches = {
270 [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
271 }
272 await makeUploadRequest({
273 url: server.url,
274 path: `${path}/${type}/pick`,
275 fields,
276 attaches,
277 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
278 })
264 } 279 }
265 await makeUploadRequest({
266 url: server.url,
267 path: path + '/avatar/pick',
268 fields,
269 attaches,
270 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
271 })
272 }) 280 })
273 281
274 it('Should succeed with the correct params', async function () { 282 it('Should succeed with the correct params', async function () {
275 const fields = {} 283 for (const type of types) {
276 const attaches = { 284 const fields = {}
277 avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png') 285 const attaches = {
286 [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
287 }
288 await makeUploadRequest({
289 url: server.url,
290 path: `${path}/${type}/pick`,
291 token: server.accessToken,
292 fields,
293 attaches,
294 statusCodeExpected: HttpStatusCode.OK_200
295 })
278 } 296 }
279 await makeUploadRequest({
280 url: server.url,
281 path: path + '/avatar/pick',
282 token: server.accessToken,
283 fields,
284 attaches,
285 statusCodeExpected: HttpStatusCode.OK_200
286 })
287 }) 297 })
288 }) 298 })
289 299
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts
index 367f99fdd..8033b9ba5 100644
--- a/server/tests/api/videos/video-channels.ts
+++ b/server/tests/api/videos/video-channels.ts
@@ -5,13 +5,14 @@ import * as chai from 'chai'
5import { 5import {
6 cleanupTests, 6 cleanupTests,
7 createUser, 7 createUser,
8 deleteVideoChannelImage,
8 doubleFollow, 9 doubleFollow,
9 flushAndRunMultipleServers, 10 flushAndRunMultipleServers,
10 getVideo, 11 getVideo,
11 getVideoChannelVideos, 12 getVideoChannelVideos,
12 testImage, 13 testImage,
13 updateVideo, 14 updateVideo,
14 updateVideoChannelAvatar, 15 updateVideoChannelImage,
15 uploadVideo, 16 uploadVideo,
16 userLogin, 17 userLogin,
17 wait 18 wait
@@ -21,7 +22,6 @@ import {
21 deleteVideoChannel, 22 deleteVideoChannel,
22 getAccountVideoChannelsList, 23 getAccountVideoChannelsList,
23 getMyUserInformation, 24 getMyUserInformation,
24 getVideoChannel,
25 getVideoChannelsList, 25 getVideoChannelsList,
26 ServerInfo, 26 ServerInfo,
27 setAccessTokensToServers, 27 setAccessTokensToServers,
@@ -33,6 +33,13 @@ import { User, Video, VideoChannel, VideoDetails } from '../../../../shared/inde
33 33
34const expect = chai.expect 34const expect = chai.expect
35 35
36async function findChannel (server: ServerInfo, channelId: number) {
37 const res = await getVideoChannelsList(server.url, 0, 5, '-name')
38 const videoChannel = res.body.data.find(c => c.id === channelId)
39
40 return videoChannel as VideoChannel
41}
42
36describe('Test video channels', function () { 43describe('Test video channels', function () {
37 let servers: ServerInfo[] 44 let servers: ServerInfo[]
38 let userInfo: User 45 let userInfo: User
@@ -262,38 +269,85 @@ describe('Test video channels', function () {
262 }) 269 })
263 270
264 it('Should update video channel avatar', async function () { 271 it('Should update video channel avatar', async function () {
265 this.timeout(5000) 272 this.timeout(15000)
266 273
267 const fixture = 'avatar.png' 274 const fixture = 'avatar.png'
268 275
269 await updateVideoChannelAvatar({ 276 await updateVideoChannelImage({
270 url: servers[0].url, 277 url: servers[0].url,
271 accessToken: servers[0].accessToken, 278 accessToken: servers[0].accessToken,
272 videoChannelName: 'second_video_channel', 279 videoChannelName: 'second_video_channel',
273 fixture 280 fixture,
281 type: 'avatar'
274 }) 282 })
275 283
276 await waitJobs(servers) 284 await waitJobs(servers)
285
286 for (const server of servers) {
287 const videoChannel = await findChannel(server, secondVideoChannelId)
288
289 await testImage(server.url, 'avatar-resized', videoChannel.avatar.path, '.png')
290 }
277 }) 291 })
278 292
279 it('Should have video channel avatar updated', async function () { 293 it('Should update video channel banner', async function () {
294 this.timeout(15000)
295
296 const fixture = 'banner.jpg'
297
298 await updateVideoChannelImage({
299 url: servers[0].url,
300 accessToken: servers[0].accessToken,
301 videoChannelName: 'second_video_channel',
302 fixture,
303 type: 'banner'
304 })
305
306 await waitJobs(servers)
307
280 for (const server of servers) { 308 for (const server of servers) {
281 const res = await getVideoChannelsList(server.url, 0, 1, '-name') 309 const videoChannel = await findChannel(server, secondVideoChannelId)
282 310
283 const videoChannel = res.body.data.find(c => c.id === secondVideoChannelId) 311 await testImage(server.url, 'banner-resized', videoChannel.banner.path)
312 }
313 })
284 314
285 await testImage(server.url, 'avatar-resized', videoChannel.avatar.path, '.png') 315 it('Should delete the video channel avatar', async function () {
316 this.timeout(15000)
317
318 await deleteVideoChannelImage({
319 url: servers[0].url,
320 accessToken: servers[0].accessToken,
321 videoChannelName: 'second_video_channel',
322 type: 'avatar'
323 })
324
325 await waitJobs(servers)
326
327 for (const server of servers) {
328 const videoChannel = await findChannel(server, secondVideoChannelId)
329
330 expect(videoChannel.avatar).to.be.null
286 } 331 }
287 }) 332 })
288 333
289 it('Should get video channel', async function () { 334 it('Should delete the video channel banner', async function () {
290 const res = await getVideoChannel(servers[0].url, 'second_video_channel') 335 this.timeout(15000)
336
337 await deleteVideoChannelImage({
338 url: servers[0].url,
339 accessToken: servers[0].accessToken,
340 videoChannelName: 'second_video_channel',
341 type: 'banner'
342 })
291 343
292 const videoChannel = res.body 344 await waitJobs(servers)
293 expect(videoChannel.name).to.equal('second_video_channel') 345
294 expect(videoChannel.displayName).to.equal('video channel updated') 346 for (const server of servers) {
295 expect(videoChannel.description).to.equal('video channel description updated') 347 const videoChannel = await findChannel(server, secondVideoChannelId)
296 expect(videoChannel.support).to.equal('video channel support text updated') 348
349 expect(videoChannel.banner).to.be.null
350 }
297 }) 351 })
298 352
299 it('Should list the second video channel videos', async function () { 353 it('Should list the second video channel videos', async function () {
diff --git a/server/tests/fixtures/banner-resized.jpg b/server/tests/fixtures/banner-resized.jpg
new file mode 100644
index 000000000..13ea422cb
--- /dev/null
+++ b/server/tests/fixtures/banner-resized.jpg
Binary files differ
diff --git a/server/tests/fixtures/banner.jpg b/server/tests/fixtures/banner.jpg
new file mode 100644
index 000000000..e5f284f59
--- /dev/null
+++ b/server/tests/fixtures/banner.jpg
Binary files differ
diff --git a/server/typings/express/index.d.ts b/server/typings/express/index.d.ts
index ee4faa35d..cf3e7ae34 100644
--- a/server/typings/express/index.d.ts
+++ b/server/typings/express/index.d.ts
@@ -3,7 +3,6 @@ import {
3 MAbuseMessage, 3 MAbuseMessage,
4 MAbuseReporter, 4 MAbuseReporter,
5 MAccountBlocklist, 5 MAccountBlocklist,
6 MActorFollowActors,
7 MActorFollowActorsDefault, 6 MActorFollowActorsDefault,
8 MActorUrl, 7 MActorUrl,
9 MChannelBannerAccountDefault, 8 MChannelBannerAccountDefault,