aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-04-25 16:15:39 +0200
committerChocobozzz <me@florianbigard.com>2018-04-25 16:16:21 +0200
commitcc918ac3f45e32f031cce7b6e0473e5c2c34b8ae (patch)
tree034c0ce9cda37d572fe1c0c34eff750681e18574 /server
parentd3e91a5f72ac9c986cdb67d7d6c85bb4819e680c (diff)
downloadPeerTube-cc918ac3f45e32f031cce7b6e0473e5c2c34b8ae.tar.gz
PeerTube-cc918ac3f45e32f031cce7b6e0473e5c2c34b8ae.tar.zst
PeerTube-cc918ac3f45e32f031cce7b6e0473e5c2c34b8ae.zip
Update video-channel routes (again)
Use /video-channels now, it's more simple for clients
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/accounts.ts168
-rw-r--r--server/controllers/api/video-channel.ts173
-rw-r--r--server/middlewares/validators/video-channels.ts25
-rw-r--r--server/tests/api/check-params/video-channels.ts58
-rw-r--r--server/tests/api/videos/video-channels.ts10
-rw-r--r--server/tests/api/videos/video-nsfw.ts4
-rw-r--r--server/tests/utils/videos/video-channels.ts14
-rw-r--r--server/tests/utils/videos/videos.ts3
8 files changed, 210 insertions, 245 deletions
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts
index 85987c912..ccae0436b 100644
--- a/server/controllers/api/accounts.ts
+++ b/server/controllers/api/accounts.ts
@@ -1,30 +1,18 @@
1import * as express from 'express' 1import * as express from 'express'
2import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils' 2import { getFormattedObjects } from '../../helpers/utils'
3import { 3import {
4 asyncMiddleware, 4 asyncMiddleware,
5 authenticate,
6 listVideoAccountChannelsValidator, 5 listVideoAccountChannelsValidator,
7 optionalAuthenticate, 6 optionalAuthenticate,
8 paginationValidator, 7 paginationValidator,
9 setDefaultPagination, 8 setDefaultPagination,
10 setDefaultSort, 9 setDefaultSort
11 videoChannelsAddValidator,
12 videoChannelsGetValidator,
13 videoChannelsRemoveValidator,
14 videoChannelsUpdateValidator
15} from '../../middlewares' 10} from '../../middlewares'
16import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators' 11import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators'
17import { AccountModel } from '../../models/account/account' 12import { AccountModel } from '../../models/account/account'
18import { VideoModel } from '../../models/video/video' 13import { VideoModel } from '../../models/video/video'
19import { isNSFWHidden } from '../../helpers/express-utils' 14import { isNSFWHidden } from '../../helpers/express-utils'
20import { VideoChannelModel } from '../../models/video/video-channel' 15import { VideoChannelModel } from '../../models/video/video-channel'
21import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
22import { sendUpdateActor } from '../../lib/activitypub/send'
23import { createVideoChannel } from '../../lib/video-channel'
24import { setAsyncActorKeys } from '../../lib/activitypub'
25import { sequelizeTypescript } from '../../initializers'
26import { logger } from '../../helpers/logger'
27import { retryTransactionWrapper } from '../../helpers/database-utils'
28 16
29const accountsRouter = express.Router() 17const accountsRouter = express.Router()
30 18
@@ -56,39 +44,6 @@ accountsRouter.get('/:accountId/video-channels',
56 asyncMiddleware(listVideoAccountChannels) 44 asyncMiddleware(listVideoAccountChannels)
57) 45)
58 46
59accountsRouter.post('/:accountId/video-channels',
60 authenticate,
61 videoChannelsAddValidator,
62 asyncMiddleware(addVideoChannelRetryWrapper)
63)
64
65accountsRouter.put('/:accountId/video-channels/:id',
66 authenticate,
67 asyncMiddleware(videoChannelsUpdateValidator),
68 updateVideoChannelRetryWrapper
69)
70
71accountsRouter.delete('/:accountId/video-channels/:id',
72 authenticate,
73 asyncMiddleware(videoChannelsRemoveValidator),
74 asyncMiddleware(removeVideoChannelRetryWrapper)
75)
76
77accountsRouter.get('/:accountId/video-channels/:id',
78 asyncMiddleware(videoChannelsGetValidator),
79 asyncMiddleware(getVideoChannel)
80)
81
82accountsRouter.get('/:accountId/video-channels/:id/videos',
83 asyncMiddleware(videoChannelsGetValidator),
84 paginationValidator,
85 videosSortValidator,
86 setDefaultSort,
87 setDefaultPagination,
88 optionalAuthenticate,
89 asyncMiddleware(listVideoChannelVideos)
90)
91
92// --------------------------------------------------------------------------- 47// ---------------------------------------------------------------------------
93 48
94export { 49export {
@@ -115,125 +70,6 @@ async function listVideoAccountChannels (req: express.Request, res: express.Resp
115 return res.json(getFormattedObjects(resultList.data, resultList.total)) 70 return res.json(getFormattedObjects(resultList.data, resultList.total))
116} 71}
117 72
118// Wrapper to video channel add that retry the async function if there is a database error
119// We need this because we run the transaction in SERIALIZABLE isolation that can fail
120async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
121 const options = {
122 arguments: [ req, res ],
123 errorMessage: 'Cannot insert the video video channel with many retries.'
124 }
125
126 const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
127 return res.json({
128 videoChannel: {
129 id: videoChannel.id,
130 uuid: videoChannel.Actor.uuid
131 }
132 }).end()
133}
134
135async function addVideoChannel (req: express.Request, res: express.Response) {
136 const videoChannelInfo: VideoChannelCreate = req.body
137 const account: AccountModel = res.locals.oauth.token.User.Account
138
139 const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
140 return createVideoChannel(videoChannelInfo, account, t)
141 })
142
143 setAsyncActorKeys(videoChannelCreated.Actor)
144 .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err }))
145
146 logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
147
148 return videoChannelCreated
149}
150
151async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
152 const options = {
153 arguments: [ req, res ],
154 errorMessage: 'Cannot update the video with many retries.'
155 }
156
157 await retryTransactionWrapper(updateVideoChannel, options)
158
159 return res.type('json').status(204).end()
160}
161
162async function updateVideoChannel (req: express.Request, res: express.Response) {
163 const videoChannelInstance = res.locals.videoChannel as VideoChannelModel
164 const videoChannelFieldsSave = videoChannelInstance.toJSON()
165 const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
166
167 try {
168 await sequelizeTypescript.transaction(async t => {
169 const sequelizeOptions = {
170 transaction: t
171 }
172
173 if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name)
174 if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description)
175 if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support)
176
177 const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
178 await sendUpdateActor(videoChannelInstanceUpdated, t)
179 })
180
181 logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
182 } catch (err) {
183 logger.debug('Cannot update the video channel.', { err })
184
185 // Force fields we want to update
186 // If the transaction is retried, sequelize will think the object has not changed
187 // So it will skip the SQL request, even if the last one was ROLLBACKed!
188 resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave)
189
190 throw err
191 }
192}
193
194async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
195 const options = {
196 arguments: [ req, res ],
197 errorMessage: 'Cannot remove the video channel with many retries.'
198 }
199
200 await retryTransactionWrapper(removeVideoChannel, options)
201
202 return res.type('json').status(204).end()
203}
204
205async function removeVideoChannel (req: express.Request, res: express.Response) {
206 const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
207
208 return sequelizeTypescript.transaction(async t => {
209 await videoChannelInstance.destroy({ transaction: t })
210
211 logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
212 })
213
214}
215
216async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
217 const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id)
218
219 return res.json(videoChannelWithVideos.toFormattedJSON())
220}
221
222async function listVideoChannelVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
223 const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
224
225 const resultList = await VideoModel.listForApi({
226 start: req.query.start,
227 count: req.query.count,
228 sort: req.query.sort,
229 hideNSFW: isNSFWHidden(res),
230 withFiles: false,
231 videoChannelId: videoChannelInstance.id
232 })
233
234 return res.json(getFormattedObjects(resultList.data, resultList.total))
235}
236
237async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) { 73async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
238 const account: AccountModel = res.locals.account 74 const account: AccountModel = res.locals.account
239 75
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts
index d57273747..6241aaa5c 100644
--- a/server/controllers/api/video-channel.ts
+++ b/server/controllers/api/video-channel.ts
@@ -1,13 +1,30 @@
1import * as express from 'express' 1import * as express from 'express'
2import { getFormattedObjects } from '../../helpers/utils' 2import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils'
3import { 3import {
4 asyncMiddleware, 4 asyncMiddleware,
5 authenticate,
6 optionalAuthenticate,
5 paginationValidator, 7 paginationValidator,
6 setDefaultPagination, 8 setDefaultPagination,
7 setDefaultSort, 9 setDefaultSort,
8 videoChannelsSortValidator 10 videoChannelsAddValidator,
11 videoChannelsGetValidator,
12 videoChannelsRemoveValidator,
13 videoChannelsSortValidator,
14 videoChannelsUpdateValidator
9} from '../../middlewares' 15} from '../../middlewares'
10import { VideoChannelModel } from '../../models/video/video-channel' 16import { VideoChannelModel } from '../../models/video/video-channel'
17import { videosSortValidator } from '../../middlewares/validators'
18import { sendUpdateActor } from '../../lib/activitypub/send'
19import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
20import { createVideoChannel } from '../../lib/video-channel'
21import { isNSFWHidden } from '../../helpers/express-utils'
22import { setAsyncActorKeys } from '../../lib/activitypub'
23import { retryTransactionWrapper } from '../../helpers/database-utils'
24import { AccountModel } from '../../models/account/account'
25import { sequelizeTypescript } from '../../initializers'
26import { logger } from '../../helpers/logger'
27import { VideoModel } from '../../models/video/video'
11 28
12const videoChannelRouter = express.Router() 29const videoChannelRouter = express.Router()
13 30
@@ -19,6 +36,39 @@ videoChannelRouter.get('/',
19 asyncMiddleware(listVideoChannels) 36 asyncMiddleware(listVideoChannels)
20) 37)
21 38
39videoChannelRouter.post('/',
40 authenticate,
41 videoChannelsAddValidator,
42 asyncMiddleware(addVideoChannelRetryWrapper)
43)
44
45videoChannelRouter.put('/:id',
46 authenticate,
47 asyncMiddleware(videoChannelsUpdateValidator),
48 updateVideoChannelRetryWrapper
49)
50
51videoChannelRouter.delete('/:id',
52 authenticate,
53 asyncMiddleware(videoChannelsRemoveValidator),
54 asyncMiddleware(removeVideoChannelRetryWrapper)
55)
56
57videoChannelRouter.get('/:id',
58 asyncMiddleware(videoChannelsGetValidator),
59 asyncMiddleware(getVideoChannel)
60)
61
62videoChannelRouter.get('/:id/videos',
63 asyncMiddleware(videoChannelsGetValidator),
64 paginationValidator,
65 videosSortValidator,
66 setDefaultSort,
67 setDefaultPagination,
68 optionalAuthenticate,
69 asyncMiddleware(listVideoChannelVideos)
70)
71
22// --------------------------------------------------------------------------- 72// ---------------------------------------------------------------------------
23 73
24export { 74export {
@@ -32,3 +82,122 @@ async function listVideoChannels (req: express.Request, res: express.Response, n
32 82
33 return res.json(getFormattedObjects(resultList.data, resultList.total)) 83 return res.json(getFormattedObjects(resultList.data, resultList.total))
34} 84}
85
86// Wrapper to video channel add that retry the async function if there is a database error
87// We need this because we run the transaction in SERIALIZABLE isolation that can fail
88async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
89 const options = {
90 arguments: [ req, res ],
91 errorMessage: 'Cannot insert the video video channel with many retries.'
92 }
93
94 const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
95 return res.json({
96 videoChannel: {
97 id: videoChannel.id,
98 uuid: videoChannel.Actor.uuid
99 }
100 }).end()
101}
102
103async function addVideoChannel (req: express.Request, res: express.Response) {
104 const videoChannelInfo: VideoChannelCreate = req.body
105 const account: AccountModel = res.locals.oauth.token.User.Account
106
107 const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
108 return createVideoChannel(videoChannelInfo, account, t)
109 })
110
111 setAsyncActorKeys(videoChannelCreated.Actor)
112 .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err }))
113
114 logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
115
116 return videoChannelCreated
117}
118
119async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
120 const options = {
121 arguments: [ req, res ],
122 errorMessage: 'Cannot update the video with many retries.'
123 }
124
125 await retryTransactionWrapper(updateVideoChannel, options)
126
127 return res.type('json').status(204).end()
128}
129
130async function updateVideoChannel (req: express.Request, res: express.Response) {
131 const videoChannelInstance = res.locals.videoChannel as VideoChannelModel
132 const videoChannelFieldsSave = videoChannelInstance.toJSON()
133 const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
134
135 try {
136 await sequelizeTypescript.transaction(async t => {
137 const sequelizeOptions = {
138 transaction: t
139 }
140
141 if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name)
142 if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description)
143 if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support)
144
145 const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
146 await sendUpdateActor(videoChannelInstanceUpdated, t)
147 })
148
149 logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
150 } catch (err) {
151 logger.debug('Cannot update the video channel.', { err })
152
153 // Force fields we want to update
154 // If the transaction is retried, sequelize will think the object has not changed
155 // So it will skip the SQL request, even if the last one was ROLLBACKed!
156 resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave)
157
158 throw err
159 }
160}
161
162async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
163 const options = {
164 arguments: [ req, res ],
165 errorMessage: 'Cannot remove the video channel with many retries.'
166 }
167
168 await retryTransactionWrapper(removeVideoChannel, options)
169
170 return res.type('json').status(204).end()
171}
172
173async function removeVideoChannel (req: express.Request, res: express.Response) {
174 const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
175
176 return sequelizeTypescript.transaction(async t => {
177 await videoChannelInstance.destroy({ transaction: t })
178
179 logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
180 })
181
182}
183
184async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
185 const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id)
186
187 return res.json(videoChannelWithVideos.toFormattedJSON())
188}
189
190async function listVideoChannelVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
191 const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
192
193 const resultList = await VideoModel.listForApi({
194 start: req.query.start,
195 count: req.query.count,
196 sort: req.query.sort,
197 hideNSFW: isNSFWHidden(res),
198 withFiles: false,
199 videoChannelId: videoChannelInstance.id
200 })
201
202 return res.json(getFormattedObjects(resultList.data, resultList.total))
203}
diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts
index 9e6f459cf..a70f196df 100644
--- a/server/middlewares/validators/video-channels.ts
+++ b/server/middlewares/validators/video-channels.ts
@@ -27,7 +27,6 @@ const listVideoAccountChannelsValidator = [
27] 27]
28 28
29const videoChannelsAddValidator = [ 29const videoChannelsAddValidator = [
30 param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
31 body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'), 30 body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
32 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), 31 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
33 body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), 32 body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
@@ -43,7 +42,6 @@ const videoChannelsAddValidator = [
43 42
44const videoChannelsUpdateValidator = [ 43const videoChannelsUpdateValidator = [
45 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 44 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
46 param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
47 body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'), 45 body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
48 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), 46 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
49 body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), 47 body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
@@ -52,9 +50,7 @@ const videoChannelsUpdateValidator = [
52 logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) 50 logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
53 51
54 if (areValidationErrors(req, res)) return 52 if (areValidationErrors(req, res)) return
55 if (!await isAccountIdExist(req.params.accountId, res)) return
56 if (!await isVideoChannelExist(req.params.id, res)) return 53 if (!await isVideoChannelExist(req.params.id, res)) return
57 if (!checkAccountOwnsVideoChannel(res.locals.account, res.locals.videoChannel, res)) return
58 54
59 // We need to make additional checks 55 // We need to make additional checks
60 if (res.locals.videoChannel.Actor.isOwned() === false) { 56 if (res.locals.videoChannel.Actor.isOwned() === false) {
@@ -75,17 +71,13 @@ const videoChannelsUpdateValidator = [
75 71
76const videoChannelsRemoveValidator = [ 72const videoChannelsRemoveValidator = [
77 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 73 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
78 param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
79 74
80 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 75 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
81 logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params }) 76 logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
82 77
83 if (areValidationErrors(req, res)) return 78 if (areValidationErrors(req, res)) return
84 if (!await isAccountIdExist(req.params.accountId, res)) return
85 if (!await isVideoChannelExist(req.params.id, res)) return 79 if (!await isVideoChannelExist(req.params.id, res)) return
86 80
87 if (!checkAccountOwnsVideoChannel(res.locals.account, res.locals.videoChannel, res)) return
88 // Check if the user who did the request is able to delete the video
89 if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return 81 if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return
90 if (!await checkVideoChannelIsNotTheLastOne(res)) return 82 if (!await checkVideoChannelIsNotTheLastOne(res)) return
91 83
@@ -95,19 +87,14 @@ const videoChannelsRemoveValidator = [
95 87
96const videoChannelsGetValidator = [ 88const videoChannelsGetValidator = [
97 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 89 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
98 param('accountId').optional().custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
99 90
100 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 91 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
101 logger.debug('Checking videoChannelsGet parameters', { parameters: req.params }) 92 logger.debug('Checking videoChannelsGet parameters', { parameters: req.params })
102 93
103 if (areValidationErrors(req, res)) return 94 if (areValidationErrors(req, res)) return
104 95
105 // On some routes, accountId is optional (for example in the ActivityPub route)
106 if (req.params.accountId && !await isAccountIdExist(req.params.accountId, res)) return
107 if (!await isVideoChannelExist(req.params.id, res)) return 96 if (!await isVideoChannelExist(req.params.id, res)) return
108 97
109 if (res.locals.account && !checkAccountOwnsVideoChannel(res.locals.account, res.locals.videoChannel, res)) return
110
111 return next() 98 return next()
112 } 99 }
113] 100]
@@ -160,15 +147,3 @@ async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
160 147
161 return true 148 return true
162} 149}
163
164function checkAccountOwnsVideoChannel (account: AccountModel, videoChannel: VideoChannelModel, res: express.Response) {
165 if (videoChannel.Account.id !== account.id) {
166 res.status(400)
167 .json({ error: 'This account does not own this video channel' })
168 .end()
169
170 return false
171 }
172
173 return true
174}
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts
index 25b2dc9b9..7cda879ed 100644
--- a/server/tests/api/check-params/video-channels.ts
+++ b/server/tests/api/check-params/video-channels.ts
@@ -27,10 +27,8 @@ const expect = chai.expect
27 27
28describe('Test videos API validator', function () { 28describe('Test videos API validator', function () {
29 const videoChannelPath = '/api/v1/video-channels' 29 const videoChannelPath = '/api/v1/video-channels'
30 const accountPath = '/api/v1/accounts/'
31 let server: ServerInfo 30 let server: ServerInfo
32 let accessTokenUser: string 31 let accessTokenUser: string
33 let accountUUID: string
34 let videoChannelUUID: string 32 let videoChannelUUID: string
35 33
36 // --------------------------------------------------------------- 34 // ---------------------------------------------------------------
@@ -57,7 +55,6 @@ describe('Test videos API validator', function () {
57 { 55 {
58 const res = await getMyUserInformation(server.url, server.accessToken) 56 const res = await getMyUserInformation(server.url, server.accessToken)
59 const user: User = res.body 57 const user: User = res.body
60 accountUUID = user.account.uuid
61 videoChannelUUID = user.videoChannels[0].uuid 58 videoChannelUUID = user.videoChannels[0].uuid
62 } 59 }
63 }) 60 })
@@ -92,45 +89,46 @@ describe('Test videos API validator', function () {
92 description: 'super description', 89 description: 'super description',
93 support: 'super support text' 90 support: 'super support text'
94 } 91 }
95 let path: string
96
97 before(async function () {
98 path = accountPath + accountUUID + '/video-channels'
99 })
100 92
101 it('Should fail with a non authenticated user', async function () { 93 it('Should fail with a non authenticated user', async function () {
102 await makePostBodyRequest({ url: server.url, path, token: 'none', fields: baseCorrectParams, statusCodeExpected: 401 }) 94 await makePostBodyRequest({
95 url: server.url,
96 path: videoChannelPath,
97 token: 'none',
98 fields: baseCorrectParams,
99 statusCodeExpected: 401
100 })
103 }) 101 })
104 102
105 it('Should fail with nothing', async function () { 103 it('Should fail with nothing', async function () {
106 const fields = {} 104 const fields = {}
107 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) 105 await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
108 }) 106 })
109 107
110 it('Should fail without name', async function () { 108 it('Should fail without name', async function () {
111 const fields = omit(baseCorrectParams, 'name') 109 const fields = omit(baseCorrectParams, 'name')
112 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) 110 await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
113 }) 111 })
114 112
115 it('Should fail with a long name', async function () { 113 it('Should fail with a long name', async function () {
116 const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(25) }) 114 const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(25) })
117 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) 115 await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
118 }) 116 })
119 117
120 it('Should fail with a long description', async function () { 118 it('Should fail with a long description', async function () {
121 const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(60) }) 119 const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(60) })
122 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) 120 await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
123 }) 121 })
124 122
125 it('Should fail with a long support text', async function () { 123 it('Should fail with a long support text', async function () {
126 const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) }) 124 const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) })
127 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) 125 await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
128 }) 126 })
129 127
130 it('Should succeed with the correct parameters', async function () { 128 it('Should succeed with the correct parameters', async function () {
131 await makePostBodyRequest({ 129 await makePostBodyRequest({
132 url: server.url, 130 url: server.url,
133 path, 131 path: videoChannelPath,
134 token: server.accessToken, 132 token: server.accessToken,
135 fields: baseCorrectParams, 133 fields: baseCorrectParams,
136 statusCodeExpected: 200 134 statusCodeExpected: 200
@@ -146,7 +144,7 @@ describe('Test videos API validator', function () {
146 let path: string 144 let path: string
147 145
148 before(async function () { 146 before(async function () {
149 path = accountPath + accountUUID + '/video-channels/' + videoChannelUUID 147 path = videoChannelPath + '/' + videoChannelUUID
150 }) 148 })
151 149
152 it('Should fail with a non authenticated user', async function () { 150 it('Should fail with a non authenticated user', async function () {
@@ -196,16 +194,10 @@ describe('Test videos API validator', function () {
196 }) 194 })
197 195
198 describe('When getting a video channel', function () { 196 describe('When getting a video channel', function () {
199 let basePath: string
200
201 before(async function () {
202 basePath = accountPath + accountUUID + '/video-channels'
203 })
204
205 it('Should return the list of the video channels with nothing', async function () { 197 it('Should return the list of the video channels with nothing', async function () {
206 const res = await makeGetRequest({ 198 const res = await makeGetRequest({
207 url: server.url, 199 url: server.url,
208 path: basePath, 200 path: videoChannelPath,
209 statusCodeExpected: 200 201 statusCodeExpected: 200
210 }) 202 })
211 203
@@ -215,7 +207,7 @@ describe('Test videos API validator', function () {
215 it('Should fail without a correct uuid', async function () { 207 it('Should fail without a correct uuid', async function () {
216 await makeGetRequest({ 208 await makeGetRequest({
217 url: server.url, 209 url: server.url,
218 path: basePath + '/coucou', 210 path: videoChannelPath + '/coucou',
219 statusCodeExpected: 400 211 statusCodeExpected: 400
220 }) 212 })
221 }) 213 })
@@ -223,7 +215,7 @@ describe('Test videos API validator', function () {
223 it('Should return 404 with an incorrect video channel', async function () { 215 it('Should return 404 with an incorrect video channel', async function () {
224 await makeGetRequest({ 216 await makeGetRequest({
225 url: server.url, 217 url: server.url,
226 path: basePath + '/4da6fde3-88f7-4d16-b119-108df5630b06', 218 path: videoChannelPath + '/4da6fde3-88f7-4d16-b119-108df5630b06',
227 statusCodeExpected: 404 219 statusCodeExpected: 404
228 }) 220 })
229 }) 221 })
@@ -231,7 +223,7 @@ describe('Test videos API validator', function () {
231 it('Should succeed with the correct parameters', async function () { 223 it('Should succeed with the correct parameters', async function () {
232 await makeGetRequest({ 224 await makeGetRequest({
233 url: server.url, 225 url: server.url,
234 path: basePath + '/' + videoChannelUUID, 226 path: videoChannelPath + '/' + videoChannelUUID,
235 statusCodeExpected: 200 227 statusCodeExpected: 200
236 }) 228 })
237 }) 229 })
@@ -239,30 +231,26 @@ describe('Test videos API validator', function () {
239 231
240 describe('When deleting a video channel', function () { 232 describe('When deleting a video channel', function () {
241 it('Should fail with a non authenticated user', async function () { 233 it('Should fail with a non authenticated user', async function () {
242 await deleteVideoChannel(server.url, 'coucou', accountUUID, videoChannelUUID, 401) 234 await deleteVideoChannel(server.url, 'coucou', videoChannelUUID, 401)
243 }) 235 })
244 236
245 it('Should fail with another authenticated user', async function () { 237 it('Should fail with another authenticated user', async function () {
246 await deleteVideoChannel(server.url, accessTokenUser, accountUUID, videoChannelUUID, 403) 238 await deleteVideoChannel(server.url, accessTokenUser, videoChannelUUID, 403)
247 })
248
249 it('Should fail with an unknown account id', async function () {
250 await deleteVideoChannel(server.url, server.accessToken, 454554,videoChannelUUID, 404)
251 }) 239 })
252 240
253 it('Should fail with an unknown video channel id', async function () { 241 it('Should fail with an unknown video channel id', async function () {
254 await deleteVideoChannel(server.url, server.accessToken, accountUUID,454554, 404) 242 await deleteVideoChannel(server.url, server.accessToken,454554, 404)
255 }) 243 })
256 244
257 it('Should succeed with the correct parameters', async function () { 245 it('Should succeed with the correct parameters', async function () {
258 await deleteVideoChannel(server.url, server.accessToken, accountUUID, videoChannelUUID) 246 await deleteVideoChannel(server.url, server.accessToken, videoChannelUUID)
259 }) 247 })
260 248
261 it('Should fail to delete the last user video channel', async function () { 249 it('Should fail to delete the last user video channel', async function () {
262 const res = await getVideoChannelsList(server.url, 0, 1) 250 const res = await getVideoChannelsList(server.url, 0, 1)
263 const lastVideoChannelUUID = res.body.data[0].uuid 251 const lastVideoChannelUUID = res.body.data[0].uuid
264 252
265 await deleteVideoChannel(server.url, server.accessToken, accountUUID, lastVideoChannelUUID, 409) 253 await deleteVideoChannel(server.url, server.accessToken, lastVideoChannelUUID, 409)
266 }) 254 })
267 }) 255 })
268 256
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts
index 04e7b8c6a..d24b8ab0b 100644
--- a/server/tests/api/videos/video-channels.ts
+++ b/server/tests/api/videos/video-channels.ts
@@ -63,7 +63,7 @@ describe('Test video channels', function () {
63 description: 'super video channel description', 63 description: 'super video channel description',
64 support: 'super video channel support text' 64 support: 'super video channel support text'
65 } 65 }
66 const res = await addVideoChannel(servers[0].url, servers[0].accessToken, accountUUID, videoChannel) 66 const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
67 videoChannelId = res.body.videoChannel.id 67 videoChannelId = res.body.videoChannel.id
68 videoChannelUUID = res.body.videoChannel.uuid 68 videoChannelUUID = res.body.videoChannel.uuid
69 69
@@ -130,7 +130,7 @@ describe('Test video channels', function () {
130 support: 'video channel support text updated' 130 support: 'video channel support text updated'
131 } 131 }
132 132
133 await updateVideoChannel(servers[0].url, servers[0].accessToken, accountUUID, videoChannelId, videoChannelAttributes) 133 await updateVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId, videoChannelAttributes)
134 134
135 await wait(3000) 135 await wait(3000)
136 }) 136 })
@@ -149,7 +149,7 @@ describe('Test video channels', function () {
149 }) 149 })
150 150
151 it('Should get video channel', async function () { 151 it('Should get video channel', async function () {
152 const res = await getVideoChannel(servers[0].url, accountUUID, videoChannelId) 152 const res = await getVideoChannel(servers[0].url, videoChannelId)
153 153
154 const videoChannel = res.body 154 const videoChannel = res.body
155 expect(videoChannel.displayName).to.equal('video channel updated') 155 expect(videoChannel.displayName).to.equal('video channel updated')
@@ -161,7 +161,7 @@ describe('Test video channels', function () {
161 this.timeout(10000) 161 this.timeout(10000)
162 162
163 for (const server of servers) { 163 for (const server of servers) {
164 const res = await getVideoChannelVideos(server.url, server.accessToken, accountUUID, videoChannelUUID, 0, 5) 164 const res = await getVideoChannelVideos(server.url, server.accessToken, videoChannelUUID, 0, 5)
165 expect(res.body.total).to.equal(1) 165 expect(res.body.total).to.equal(1)
166 expect(res.body.data).to.be.an('array') 166 expect(res.body.data).to.be.an('array')
167 expect(res.body.data).to.have.lengthOf(1) 167 expect(res.body.data).to.have.lengthOf(1)
@@ -170,7 +170,7 @@ describe('Test video channels', function () {
170 }) 170 })
171 171
172 it('Should delete video channel', async function () { 172 it('Should delete video channel', async function () {
173 await deleteVideoChannel(servers[0].url, servers[0].accessToken, accountUUID, videoChannelId) 173 await deleteVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId)
174 }) 174 })
175 175
176 it('Should have video channel deleted', async function () { 176 it('Should have video channel deleted', async function () {
diff --git a/server/tests/api/videos/video-nsfw.ts b/server/tests/api/videos/video-nsfw.ts
index 8901f38f9..b8c85f45b 100644
--- a/server/tests/api/videos/video-nsfw.ts
+++ b/server/tests/api/videos/video-nsfw.ts
@@ -39,7 +39,7 @@ describe('Test video NSFW policy', function () {
39 getVideosListWithToken(server.url, token), 39 getVideosListWithToken(server.url, token),
40 searchVideoWithToken(server.url, 'n', token), 40 searchVideoWithToken(server.url, 'n', token),
41 getAccountVideos(server.url, token, accountUUID, 0, 5), 41 getAccountVideos(server.url, token, accountUUID, 0, 5),
42 getVideoChannelVideos(server.url, token, accountUUID, videoChannelUUID, 0, 5) 42 getVideoChannelVideos(server.url, token, videoChannelUUID, 0, 5)
43 ]) 43 ])
44 } 44 }
45 45
@@ -47,7 +47,7 @@ describe('Test video NSFW policy', function () {
47 getVideosList(server.url), 47 getVideosList(server.url),
48 searchVideo(server.url, 'n'), 48 searchVideo(server.url, 'n'),
49 getAccountVideos(server.url, undefined, accountUUID, 0, 5), 49 getAccountVideos(server.url, undefined, accountUUID, 0, 5),
50 getVideoChannelVideos(server.url, undefined, accountUUID, videoChannelUUID, 0, 5) 50 getVideoChannelVideos(server.url, undefined, videoChannelUUID, 0, 5)
51 ]) 51 ])
52 }) 52 })
53 } 53 }
diff --git a/server/tests/utils/videos/video-channels.ts b/server/tests/utils/videos/video-channels.ts
index 0b4fa89b7..978e21b19 100644
--- a/server/tests/utils/videos/video-channels.ts
+++ b/server/tests/utils/videos/video-channels.ts
@@ -34,11 +34,10 @@ function getAccountVideoChannelsList (url: string, accountId: number | string, s
34function addVideoChannel ( 34function addVideoChannel (
35 url: string, 35 url: string,
36 token: string, 36 token: string,
37 accountId: number | string,
38 videoChannelAttributesArg: VideoChannelAttributes, 37 videoChannelAttributesArg: VideoChannelAttributes,
39 expectedStatus = 200 38 expectedStatus = 200
40) { 39) {
41 const path = '/api/v1/accounts/' + accountId + '/video-channels/' 40 const path = '/api/v1/video-channels/'
42 41
43 // Default attributes 42 // Default attributes
44 let attributes = { 43 let attributes = {
@@ -59,13 +58,12 @@ function addVideoChannel (
59function updateVideoChannel ( 58function updateVideoChannel (
60 url: string, 59 url: string,
61 token: string, 60 token: string,
62 accountId: number | string,
63 channelId: number | string, 61 channelId: number | string,
64 attributes: VideoChannelAttributes, 62 attributes: VideoChannelAttributes,
65 expectedStatus = 204 63 expectedStatus = 204
66) { 64) {
67 const body = {} 65 const body = {}
68 const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId 66 const path = '/api/v1/video-channels/' + channelId
69 67
70 if (attributes.name) body['name'] = attributes.name 68 if (attributes.name) body['name'] = attributes.name
71 if (attributes.description) body['description'] = attributes.description 69 if (attributes.description) body['description'] = attributes.description
@@ -79,8 +77,8 @@ function updateVideoChannel (
79 .expect(expectedStatus) 77 .expect(expectedStatus)
80} 78}
81 79
82function deleteVideoChannel (url: string, token: string, accountId: number | string, channelId: number | string, expectedStatus = 204) { 80function deleteVideoChannel (url: string, token: string, channelId: number | string, expectedStatus = 204) {
83 const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId 81 const path = '/api/v1/video-channels/' + channelId
84 82
85 return request(url) 83 return request(url)
86 .delete(path) 84 .delete(path)
@@ -89,8 +87,8 @@ function deleteVideoChannel (url: string, token: string, accountId: number | str
89 .expect(expectedStatus) 87 .expect(expectedStatus)
90} 88}
91 89
92function getVideoChannel (url: string, accountId: number | string, channelId: number | string) { 90function getVideoChannel (url: string, channelId: number | string) {
93 const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId 91 const path = '/api/v1/video-channels/' + channelId
94 92
95 return request(url) 93 return request(url)
96 .get(path) 94 .get(path)
diff --git a/server/tests/utils/videos/videos.ts b/server/tests/utils/videos/videos.ts
index d1d8c07df..870dfd21f 100644
--- a/server/tests/utils/videos/videos.ts
+++ b/server/tests/utils/videos/videos.ts
@@ -186,13 +186,12 @@ function getAccountVideos (url: string, accessToken: string, accountId: number |
186function getVideoChannelVideos ( 186function getVideoChannelVideos (
187 url: string, 187 url: string,
188 accessToken: string, 188 accessToken: string,
189 accountId: number | string,
190 videoChannelId: number | string, 189 videoChannelId: number | string,
191 start: number, 190 start: number,
192 count: number, 191 count: number,
193 sort?: string 192 sort?: string
194) { 193) {
195 const path = '/api/v1/accounts/' + accountId + '/video-channels/' + videoChannelId + '/videos' 194 const path = '/api/v1/video-channels/' + videoChannelId + '/videos'
196 195
197 return makeGetRequest({ 196 return makeGetRequest({
198 url, 197 url,