diff options
author | Chocobozzz <me@florianbigard.com> | 2018-04-24 17:05:32 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-04-24 17:12:57 +0200 |
commit | 48dce1c90dff4e90a4bcffefaecf157336cf904b (patch) | |
tree | 478de23812d0bfd93f47e9ad6ad8888c9edcc235 | |
parent | 82e392f8a42a19815e932dd386e96e61ebe6d191 (diff) | |
download | PeerTube-48dce1c90dff4e90a4bcffefaecf157336cf904b.tar.gz PeerTube-48dce1c90dff4e90a4bcffefaecf157336cf904b.tar.zst PeerTube-48dce1c90dff4e90a4bcffefaecf157336cf904b.zip |
Update video channel routes
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | server/controllers/api/accounts.ts | 209 | ||||
-rw-r--r-- | server/controllers/api/index.ts | 2 | ||||
-rw-r--r-- | server/controllers/api/video-channel.ts | 34 | ||||
-rw-r--r-- | server/controllers/api/videos/channel.ts | 177 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 17 | ||||
-rw-r--r-- | server/controllers/feeds.ts | 14 | ||||
-rw-r--r-- | server/middlewares/validators/follows.ts | 2 | ||||
-rw-r--r-- | server/middlewares/validators/video-channels.ts | 8 | ||||
-rw-r--r-- | server/models/video/video.ts | 92 | ||||
-rw-r--r-- | server/tests/api/check-params/video-channels.ts | 101 | ||||
-rw-r--r-- | server/tests/api/videos/multiple-servers.ts | 21 | ||||
-rw-r--r-- | server/tests/api/videos/video-channels.ts | 15 | ||||
-rw-r--r-- | server/tests/utils/videos/video-channels.ts | 35 | ||||
-rw-r--r-- | support/doc/api/html/index.html | 543 | ||||
-rw-r--r-- | support/doc/api/openapi.yaml | 72 |
16 files changed, 859 insertions, 486 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 470b4f295..ac3f61735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md | |||
@@ -5,6 +5,9 @@ | |||
5 | ### BREAKING CHANGES | 5 | ### BREAKING CHANGES |
6 | 6 | ||
7 | * Hide by default NSFW videos. Update the `instance.default_nsfw_policy` configuration to `blur` to keep the old behaviour | 7 | * Hide by default NSFW videos. Update the `instance.default_nsfw_policy` configuration to `blur` to keep the old behaviour |
8 | * Move video channels routes: | ||
9 | * `/videos/channels` routes to `/accounts/{accountId}/video-channels` | ||
10 | * `/videos/accounts/{accountId}/channels` route to `/accounts/{accountId}/video-channels` | ||
8 | * PeerTube now listen on 127.0.0.1 by default | 11 | * PeerTube now listen on 127.0.0.1 by default |
9 | * Use ISO 639 for language (*en*, *es*, *fr*...) | 12 | * Use ISO 639 for language (*en*, *es*, *fr*...) |
10 | * Tools (`import-videos`...) need the language ISO639 code instead of a number | 13 | * Tools (`import-videos`...) need the language ISO639 code instead of a number |
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 06ab04033..04c5897c5 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts | |||
@@ -1,11 +1,30 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { getFormattedObjects } from '../../helpers/utils' | 2 | import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils' |
3 | import { asyncMiddleware, optionalAuthenticate, paginationValidator, setDefaultPagination, setDefaultSort } from '../../middlewares' | 3 | import { |
4 | asyncMiddleware, | ||
5 | authenticate, | ||
6 | listVideoAccountChannelsValidator, | ||
7 | optionalAuthenticate, | ||
8 | paginationValidator, | ||
9 | setDefaultPagination, | ||
10 | setDefaultSort, | ||
11 | videoChannelsAddValidator, | ||
12 | videoChannelsGetValidator, | ||
13 | videoChannelsRemoveValidator, | ||
14 | videoChannelsUpdateValidator | ||
15 | } from '../../middlewares' | ||
4 | import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators' | 16 | import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators' |
5 | import { AccountModel } from '../../models/account/account' | 17 | import { AccountModel } from '../../models/account/account' |
6 | import { VideoModel } from '../../models/video/video' | 18 | import { VideoModel } from '../../models/video/video' |
7 | import { VideoSortField } from '../../../client/src/app/shared/video/sort-field.type' | ||
8 | import { isNSFWHidden } from '../../helpers/express-utils' | 19 | import { isNSFWHidden } from '../../helpers/express-utils' |
20 | import { VideoChannelModel } from '../../models/video/video-channel' | ||
21 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' | ||
22 | import { sendUpdateActor } from '../../lib/activitypub/send' | ||
23 | import { createVideoChannel } from '../../lib/video-channel' | ||
24 | import { setAsyncActorKeys } from '../../lib/activitypub' | ||
25 | import { sequelizeTypescript } from '../../initializers' | ||
26 | import { logger } from '../../helpers/logger' | ||
27 | import { retryTransactionWrapper } from '../../helpers/database-utils' | ||
9 | 28 | ||
10 | const accountsRouter = express.Router() | 29 | const accountsRouter = express.Router() |
11 | 30 | ||
@@ -29,7 +48,45 @@ accountsRouter.get('/:id/videos', | |||
29 | setDefaultSort, | 48 | setDefaultSort, |
30 | setDefaultPagination, | 49 | setDefaultPagination, |
31 | optionalAuthenticate, | 50 | optionalAuthenticate, |
32 | asyncMiddleware(getAccountVideos) | 51 | asyncMiddleware(listAccountVideos) |
52 | ) | ||
53 | |||
54 | accountsRouter.get('/:accountId/video-channels', | ||
55 | asyncMiddleware(listVideoAccountChannelsValidator), | ||
56 | asyncMiddleware(listVideoAccountChannels) | ||
57 | ) | ||
58 | |||
59 | accountsRouter.post('/:accountId/video-channels', | ||
60 | authenticate, | ||
61 | videoChannelsAddValidator, | ||
62 | asyncMiddleware(addVideoChannelRetryWrapper) | ||
63 | ) | ||
64 | |||
65 | accountsRouter.put('/:accountId/video-channels/:id', | ||
66 | authenticate, | ||
67 | asyncMiddleware(videoChannelsUpdateValidator), | ||
68 | updateVideoChannelRetryWrapper | ||
69 | ) | ||
70 | |||
71 | accountsRouter.delete('/:accountId/video-channels/:id', | ||
72 | authenticate, | ||
73 | asyncMiddleware(videoChannelsRemoveValidator), | ||
74 | asyncMiddleware(removeVideoChannelRetryWrapper) | ||
75 | ) | ||
76 | |||
77 | accountsRouter.get('/:accountId/video-channels/:id', | ||
78 | asyncMiddleware(videoChannelsGetValidator), | ||
79 | asyncMiddleware(getVideoChannel) | ||
80 | ) | ||
81 | |||
82 | accountsRouter.get('/:accountId/video-channels/:id/videos', | ||
83 | asyncMiddleware(videoChannelsGetValidator), | ||
84 | paginationValidator, | ||
85 | videosSortValidator, | ||
86 | setDefaultSort, | ||
87 | setDefaultPagination, | ||
88 | optionalAuthenticate, | ||
89 | asyncMiddleware(listVideoChannelVideos) | ||
33 | ) | 90 | ) |
34 | 91 | ||
35 | // --------------------------------------------------------------------------- | 92 | // --------------------------------------------------------------------------- |
@@ -52,18 +109,142 @@ async function listAccounts (req: express.Request, res: express.Response, next: | |||
52 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 109 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
53 | } | 110 | } |
54 | 111 | ||
55 | async function getAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 112 | async function listVideoAccountChannels (req: express.Request, res: express.Response, next: express.NextFunction) { |
113 | const resultList = await VideoChannelModel.listByAccount(res.locals.account.id) | ||
114 | |||
115 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
116 | } | ||
117 | |||
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 | ||
120 | async 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 | } | ||
131 | }).end() | ||
132 | } | ||
133 | |||
134 | async function addVideoChannel (req: express.Request, res: express.Response) { | ||
135 | const videoChannelInfo: VideoChannelCreate = req.body | ||
136 | const account: AccountModel = res.locals.oauth.token.User.Account | ||
137 | |||
138 | const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => { | ||
139 | return createVideoChannel(videoChannelInfo, account, t) | ||
140 | }) | ||
141 | |||
142 | setAsyncActorKeys(videoChannelCreated.Actor) | ||
143 | .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err })) | ||
144 | |||
145 | logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid) | ||
146 | |||
147 | return videoChannelCreated | ||
148 | } | ||
149 | |||
150 | async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
151 | const options = { | ||
152 | arguments: [ req, res ], | ||
153 | errorMessage: 'Cannot update the video with many retries.' | ||
154 | } | ||
155 | |||
156 | await retryTransactionWrapper(updateVideoChannel, options) | ||
157 | |||
158 | return res.type('json').status(204).end() | ||
159 | } | ||
160 | |||
161 | async function updateVideoChannel (req: express.Request, res: express.Response) { | ||
162 | const videoChannelInstance = res.locals.videoChannel as VideoChannelModel | ||
163 | const videoChannelFieldsSave = videoChannelInstance.toJSON() | ||
164 | const videoChannelInfoToUpdate = req.body as VideoChannelUpdate | ||
165 | |||
166 | try { | ||
167 | await sequelizeTypescript.transaction(async t => { | ||
168 | const sequelizeOptions = { | ||
169 | transaction: t | ||
170 | } | ||
171 | |||
172 | if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name) | ||
173 | if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description) | ||
174 | if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support) | ||
175 | |||
176 | const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) | ||
177 | await sendUpdateActor(videoChannelInstanceUpdated, t) | ||
178 | }) | ||
179 | |||
180 | logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) | ||
181 | } catch (err) { | ||
182 | logger.debug('Cannot update the video channel.', { err }) | ||
183 | |||
184 | // Force fields we want to update | ||
185 | // If the transaction is retried, sequelize will think the object has not changed | ||
186 | // So it will skip the SQL request, even if the last one was ROLLBACKed! | ||
187 | resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave) | ||
188 | |||
189 | throw err | ||
190 | } | ||
191 | } | ||
192 | |||
193 | async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
194 | const options = { | ||
195 | arguments: [ req, res ], | ||
196 | errorMessage: 'Cannot remove the video channel with many retries.' | ||
197 | } | ||
198 | |||
199 | await retryTransactionWrapper(removeVideoChannel, options) | ||
200 | |||
201 | return res.type('json').status(204).end() | ||
202 | } | ||
203 | |||
204 | async function removeVideoChannel (req: express.Request, res: express.Response) { | ||
205 | const videoChannelInstance: VideoChannelModel = res.locals.videoChannel | ||
206 | |||
207 | return sequelizeTypescript.transaction(async t => { | ||
208 | await videoChannelInstance.destroy({ transaction: t }) | ||
209 | |||
210 | logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) | ||
211 | }) | ||
212 | |||
213 | } | ||
214 | |||
215 | async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
216 | const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id) | ||
217 | |||
218 | return res.json(videoChannelWithVideos.toFormattedJSON()) | ||
219 | } | ||
220 | |||
221 | async function listVideoChannelVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
222 | const videoChannelInstance: VideoChannelModel = res.locals.videoChannel | ||
223 | |||
224 | const resultList = await VideoModel.listForApi({ | ||
225 | start: req.query.start, | ||
226 | count: req.query.count, | ||
227 | sort: req.query.sort, | ||
228 | hideNSFW: isNSFWHidden(res), | ||
229 | withFiles: false, | ||
230 | videoChannelId: videoChannelInstance.id | ||
231 | }) | ||
232 | |||
233 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
234 | } | ||
235 | |||
236 | |||
237 | async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
56 | const account: AccountModel = res.locals.account | 238 | const account: AccountModel = res.locals.account |
57 | 239 | ||
58 | const resultList = await VideoModel.listForApi( | 240 | const resultList = await VideoModel.listForApi({ |
59 | req.query.start as number, | 241 | start: req.query.start, |
60 | req.query.count as number, | 242 | count: req.query.count, |
61 | req.query.sort as VideoSortField, | 243 | sort: req.query.sort, |
62 | isNSFWHidden(res), | 244 | hideNSFW: isNSFWHidden(res), |
63 | null, | 245 | withFiles: false, |
64 | false, | 246 | accountId: account.id |
65 | account.id | 247 | }) |
66 | ) | ||
67 | 248 | ||
68 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 249 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
69 | } | 250 | } |
diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts index 964d5d04c..8f63b9535 100644 --- a/server/controllers/api/index.ts +++ b/server/controllers/api/index.ts | |||
@@ -7,6 +7,7 @@ import { usersRouter } from './users' | |||
7 | import { accountsRouter } from './accounts' | 7 | import { accountsRouter } from './accounts' |
8 | import { videosRouter } from './videos' | 8 | import { videosRouter } from './videos' |
9 | import { badRequest } from '../../helpers/express-utils' | 9 | import { badRequest } from '../../helpers/express-utils' |
10 | import { videoChannelRouter } from './video-channel' | ||
10 | 11 | ||
11 | const apiRouter = express.Router() | 12 | const apiRouter = express.Router() |
12 | 13 | ||
@@ -15,6 +16,7 @@ apiRouter.use('/oauth-clients', oauthClientsRouter) | |||
15 | apiRouter.use('/config', configRouter) | 16 | apiRouter.use('/config', configRouter) |
16 | apiRouter.use('/users', usersRouter) | 17 | apiRouter.use('/users', usersRouter) |
17 | apiRouter.use('/accounts', accountsRouter) | 18 | apiRouter.use('/accounts', accountsRouter) |
19 | apiRouter.use('/video-channels', videoChannelRouter) | ||
18 | apiRouter.use('/videos', videosRouter) | 20 | apiRouter.use('/videos', videosRouter) |
19 | apiRouter.use('/jobs', jobsRouter) | 21 | apiRouter.use('/jobs', jobsRouter) |
20 | apiRouter.use('/ping', pong) | 22 | apiRouter.use('/ping', pong) |
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts new file mode 100644 index 000000000..d57273747 --- /dev/null +++ b/server/controllers/api/video-channel.ts | |||
@@ -0,0 +1,34 @@ | |||
1 | import * as express from 'express' | ||
2 | import { getFormattedObjects } from '../../helpers/utils' | ||
3 | import { | ||
4 | asyncMiddleware, | ||
5 | paginationValidator, | ||
6 | setDefaultPagination, | ||
7 | setDefaultSort, | ||
8 | videoChannelsSortValidator | ||
9 | } from '../../middlewares' | ||
10 | import { VideoChannelModel } from '../../models/video/video-channel' | ||
11 | |||
12 | const videoChannelRouter = express.Router() | ||
13 | |||
14 | videoChannelRouter.get('/', | ||
15 | paginationValidator, | ||
16 | videoChannelsSortValidator, | ||
17 | setDefaultSort, | ||
18 | setDefaultPagination, | ||
19 | asyncMiddleware(listVideoChannels) | ||
20 | ) | ||
21 | |||
22 | // --------------------------------------------------------------------------- | ||
23 | |||
24 | export { | ||
25 | videoChannelRouter | ||
26 | } | ||
27 | |||
28 | // --------------------------------------------------------------------------- | ||
29 | |||
30 | async function listVideoChannels (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
31 | const resultList = await VideoChannelModel.listForApi(req.query.start, req.query.count, req.query.sort) | ||
32 | |||
33 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
34 | } | ||
diff --git a/server/controllers/api/videos/channel.ts b/server/controllers/api/videos/channel.ts deleted file mode 100644 index e547d375f..000000000 --- a/server/controllers/api/videos/channel.ts +++ /dev/null | |||
@@ -1,177 +0,0 @@ | |||
1 | import * as express from 'express' | ||
2 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../../shared' | ||
3 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | ||
4 | import { logger } from '../../../helpers/logger' | ||
5 | import { getFormattedObjects, resetSequelizeInstance } from '../../../helpers/utils' | ||
6 | import { sequelizeTypescript } from '../../../initializers' | ||
7 | import { setAsyncActorKeys } from '../../../lib/activitypub' | ||
8 | import { sendUpdateActor } from '../../../lib/activitypub/send' | ||
9 | import { createVideoChannel } from '../../../lib/video-channel' | ||
10 | import { | ||
11 | asyncMiddleware, authenticate, listVideoAccountChannelsValidator, paginationValidator, setDefaultSort, setDefaultPagination, | ||
12 | videoChannelsAddValidator, videoChannelsGetValidator, videoChannelsRemoveValidator, videoChannelsSortValidator, | ||
13 | videoChannelsUpdateValidator | ||
14 | } from '../../../middlewares' | ||
15 | import { AccountModel } from '../../../models/account/account' | ||
16 | import { VideoChannelModel } from '../../../models/video/video-channel' | ||
17 | |||
18 | const videoChannelRouter = express.Router() | ||
19 | |||
20 | videoChannelRouter.get('/channels', | ||
21 | paginationValidator, | ||
22 | videoChannelsSortValidator, | ||
23 | setDefaultSort, | ||
24 | setDefaultPagination, | ||
25 | asyncMiddleware(listVideoChannels) | ||
26 | ) | ||
27 | |||
28 | videoChannelRouter.get('/accounts/:accountId/channels', | ||
29 | asyncMiddleware(listVideoAccountChannelsValidator), | ||
30 | asyncMiddleware(listVideoAccountChannels) | ||
31 | ) | ||
32 | |||
33 | videoChannelRouter.post('/channels', | ||
34 | authenticate, | ||
35 | videoChannelsAddValidator, | ||
36 | asyncMiddleware(addVideoChannelRetryWrapper) | ||
37 | ) | ||
38 | |||
39 | videoChannelRouter.put('/channels/:id', | ||
40 | authenticate, | ||
41 | asyncMiddleware(videoChannelsUpdateValidator), | ||
42 | updateVideoChannelRetryWrapper | ||
43 | ) | ||
44 | |||
45 | videoChannelRouter.delete('/channels/:id', | ||
46 | authenticate, | ||
47 | asyncMiddleware(videoChannelsRemoveValidator), | ||
48 | asyncMiddleware(removeVideoChannelRetryWrapper) | ||
49 | ) | ||
50 | |||
51 | videoChannelRouter.get('/channels/:id', | ||
52 | asyncMiddleware(videoChannelsGetValidator), | ||
53 | asyncMiddleware(getVideoChannel) | ||
54 | ) | ||
55 | |||
56 | // --------------------------------------------------------------------------- | ||
57 | |||
58 | export { | ||
59 | videoChannelRouter | ||
60 | } | ||
61 | |||
62 | // --------------------------------------------------------------------------- | ||
63 | |||
64 | async function listVideoChannels (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
65 | const resultList = await VideoChannelModel.listForApi(req.query.start, req.query.count, req.query.sort) | ||
66 | |||
67 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
68 | } | ||
69 | |||
70 | async function listVideoAccountChannels (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
71 | const resultList = await VideoChannelModel.listByAccount(res.locals.account.id) | ||
72 | |||
73 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
74 | } | ||
75 | |||
76 | // Wrapper to video channel add that retry the async function if there is a database error | ||
77 | // We need this because we run the transaction in SERIALIZABLE isolation that can fail | ||
78 | async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
79 | const options = { | ||
80 | arguments: [ req, res ], | ||
81 | errorMessage: 'Cannot insert the video video channel with many retries.' | ||
82 | } | ||
83 | |||
84 | const videoChannel = await retryTransactionWrapper(addVideoChannel, options) | ||
85 | return res.json({ | ||
86 | videoChannel: { | ||
87 | id: videoChannel.id | ||
88 | } | ||
89 | }).end() | ||
90 | } | ||
91 | |||
92 | async function addVideoChannel (req: express.Request, res: express.Response) { | ||
93 | const videoChannelInfo: VideoChannelCreate = req.body | ||
94 | const account: AccountModel = res.locals.oauth.token.User.Account | ||
95 | |||
96 | const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => { | ||
97 | return createVideoChannel(videoChannelInfo, account, t) | ||
98 | }) | ||
99 | |||
100 | setAsyncActorKeys(videoChannelCreated.Actor) | ||
101 | .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err })) | ||
102 | |||
103 | logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid) | ||
104 | |||
105 | return videoChannelCreated | ||
106 | } | ||
107 | |||
108 | async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
109 | const options = { | ||
110 | arguments: [ req, res ], | ||
111 | errorMessage: 'Cannot update the video with many retries.' | ||
112 | } | ||
113 | |||
114 | await retryTransactionWrapper(updateVideoChannel, options) | ||
115 | |||
116 | return res.type('json').status(204).end() | ||
117 | } | ||
118 | |||
119 | async function updateVideoChannel (req: express.Request, res: express.Response) { | ||
120 | const videoChannelInstance = res.locals.videoChannel as VideoChannelModel | ||
121 | const videoChannelFieldsSave = videoChannelInstance.toJSON() | ||
122 | const videoChannelInfoToUpdate = req.body as VideoChannelUpdate | ||
123 | |||
124 | try { | ||
125 | await sequelizeTypescript.transaction(async t => { | ||
126 | const sequelizeOptions = { | ||
127 | transaction: t | ||
128 | } | ||
129 | |||
130 | if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name) | ||
131 | if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description) | ||
132 | if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support) | ||
133 | |||
134 | const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions) | ||
135 | await sendUpdateActor(videoChannelInstanceUpdated, t) | ||
136 | }) | ||
137 | |||
138 | logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) | ||
139 | } catch (err) { | ||
140 | logger.debug('Cannot update the video channel.', { err }) | ||
141 | |||
142 | // Force fields we want to update | ||
143 | // If the transaction is retried, sequelize will think the object has not changed | ||
144 | // So it will skip the SQL request, even if the last one was ROLLBACKed! | ||
145 | resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave) | ||
146 | |||
147 | throw err | ||
148 | } | ||
149 | } | ||
150 | |||
151 | async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
152 | const options = { | ||
153 | arguments: [ req, res ], | ||
154 | errorMessage: 'Cannot remove the video channel with many retries.' | ||
155 | } | ||
156 | |||
157 | await retryTransactionWrapper(removeVideoChannel, options) | ||
158 | |||
159 | return res.type('json').status(204).end() | ||
160 | } | ||
161 | |||
162 | async function removeVideoChannel (req: express.Request, res: express.Response) { | ||
163 | const videoChannelInstance: VideoChannelModel = res.locals.videoChannel | ||
164 | |||
165 | return sequelizeTypescript.transaction(async t => { | ||
166 | await videoChannelInstance.destroy({ transaction: t }) | ||
167 | |||
168 | logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid) | ||
169 | }) | ||
170 | |||
171 | } | ||
172 | |||
173 | async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
174 | const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id) | ||
175 | |||
176 | return res.json(videoChannelWithVideos.toFormattedJSON()) | ||
177 | } | ||
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 61b6c5826..4b3198a74 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -42,7 +42,6 @@ import { VideoModel } from '../../../models/video/video' | |||
42 | import { VideoFileModel } from '../../../models/video/video-file' | 42 | import { VideoFileModel } from '../../../models/video/video-file' |
43 | import { abuseVideoRouter } from './abuse' | 43 | import { abuseVideoRouter } from './abuse' |
44 | import { blacklistRouter } from './blacklist' | 44 | import { blacklistRouter } from './blacklist' |
45 | import { videoChannelRouter } from './channel' | ||
46 | import { videoCommentRouter } from './comment' | 45 | import { videoCommentRouter } from './comment' |
47 | import { rateVideoRouter } from './rate' | 46 | import { rateVideoRouter } from './rate' |
48 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' | 47 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' |
@@ -72,7 +71,6 @@ const reqVideoFileUpdate = createReqFiles( | |||
72 | videosRouter.use('/', abuseVideoRouter) | 71 | videosRouter.use('/', abuseVideoRouter) |
73 | videosRouter.use('/', blacklistRouter) | 72 | videosRouter.use('/', blacklistRouter) |
74 | videosRouter.use('/', rateVideoRouter) | 73 | videosRouter.use('/', rateVideoRouter) |
75 | videosRouter.use('/', videoChannelRouter) | ||
76 | videosRouter.use('/', videoCommentRouter) | 74 | videosRouter.use('/', videoCommentRouter) |
77 | 75 | ||
78 | videosRouter.get('/categories', listVideoCategories) | 76 | videosRouter.get('/categories', listVideoCategories) |
@@ -397,13 +395,14 @@ async function getVideoDescription (req: express.Request, res: express.Response) | |||
397 | } | 395 | } |
398 | 396 | ||
399 | async function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 397 | async function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) { |
400 | const resultList = await VideoModel.listForApi( | 398 | const resultList = await VideoModel.listForApi({ |
401 | req.query.start as number, | 399 | start: req.query.start, |
402 | req.query.count as number, | 400 | count: req.query.count, |
403 | req.query.sort as VideoSortField, | 401 | sort: req.query.sort, |
404 | isNSFWHidden(res), | 402 | hideNSFW: isNSFWHidden(res), |
405 | req.query.filter as VideoFilter | 403 | filter: req.query.filter as VideoFilter, |
406 | ) | 404 | withFiles: false |
405 | }) | ||
407 | 406 | ||
408 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 407 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
409 | } | 408 | } |
diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts index 6a6af3e09..7dcaf7004 100644 --- a/server/controllers/feeds.ts +++ b/server/controllers/feeds.ts | |||
@@ -33,15 +33,15 @@ async function generateFeed (req: express.Request, res: express.Response, next: | |||
33 | const account: AccountModel = res.locals.account | 33 | const account: AccountModel = res.locals.account |
34 | const hideNSFW = CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list' | 34 | const hideNSFW = CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list' |
35 | 35 | ||
36 | const resultList = await VideoModel.listForApi( | 36 | const resultList = await VideoModel.listForApi({ |
37 | start, | 37 | start, |
38 | FEEDS.COUNT, | 38 | count: FEEDS.COUNT, |
39 | req.query.sort as VideoSortField, | 39 | sort: req.query.sort, |
40 | hideNSFW, | 40 | hideNSFW, |
41 | req.query.filter, | 41 | filter: req.query.filter, |
42 | true, | 42 | withFiles: true, |
43 | account ? account.id : null | 43 | accountId: account ? account.id : null |
44 | ) | 44 | }) |
45 | 45 | ||
46 | // Adding video items to the feed, one at a time | 46 | // Adding video items to the feed, one at a time |
47 | resultList.data.forEach(video => { | 47 | resultList.data.forEach(video => { |
diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts index 991a2e175..bdf39eb9c 100644 --- a/server/middlewares/validators/follows.ts +++ b/server/middlewares/validators/follows.ts | |||
@@ -16,7 +16,7 @@ const followValidator = [ | |||
16 | if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') { | 16 | if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') { |
17 | return res.status(400) | 17 | return res.status(400) |
18 | .json({ | 18 | .json({ |
19 | error: 'Cannot follow non HTTPS web server.' | 19 | error: 'Cannot follow on a non HTTPS web server.' |
20 | }) | 20 | }) |
21 | .end() | 21 | .end() |
22 | } | 22 | } |
diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts index fe42105e8..e3a11a41b 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/video-channels.ts | |||
@@ -26,6 +26,7 @@ const listVideoAccountChannelsValidator = [ | |||
26 | ] | 26 | ] |
27 | 27 | ||
28 | const videoChannelsAddValidator = [ | 28 | const videoChannelsAddValidator = [ |
29 | param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'), | ||
29 | body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'), | 30 | body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'), |
30 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), | 31 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), |
31 | 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'), |
@@ -41,6 +42,7 @@ const videoChannelsAddValidator = [ | |||
41 | 42 | ||
42 | const videoChannelsUpdateValidator = [ | 43 | const videoChannelsUpdateValidator = [ |
43 | 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'), |
45 | param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'), | ||
44 | body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'), | 46 | body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'), |
45 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), | 47 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), |
46 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), | 48 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), |
@@ -49,6 +51,7 @@ const videoChannelsUpdateValidator = [ | |||
49 | logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) | 51 | logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) |
50 | 52 | ||
51 | if (areValidationErrors(req, res)) return | 53 | if (areValidationErrors(req, res)) return |
54 | if (!await isAccountIdExist(req.params.accountId, res)) return | ||
52 | if (!await isVideoChannelExist(req.params.id, res)) return | 55 | if (!await isVideoChannelExist(req.params.id, res)) return |
53 | 56 | ||
54 | // We need to make additional checks | 57 | // We need to make additional checks |
@@ -70,11 +73,13 @@ const videoChannelsUpdateValidator = [ | |||
70 | 73 | ||
71 | const videoChannelsRemoveValidator = [ | 74 | const videoChannelsRemoveValidator = [ |
72 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 75 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
76 | param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'), | ||
73 | 77 | ||
74 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 78 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
75 | logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params }) | 79 | logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params }) |
76 | 80 | ||
77 | if (areValidationErrors(req, res)) return | 81 | if (areValidationErrors(req, res)) return |
82 | if (!await isAccountIdExist(req.params.accountId, res)) return | ||
78 | if (!await isVideoChannelExist(req.params.id, res)) return | 83 | if (!await isVideoChannelExist(req.params.id, res)) return |
79 | 84 | ||
80 | // Check if the user who did the request is able to delete the video | 85 | // Check if the user who did the request is able to delete the video |
@@ -87,11 +92,14 @@ const videoChannelsRemoveValidator = [ | |||
87 | 92 | ||
88 | const videoChannelsGetValidator = [ | 93 | const videoChannelsGetValidator = [ |
89 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 94 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), |
95 | param('accountId').optional().custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'), | ||
90 | 96 | ||
91 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 97 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
92 | logger.debug('Checking videoChannelsGet parameters', { parameters: req.params }) | 98 | logger.debug('Checking videoChannelsGet parameters', { parameters: req.params }) |
93 | 99 | ||
94 | if (areValidationErrors(req, res)) return | 100 | if (areValidationErrors(req, res)) return |
101 | // On some routes, accountId is optional (for example in the ActivityPub route) | ||
102 | if (req.params.accountId && !await isAccountIdExist(req.params.accountId, res)) return | ||
95 | if (!await isVideoChannelExist(req.params.id, res)) return | 103 | if (!await isVideoChannelExist(req.params.id, res)) return |
96 | 104 | ||
97 | return next() | 105 | return next() |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 2ad9c00dd..7ababbf23 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -95,7 +95,14 @@ enum ScopeNames { | |||
95 | } | 95 | } |
96 | 96 | ||
97 | @Scopes({ | 97 | @Scopes({ |
98 | [ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, hideNSFW: boolean, filter?: VideoFilter, withFiles?: boolean, accountId?: number) => { | 98 | [ScopeNames.AVAILABLE_FOR_LIST]: (options: { |
99 | actorId: number, | ||
100 | hideNSFW: boolean, | ||
101 | filter?: VideoFilter, | ||
102 | withFiles?: boolean, | ||
103 | accountId?: number, | ||
104 | videoChannelId?: number | ||
105 | }) => { | ||
99 | const accountInclude = { | 106 | const accountInclude = { |
100 | attributes: [ 'name' ], | 107 | attributes: [ 'name' ], |
101 | model: AccountModel.unscoped(), | 108 | model: AccountModel.unscoped(), |
@@ -106,7 +113,7 @@ enum ScopeNames { | |||
106 | attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ], | 113 | attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ], |
107 | model: ActorModel.unscoped(), | 114 | model: ActorModel.unscoped(), |
108 | required: true, | 115 | required: true, |
109 | where: VideoModel.buildActorWhereWithFilter(filter), | 116 | where: VideoModel.buildActorWhereWithFilter(options.filter), |
110 | include: [ | 117 | include: [ |
111 | { | 118 | { |
112 | attributes: [ 'host' ], | 119 | attributes: [ 'host' ], |
@@ -122,6 +129,18 @@ enum ScopeNames { | |||
122 | ] | 129 | ] |
123 | } | 130 | } |
124 | 131 | ||
132 | const videoChannelInclude = { | ||
133 | attributes: [ 'name', 'description' ], | ||
134 | model: VideoChannelModel.unscoped(), | ||
135 | required: true, | ||
136 | where: {}, | ||
137 | include: [ | ||
138 | accountInclude | ||
139 | ] | ||
140 | } | ||
141 | |||
142 | // Force actorId to be a number to avoid SQL injections | ||
143 | const actorIdNumber = parseInt(options.actorId.toString(), 10) | ||
125 | const query: IFindOptions<VideoModel> = { | 144 | const query: IFindOptions<VideoModel> = { |
126 | where: { | 145 | where: { |
127 | id: { | 146 | id: { |
@@ -132,32 +151,23 @@ enum ScopeNames { | |||
132 | '(' + | 151 | '(' + |
133 | 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + | 152 | 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + |
134 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + | 153 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + |
135 | 'WHERE "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) + | 154 | 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + |
136 | ' UNION ' + | 155 | ' UNION ' + |
137 | 'SELECT "video"."id" AS "id" FROM "video" ' + | 156 | 'SELECT "video"."id" AS "id" FROM "video" ' + |
138 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + | 157 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + |
139 | 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + | 158 | 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + |
140 | 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + | 159 | 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + |
141 | 'LEFT JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + | 160 | 'LEFT JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + |
142 | 'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) + | 161 | 'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + actorIdNumber + |
143 | ')' | 162 | ')' |
144 | ) | 163 | ) |
145 | }, | 164 | }, |
146 | privacy: VideoPrivacy.PUBLIC | 165 | privacy: VideoPrivacy.PUBLIC |
147 | }, | 166 | }, |
148 | include: [ | 167 | include: [ videoChannelInclude ] |
149 | { | ||
150 | attributes: [ 'name', 'description' ], | ||
151 | model: VideoChannelModel.unscoped(), | ||
152 | required: true, | ||
153 | include: [ | ||
154 | accountInclude | ||
155 | ] | ||
156 | } | ||
157 | ] | ||
158 | } | 168 | } |
159 | 169 | ||
160 | if (withFiles === true) { | 170 | if (options.withFiles === true) { |
161 | query.include.push({ | 171 | query.include.push({ |
162 | model: VideoFileModel.unscoped(), | 172 | model: VideoFileModel.unscoped(), |
163 | required: true | 173 | required: true |
@@ -165,13 +175,19 @@ enum ScopeNames { | |||
165 | } | 175 | } |
166 | 176 | ||
167 | // Hide nsfw videos? | 177 | // Hide nsfw videos? |
168 | if (hideNSFW === true) { | 178 | if (options.hideNSFW === true) { |
169 | query.where['nsfw'] = false | 179 | query.where['nsfw'] = false |
170 | } | 180 | } |
171 | 181 | ||
172 | if (accountId) { | 182 | if (options.accountId) { |
173 | accountInclude.where = { | 183 | accountInclude.where = { |
174 | id: accountId | 184 | id: options.accountId |
185 | } | ||
186 | } | ||
187 | |||
188 | if (options.videoChannelId) { | ||
189 | videoChannelInclude.where = { | ||
190 | id: options.videoChannelId | ||
175 | } | 191 | } |
176 | } | 192 | } |
177 | 193 | ||
@@ -697,23 +713,37 @@ export class VideoModel extends Model<VideoModel> { | |||
697 | }) | 713 | }) |
698 | } | 714 | } |
699 | 715 | ||
700 | static async listForApi ( | 716 | static async listForApi (options: { |
701 | start: number, | 717 | start: number, |
702 | count: number, | 718 | count: number, |
703 | sort: string, | 719 | sort: string, |
704 | hideNSFW: boolean, | 720 | hideNSFW: boolean, |
721 | withFiles: boolean, | ||
705 | filter?: VideoFilter, | 722 | filter?: VideoFilter, |
706 | withFiles = false, | 723 | accountId?: number, |
707 | accountId?: number | 724 | videoChannelId?: number |
708 | ) { | 725 | }) { |
709 | const query = { | 726 | const query = { |
710 | offset: start, | 727 | offset: options.start, |
711 | limit: count, | 728 | limit: options.count, |
712 | order: getSort(sort) | 729 | order: getSort(options.sort) |
713 | } | 730 | } |
714 | 731 | ||
715 | const serverActor = await getServerActor() | 732 | const serverActor = await getServerActor() |
716 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW, filter, withFiles, accountId ] }) | 733 | const scopes = { |
734 | method: [ | ||
735 | ScopeNames.AVAILABLE_FOR_LIST, { | ||
736 | actorId: serverActor.id, | ||
737 | hideNSFW: options.hideNSFW, | ||
738 | filter: options.filter, | ||
739 | withFiles: options.withFiles, | ||
740 | accountId: options.accountId, | ||
741 | videoChannelId: options.videoChannelId | ||
742 | } | ||
743 | ] | ||
744 | } | ||
745 | |||
746 | return VideoModel.scope(scopes) | ||
717 | .findAndCountAll(query) | 747 | .findAndCountAll(query) |
718 | .then(({ rows, count }) => { | 748 | .then(({ rows, count }) => { |
719 | return { | 749 | return { |
@@ -750,8 +780,16 @@ export class VideoModel extends Model<VideoModel> { | |||
750 | } | 780 | } |
751 | 781 | ||
752 | const serverActor = await getServerActor() | 782 | const serverActor = await getServerActor() |
783 | const scopes = { | ||
784 | method: [ | ||
785 | ScopeNames.AVAILABLE_FOR_LIST, { | ||
786 | actorId: serverActor.id, | ||
787 | hideNSFW | ||
788 | } | ||
789 | ] | ||
790 | } | ||
753 | 791 | ||
754 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW ] }) | 792 | return VideoModel.scope(scopes) |
755 | .findAndCountAll(query) | 793 | .findAndCountAll(query) |
756 | .then(({ rows, count }) => { | 794 | .then(({ rows, count }) => { |
757 | return { | 795 | return { |
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts index 43c5462ee..acb6bdd57 100644 --- a/server/tests/api/check-params/video-channels.ts +++ b/server/tests/api/check-params/video-channels.ts | |||
@@ -4,15 +4,29 @@ import * as chai from 'chai' | |||
4 | import { omit } from 'lodash' | 4 | import { omit } from 'lodash' |
5 | import 'mocha' | 5 | import 'mocha' |
6 | import { | 6 | import { |
7 | createUser, deleteVideoChannel, flushTests, getAccountVideoChannelsList, getVideoChannelsList, immutableAssign, killallServers, | 7 | createUser, |
8 | makeGetRequest, makePostBodyRequest, makePutBodyRequest, runServer, ServerInfo, setAccessTokensToServers, userLogin | 8 | deleteVideoChannel, |
9 | flushTests, | ||
10 | getAccountVideoChannelsList, | ||
11 | getVideoChannelsList, | ||
12 | immutableAssign, | ||
13 | killallServers, | ||
14 | makeGetRequest, | ||
15 | makePostBodyRequest, | ||
16 | makePutBodyRequest, | ||
17 | runServer, | ||
18 | ServerInfo, | ||
19 | setAccessTokensToServers, | ||
20 | userLogin | ||
9 | } from '../../utils' | 21 | } from '../../utils' |
10 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 22 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' |
23 | import { getAccountsList } from '../../utils/users/accounts' | ||
11 | 24 | ||
12 | const expect = chai.expect | 25 | const expect = chai.expect |
13 | 26 | ||
14 | describe('Test videos API validator', function () { | 27 | describe('Test videos API validator', function () { |
15 | const path = '/api/v1/videos/channels' | 28 | const videoChannelPath = '/api/v1/video-channels' |
29 | const accountPath = '/api/v1/accounts/' | ||
16 | let server: ServerInfo | 30 | let server: ServerInfo |
17 | let accessTokenUser: string | 31 | let accessTokenUser: string |
18 | 32 | ||
@@ -37,15 +51,15 @@ describe('Test videos API validator', function () { | |||
37 | 51 | ||
38 | describe('When listing a video channels', function () { | 52 | describe('When listing a video channels', function () { |
39 | it('Should fail with a bad start pagination', async function () { | 53 | it('Should fail with a bad start pagination', async function () { |
40 | await checkBadStartPagination(server.url, path, server.accessToken) | 54 | await checkBadStartPagination(server.url, videoChannelPath, server.accessToken) |
41 | }) | 55 | }) |
42 | 56 | ||
43 | it('Should fail with a bad count pagination', async function () { | 57 | it('Should fail with a bad count pagination', async function () { |
44 | await checkBadCountPagination(server.url, path, server.accessToken) | 58 | await checkBadCountPagination(server.url, videoChannelPath, server.accessToken) |
45 | }) | 59 | }) |
46 | 60 | ||
47 | it('Should fail with an incorrect sort', async function () { | 61 | it('Should fail with an incorrect sort', async function () { |
48 | await checkBadSortPagination(server.url, path, server.accessToken) | 62 | await checkBadSortPagination(server.url, videoChannelPath, server.accessToken) |
49 | }) | 63 | }) |
50 | }) | 64 | }) |
51 | 65 | ||
@@ -60,12 +74,20 @@ describe('Test videos API validator', function () { | |||
60 | }) | 74 | }) |
61 | 75 | ||
62 | describe('When adding a video channel', function () { | 76 | describe('When adding a video channel', function () { |
77 | let path: string | ||
78 | |||
63 | const baseCorrectParams = { | 79 | const baseCorrectParams = { |
64 | name: 'hello', | 80 | name: 'hello', |
65 | description: 'super description', | 81 | description: 'super description', |
66 | support: 'super support text' | 82 | support: 'super support text' |
67 | } | 83 | } |
68 | 84 | ||
85 | before(async function () { | ||
86 | const res = await getAccountsList(server.url) | ||
87 | const accountId = res.body.data[0].id | ||
88 | path = accountPath + accountId + '/video-channels' | ||
89 | }) | ||
90 | |||
69 | it('Should fail with a non authenticated user', async function () { | 91 | it('Should fail with a non authenticated user', async function () { |
70 | await makePostBodyRequest({ url: server.url, path, token: 'none', fields: baseCorrectParams, statusCodeExpected: 401 }) | 92 | await makePostBodyRequest({ url: server.url, path, token: 'none', fields: baseCorrectParams, statusCodeExpected: 401 }) |
71 | }) | 93 | }) |
@@ -107,22 +129,27 @@ describe('Test videos API validator', function () { | |||
107 | }) | 129 | }) |
108 | 130 | ||
109 | describe('When updating a video channel', function () { | 131 | describe('When updating a video channel', function () { |
132 | let path: string | ||
133 | |||
110 | const baseCorrectParams = { | 134 | const baseCorrectParams = { |
111 | name: 'hello', | 135 | name: 'hello', |
112 | description: 'super description' | 136 | description: 'super description' |
113 | } | 137 | } |
114 | 138 | ||
115 | let videoChannelId | ||
116 | |||
117 | before(async function () { | 139 | before(async function () { |
118 | const res = await getVideoChannelsList(server.url, 0, 1) | 140 | const res1 = await getVideoChannelsList(server.url, 0, 1) |
119 | videoChannelId = res.body.data[0].id | 141 | const videoChannelId = res1.body.data[0].id |
142 | |||
143 | const res2 = await getAccountsList(server.url) | ||
144 | const accountId = res2.body.data[0].id | ||
145 | |||
146 | path = accountPath + accountId + '/video-channels/' + videoChannelId | ||
120 | }) | 147 | }) |
121 | 148 | ||
122 | it('Should fail with a non authenticated user', async function () { | 149 | it('Should fail with a non authenticated user', async function () { |
123 | await makePutBodyRequest({ | 150 | await makePutBodyRequest({ |
124 | url: server.url, | 151 | url: server.url, |
125 | path: path + '/' + videoChannelId, | 152 | path, |
126 | token: 'hi', | 153 | token: 'hi', |
127 | fields: baseCorrectParams, | 154 | fields: baseCorrectParams, |
128 | statusCodeExpected: 401 | 155 | statusCodeExpected: 401 |
@@ -132,7 +159,7 @@ describe('Test videos API validator', function () { | |||
132 | it('Should fail with another authenticated user', async function () { | 159 | it('Should fail with another authenticated user', async function () { |
133 | await makePutBodyRequest({ | 160 | await makePutBodyRequest({ |
134 | url: server.url, | 161 | url: server.url, |
135 | path: path + '/' + videoChannelId, | 162 | path, |
136 | token: accessTokenUser, | 163 | token: accessTokenUser, |
137 | fields: baseCorrectParams, | 164 | fields: baseCorrectParams, |
138 | statusCodeExpected: 403 | 165 | statusCodeExpected: 403 |
@@ -141,23 +168,23 @@ describe('Test videos API validator', function () { | |||
141 | 168 | ||
142 | it('Should fail with a long name', async function () { | 169 | it('Should fail with a long name', async function () { |
143 | const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(25) }) | 170 | const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(25) }) |
144 | await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields }) | 171 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
145 | }) | 172 | }) |
146 | 173 | ||
147 | it('Should fail with a long description', async function () { | 174 | it('Should fail with a long description', async function () { |
148 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(60) }) | 175 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(60) }) |
149 | await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields }) | 176 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
150 | }) | 177 | }) |
151 | 178 | ||
152 | it('Should fail with a long support text', async function () { | 179 | it('Should fail with a long support text', async function () { |
153 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) }) | 180 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) }) |
154 | await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields }) | 181 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
155 | }) | 182 | }) |
156 | 183 | ||
157 | it('Should succeed with the correct parameters', async function () { | 184 | it('Should succeed with the correct parameters', async function () { |
158 | await makePutBodyRequest({ | 185 | await makePutBodyRequest({ |
159 | url: server.url, | 186 | url: server.url, |
160 | path: path + '/' + videoChannelId, | 187 | path, |
161 | token: server.accessToken, | 188 | token: server.accessToken, |
162 | fields: baseCorrectParams, | 189 | fields: baseCorrectParams, |
163 | statusCodeExpected: 204 | 190 | statusCodeExpected: 204 |
@@ -166,17 +193,23 @@ describe('Test videos API validator', function () { | |||
166 | }) | 193 | }) |
167 | 194 | ||
168 | describe('When getting a video channel', function () { | 195 | describe('When getting a video channel', function () { |
196 | let basePath: string | ||
169 | let videoChannelId: number | 197 | let videoChannelId: number |
170 | 198 | ||
171 | before(async function () { | 199 | before(async function () { |
172 | const res = await getVideoChannelsList(server.url, 0, 1) | 200 | const res1 = await getVideoChannelsList(server.url, 0, 1) |
173 | videoChannelId = res.body.data[0].id | 201 | videoChannelId = res1.body.data[0].id |
202 | |||
203 | const res2 = await getAccountsList(server.url) | ||
204 | const accountId = res2.body.data[0].id | ||
205 | |||
206 | basePath = accountPath + accountId + '/video-channels' | ||
174 | }) | 207 | }) |
175 | 208 | ||
176 | it('Should return the list of the video channels with nothing', async function () { | 209 | it('Should return the list of the video channels with nothing', async function () { |
177 | const res = await makeGetRequest({ | 210 | const res = await makeGetRequest({ |
178 | url: server.url, | 211 | url: server.url, |
179 | path, | 212 | path: basePath, |
180 | statusCodeExpected: 200 | 213 | statusCodeExpected: 200 |
181 | }) | 214 | }) |
182 | 215 | ||
@@ -186,7 +219,7 @@ describe('Test videos API validator', function () { | |||
186 | it('Should fail without a correct uuid', async function () { | 219 | it('Should fail without a correct uuid', async function () { |
187 | await makeGetRequest({ | 220 | await makeGetRequest({ |
188 | url: server.url, | 221 | url: server.url, |
189 | path: path + '/coucou', | 222 | path: basePath + '/coucou', |
190 | statusCodeExpected: 400 | 223 | statusCodeExpected: 400 |
191 | }) | 224 | }) |
192 | }) | 225 | }) |
@@ -194,7 +227,7 @@ describe('Test videos API validator', function () { | |||
194 | it('Should return 404 with an incorrect video channel', async function () { | 227 | it('Should return 404 with an incorrect video channel', async function () { |
195 | await makeGetRequest({ | 228 | await makeGetRequest({ |
196 | url: server.url, | 229 | url: server.url, |
197 | path: path + '/4da6fde3-88f7-4d16-b119-108df5630b06', | 230 | path: basePath + '/4da6fde3-88f7-4d16-b119-108df5630b06', |
198 | statusCodeExpected: 404 | 231 | statusCodeExpected: 404 |
199 | }) | 232 | }) |
200 | }) | 233 | }) |
@@ -202,7 +235,7 @@ describe('Test videos API validator', function () { | |||
202 | it('Should succeed with the correct parameters', async function () { | 235 | it('Should succeed with the correct parameters', async function () { |
203 | await makeGetRequest({ | 236 | await makeGetRequest({ |
204 | url: server.url, | 237 | url: server.url, |
205 | path: path + '/' + videoChannelId, | 238 | path: basePath + '/' + videoChannelId, |
206 | statusCodeExpected: 200 | 239 | statusCodeExpected: 200 |
207 | }) | 240 | }) |
208 | }) | 241 | }) |
@@ -210,33 +243,41 @@ describe('Test videos API validator', function () { | |||
210 | 243 | ||
211 | describe('When deleting a video channel', function () { | 244 | describe('When deleting a video channel', function () { |
212 | let videoChannelId: number | 245 | let videoChannelId: number |
246 | let accountId: number | ||
213 | 247 | ||
214 | before(async function () { | 248 | before(async function () { |
215 | const res = await getVideoChannelsList(server.url, 0, 1) | 249 | const res1 = await getVideoChannelsList(server.url, 0, 1) |
216 | videoChannelId = res.body.data[0].id | 250 | videoChannelId = res1.body.data[0].id |
251 | |||
252 | const res2 = await getAccountsList(server.url) | ||
253 | accountId = res2.body.data[0].id | ||
217 | }) | 254 | }) |
218 | 255 | ||
219 | it('Should fail with a non authenticated user', async function () { | 256 | it('Should fail with a non authenticated user', async function () { |
220 | await deleteVideoChannel(server.url, 'coucou', videoChannelId, 401) | 257 | await deleteVideoChannel(server.url, 'coucou', accountId, videoChannelId, 401) |
221 | }) | 258 | }) |
222 | 259 | ||
223 | it('Should fail with another authenticated user', async function () { | 260 | it('Should fail with another authenticated user', async function () { |
224 | await deleteVideoChannel(server.url, accessTokenUser, videoChannelId, 403) | 261 | await deleteVideoChannel(server.url, accessTokenUser, accountId, videoChannelId, 403) |
262 | }) | ||
263 | |||
264 | it('Should fail with an unknown account id', async function () { | ||
265 | await deleteVideoChannel(server.url, server.accessToken, 454554,videoChannelId, 404) | ||
225 | }) | 266 | }) |
226 | 267 | ||
227 | it('Should fail with an unknown id', async function () { | 268 | it('Should fail with an unknown video channel id', async function () { |
228 | await deleteVideoChannel(server.url, server.accessToken, 454554, 404) | 269 | await deleteVideoChannel(server.url, server.accessToken, accountId,454554, 404) |
229 | }) | 270 | }) |
230 | 271 | ||
231 | it('Should succeed with the correct parameters', async function () { | 272 | it('Should succeed with the correct parameters', async function () { |
232 | await deleteVideoChannel(server.url, server.accessToken, videoChannelId) | 273 | await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId) |
233 | }) | 274 | }) |
234 | 275 | ||
235 | it('Should fail to delete the last user video channel', async function () { | 276 | it('Should fail to delete the last user video channel', async function () { |
236 | const res = await getVideoChannelsList(server.url, 0, 1) | 277 | const res = await getVideoChannelsList(server.url, 0, 1) |
237 | videoChannelId = res.body.data[0].id | 278 | videoChannelId = res.body.data[0].id |
238 | 279 | ||
239 | await deleteVideoChannel(server.url, server.accessToken, videoChannelId, 409) | 280 | await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId, 409) |
240 | }) | 281 | }) |
241 | }) | 282 | }) |
242 | 283 | ||
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index 2563939ec..6238cdc08 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -39,6 +39,7 @@ import { | |||
39 | getVideoCommentThreads, | 39 | getVideoCommentThreads, |
40 | getVideoThreadComments | 40 | getVideoThreadComments |
41 | } from '../../utils/videos/video-comments' | 41 | } from '../../utils/videos/video-comments' |
42 | import { getAccountsList } from '../../utils/users/accounts' | ||
42 | 43 | ||
43 | const expect = chai.expect | 44 | const expect = chai.expect |
44 | 45 | ||
@@ -46,6 +47,7 @@ describe('Test multiple servers', function () { | |||
46 | let servers: ServerInfo[] = [] | 47 | let servers: ServerInfo[] = [] |
47 | const toRemove = [] | 48 | const toRemove = [] |
48 | let videoUUID = '' | 49 | let videoUUID = '' |
50 | let accountId: number | ||
49 | let videoChannelId: number | 51 | let videoChannelId: number |
50 | 52 | ||
51 | before(async function () { | 53 | before(async function () { |
@@ -56,13 +58,20 @@ describe('Test multiple servers', function () { | |||
56 | // Get the access tokens | 58 | // Get the access tokens |
57 | await setAccessTokensToServers(servers) | 59 | await setAccessTokensToServers(servers) |
58 | 60 | ||
59 | const videoChannel = { | 61 | { |
60 | name: 'my channel', | 62 | const res = await getAccountsList(servers[0].url) |
61 | description: 'super channel' | 63 | accountId = res.body.data[0].id |
64 | } | ||
65 | |||
66 | { | ||
67 | const videoChannel = { | ||
68 | name: 'my channel', | ||
69 | description: 'super channel' | ||
70 | } | ||
71 | await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, accountId, videoChannel) | ||
72 | const channelRes = await getVideoChannelsList(servers[ 0 ].url, 0, 1) | ||
73 | videoChannelId = channelRes.body.data[ 0 ].id | ||
62 | } | 74 | } |
63 | await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel) | ||
64 | const channelRes = await getVideoChannelsList(servers[0].url, 0, 1) | ||
65 | videoChannelId = channelRes.body.data[0].id | ||
66 | 75 | ||
67 | // Server 1 and server 2 follow each other | 76 | // Server 1 and server 2 follow each other |
68 | await doubleFollow(servers[0], servers[1]) | 77 | await doubleFollow(servers[0], servers[1]) |
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index b9c9bbf3c..a7552a83a 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts | |||
@@ -17,12 +17,14 @@ import { | |||
17 | setAccessTokensToServers, | 17 | setAccessTokensToServers, |
18 | updateVideoChannel | 18 | updateVideoChannel |
19 | } from '../../utils/index' | 19 | } from '../../utils/index' |
20 | import { getAccountsList } from '../../utils/users/accounts' | ||
20 | 21 | ||
21 | const expect = chai.expect | 22 | const expect = chai.expect |
22 | 23 | ||
23 | describe('Test video channels', function () { | 24 | describe('Test video channels', function () { |
24 | let servers: ServerInfo[] | 25 | let servers: ServerInfo[] |
25 | let userInfo: User | 26 | let userInfo: User |
27 | let accountId: number | ||
26 | let videoChannelId: number | 28 | let videoChannelId: number |
27 | 29 | ||
28 | before(async function () { | 30 | before(async function () { |
@@ -35,6 +37,11 @@ describe('Test video channels', function () { | |||
35 | await setAccessTokensToServers(servers) | 37 | await setAccessTokensToServers(servers) |
36 | await doubleFollow(servers[0], servers[1]) | 38 | await doubleFollow(servers[0], servers[1]) |
37 | 39 | ||
40 | { | ||
41 | const res = await getAccountsList(servers[0].url) | ||
42 | accountId = res.body.data[0].id | ||
43 | } | ||
44 | |||
38 | await wait(5000) | 45 | await wait(5000) |
39 | }) | 46 | }) |
40 | 47 | ||
@@ -54,7 +61,7 @@ describe('Test video channels', function () { | |||
54 | description: 'super video channel description', | 61 | description: 'super video channel description', |
55 | support: 'super video channel support text' | 62 | support: 'super video channel support text' |
56 | } | 63 | } |
57 | const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel) | 64 | const res = await addVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannel) |
58 | videoChannelId = res.body.videoChannel.id | 65 | videoChannelId = res.body.videoChannel.id |
59 | 66 | ||
60 | // The channel is 1 is propagated to servers 2 | 67 | // The channel is 1 is propagated to servers 2 |
@@ -120,7 +127,7 @@ describe('Test video channels', function () { | |||
120 | support: 'video channel support text updated' | 127 | support: 'video channel support text updated' |
121 | } | 128 | } |
122 | 129 | ||
123 | await updateVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId, videoChannelAttributes) | 130 | await updateVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId, videoChannelAttributes) |
124 | 131 | ||
125 | await wait(3000) | 132 | await wait(3000) |
126 | }) | 133 | }) |
@@ -139,7 +146,7 @@ describe('Test video channels', function () { | |||
139 | }) | 146 | }) |
140 | 147 | ||
141 | it('Should get video channel', async function () { | 148 | it('Should get video channel', async function () { |
142 | const res = await getVideoChannel(servers[0].url, videoChannelId) | 149 | const res = await getVideoChannel(servers[0].url, accountId, videoChannelId) |
143 | 150 | ||
144 | const videoChannel = res.body | 151 | const videoChannel = res.body |
145 | expect(videoChannel.displayName).to.equal('video channel updated') | 152 | expect(videoChannel.displayName).to.equal('video channel updated') |
@@ -148,7 +155,7 @@ describe('Test video channels', function () { | |||
148 | }) | 155 | }) |
149 | 156 | ||
150 | it('Should delete video channel', async function () { | 157 | it('Should delete video channel', async function () { |
151 | await deleteVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId) | 158 | await deleteVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId) |
152 | }) | 159 | }) |
153 | 160 | ||
154 | it('Should have video channel deleted', async function () { | 161 | it('Should have video channel deleted', async function () { |
diff --git a/server/tests/utils/videos/video-channels.ts b/server/tests/utils/videos/video-channels.ts index 2d095d8ab..cfc541431 100644 --- a/server/tests/utils/videos/video-channels.ts +++ b/server/tests/utils/videos/video-channels.ts | |||
@@ -7,7 +7,7 @@ type VideoChannelAttributes = { | |||
7 | } | 7 | } |
8 | 8 | ||
9 | function getVideoChannelsList (url: string, start: number, count: number, sort?: string) { | 9 | function getVideoChannelsList (url: string, start: number, count: number, sort?: string) { |
10 | const path = '/api/v1/videos/channels' | 10 | const path = '/api/v1/video-channels' |
11 | 11 | ||
12 | const req = request(url) | 12 | const req = request(url) |
13 | .get(path) | 13 | .get(path) |
@@ -22,7 +22,7 @@ function getVideoChannelsList (url: string, start: number, count: number, sort?: | |||
22 | } | 22 | } |
23 | 23 | ||
24 | function getAccountVideoChannelsList (url: string, accountId: number | string, specialStatus = 200) { | 24 | function getAccountVideoChannelsList (url: string, accountId: number | string, specialStatus = 200) { |
25 | const path = '/api/v1/videos/accounts/' + accountId + '/channels' | 25 | const path = '/api/v1/accounts/' + accountId + '/video-channels' |
26 | 26 | ||
27 | return request(url) | 27 | return request(url) |
28 | .get(path) | 28 | .get(path) |
@@ -31,8 +31,14 @@ function getAccountVideoChannelsList (url: string, accountId: number | string, s | |||
31 | .expect('Content-Type', /json/) | 31 | .expect('Content-Type', /json/) |
32 | } | 32 | } |
33 | 33 | ||
34 | function addVideoChannel (url: string, token: string, videoChannelAttributesArg: VideoChannelAttributes, expectedStatus = 200) { | 34 | function addVideoChannel ( |
35 | const path = '/api/v1/videos/channels' | 35 | url: string, |
36 | token: string, | ||
37 | accountId: number, | ||
38 | videoChannelAttributesArg: VideoChannelAttributes, | ||
39 | expectedStatus = 200 | ||
40 | ) { | ||
41 | const path = '/api/v1/accounts/' + accountId + '/video-channels/' | ||
36 | 42 | ||
37 | // Default attributes | 43 | // Default attributes |
38 | let attributes = { | 44 | let attributes = { |
@@ -50,9 +56,16 @@ function addVideoChannel (url: string, token: string, videoChannelAttributesArg: | |||
50 | .expect(expectedStatus) | 56 | .expect(expectedStatus) |
51 | } | 57 | } |
52 | 58 | ||
53 | function updateVideoChannel (url: string, token: string, channelId: number, attributes: VideoChannelAttributes, expectedStatus = 204) { | 59 | function updateVideoChannel ( |
60 | url: string, | ||
61 | token: string, | ||
62 | accountId: number, | ||
63 | channelId: number, | ||
64 | attributes: VideoChannelAttributes, | ||
65 | expectedStatus = 204 | ||
66 | ) { | ||
54 | const body = {} | 67 | const body = {} |
55 | const path = '/api/v1/videos/channels/' + channelId | 68 | const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId |
56 | 69 | ||
57 | if (attributes.name) body['name'] = attributes.name | 70 | if (attributes.name) body['name'] = attributes.name |
58 | if (attributes.description) body['description'] = attributes.description | 71 | if (attributes.description) body['description'] = attributes.description |
@@ -66,18 +79,18 @@ function updateVideoChannel (url: string, token: string, channelId: number, attr | |||
66 | .expect(expectedStatus) | 79 | .expect(expectedStatus) |
67 | } | 80 | } |
68 | 81 | ||
69 | function deleteVideoChannel (url: string, token: string, channelId: number, expectedStatus = 204) { | 82 | function deleteVideoChannel (url: string, token: string, accountId: number, channelId: number, expectedStatus = 204) { |
70 | const path = '/api/v1/videos/channels/' | 83 | const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId |
71 | 84 | ||
72 | return request(url) | 85 | return request(url) |
73 | .delete(path + channelId) | 86 | .delete(path) |
74 | .set('Accept', 'application/json') | 87 | .set('Accept', 'application/json') |
75 | .set('Authorization', 'Bearer ' + token) | 88 | .set('Authorization', 'Bearer ' + token) |
76 | .expect(expectedStatus) | 89 | .expect(expectedStatus) |
77 | } | 90 | } |
78 | 91 | ||
79 | function getVideoChannel (url: string, channelId: number) { | 92 | function getVideoChannel (url: string, accountId: number, channelId: number) { |
80 | const path = '/api/v1/videos/channels/' + channelId | 93 | const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId |
81 | 94 | ||
82 | return request(url) | 95 | return request(url) |
83 | .get(path) | 96 | .get(path) |
diff --git a/support/doc/api/html/index.html b/support/doc/api/html/index.html index bf9430e79..23162c307 100644 --- a/support/doc/api/html/index.html +++ b/support/doc/api/html/index.html | |||
@@ -41,6 +41,14 @@ | |||
41 | </ul> | 41 | </ul> |
42 | </section> | 42 | </section> |
43 | <section> | 43 | <section> |
44 | <a href="#tag-Feeds">Feeds</a> | ||
45 | <ul> | ||
46 | <li> | ||
47 | <a href="#operation--feeds-videos.-format--get"> GET /feeds/videos.{format} </a> | ||
48 | </li> | ||
49 | </ul> | ||
50 | </section> | ||
51 | <section> | ||
44 | <a href="#tag-Job">Job</a> | 52 | <a href="#tag-Job">Job</a> |
45 | <ul> | 53 | <ul> |
46 | <li> | 54 | <li> |
@@ -176,22 +184,22 @@ | |||
176 | <a href="#tag-VideoChannel">VideoChannel</a> | 184 | <a href="#tag-VideoChannel">VideoChannel</a> |
177 | <ul> | 185 | <ul> |
178 | <li> | 186 | <li> |
179 | <a href="#operation--videos-channels-get"> GET /videos/channels </a> | 187 | <a href="#operation--video-channels-get"> GET /video-channels </a> |
180 | </li> | 188 | </li> |
181 | <li> | 189 | <li> |
182 | <a href="#operation--videos-channels-post"> POST /videos/channels </a> | 190 | <a href="#operation--accounts--accountId--video-channels-get"> GET /accounts/{accountId}/video-channels </a> |
183 | </li> | 191 | </li> |
184 | <li> | 192 | <li> |
185 | <a href="#operation--videos-channels--id--get"> GET /videos/channels/{id} </a> | 193 | <a href="#operation--accounts--accountId--video-channels-post"> POST /accounts/{accountId}/video-channels </a> |
186 | </li> | 194 | </li> |
187 | <li> | 195 | <li> |
188 | <a href="#operation--videos-channels--id--put"> PUT /videos/channels/{id} </a> | 196 | <a href="#operation--account--accountId--video-channels--id--get"> GET /account/{accountId}/video-channels/{id} </a> |
189 | </li> | 197 | </li> |
190 | <li> | 198 | <li> |
191 | <a href="#operation--videos-channels--id--delete"> DELETE /videos/channels/{id} </a> | 199 | <a href="#operation--account--accountId--video-channels--id--put"> PUT /account/{accountId}/video-channels/{id} </a> |
192 | </li> | 200 | </li> |
193 | <li> | 201 | <li> |
194 | <a href="#operation--videos-accounts--accountId--channels-get"> GET /videos/accounts/{accountId}/channels </a> | 202 | <a href="#operation--account--accountId--video-channels--id--delete"> DELETE /account/{accountId}/video-channels/{id} </a> |
195 | </li> | 203 | </li> |
196 | </ul> | 204 | </ul> |
197 | </section> | 205 | </section> |
@@ -224,7 +232,8 @@ | |||
224 | </ul> | 232 | </ul> |
225 | </section> | 233 | </section> |
226 | <h5>Schema Definitions</h5> | 234 | <h5>Schema Definitions</h5> |
227 | <a href="#definition-VideoConstant"> VideoConstant </a> | 235 | <a href="#definition-VideoConstantNumber"> VideoConstantNumber </a> |
236 | <a href="#definition-VideoConstantString"> VideoConstantString </a> | ||
228 | <a href="#definition-VideoPrivacy"> VideoPrivacy </a> | 237 | <a href="#definition-VideoPrivacy"> VideoPrivacy </a> |
229 | <a href="#definition-Video"> Video </a> | 238 | <a href="#definition-Video"> Video </a> |
230 | <a href="#definition-VideoAbuse"> VideoAbuse </a> | 239 | <a href="#definition-VideoAbuse"> VideoAbuse </a> |
@@ -605,6 +614,95 @@ | |||
605 | </div> | 614 | </div> |
606 | </div> | 615 | </div> |
607 | </div> | 616 | </div> |
617 | <h1 id="tag-Feeds" class="swagger-summary-tag" data-traverse-target="tag-Feeds">Feeds</h1> | ||
618 | <div id="operation--feeds-videos.-format--get" class="operation panel" data-traverse-target="operation--feeds-videos.-format--get"> | ||
619 | <!-- <section class="operation-tags row"> --> | ||
620 | <!-- <div class="doc-copy"> --> | ||
621 | <div class="operation-tags"> | ||
622 | <a class="label" href="#tag-Feeds">Feeds</a> | ||
623 | <!----> | ||
624 | </div> | ||
625 | <!-- </div> --> | ||
626 | <!-- </section> --> | ||
627 | <h2 class="operation-title"> | ||
628 | <span class="operation-name"> | ||
629 | <span class="operation-name">GET</span> | ||
630 | <span class="operation-path">/feeds/videos.{format}</span> | ||
631 | </span> | ||
632 | </h2> | ||
633 | <div class="doc-row"> | ||
634 | <div class="doc-copy"> | ||
635 | <section class="swagger-request-params"> | ||
636 | <div class="prop-row prop-group"> | ||
637 | <div class="prop-name"> | ||
638 | <div class="prop-title">format</div> | ||
639 | <span class="json-property-required"></span> | ||
640 | <div class="prop-subtitle"> in path </div> | ||
641 | <div class="prop-subtitle"> | ||
642 | <span class="json-property-type">string</span> | ||
643 | <span class="json-property-enum" title="Possible values"> | ||
644 | <span class="json-property-enum-item json-property-enum-default-value">xml</span>, | ||
645 | <span class="json-property-enum-item">atom</span>, | ||
646 | <span class="json-property-enum-item">json</span> | ||
647 | </span> | ||
648 | <span class="json-property-range" title="Value limits"></span> | ||
649 | <span class="json-property-default-value" title="Default value">xml</span> | ||
650 | </div> | ||
651 | </div> | ||
652 | <div class="prop-value"> | ||
653 | <p>The format expected (xml defaults to RSS 2.0, atom to ATOM 1.0 and json to JSON FEED 1.0</p> | ||
654 | </div> | ||
655 | </div> | ||
656 | <div class="prop-row prop-group"> | ||
657 | <div class="prop-name"> | ||
658 | <div class="prop-title">accountId</div> | ||
659 | <div class="prop-subtitle"> in query </div> | ||
660 | <div class="prop-subtitle"> | ||
661 | <span class="json-property-type">number</span> | ||
662 | <span class="json-property-range" title="Value limits"></span> | ||
663 | </div> | ||
664 | </div> | ||
665 | <div class="prop-value"> | ||
666 | <p>The id of the local account to filter to (beware, users IDs and not actors IDs which will return empty feeds</p> | ||
667 | </div> | ||
668 | </div> | ||
669 | <div class="prop-row prop-group"> | ||
670 | <div class="prop-name"> | ||
671 | <div class="prop-title">accountName</div> | ||
672 | <div class="prop-subtitle"> in query </div> | ||
673 | <div class="prop-subtitle"> | ||
674 | <span class="json-property-type">string</span> | ||
675 | <span class="json-property-range" title="Value limits"></span> | ||
676 | </div> | ||
677 | </div> | ||
678 | <div class="prop-value"> | ||
679 | <p>The name of the local account to filter to</p> | ||
680 | </div> | ||
681 | </div> | ||
682 | </section> | ||
683 | </div> | ||
684 | <div class="doc-examples"></div> | ||
685 | </div> | ||
686 | <div class="doc-row"> | ||
687 | <div class="doc-copy"> | ||
688 | <section class="swagger-responses"> | ||
689 | <div class="prop-row prop-group"> | ||
690 | <div class="prop-name"> | ||
691 | <div class="prop-title">200 OK</div> | ||
692 | </div> | ||
693 | <div class="prop-value"> | ||
694 | <p>successful operation</p> | ||
695 | </div> | ||
696 | </div> | ||
697 | </section> | ||
698 | </div> | ||
699 | <div class="doc-examples"> | ||
700 | <h5>Response Content-Types: | ||
701 | <span>application/atom+xml, application/rss+xml, application/json</span> | ||
702 | </h5> | ||
703 | </div> | ||
704 | </div> | ||
705 | </div> | ||
608 | <h1 id="tag-Job" class="swagger-summary-tag" data-traverse-target="tag-Job">Job</h1> | 706 | <h1 id="tag-Job" class="swagger-summary-tag" data-traverse-target="tag-Job">Job</h1> |
609 | <div id="operation--jobs-get" class="operation panel" data-traverse-target="operation--jobs-get"> | 707 | <div id="operation--jobs-get" class="operation panel" data-traverse-target="operation--jobs-get"> |
610 | <!-- <section class="operation-tags row"> --> | 708 | <!-- <section class="operation-tags row"> --> |
@@ -1518,7 +1616,7 @@ | |||
1518 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 1616 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
1519 | }, | 1617 | }, |
1520 | <span class="hljs-attr">"language"</span>: { | 1618 | <span class="hljs-attr">"language"</span>: { |
1521 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 1619 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
1522 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 1620 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
1523 | }, | 1621 | }, |
1524 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 1622 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -1770,7 +1868,7 @@ | |||
1770 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 1868 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
1771 | }, | 1869 | }, |
1772 | <span class="hljs-attr">"language"</span>: { | 1870 | <span class="hljs-attr">"language"</span>: { |
1773 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 1871 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
1774 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 1872 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
1775 | }, | 1873 | }, |
1776 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 1874 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -2047,7 +2145,7 @@ | |||
2047 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 2145 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
2048 | }, | 2146 | }, |
2049 | <span class="hljs-attr">"language"</span>: { | 2147 | <span class="hljs-attr">"language"</span>: { |
2050 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 2148 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
2051 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 2149 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
2052 | }, | 2150 | }, |
2053 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 2151 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -2488,7 +2586,7 @@ | |||
2488 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 2586 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
2489 | }, | 2587 | }, |
2490 | <span class="hljs-attr">"language"</span>: { | 2588 | <span class="hljs-attr">"language"</span>: { |
2491 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 2589 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
2492 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 2590 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
2493 | }, | 2591 | }, |
2494 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 2592 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -2825,7 +2923,7 @@ | |||
2825 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 2923 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
2826 | }, | 2924 | }, |
2827 | <span class="hljs-attr">"language"</span>: { | 2925 | <span class="hljs-attr">"language"</span>: { |
2828 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 2926 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
2829 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 2927 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
2830 | }, | 2928 | }, |
2831 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 2929 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -3206,7 +3304,7 @@ | |||
3206 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 3304 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
3207 | }, | 3305 | }, |
3208 | <span class="hljs-attr">"language"</span>: { | 3306 | <span class="hljs-attr">"language"</span>: { |
3209 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 3307 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
3210 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 3308 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
3211 | }, | 3309 | }, |
3212 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 3310 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -3329,7 +3427,7 @@ | |||
3329 | <div class="prop-title">language</div> | 3427 | <div class="prop-title">language</div> |
3330 | <div class="prop-subtitle"> in formData </div> | 3428 | <div class="prop-subtitle"> in formData </div> |
3331 | <div class="prop-subtitle"> | 3429 | <div class="prop-subtitle"> |
3332 | <span class="json-property-type">number</span> | 3430 | <span class="json-property-type">string</span> |
3333 | <span class="json-property-range" title="Value limits"></span> | 3431 | <span class="json-property-range" title="Value limits"></span> |
3334 | </div> | 3432 | </div> |
3335 | </div> | 3433 | </div> |
@@ -3478,7 +3576,7 @@ | |||
3478 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 3576 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
3479 | }, | 3577 | }, |
3480 | <span class="hljs-attr">"language"</span>: { | 3578 | <span class="hljs-attr">"language"</span>: { |
3481 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 3579 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
3482 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 3580 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
3483 | }, | 3581 | }, |
3484 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 3582 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -3611,7 +3709,7 @@ | |||
3611 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 3709 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
3612 | }, | 3710 | }, |
3613 | <span class="hljs-attr">"language"</span>: { | 3711 | <span class="hljs-attr">"language"</span>: { |
3614 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 3712 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
3615 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 3713 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
3616 | }, | 3714 | }, |
3617 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 3715 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -3942,7 +4040,7 @@ | |||
3942 | <div class="prop-title">language</div> | 4040 | <div class="prop-title">language</div> |
3943 | <div class="prop-subtitle"> in formData </div> | 4041 | <div class="prop-subtitle"> in formData </div> |
3944 | <div class="prop-subtitle"> | 4042 | <div class="prop-subtitle"> |
3945 | <span class="json-property-type">number</span> | 4043 | <span class="json-property-type">string</span> |
3946 | <span class="json-property-range" title="Value limits"></span> | 4044 | <span class="json-property-range" title="Value limits"></span> |
3947 | </div> | 4045 | </div> |
3948 | </div> | 4046 | </div> |
@@ -4665,7 +4763,7 @@ | |||
4665 | </div> | 4763 | </div> |
4666 | </div> | 4764 | </div> |
4667 | <h1 id="tag-VideoChannel" class="swagger-summary-tag" data-traverse-target="tag-VideoChannel">VideoChannel</h1> | 4765 | <h1 id="tag-VideoChannel" class="swagger-summary-tag" data-traverse-target="tag-VideoChannel">VideoChannel</h1> |
4668 | <div id="operation--videos-channels-get" class="operation panel" data-traverse-target="operation--videos-channels-get"> | 4766 | <div id="operation--video-channels-get" class="operation panel" data-traverse-target="operation--video-channels-get"> |
4669 | <!-- <section class="operation-tags row"> --> | 4767 | <!-- <section class="operation-tags row"> --> |
4670 | <!-- <div class="doc-copy"> --> | 4768 | <!-- <div class="doc-copy"> --> |
4671 | <div class="operation-tags"> | 4769 | <div class="operation-tags"> |
@@ -4677,7 +4775,7 @@ | |||
4677 | <h2 class="operation-title"> | 4775 | <h2 class="operation-title"> |
4678 | <span class="operation-name"> | 4776 | <span class="operation-name"> |
4679 | <span class="operation-name">GET</span> | 4777 | <span class="operation-name">GET</span> |
4680 | <span class="operation-path">/videos/channels</span> | 4778 | <span class="operation-path">/video-channels</span> |
4681 | </span> | 4779 | </span> |
4682 | </h2> | 4780 | </h2> |
4683 | <div class="doc-row"> | 4781 | <div class="doc-row"> |
@@ -4789,9 +4887,144 @@ | |||
4789 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 4887 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
4790 | }, | 4888 | }, |
4791 | <span class="hljs-attr">"language"</span>: { | 4889 | <span class="hljs-attr">"language"</span>: { |
4890 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, | ||
4891 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | ||
4892 | }, | ||
4893 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | ||
4894 | <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>, | ||
4895 | <span class="hljs-attr">"duration"</span>: <span class="hljs-string">"number"</span>, | ||
4896 | <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>, | ||
4897 | <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>, | ||
4898 | <span class="hljs-attr">"thumbnailPath"</span>: <span class="hljs-string">"string"</span>, | ||
4899 | <span class="hljs-attr">"previewPath"</span>: <span class="hljs-string">"string"</span>, | ||
4900 | <span class="hljs-attr">"embedPath"</span>: <span class="hljs-string">"string"</span>, | ||
4901 | <span class="hljs-attr">"views"</span>: <span class="hljs-string">"number"</span>, | ||
4902 | <span class="hljs-attr">"likes"</span>: <span class="hljs-string">"number"</span>, | ||
4903 | <span class="hljs-attr">"dislikes"</span>: <span class="hljs-string">"number"</span>, | ||
4904 | <span class="hljs-attr">"nsfw"</span>: <span class="hljs-string">"boolean"</span>, | ||
4905 | <span class="hljs-attr">"account"</span>: { | ||
4906 | <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>, | ||
4907 | <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>, | ||
4908 | <span class="hljs-attr">"url"</span>: <span class="hljs-string">"string"</span>, | ||
4909 | <span class="hljs-attr">"host"</span>: <span class="hljs-string">"string"</span>, | ||
4910 | <span class="hljs-attr">"avatar"</span>: { | ||
4911 | <span class="hljs-attr">"path"</span>: <span class="hljs-string">"string"</span>, | ||
4912 | <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>, | ||
4913 | <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span> | ||
4914 | } | ||
4915 | } | ||
4916 | } | ||
4917 | ] | ||
4918 | } | ||
4919 | ] | ||
4920 | </code></pre> | ||
4921 | <!-- </div> --> | ||
4922 | </section> | ||
4923 | </div> | ||
4924 | </div> | ||
4925 | </div> | ||
4926 | <div id="operation--accounts--accountId--video-channels-get" class="operation panel" data-traverse-target="operation--accounts--accountId--video-channels-get"> | ||
4927 | <!-- <section class="operation-tags row"> --> | ||
4928 | <!-- <div class="doc-copy"> --> | ||
4929 | <div class="operation-tags"> | ||
4930 | <a class="label" href="#tag-VideoChannel">VideoChannel</a> | ||
4931 | <!----> | ||
4932 | </div> | ||
4933 | <!-- </div> --> | ||
4934 | <!-- </section> --> | ||
4935 | <h2 class="operation-title"> | ||
4936 | <span class="operation-name"> | ||
4937 | <span class="operation-name">GET</span> | ||
4938 | <span class="operation-path">/accounts/{accountId}/video-channels</span> | ||
4939 | </span> | ||
4940 | </h2> | ||
4941 | <div class="doc-row"> | ||
4942 | <div class="doc-copy"> | ||
4943 | <section class="swagger-request-params"> | ||
4944 | <div class="prop-row prop-group"> | ||
4945 | <div class="prop-name"> | ||
4946 | <div class="prop-title">accountId</div> | ||
4947 | <span class="json-property-required"></span> | ||
4948 | <div class="prop-subtitle"> in path </div> | ||
4949 | <div class="prop-subtitle"> | ||
4950 | <span class="json-property-type">string</span> | ||
4951 | <span class="json-property-range" title="Value limits"></span> | ||
4952 | </div> | ||
4953 | </div> | ||
4954 | <div class="prop-value"> | ||
4955 | <p>The account id </p> | ||
4956 | </div> | ||
4957 | </div> | ||
4958 | </section> | ||
4959 | </div> | ||
4960 | <div class="doc-examples"></div> | ||
4961 | </div> | ||
4962 | <div class="doc-row"> | ||
4963 | <div class="doc-copy"> | ||
4964 | <section class="swagger-responses"> | ||
4965 | <div class="prop-row prop-group"> | ||
4966 | <div class="prop-name"> | ||
4967 | <div class="prop-title">200 OK</div> | ||
4968 | <div class="prop-ref"> | ||
4969 | <span class="json-schema-ref-array"> | ||
4970 | <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a> | ||
4971 | </span> | ||
4972 | </div> | ||
4973 | <!-- <span class="swagger-global"></span> <span class="json-schema-reference"><a href=""></a></span> --> | ||
4974 | </div> | ||
4975 | <div class="prop-value"> | ||
4976 | <p>successful operation</p> | ||
4977 | </div> | ||
4978 | </div> | ||
4979 | <div class="prop-row prop-inner"> | ||
4980 | <div class="prop-name">type</div> | ||
4981 | <div class="prop-value"> | ||
4982 | <span class="json-property-type"> | ||
4983 | <span class="json-schema-ref-array"> | ||
4984 | <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a> | ||
4985 | </span> | ||
4986 | </span> | ||
4987 | <span class="json-property-range" title="Value limits"></span> | ||
4988 | </div> | ||
4989 | </div> | ||
4990 | </section> | ||
4991 | </div> | ||
4992 | <div class="doc-examples"> | ||
4993 | <h5>Response Content-Types: | ||
4994 | <span>application/json</span> | ||
4995 | </h5> | ||
4996 | <section> | ||
4997 | <h5>Response Example | ||
4998 | <span>(200 OK)</span> | ||
4999 | </h5> | ||
5000 | <!-- <div class="hljs"> --><pre><code class="hljs lang-json">[ | ||
5001 | { | ||
5002 | <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>, | ||
5003 | <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>, | ||
5004 | <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>, | ||
5005 | <span class="hljs-attr">"owner"</span>: { | ||
5006 | <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>, | ||
5007 | <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span> | ||
5008 | }, | ||
5009 | <span class="hljs-attr">"videos"</span>: [ | ||
5010 | { | ||
5011 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | ||
5012 | <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span>, | ||
5013 | <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>, | ||
5014 | <span class="hljs-attr">"publishedAt"</span>: <span class="hljs-string">"string"</span>, | ||
5015 | <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span>, | ||
5016 | <span class="hljs-attr">"category"</span>: { | ||
4792 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 5017 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, |
4793 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 5018 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
4794 | }, | 5019 | }, |
5020 | <span class="hljs-attr">"licence"</span>: { | ||
5021 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | ||
5022 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | ||
5023 | }, | ||
5024 | <span class="hljs-attr">"language"</span>: { | ||
5025 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, | ||
5026 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | ||
5027 | }, | ||
4795 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 5028 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
4796 | <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>, | 5029 | <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>, |
4797 | <span class="hljs-attr">"duration"</span>: <span class="hljs-string">"number"</span>, | 5030 | <span class="hljs-attr">"duration"</span>: <span class="hljs-string">"number"</span>, |
@@ -4825,7 +5058,7 @@ | |||
4825 | </div> | 5058 | </div> |
4826 | </div> | 5059 | </div> |
4827 | </div> | 5060 | </div> |
4828 | <div id="operation--videos-channels-post" class="operation panel" data-traverse-target="operation--videos-channels-post"> | 5061 | <div id="operation--accounts--accountId--video-channels-post" class="operation panel" data-traverse-target="operation--accounts--accountId--video-channels-post"> |
4829 | <!-- <section class="operation-tags row"> --> | 5062 | <!-- <section class="operation-tags row"> --> |
4830 | <!-- <div class="doc-copy"> --> | 5063 | <!-- <div class="doc-copy"> --> |
4831 | <div class="operation-tags"> | 5064 | <div class="operation-tags"> |
@@ -4837,7 +5070,7 @@ | |||
4837 | <h2 class="operation-title"> | 5070 | <h2 class="operation-title"> |
4838 | <span class="operation-name"> | 5071 | <span class="operation-name"> |
4839 | <span class="operation-name">POST</span> | 5072 | <span class="operation-name">POST</span> |
4840 | <span class="operation-path">/videos/channels</span> | 5073 | <span class="operation-path">/accounts/{accountId}/video-channels</span> |
4841 | </span> | 5074 | </span> |
4842 | </h2> | 5075 | </h2> |
4843 | <div class="doc-row"> | 5076 | <div class="doc-row"> |
@@ -4858,6 +5091,22 @@ | |||
4858 | </div> | 5091 | </div> |
4859 | </div> | 5092 | </div> |
4860 | </section> | 5093 | </section> |
5094 | <section class="swagger-request-params"> | ||
5095 | <div class="prop-row prop-group"> | ||
5096 | <div class="prop-name"> | ||
5097 | <div class="prop-title">accountId</div> | ||
5098 | <span class="json-property-required"></span> | ||
5099 | <div class="prop-subtitle"> in path </div> | ||
5100 | <div class="prop-subtitle"> | ||
5101 | <span class="json-property-type">string</span> | ||
5102 | <span class="json-property-range" title="Value limits"></span> | ||
5103 | </div> | ||
5104 | </div> | ||
5105 | <div class="prop-value"> | ||
5106 | <p>The account id </p> | ||
5107 | </div> | ||
5108 | </div> | ||
5109 | </section> | ||
4861 | </div> | 5110 | </div> |
4862 | <div class="doc-examples"> | 5111 | <div class="doc-examples"> |
4863 | <section> | 5112 | <section> |
@@ -4916,7 +5165,7 @@ | |||
4916 | </div> | 5165 | </div> |
4917 | </div> | 5166 | </div> |
4918 | </div> | 5167 | </div> |
4919 | <div id="operation--videos-channels--id--get" class="operation panel" data-traverse-target="operation--videos-channels--id--get"> | 5168 | <div id="operation--account--accountId--video-channels--id--get" class="operation panel" data-traverse-target="operation--account--accountId--video-channels--id--get"> |
4920 | <!-- <section class="operation-tags row"> --> | 5169 | <!-- <section class="operation-tags row"> --> |
4921 | <!-- <div class="doc-copy"> --> | 5170 | <!-- <div class="doc-copy"> --> |
4922 | <div class="operation-tags"> | 5171 | <div class="operation-tags"> |
@@ -4928,7 +5177,7 @@ | |||
4928 | <h2 class="operation-title"> | 5177 | <h2 class="operation-title"> |
4929 | <span class="operation-name"> | 5178 | <span class="operation-name"> |
4930 | <span class="operation-name">GET</span> | 5179 | <span class="operation-name">GET</span> |
4931 | <span class="operation-path">/videos/channels/{id}</span> | 5180 | <span class="operation-path">/account/{accountId}/video-channels/{id}</span> |
4932 | </span> | 5181 | </span> |
4933 | </h2> | 5182 | </h2> |
4934 | <div class="doc-row"> | 5183 | <div class="doc-row"> |
@@ -4936,6 +5185,20 @@ | |||
4936 | <section class="swagger-request-params"> | 5185 | <section class="swagger-request-params"> |
4937 | <div class="prop-row prop-group"> | 5186 | <div class="prop-row prop-group"> |
4938 | <div class="prop-name"> | 5187 | <div class="prop-name"> |
5188 | <div class="prop-title">accountId</div> | ||
5189 | <span class="json-property-required"></span> | ||
5190 | <div class="prop-subtitle"> in path </div> | ||
5191 | <div class="prop-subtitle"> | ||
5192 | <span class="json-property-type">string</span> | ||
5193 | <span class="json-property-range" title="Value limits"></span> | ||
5194 | </div> | ||
5195 | </div> | ||
5196 | <div class="prop-value"> | ||
5197 | <p>The account id </p> | ||
5198 | </div> | ||
5199 | </div> | ||
5200 | <div class="prop-row prop-group"> | ||
5201 | <div class="prop-name"> | ||
4939 | <div class="prop-title">id</div> | 5202 | <div class="prop-title">id</div> |
4940 | <span class="json-property-required"></span> | 5203 | <span class="json-property-required"></span> |
4941 | <div class="prop-subtitle"> in path </div> | 5204 | <div class="prop-subtitle"> in path </div> |
@@ -4945,7 +5208,7 @@ | |||
4945 | </div> | 5208 | </div> |
4946 | </div> | 5209 | </div> |
4947 | <div class="prop-value"> | 5210 | <div class="prop-value"> |
4948 | <p>The video id </p> | 5211 | <p>The video channel id </p> |
4949 | </div> | 5212 | </div> |
4950 | </div> | 5213 | </div> |
4951 | </section> | 5214 | </section> |
@@ -5003,7 +5266,7 @@ | |||
5003 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 5266 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
5004 | }, | 5267 | }, |
5005 | <span class="hljs-attr">"language"</span>: { | 5268 | <span class="hljs-attr">"language"</span>: { |
5006 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 5269 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
5007 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 5270 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
5008 | }, | 5271 | }, |
5009 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 5272 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -5038,7 +5301,7 @@ | |||
5038 | </div> | 5301 | </div> |
5039 | </div> | 5302 | </div> |
5040 | </div> | 5303 | </div> |
5041 | <div id="operation--videos-channels--id--put" class="operation panel" data-traverse-target="operation--videos-channels--id--put"> | 5304 | <div id="operation--account--accountId--video-channels--id--put" class="operation panel" data-traverse-target="operation--account--accountId--video-channels--id--put"> |
5042 | <!-- <section class="operation-tags row"> --> | 5305 | <!-- <section class="operation-tags row"> --> |
5043 | <!-- <div class="doc-copy"> --> | 5306 | <!-- <div class="doc-copy"> --> |
5044 | <div class="operation-tags"> | 5307 | <div class="operation-tags"> |
@@ -5050,7 +5313,7 @@ | |||
5050 | <h2 class="operation-title"> | 5313 | <h2 class="operation-title"> |
5051 | <span class="operation-name"> | 5314 | <span class="operation-name"> |
5052 | <span class="operation-name">PUT</span> | 5315 | <span class="operation-name">PUT</span> |
5053 | <span class="operation-path">/videos/channels/{id}</span> | 5316 | <span class="operation-path">/account/{accountId}/video-channels/{id}</span> |
5054 | </span> | 5317 | </span> |
5055 | </h2> | 5318 | </h2> |
5056 | <div class="doc-row"> | 5319 | <div class="doc-row"> |
@@ -5074,6 +5337,20 @@ | |||
5074 | <section class="swagger-request-params"> | 5337 | <section class="swagger-request-params"> |
5075 | <div class="prop-row prop-group"> | 5338 | <div class="prop-row prop-group"> |
5076 | <div class="prop-name"> | 5339 | <div class="prop-name"> |
5340 | <div class="prop-title">accountId</div> | ||
5341 | <span class="json-property-required"></span> | ||
5342 | <div class="prop-subtitle"> in path </div> | ||
5343 | <div class="prop-subtitle"> | ||
5344 | <span class="json-property-type">string</span> | ||
5345 | <span class="json-property-range" title="Value limits"></span> | ||
5346 | </div> | ||
5347 | </div> | ||
5348 | <div class="prop-value"> | ||
5349 | <p>The account id </p> | ||
5350 | </div> | ||
5351 | </div> | ||
5352 | <div class="prop-row prop-group"> | ||
5353 | <div class="prop-name"> | ||
5077 | <div class="prop-title">id</div> | 5354 | <div class="prop-title">id</div> |
5078 | <span class="json-property-required"></span> | 5355 | <span class="json-property-required"></span> |
5079 | <div class="prop-subtitle"> in path </div> | 5356 | <div class="prop-subtitle"> in path </div> |
@@ -5083,7 +5360,7 @@ | |||
5083 | </div> | 5360 | </div> |
5084 | </div> | 5361 | </div> |
5085 | <div class="prop-value"> | 5362 | <div class="prop-value"> |
5086 | <p>The video id </p> | 5363 | <p>The video channel id </p> |
5087 | </div> | 5364 | </div> |
5088 | </div> | 5365 | </div> |
5089 | </section> | 5366 | </section> |
@@ -5145,7 +5422,7 @@ | |||
5145 | </div> | 5422 | </div> |
5146 | </div> | 5423 | </div> |
5147 | </div> | 5424 | </div> |
5148 | <div id="operation--videos-channels--id--delete" class="operation panel" data-traverse-target="operation--videos-channels--id--delete"> | 5425 | <div id="operation--account--accountId--video-channels--id--delete" class="operation panel" data-traverse-target="operation--account--accountId--video-channels--id--delete"> |
5149 | <!-- <section class="operation-tags row"> --> | 5426 | <!-- <section class="operation-tags row"> --> |
5150 | <!-- <div class="doc-copy"> --> | 5427 | <!-- <div class="doc-copy"> --> |
5151 | <div class="operation-tags"> | 5428 | <div class="operation-tags"> |
@@ -5157,7 +5434,7 @@ | |||
5157 | <h2 class="operation-title"> | 5434 | <h2 class="operation-title"> |
5158 | <span class="operation-name"> | 5435 | <span class="operation-name"> |
5159 | <span class="operation-name">DELETE</span> | 5436 | <span class="operation-name">DELETE</span> |
5160 | <span class="operation-path">/videos/channels/{id}</span> | 5437 | <span class="operation-path">/account/{accountId}/video-channels/{id}</span> |
5161 | </span> | 5438 | </span> |
5162 | </h2> | 5439 | </h2> |
5163 | <div class="doc-row"> | 5440 | <div class="doc-row"> |
@@ -5165,6 +5442,20 @@ | |||
5165 | <section class="swagger-request-params"> | 5442 | <section class="swagger-request-params"> |
5166 | <div class="prop-row prop-group"> | 5443 | <div class="prop-row prop-group"> |
5167 | <div class="prop-name"> | 5444 | <div class="prop-name"> |
5445 | <div class="prop-title">accountId</div> | ||
5446 | <span class="json-property-required"></span> | ||
5447 | <div class="prop-subtitle"> in path </div> | ||
5448 | <div class="prop-subtitle"> | ||
5449 | <span class="json-property-type">string</span> | ||
5450 | <span class="json-property-range" title="Value limits"></span> | ||
5451 | </div> | ||
5452 | </div> | ||
5453 | <div class="prop-value"> | ||
5454 | <p>The account id </p> | ||
5455 | </div> | ||
5456 | </div> | ||
5457 | <div class="prop-row prop-group"> | ||
5458 | <div class="prop-name"> | ||
5168 | <div class="prop-title">id</div> | 5459 | <div class="prop-title">id</div> |
5169 | <span class="json-property-required"></span> | 5460 | <span class="json-property-required"></span> |
5170 | <div class="prop-subtitle"> in path </div> | 5461 | <div class="prop-subtitle"> in path </div> |
@@ -5174,7 +5465,7 @@ | |||
5174 | </div> | 5465 | </div> |
5175 | </div> | 5466 | </div> |
5176 | <div class="prop-value"> | 5467 | <div class="prop-value"> |
5177 | <p>The video id </p> | 5468 | <p>The video channel id </p> |
5178 | </div> | 5469 | </div> |
5179 | </div> | 5470 | </div> |
5180 | </section> | 5471 | </section> |
@@ -5223,141 +5514,6 @@ | |||
5223 | </div> | 5514 | </div> |
5224 | </div> | 5515 | </div> |
5225 | </div> | 5516 | </div> |
5226 | <div id="operation--videos-accounts--accountId--channels-get" class="operation panel" data-traverse-target="operation--videos-accounts--accountId--channels-get"> | ||
5227 | <!-- <section class="operation-tags row"> --> | ||
5228 | <!-- <div class="doc-copy"> --> | ||
5229 | <div class="operation-tags"> | ||
5230 | <a class="label" href="#tag-VideoChannel">VideoChannel</a> | ||
5231 | <!----> | ||
5232 | </div> | ||
5233 | <!-- </div> --> | ||
5234 | <!-- </section> --> | ||
5235 | <h2 class="operation-title"> | ||
5236 | <span class="operation-name"> | ||
5237 | <span class="operation-name">GET</span> | ||
5238 | <span class="operation-path">/videos/accounts/{accountId}/channels</span> | ||
5239 | </span> | ||
5240 | </h2> | ||
5241 | <div class="doc-row"> | ||
5242 | <div class="doc-copy"> | ||
5243 | <section class="swagger-request-params"> | ||
5244 | <div class="prop-row prop-group"> | ||
5245 | <div class="prop-name"> | ||
5246 | <div class="prop-title">accountId</div> | ||
5247 | <span class="json-property-required"></span> | ||
5248 | <div class="prop-subtitle"> in path </div> | ||
5249 | <div class="prop-subtitle"> | ||
5250 | <span class="json-property-type">string</span> | ||
5251 | <span class="json-property-range" title="Value limits"></span> | ||
5252 | </div> | ||
5253 | </div> | ||
5254 | <div class="prop-value"> | ||
5255 | <p>The account id </p> | ||
5256 | </div> | ||
5257 | </div> | ||
5258 | </section> | ||
5259 | </div> | ||
5260 | <div class="doc-examples"></div> | ||
5261 | </div> | ||
5262 | <div class="doc-row"> | ||
5263 | <div class="doc-copy"> | ||
5264 | <section class="swagger-responses"> | ||
5265 | <div class="prop-row prop-group"> | ||
5266 | <div class="prop-name"> | ||
5267 | <div class="prop-title">200 OK</div> | ||
5268 | <div class="prop-ref"> | ||
5269 | <span class="json-schema-ref-array"> | ||
5270 | <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a> | ||
5271 | </span> | ||
5272 | </div> | ||
5273 | <!-- <span class="swagger-global"></span> <span class="json-schema-reference"><a href=""></a></span> --> | ||
5274 | </div> | ||
5275 | <div class="prop-value"> | ||
5276 | <p>successful operation</p> | ||
5277 | </div> | ||
5278 | </div> | ||
5279 | <div class="prop-row prop-inner"> | ||
5280 | <div class="prop-name">type</div> | ||
5281 | <div class="prop-value"> | ||
5282 | <span class="json-property-type"> | ||
5283 | <span class="json-schema-ref-array"> | ||
5284 | <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a> | ||
5285 | </span> | ||
5286 | </span> | ||
5287 | <span class="json-property-range" title="Value limits"></span> | ||
5288 | </div> | ||
5289 | </div> | ||
5290 | </section> | ||
5291 | </div> | ||
5292 | <div class="doc-examples"> | ||
5293 | <h5>Response Content-Types: | ||
5294 | <span>application/json</span> | ||
5295 | </h5> | ||
5296 | <section> | ||
5297 | <h5>Response Example | ||
5298 | <span>(200 OK)</span> | ||
5299 | </h5> | ||
5300 | <!-- <div class="hljs"> --><pre><code class="hljs lang-json">[ | ||
5301 | { | ||
5302 | <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>, | ||
5303 | <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>, | ||
5304 | <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>, | ||
5305 | <span class="hljs-attr">"owner"</span>: { | ||
5306 | <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>, | ||
5307 | <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span> | ||
5308 | }, | ||
5309 | <span class="hljs-attr">"videos"</span>: [ | ||
5310 | { | ||
5311 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | ||
5312 | <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span>, | ||
5313 | <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>, | ||
5314 | <span class="hljs-attr">"publishedAt"</span>: <span class="hljs-string">"string"</span>, | ||
5315 | <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span>, | ||
5316 | <span class="hljs-attr">"category"</span>: { | ||
5317 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | ||
5318 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | ||
5319 | }, | ||
5320 | <span class="hljs-attr">"licence"</span>: { | ||
5321 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | ||
5322 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | ||
5323 | }, | ||
5324 | <span class="hljs-attr">"language"</span>: { | ||
5325 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | ||
5326 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | ||
5327 | }, | ||
5328 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | ||
5329 | <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>, | ||
5330 | <span class="hljs-attr">"duration"</span>: <span class="hljs-string">"number"</span>, | ||
5331 | <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>, | ||
5332 | <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>, | ||
5333 | <span class="hljs-attr">"thumbnailPath"</span>: <span class="hljs-string">"string"</span>, | ||
5334 | <span class="hljs-attr">"previewPath"</span>: <span class="hljs-string">"string"</span>, | ||
5335 | <span class="hljs-attr">"embedPath"</span>: <span class="hljs-string">"string"</span>, | ||
5336 | <span class="hljs-attr">"views"</span>: <span class="hljs-string">"number"</span>, | ||
5337 | <span class="hljs-attr">"likes"</span>: <span class="hljs-string">"number"</span>, | ||
5338 | <span class="hljs-attr">"dislikes"</span>: <span class="hljs-string">"number"</span>, | ||
5339 | <span class="hljs-attr">"nsfw"</span>: <span class="hljs-string">"boolean"</span>, | ||
5340 | <span class="hljs-attr">"account"</span>: { | ||
5341 | <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>, | ||
5342 | <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>, | ||
5343 | <span class="hljs-attr">"url"</span>: <span class="hljs-string">"string"</span>, | ||
5344 | <span class="hljs-attr">"host"</span>: <span class="hljs-string">"string"</span>, | ||
5345 | <span class="hljs-attr">"avatar"</span>: { | ||
5346 | <span class="hljs-attr">"path"</span>: <span class="hljs-string">"string"</span>, | ||
5347 | <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>, | ||
5348 | <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span> | ||
5349 | } | ||
5350 | } | ||
5351 | } | ||
5352 | ] | ||
5353 | } | ||
5354 | ] | ||
5355 | </code></pre> | ||
5356 | <!-- </div> --> | ||
5357 | </section> | ||
5358 | </div> | ||
5359 | </div> | ||
5360 | </div> | ||
5361 | <h1 id="tag-VideoComment" class="swagger-summary-tag" data-traverse-target="tag-VideoComment">VideoComment</h1> | 5517 | <h1 id="tag-VideoComment" class="swagger-summary-tag" data-traverse-target="tag-VideoComment">VideoComment</h1> |
5362 | <div id="operation--videos--videoId--comment-threads-get" class="operation panel" data-traverse-target="operation--videos--videoId--comment-threads-get"> | 5518 | <div id="operation--videos--videoId--comment-threads-get" class="operation panel" data-traverse-target="operation--videos--videoId--comment-threads-get"> |
5363 | <!-- <section class="operation-tags row"> --> | 5519 | <!-- <section class="operation-tags row"> --> |
@@ -6104,9 +6260,9 @@ | |||
6104 | </div> | 6260 | </div> |
6105 | </div> | 6261 | </div> |
6106 | <h1>Schema Definitions</h1> | 6262 | <h1>Schema Definitions</h1> |
6107 | <div id="definition-VideoConstant" class="definition panel" data-traverse-target="definition-VideoConstant"> | 6263 | <div id="definition-VideoConstantNumber" class="definition panel" data-traverse-target="definition-VideoConstantNumber"> |
6108 | <h2 class="panel-title"> | 6264 | <h2 class="panel-title"> |
6109 | <a name="/definitions/VideoConstant"></a>VideoConstant: | 6265 | <a name="/definitions/VideoConstantNumber"></a>VideoConstantNumber: |
6110 | <!-- <span class="json-property-type"><span class="json-property-type">object</span> | 6266 | <!-- <span class="json-property-type"><span class="json-property-type">object</span> |
6111 | <span class="json-property-range" title="Value limits"></span> | 6267 | <span class="json-property-range" title="Value limits"></span> |
6112 | 6268 | ||
@@ -6143,6 +6299,45 @@ | |||
6143 | </div> | 6299 | </div> |
6144 | </div> | 6300 | </div> |
6145 | </div> | 6301 | </div> |
6302 | <div id="definition-VideoConstantString" class="definition panel" data-traverse-target="definition-VideoConstantString"> | ||
6303 | <h2 class="panel-title"> | ||
6304 | <a name="/definitions/VideoConstantString"></a>VideoConstantString: | ||
6305 | <!-- <span class="json-property-type"><span class="json-property-type">object</span> | ||
6306 | <span class="json-property-range" title="Value limits"></span> | ||
6307 | |||
6308 | |||
6309 | </span> --> | ||
6310 | </h2> | ||
6311 | <div class="doc-row"> | ||
6312 | <div class="doc-copy"> | ||
6313 | <section class="json-schema-properties"> | ||
6314 | <dl> | ||
6315 | <dt data-property-name="id"> | ||
6316 | <span class="json-property-name">id:</span> | ||
6317 | <span class="json-property-type">string</span> | ||
6318 | <span class="json-property-range" title="Value limits"></span> | ||
6319 | </dt> | ||
6320 | <dt data-property-name="label"> | ||
6321 | <span class="json-property-name">label:</span> | ||
6322 | <span class="json-property-type">string</span> | ||
6323 | <span class="json-property-range" title="Value limits"></span> | ||
6324 | </dt> | ||
6325 | </dl> | ||
6326 | </section> | ||
6327 | </div> | ||
6328 | <div class="doc-examples"> | ||
6329 | <section> | ||
6330 | <h5>Example</h5> | ||
6331 | <!-- <div class="hljs"> --><pre><code class="hljs lang-json">{ | ||
6332 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, | ||
6333 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | ||
6334 | } | ||
6335 | </code></pre> | ||
6336 | <!-- </div> --> | ||
6337 | </section> | ||
6338 | </div> | ||
6339 | </div> | ||
6340 | </div> | ||
6146 | <div id="definition-VideoPrivacy" class="definition panel" data-traverse-target="definition-VideoPrivacy"> | 6341 | <div id="definition-VideoPrivacy" class="definition panel" data-traverse-target="definition-VideoPrivacy"> |
6147 | <h2 class="panel-title"> | 6342 | <h2 class="panel-title"> |
6148 | <a name="/definitions/VideoPrivacy"></a>VideoPrivacy: string | 6343 | <a name="/definitions/VideoPrivacy"></a>VideoPrivacy: string |
@@ -6210,7 +6405,7 @@ | |||
6210 | <span class="json-property-name">category:</span> | 6405 | <span class="json-property-name">category:</span> |
6211 | <span class="json-property-type"> | 6406 | <span class="json-property-type"> |
6212 | <span class=""> | 6407 | <span class=""> |
6213 | <a class="json-schema-ref" href="#/definitions/VideoConstant">VideoConstant</a> | 6408 | <a class="json-schema-ref" href="#/definitions/VideoConstantNumber">VideoConstantNumber</a> |
6214 | </span> | 6409 | </span> |
6215 | </span> | 6410 | </span> |
6216 | <span class="json-property-range" title="Value limits"></span> | 6411 | <span class="json-property-range" title="Value limits"></span> |
@@ -6219,7 +6414,7 @@ | |||
6219 | <span class="json-property-name">licence:</span> | 6414 | <span class="json-property-name">licence:</span> |
6220 | <span class="json-property-type"> | 6415 | <span class="json-property-type"> |
6221 | <span class=""> | 6416 | <span class=""> |
6222 | <a class="json-schema-ref" href="#/definitions/VideoConstant">VideoConstant</a> | 6417 | <a class="json-schema-ref" href="#/definitions/VideoConstantNumber">VideoConstantNumber</a> |
6223 | </span> | 6418 | </span> |
6224 | </span> | 6419 | </span> |
6225 | <span class="json-property-range" title="Value limits"></span> | 6420 | <span class="json-property-range" title="Value limits"></span> |
@@ -6228,7 +6423,7 @@ | |||
6228 | <span class="json-property-name">language:</span> | 6423 | <span class="json-property-name">language:</span> |
6229 | <span class="json-property-type"> | 6424 | <span class="json-property-type"> |
6230 | <span class=""> | 6425 | <span class=""> |
6231 | <a class="json-schema-ref" href="#/definitions/VideoConstant">VideoConstant</a> | 6426 | <a class="json-schema-ref" href="#/definitions/VideoConstantString">VideoConstantString</a> |
6232 | </span> | 6427 | </span> |
6233 | </span> | 6428 | </span> |
6234 | <span class="json-property-range" title="Value limits"></span> | 6429 | <span class="json-property-range" title="Value limits"></span> |
@@ -6323,7 +6518,7 @@ | |||
6323 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 6518 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
6324 | }, | 6519 | }, |
6325 | <span class="hljs-attr">"language"</span>: { | 6520 | <span class="hljs-attr">"language"</span>: { |
6326 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 6521 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
6327 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 6522 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
6328 | }, | 6523 | }, |
6329 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 6524 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -6609,7 +6804,7 @@ | |||
6609 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 6804 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
6610 | }, | 6805 | }, |
6611 | <span class="hljs-attr">"language"</span>: { | 6806 | <span class="hljs-attr">"language"</span>: { |
6612 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 6807 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
6613 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 6808 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
6614 | }, | 6809 | }, |
6615 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 6810 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
@@ -7219,7 +7414,7 @@ | |||
7219 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 7414 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
7220 | }, | 7415 | }, |
7221 | <span class="hljs-attr">"language"</span>: { | 7416 | <span class="hljs-attr">"language"</span>: { |
7222 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>, | 7417 | <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>, |
7223 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> | 7418 | <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span> |
7224 | }, | 7419 | }, |
7225 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, | 7420 | <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>, |
diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml index 10f60175d..4a1f06d00 100644 --- a/support/doc/api/openapi.yaml +++ b/support/doc/api/openapi.yaml | |||
@@ -91,7 +91,7 @@ paths: | |||
91 | in: path | 91 | in: path |
92 | required: true | 92 | required: true |
93 | type: string | 93 | type: string |
94 | enum: ['xml', 'atom' 'json'] | 94 | enum: [ 'xml', 'atom', 'json'] |
95 | default: 'xml' | 95 | default: 'xml' |
96 | description: 'The format expected (xml defaults to RSS 2.0, atom to ATOM 1.0 and json to JSON FEED 1.0' | 96 | description: 'The format expected (xml defaults to RSS 2.0, atom to ATOM 1.0 and json to JSON FEED 1.0' |
97 | - name: accountId | 97 | - name: accountId |
@@ -967,7 +967,7 @@ paths: | |||
967 | type: array | 967 | type: array |
968 | items: | 968 | items: |
969 | $ref: '#/definitions/VideoBlacklist' | 969 | $ref: '#/definitions/VideoBlacklist' |
970 | /videos/channels: | 970 | /video-channels: |
971 | get: | 971 | get: |
972 | tags: | 972 | tags: |
973 | - VideoChannel | 973 | - VideoChannel |
@@ -998,6 +998,27 @@ paths: | |||
998 | type: array | 998 | type: array |
999 | items: | 999 | items: |
1000 | $ref: '#/definitions/VideoChannel' | 1000 | $ref: '#/definitions/VideoChannel' |
1001 | /accounts/{accountId}/video-channels: | ||
1002 | get: | ||
1003 | tags: | ||
1004 | - VideoChannel | ||
1005 | consumes: | ||
1006 | - application/json | ||
1007 | produces: | ||
1008 | - application/json | ||
1009 | parameters: | ||
1010 | - name: accountId | ||
1011 | in: path | ||
1012 | required: true | ||
1013 | type: string | ||
1014 | description: 'The account id ' | ||
1015 | responses: | ||
1016 | '200': | ||
1017 | description: successful operation | ||
1018 | schema: | ||
1019 | type: array | ||
1020 | items: | ||
1021 | $ref: '#/definitions/VideoChannel' | ||
1001 | post: | 1022 | post: |
1002 | security: | 1023 | security: |
1003 | - OAuth2: [ ] | 1024 | - OAuth2: [ ] |
@@ -1008,6 +1029,11 @@ paths: | |||
1008 | produces: | 1029 | produces: |
1009 | - application/json | 1030 | - application/json |
1010 | parameters: | 1031 | parameters: |
1032 | - name: accountId | ||
1033 | in: path | ||
1034 | required: true | ||
1035 | type: string | ||
1036 | description: 'The account id ' | ||
1011 | - in: body | 1037 | - in: body |
1012 | name: body | 1038 | name: body |
1013 | schema: | 1039 | schema: |
@@ -1015,7 +1041,7 @@ paths: | |||
1015 | responses: | 1041 | responses: |
1016 | '204': | 1042 | '204': |
1017 | description: successful operation | 1043 | description: successful operation |
1018 | "/videos/channels/{id}": | 1044 | "/account/{accountId}/video-channels/{id}": |
1019 | get: | 1045 | get: |
1020 | tags: | 1046 | tags: |
1021 | - VideoChannel | 1047 | - VideoChannel |
@@ -1024,11 +1050,16 @@ paths: | |||
1024 | produces: | 1050 | produces: |
1025 | - application/json | 1051 | - application/json |
1026 | parameters: | 1052 | parameters: |
1053 | - name: accountId | ||
1054 | in: path | ||
1055 | required: true | ||
1056 | type: string | ||
1057 | description: 'The account id ' | ||
1027 | - name: id | 1058 | - name: id |
1028 | in: path | 1059 | in: path |
1029 | required: true | 1060 | required: true |
1030 | type: string | 1061 | type: string |
1031 | description: 'The video id ' | 1062 | description: 'The video channel id ' |
1032 | responses: | 1063 | responses: |
1033 | '200': | 1064 | '200': |
1034 | description: successful operation | 1065 | description: successful operation |
@@ -1044,11 +1075,16 @@ paths: | |||
1044 | produces: | 1075 | produces: |
1045 | - application/json | 1076 | - application/json |
1046 | parameters: | 1077 | parameters: |
1078 | - name: accountId | ||
1079 | in: path | ||
1080 | required: true | ||
1081 | type: string | ||
1082 | description: 'The account id ' | ||
1047 | - name: id | 1083 | - name: id |
1048 | in: path | 1084 | in: path |
1049 | required: true | 1085 | required: true |
1050 | type: string | 1086 | type: string |
1051 | description: 'The video id ' | 1087 | description: 'The video channel id ' |
1052 | - in: body | 1088 | - in: body |
1053 | name: body | 1089 | name: body |
1054 | schema: | 1090 | schema: |
@@ -1066,35 +1102,19 @@ paths: | |||
1066 | produces: | 1102 | produces: |
1067 | - application/json | 1103 | - application/json |
1068 | parameters: | 1104 | parameters: |
1069 | - name: id | 1105 | - name: accountId |
1070 | in: path | 1106 | in: path |
1071 | required: true | 1107 | required: true |
1072 | type: string | 1108 | type: string |
1073 | description: 'The video id ' | 1109 | description: 'The account id ' |
1074 | responses: | 1110 | - name: id |
1075 | '204': | ||
1076 | description: successful operation | ||
1077 | /videos/accounts/{accountId}/channels: | ||
1078 | get: | ||
1079 | tags: | ||
1080 | - VideoChannel | ||
1081 | consumes: | ||
1082 | - application/json | ||
1083 | produces: | ||
1084 | - application/json | ||
1085 | parameters: | ||
1086 | - name: accountId | ||
1087 | in: path | 1111 | in: path |
1088 | required: true | 1112 | required: true |
1089 | type: string | 1113 | type: string |
1090 | description: 'The account id ' | 1114 | description: 'The video channel id ' |
1091 | responses: | 1115 | responses: |
1092 | '200': | 1116 | '204': |
1093 | description: successful operation | 1117 | description: successful operation |
1094 | schema: | ||
1095 | type: array | ||
1096 | items: | ||
1097 | $ref: '#/definitions/VideoChannel' | ||
1098 | "/videos/{videoId}/comment-threads": | 1118 | "/videos/{videoId}/comment-threads": |
1099 | get: | 1119 | get: |
1100 | tags: | 1120 | tags: |