Update video channel routes
This commit is contained in:
parent
82e392f8a4
commit
48dce1c90d
|
@ -5,6 +5,9 @@
|
||||||
### BREAKING CHANGES
|
### BREAKING CHANGES
|
||||||
|
|
||||||
* Hide by default NSFW videos. Update the `instance.default_nsfw_policy` configuration to `blur` to keep the old behaviour
|
* Hide by default NSFW videos. Update the `instance.default_nsfw_policy` configuration to `blur` to keep the old behaviour
|
||||||
|
* Move video channels routes:
|
||||||
|
* `/videos/channels` routes to `/accounts/{accountId}/video-channels`
|
||||||
|
* `/videos/accounts/{accountId}/channels` route to `/accounts/{accountId}/video-channels`
|
||||||
* PeerTube now listen on 127.0.0.1 by default
|
* PeerTube now listen on 127.0.0.1 by default
|
||||||
* Use ISO 639 for language (*en*, *es*, *fr*...)
|
* Use ISO 639 for language (*en*, *es*, *fr*...)
|
||||||
* Tools (`import-videos`...) need the language ISO639 code instead of a number
|
* Tools (`import-videos`...) need the language ISO639 code instead of a number
|
||||||
|
|
|
@ -1,11 +1,30 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { getFormattedObjects } from '../../helpers/utils'
|
import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils'
|
||||||
import { asyncMiddleware, optionalAuthenticate, paginationValidator, setDefaultPagination, setDefaultSort } from '../../middlewares'
|
import {
|
||||||
|
asyncMiddleware,
|
||||||
|
authenticate,
|
||||||
|
listVideoAccountChannelsValidator,
|
||||||
|
optionalAuthenticate,
|
||||||
|
paginationValidator,
|
||||||
|
setDefaultPagination,
|
||||||
|
setDefaultSort,
|
||||||
|
videoChannelsAddValidator,
|
||||||
|
videoChannelsGetValidator,
|
||||||
|
videoChannelsRemoveValidator,
|
||||||
|
videoChannelsUpdateValidator
|
||||||
|
} from '../../middlewares'
|
||||||
import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators'
|
import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators'
|
||||||
import { AccountModel } from '../../models/account/account'
|
import { AccountModel } from '../../models/account/account'
|
||||||
import { VideoModel } from '../../models/video/video'
|
import { VideoModel } from '../../models/video/video'
|
||||||
import { VideoSortField } from '../../../client/src/app/shared/video/sort-field.type'
|
|
||||||
import { isNSFWHidden } from '../../helpers/express-utils'
|
import { isNSFWHidden } from '../../helpers/express-utils'
|
||||||
|
import { VideoChannelModel } from '../../models/video/video-channel'
|
||||||
|
import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
|
||||||
|
import { sendUpdateActor } from '../../lib/activitypub/send'
|
||||||
|
import { createVideoChannel } from '../../lib/video-channel'
|
||||||
|
import { setAsyncActorKeys } from '../../lib/activitypub'
|
||||||
|
import { sequelizeTypescript } from '../../initializers'
|
||||||
|
import { logger } from '../../helpers/logger'
|
||||||
|
import { retryTransactionWrapper } from '../../helpers/database-utils'
|
||||||
|
|
||||||
const accountsRouter = express.Router()
|
const accountsRouter = express.Router()
|
||||||
|
|
||||||
|
@ -29,7 +48,45 @@ accountsRouter.get('/:id/videos',
|
||||||
setDefaultSort,
|
setDefaultSort,
|
||||||
setDefaultPagination,
|
setDefaultPagination,
|
||||||
optionalAuthenticate,
|
optionalAuthenticate,
|
||||||
asyncMiddleware(getAccountVideos)
|
asyncMiddleware(listAccountVideos)
|
||||||
|
)
|
||||||
|
|
||||||
|
accountsRouter.get('/:accountId/video-channels',
|
||||||
|
asyncMiddleware(listVideoAccountChannelsValidator),
|
||||||
|
asyncMiddleware(listVideoAccountChannels)
|
||||||
|
)
|
||||||
|
|
||||||
|
accountsRouter.post('/:accountId/video-channels',
|
||||||
|
authenticate,
|
||||||
|
videoChannelsAddValidator,
|
||||||
|
asyncMiddleware(addVideoChannelRetryWrapper)
|
||||||
|
)
|
||||||
|
|
||||||
|
accountsRouter.put('/:accountId/video-channels/:id',
|
||||||
|
authenticate,
|
||||||
|
asyncMiddleware(videoChannelsUpdateValidator),
|
||||||
|
updateVideoChannelRetryWrapper
|
||||||
|
)
|
||||||
|
|
||||||
|
accountsRouter.delete('/:accountId/video-channels/:id',
|
||||||
|
authenticate,
|
||||||
|
asyncMiddleware(videoChannelsRemoveValidator),
|
||||||
|
asyncMiddleware(removeVideoChannelRetryWrapper)
|
||||||
|
)
|
||||||
|
|
||||||
|
accountsRouter.get('/:accountId/video-channels/:id',
|
||||||
|
asyncMiddleware(videoChannelsGetValidator),
|
||||||
|
asyncMiddleware(getVideoChannel)
|
||||||
|
)
|
||||||
|
|
||||||
|
accountsRouter.get('/:accountId/video-channels/:id/videos',
|
||||||
|
asyncMiddleware(videoChannelsGetValidator),
|
||||||
|
paginationValidator,
|
||||||
|
videosSortValidator,
|
||||||
|
setDefaultSort,
|
||||||
|
setDefaultPagination,
|
||||||
|
optionalAuthenticate,
|
||||||
|
asyncMiddleware(listVideoChannelVideos)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -52,18 +109,142 @@ async function listAccounts (req: express.Request, res: express.Response, next:
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
async function listVideoAccountChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
const account: AccountModel = res.locals.account
|
const resultList = await VideoChannelModel.listByAccount(res.locals.account.id)
|
||||||
|
|
||||||
const resultList = await VideoModel.listForApi(
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
req.query.start as number,
|
}
|
||||||
req.query.count as number,
|
|
||||||
req.query.sort as VideoSortField,
|
// Wrapper to video channel add that retry the async function if there is a database error
|
||||||
isNSFWHidden(res),
|
// We need this because we run the transaction in SERIALIZABLE isolation that can fail
|
||||||
null,
|
async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
false,
|
const options = {
|
||||||
account.id
|
arguments: [ req, res ],
|
||||||
)
|
errorMessage: 'Cannot insert the video video channel with many retries.'
|
||||||
|
}
|
||||||
|
|
||||||
|
const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
|
||||||
|
return res.json({
|
||||||
|
videoChannel: {
|
||||||
|
id: videoChannel.id
|
||||||
|
}
|
||||||
|
}).end()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addVideoChannel (req: express.Request, res: express.Response) {
|
||||||
|
const videoChannelInfo: VideoChannelCreate = req.body
|
||||||
|
const account: AccountModel = res.locals.oauth.token.User.Account
|
||||||
|
|
||||||
|
const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
|
||||||
|
return createVideoChannel(videoChannelInfo, account, t)
|
||||||
|
})
|
||||||
|
|
||||||
|
setAsyncActorKeys(videoChannelCreated.Actor)
|
||||||
|
.catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err }))
|
||||||
|
|
||||||
|
logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
|
||||||
|
|
||||||
|
return videoChannelCreated
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
const options = {
|
||||||
|
arguments: [ req, res ],
|
||||||
|
errorMessage: 'Cannot update the video with many retries.'
|
||||||
|
}
|
||||||
|
|
||||||
|
await retryTransactionWrapper(updateVideoChannel, options)
|
||||||
|
|
||||||
|
return res.type('json').status(204).end()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateVideoChannel (req: express.Request, res: express.Response) {
|
||||||
|
const videoChannelInstance = res.locals.videoChannel as VideoChannelModel
|
||||||
|
const videoChannelFieldsSave = videoChannelInstance.toJSON()
|
||||||
|
const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sequelizeTypescript.transaction(async t => {
|
||||||
|
const sequelizeOptions = {
|
||||||
|
transaction: t
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name)
|
||||||
|
if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description)
|
||||||
|
if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support)
|
||||||
|
|
||||||
|
const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
|
||||||
|
await sendUpdateActor(videoChannelInstanceUpdated, t)
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
|
||||||
|
} catch (err) {
|
||||||
|
logger.debug('Cannot update the video channel.', { err })
|
||||||
|
|
||||||
|
// Force fields we want to update
|
||||||
|
// If the transaction is retried, sequelize will think the object has not changed
|
||||||
|
// So it will skip the SQL request, even if the last one was ROLLBACKed!
|
||||||
|
resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave)
|
||||||
|
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
const options = {
|
||||||
|
arguments: [ req, res ],
|
||||||
|
errorMessage: 'Cannot remove the video channel with many retries.'
|
||||||
|
}
|
||||||
|
|
||||||
|
await retryTransactionWrapper(removeVideoChannel, options)
|
||||||
|
|
||||||
|
return res.type('json').status(204).end()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeVideoChannel (req: express.Request, res: express.Response) {
|
||||||
|
const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
|
||||||
|
|
||||||
|
return sequelizeTypescript.transaction(async t => {
|
||||||
|
await videoChannelInstance.destroy({ transaction: t })
|
||||||
|
|
||||||
|
logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id)
|
||||||
|
|
||||||
|
return res.json(videoChannelWithVideos.toFormattedJSON())
|
||||||
|
}
|
||||||
|
|
||||||
|
async function listVideoChannelVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
|
||||||
|
|
||||||
|
const resultList = await VideoModel.listForApi({
|
||||||
|
start: req.query.start,
|
||||||
|
count: req.query.count,
|
||||||
|
sort: req.query.sort,
|
||||||
|
hideNSFW: isNSFWHidden(res),
|
||||||
|
withFiles: false,
|
||||||
|
videoChannelId: videoChannelInstance.id
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
const account: AccountModel = res.locals.account
|
||||||
|
|
||||||
|
const resultList = await VideoModel.listForApi({
|
||||||
|
start: req.query.start,
|
||||||
|
count: req.query.count,
|
||||||
|
sort: req.query.sort,
|
||||||
|
hideNSFW: isNSFWHidden(res),
|
||||||
|
withFiles: false,
|
||||||
|
accountId: account.id
|
||||||
|
})
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { usersRouter } from './users'
|
||||||
import { accountsRouter } from './accounts'
|
import { accountsRouter } from './accounts'
|
||||||
import { videosRouter } from './videos'
|
import { videosRouter } from './videos'
|
||||||
import { badRequest } from '../../helpers/express-utils'
|
import { badRequest } from '../../helpers/express-utils'
|
||||||
|
import { videoChannelRouter } from './video-channel'
|
||||||
|
|
||||||
const apiRouter = express.Router()
|
const apiRouter = express.Router()
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ apiRouter.use('/oauth-clients', oauthClientsRouter)
|
||||||
apiRouter.use('/config', configRouter)
|
apiRouter.use('/config', configRouter)
|
||||||
apiRouter.use('/users', usersRouter)
|
apiRouter.use('/users', usersRouter)
|
||||||
apiRouter.use('/accounts', accountsRouter)
|
apiRouter.use('/accounts', accountsRouter)
|
||||||
|
apiRouter.use('/video-channels', videoChannelRouter)
|
||||||
apiRouter.use('/videos', videosRouter)
|
apiRouter.use('/videos', videosRouter)
|
||||||
apiRouter.use('/jobs', jobsRouter)
|
apiRouter.use('/jobs', jobsRouter)
|
||||||
apiRouter.use('/ping', pong)
|
apiRouter.use('/ping', pong)
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import * as express from 'express'
|
||||||
|
import { getFormattedObjects } from '../../helpers/utils'
|
||||||
|
import {
|
||||||
|
asyncMiddleware,
|
||||||
|
paginationValidator,
|
||||||
|
setDefaultPagination,
|
||||||
|
setDefaultSort,
|
||||||
|
videoChannelsSortValidator
|
||||||
|
} from '../../middlewares'
|
||||||
|
import { VideoChannelModel } from '../../models/video/video-channel'
|
||||||
|
|
||||||
|
const videoChannelRouter = express.Router()
|
||||||
|
|
||||||
|
videoChannelRouter.get('/',
|
||||||
|
paginationValidator,
|
||||||
|
videoChannelsSortValidator,
|
||||||
|
setDefaultSort,
|
||||||
|
setDefaultPagination,
|
||||||
|
asyncMiddleware(listVideoChannels)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export {
|
||||||
|
videoChannelRouter
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
async function listVideoChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
const resultList = await VideoChannelModel.listForApi(req.query.start, req.query.count, req.query.sort)
|
||||||
|
|
||||||
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
|
}
|
|
@ -1,177 +0,0 @@
|
||||||
import * as express from 'express'
|
|
||||||
import { VideoChannelCreate, VideoChannelUpdate } from '../../../../shared'
|
|
||||||
import { retryTransactionWrapper } from '../../../helpers/database-utils'
|
|
||||||
import { logger } from '../../../helpers/logger'
|
|
||||||
import { getFormattedObjects, resetSequelizeInstance } from '../../../helpers/utils'
|
|
||||||
import { sequelizeTypescript } from '../../../initializers'
|
|
||||||
import { setAsyncActorKeys } from '../../../lib/activitypub'
|
|
||||||
import { sendUpdateActor } from '../../../lib/activitypub/send'
|
|
||||||
import { createVideoChannel } from '../../../lib/video-channel'
|
|
||||||
import {
|
|
||||||
asyncMiddleware, authenticate, listVideoAccountChannelsValidator, paginationValidator, setDefaultSort, setDefaultPagination,
|
|
||||||
videoChannelsAddValidator, videoChannelsGetValidator, videoChannelsRemoveValidator, videoChannelsSortValidator,
|
|
||||||
videoChannelsUpdateValidator
|
|
||||||
} from '../../../middlewares'
|
|
||||||
import { AccountModel } from '../../../models/account/account'
|
|
||||||
import { VideoChannelModel } from '../../../models/video/video-channel'
|
|
||||||
|
|
||||||
const videoChannelRouter = express.Router()
|
|
||||||
|
|
||||||
videoChannelRouter.get('/channels',
|
|
||||||
paginationValidator,
|
|
||||||
videoChannelsSortValidator,
|
|
||||||
setDefaultSort,
|
|
||||||
setDefaultPagination,
|
|
||||||
asyncMiddleware(listVideoChannels)
|
|
||||||
)
|
|
||||||
|
|
||||||
videoChannelRouter.get('/accounts/:accountId/channels',
|
|
||||||
asyncMiddleware(listVideoAccountChannelsValidator),
|
|
||||||
asyncMiddleware(listVideoAccountChannels)
|
|
||||||
)
|
|
||||||
|
|
||||||
videoChannelRouter.post('/channels',
|
|
||||||
authenticate,
|
|
||||||
videoChannelsAddValidator,
|
|
||||||
asyncMiddleware(addVideoChannelRetryWrapper)
|
|
||||||
)
|
|
||||||
|
|
||||||
videoChannelRouter.put('/channels/:id',
|
|
||||||
authenticate,
|
|
||||||
asyncMiddleware(videoChannelsUpdateValidator),
|
|
||||||
updateVideoChannelRetryWrapper
|
|
||||||
)
|
|
||||||
|
|
||||||
videoChannelRouter.delete('/channels/:id',
|
|
||||||
authenticate,
|
|
||||||
asyncMiddleware(videoChannelsRemoveValidator),
|
|
||||||
asyncMiddleware(removeVideoChannelRetryWrapper)
|
|
||||||
)
|
|
||||||
|
|
||||||
videoChannelRouter.get('/channels/:id',
|
|
||||||
asyncMiddleware(videoChannelsGetValidator),
|
|
||||||
asyncMiddleware(getVideoChannel)
|
|
||||||
)
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export {
|
|
||||||
videoChannelRouter
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
async function listVideoChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
const resultList = await VideoChannelModel.listForApi(req.query.start, req.query.count, req.query.sort)
|
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listVideoAccountChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
const resultList = await VideoChannelModel.listByAccount(res.locals.account.id)
|
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapper to video channel add that retry the async function if there is a database error
|
|
||||||
// We need this because we run the transaction in SERIALIZABLE isolation that can fail
|
|
||||||
async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
const options = {
|
|
||||||
arguments: [ req, res ],
|
|
||||||
errorMessage: 'Cannot insert the video video channel with many retries.'
|
|
||||||
}
|
|
||||||
|
|
||||||
const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
|
|
||||||
return res.json({
|
|
||||||
videoChannel: {
|
|
||||||
id: videoChannel.id
|
|
||||||
}
|
|
||||||
}).end()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function addVideoChannel (req: express.Request, res: express.Response) {
|
|
||||||
const videoChannelInfo: VideoChannelCreate = req.body
|
|
||||||
const account: AccountModel = res.locals.oauth.token.User.Account
|
|
||||||
|
|
||||||
const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
|
|
||||||
return createVideoChannel(videoChannelInfo, account, t)
|
|
||||||
})
|
|
||||||
|
|
||||||
setAsyncActorKeys(videoChannelCreated.Actor)
|
|
||||||
.catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err }))
|
|
||||||
|
|
||||||
logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
|
|
||||||
|
|
||||||
return videoChannelCreated
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
const options = {
|
|
||||||
arguments: [ req, res ],
|
|
||||||
errorMessage: 'Cannot update the video with many retries.'
|
|
||||||
}
|
|
||||||
|
|
||||||
await retryTransactionWrapper(updateVideoChannel, options)
|
|
||||||
|
|
||||||
return res.type('json').status(204).end()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateVideoChannel (req: express.Request, res: express.Response) {
|
|
||||||
const videoChannelInstance = res.locals.videoChannel as VideoChannelModel
|
|
||||||
const videoChannelFieldsSave = videoChannelInstance.toJSON()
|
|
||||||
const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
|
|
||||||
|
|
||||||
try {
|
|
||||||
await sequelizeTypescript.transaction(async t => {
|
|
||||||
const sequelizeOptions = {
|
|
||||||
transaction: t
|
|
||||||
}
|
|
||||||
|
|
||||||
if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name)
|
|
||||||
if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description)
|
|
||||||
if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support)
|
|
||||||
|
|
||||||
const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
|
|
||||||
await sendUpdateActor(videoChannelInstanceUpdated, t)
|
|
||||||
})
|
|
||||||
|
|
||||||
logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
|
|
||||||
} catch (err) {
|
|
||||||
logger.debug('Cannot update the video channel.', { err })
|
|
||||||
|
|
||||||
// Force fields we want to update
|
|
||||||
// If the transaction is retried, sequelize will think the object has not changed
|
|
||||||
// So it will skip the SQL request, even if the last one was ROLLBACKed!
|
|
||||||
resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave)
|
|
||||||
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
const options = {
|
|
||||||
arguments: [ req, res ],
|
|
||||||
errorMessage: 'Cannot remove the video channel with many retries.'
|
|
||||||
}
|
|
||||||
|
|
||||||
await retryTransactionWrapper(removeVideoChannel, options)
|
|
||||||
|
|
||||||
return res.type('json').status(204).end()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function removeVideoChannel (req: express.Request, res: express.Response) {
|
|
||||||
const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
|
|
||||||
|
|
||||||
return sequelizeTypescript.transaction(async t => {
|
|
||||||
await videoChannelInstance.destroy({ transaction: t })
|
|
||||||
|
|
||||||
logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
||||||
const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id)
|
|
||||||
|
|
||||||
return res.json(videoChannelWithVideos.toFormattedJSON())
|
|
||||||
}
|
|
|
@ -42,7 +42,6 @@ import { VideoModel } from '../../../models/video/video'
|
||||||
import { VideoFileModel } from '../../../models/video/video-file'
|
import { VideoFileModel } from '../../../models/video/video-file'
|
||||||
import { abuseVideoRouter } from './abuse'
|
import { abuseVideoRouter } from './abuse'
|
||||||
import { blacklistRouter } from './blacklist'
|
import { blacklistRouter } from './blacklist'
|
||||||
import { videoChannelRouter } from './channel'
|
|
||||||
import { videoCommentRouter } from './comment'
|
import { videoCommentRouter } from './comment'
|
||||||
import { rateVideoRouter } from './rate'
|
import { rateVideoRouter } from './rate'
|
||||||
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
|
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
|
||||||
|
@ -72,7 +71,6 @@ const reqVideoFileUpdate = createReqFiles(
|
||||||
videosRouter.use('/', abuseVideoRouter)
|
videosRouter.use('/', abuseVideoRouter)
|
||||||
videosRouter.use('/', blacklistRouter)
|
videosRouter.use('/', blacklistRouter)
|
||||||
videosRouter.use('/', rateVideoRouter)
|
videosRouter.use('/', rateVideoRouter)
|
||||||
videosRouter.use('/', videoChannelRouter)
|
|
||||||
videosRouter.use('/', videoCommentRouter)
|
videosRouter.use('/', videoCommentRouter)
|
||||||
|
|
||||||
videosRouter.get('/categories', listVideoCategories)
|
videosRouter.get('/categories', listVideoCategories)
|
||||||
|
@ -397,13 +395,14 @@ async function getVideoDescription (req: express.Request, res: express.Response)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
async function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
const resultList = await VideoModel.listForApi(
|
const resultList = await VideoModel.listForApi({
|
||||||
req.query.start as number,
|
start: req.query.start,
|
||||||
req.query.count as number,
|
count: req.query.count,
|
||||||
req.query.sort as VideoSortField,
|
sort: req.query.sort,
|
||||||
isNSFWHidden(res),
|
hideNSFW: isNSFWHidden(res),
|
||||||
req.query.filter as VideoFilter
|
filter: req.query.filter as VideoFilter,
|
||||||
)
|
withFiles: false
|
||||||
|
})
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,15 +33,15 @@ async function generateFeed (req: express.Request, res: express.Response, next:
|
||||||
const account: AccountModel = res.locals.account
|
const account: AccountModel = res.locals.account
|
||||||
const hideNSFW = CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list'
|
const hideNSFW = CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list'
|
||||||
|
|
||||||
const resultList = await VideoModel.listForApi(
|
const resultList = await VideoModel.listForApi({
|
||||||
start,
|
start,
|
||||||
FEEDS.COUNT,
|
count: FEEDS.COUNT,
|
||||||
req.query.sort as VideoSortField,
|
sort: req.query.sort,
|
||||||
hideNSFW,
|
hideNSFW,
|
||||||
req.query.filter,
|
filter: req.query.filter,
|
||||||
true,
|
withFiles: true,
|
||||||
account ? account.id : null
|
accountId: account ? account.id : null
|
||||||
)
|
})
|
||||||
|
|
||||||
// Adding video items to the feed, one at a time
|
// Adding video items to the feed, one at a time
|
||||||
resultList.data.forEach(video => {
|
resultList.data.forEach(video => {
|
||||||
|
|
|
@ -16,7 +16,7 @@ const followValidator = [
|
||||||
if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
|
if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
|
||||||
return res.status(400)
|
return res.status(400)
|
||||||
.json({
|
.json({
|
||||||
error: 'Cannot follow non HTTPS web server.'
|
error: 'Cannot follow on a non HTTPS web server.'
|
||||||
})
|
})
|
||||||
.end()
|
.end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ const listVideoAccountChannelsValidator = [
|
||||||
]
|
]
|
||||||
|
|
||||||
const videoChannelsAddValidator = [
|
const videoChannelsAddValidator = [
|
||||||
|
param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
|
||||||
body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
|
body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
|
||||||
body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
|
body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
|
||||||
body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
|
body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
|
||||||
|
@ -41,6 +42,7 @@ const videoChannelsAddValidator = [
|
||||||
|
|
||||||
const videoChannelsUpdateValidator = [
|
const videoChannelsUpdateValidator = [
|
||||||
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
|
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
|
||||||
|
param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
|
||||||
body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
|
body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
|
||||||
body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
|
body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
|
||||||
body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
|
body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
|
||||||
|
@ -49,6 +51,7 @@ const videoChannelsUpdateValidator = [
|
||||||
logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
|
logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
if (!await isAccountIdExist(req.params.accountId, res)) return
|
||||||
if (!await isVideoChannelExist(req.params.id, res)) return
|
if (!await isVideoChannelExist(req.params.id, res)) return
|
||||||
|
|
||||||
// We need to make additional checks
|
// We need to make additional checks
|
||||||
|
@ -70,11 +73,13 @@ const videoChannelsUpdateValidator = [
|
||||||
|
|
||||||
const videoChannelsRemoveValidator = [
|
const videoChannelsRemoveValidator = [
|
||||||
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
|
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
|
||||||
|
param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
|
||||||
|
|
||||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
|
logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
if (!await isAccountIdExist(req.params.accountId, res)) return
|
||||||
if (!await isVideoChannelExist(req.params.id, res)) return
|
if (!await isVideoChannelExist(req.params.id, res)) return
|
||||||
|
|
||||||
// Check if the user who did the request is able to delete the video
|
// Check if the user who did the request is able to delete the video
|
||||||
|
@ -87,11 +92,14 @@ const videoChannelsRemoveValidator = [
|
||||||
|
|
||||||
const videoChannelsGetValidator = [
|
const videoChannelsGetValidator = [
|
||||||
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
|
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
|
||||||
|
param('accountId').optional().custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
|
||||||
|
|
||||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking videoChannelsGet parameters', { parameters: req.params })
|
logger.debug('Checking videoChannelsGet parameters', { parameters: req.params })
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
// On some routes, accountId is optional (for example in the ActivityPub route)
|
||||||
|
if (req.params.accountId && !await isAccountIdExist(req.params.accountId, res)) return
|
||||||
if (!await isVideoChannelExist(req.params.id, res)) return
|
if (!await isVideoChannelExist(req.params.id, res)) return
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
|
|
|
@ -95,7 +95,14 @@ enum ScopeNames {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scopes({
|
@Scopes({
|
||||||
[ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, hideNSFW: boolean, filter?: VideoFilter, withFiles?: boolean, accountId?: number) => {
|
[ScopeNames.AVAILABLE_FOR_LIST]: (options: {
|
||||||
|
actorId: number,
|
||||||
|
hideNSFW: boolean,
|
||||||
|
filter?: VideoFilter,
|
||||||
|
withFiles?: boolean,
|
||||||
|
accountId?: number,
|
||||||
|
videoChannelId?: number
|
||||||
|
}) => {
|
||||||
const accountInclude = {
|
const accountInclude = {
|
||||||
attributes: [ 'name' ],
|
attributes: [ 'name' ],
|
||||||
model: AccountModel.unscoped(),
|
model: AccountModel.unscoped(),
|
||||||
|
@ -106,7 +113,7 @@ enum ScopeNames {
|
||||||
attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ],
|
attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ],
|
||||||
model: ActorModel.unscoped(),
|
model: ActorModel.unscoped(),
|
||||||
required: true,
|
required: true,
|
||||||
where: VideoModel.buildActorWhereWithFilter(filter),
|
where: VideoModel.buildActorWhereWithFilter(options.filter),
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
attributes: [ 'host' ],
|
attributes: [ 'host' ],
|
||||||
|
@ -122,6 +129,18 @@ enum ScopeNames {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const videoChannelInclude = {
|
||||||
|
attributes: [ 'name', 'description' ],
|
||||||
|
model: VideoChannelModel.unscoped(),
|
||||||
|
required: true,
|
||||||
|
where: {},
|
||||||
|
include: [
|
||||||
|
accountInclude
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force actorId to be a number to avoid SQL injections
|
||||||
|
const actorIdNumber = parseInt(options.actorId.toString(), 10)
|
||||||
const query: IFindOptions<VideoModel> = {
|
const query: IFindOptions<VideoModel> = {
|
||||||
where: {
|
where: {
|
||||||
id: {
|
id: {
|
||||||
|
@ -132,32 +151,23 @@ enum ScopeNames {
|
||||||
'(' +
|
'(' +
|
||||||
'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' +
|
'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' +
|
||||||
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' +
|
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' +
|
||||||
'WHERE "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) +
|
'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
|
||||||
' UNION ' +
|
' UNION ' +
|
||||||
'SELECT "video"."id" AS "id" FROM "video" ' +
|
'SELECT "video"."id" AS "id" FROM "video" ' +
|
||||||
'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
|
'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
|
||||||
'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' +
|
'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' +
|
||||||
'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' +
|
'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' +
|
||||||
'LEFT JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' +
|
'LEFT JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' +
|
||||||
'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) +
|
'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + actorIdNumber +
|
||||||
')'
|
')'
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
privacy: VideoPrivacy.PUBLIC
|
privacy: VideoPrivacy.PUBLIC
|
||||||
},
|
},
|
||||||
include: [
|
include: [ videoChannelInclude ]
|
||||||
{
|
|
||||||
attributes: [ 'name', 'description' ],
|
|
||||||
model: VideoChannelModel.unscoped(),
|
|
||||||
required: true,
|
|
||||||
include: [
|
|
||||||
accountInclude
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withFiles === true) {
|
if (options.withFiles === true) {
|
||||||
query.include.push({
|
query.include.push({
|
||||||
model: VideoFileModel.unscoped(),
|
model: VideoFileModel.unscoped(),
|
||||||
required: true
|
required: true
|
||||||
|
@ -165,13 +175,19 @@ enum ScopeNames {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide nsfw videos?
|
// Hide nsfw videos?
|
||||||
if (hideNSFW === true) {
|
if (options.hideNSFW === true) {
|
||||||
query.where['nsfw'] = false
|
query.where['nsfw'] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accountId) {
|
if (options.accountId) {
|
||||||
accountInclude.where = {
|
accountInclude.where = {
|
||||||
id: accountId
|
id: options.accountId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.videoChannelId) {
|
||||||
|
videoChannelInclude.where = {
|
||||||
|
id: options.videoChannelId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -697,23 +713,37 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async listForApi (
|
static async listForApi (options: {
|
||||||
start: number,
|
start: number,
|
||||||
count: number,
|
count: number,
|
||||||
sort: string,
|
sort: string,
|
||||||
hideNSFW: boolean,
|
hideNSFW: boolean,
|
||||||
|
withFiles: boolean,
|
||||||
filter?: VideoFilter,
|
filter?: VideoFilter,
|
||||||
withFiles = false,
|
accountId?: number,
|
||||||
accountId?: number
|
videoChannelId?: number
|
||||||
) {
|
}) {
|
||||||
const query = {
|
const query = {
|
||||||
offset: start,
|
offset: options.start,
|
||||||
limit: count,
|
limit: options.count,
|
||||||
order: getSort(sort)
|
order: getSort(options.sort)
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverActor = await getServerActor()
|
const serverActor = await getServerActor()
|
||||||
return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW, filter, withFiles, accountId ] })
|
const scopes = {
|
||||||
|
method: [
|
||||||
|
ScopeNames.AVAILABLE_FOR_LIST, {
|
||||||
|
actorId: serverActor.id,
|
||||||
|
hideNSFW: options.hideNSFW,
|
||||||
|
filter: options.filter,
|
||||||
|
withFiles: options.withFiles,
|
||||||
|
accountId: options.accountId,
|
||||||
|
videoChannelId: options.videoChannelId
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return VideoModel.scope(scopes)
|
||||||
.findAndCountAll(query)
|
.findAndCountAll(query)
|
||||||
.then(({ rows, count }) => {
|
.then(({ rows, count }) => {
|
||||||
return {
|
return {
|
||||||
|
@ -750,8 +780,16 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverActor = await getServerActor()
|
const serverActor = await getServerActor()
|
||||||
|
const scopes = {
|
||||||
|
method: [
|
||||||
|
ScopeNames.AVAILABLE_FOR_LIST, {
|
||||||
|
actorId: serverActor.id,
|
||||||
|
hideNSFW
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW ] })
|
return VideoModel.scope(scopes)
|
||||||
.findAndCountAll(query)
|
.findAndCountAll(query)
|
||||||
.then(({ rows, count }) => {
|
.then(({ rows, count }) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,15 +4,29 @@ import * as chai from 'chai'
|
||||||
import { omit } from 'lodash'
|
import { omit } from 'lodash'
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import {
|
import {
|
||||||
createUser, deleteVideoChannel, flushTests, getAccountVideoChannelsList, getVideoChannelsList, immutableAssign, killallServers,
|
createUser,
|
||||||
makeGetRequest, makePostBodyRequest, makePutBodyRequest, runServer, ServerInfo, setAccessTokensToServers, userLogin
|
deleteVideoChannel,
|
||||||
|
flushTests,
|
||||||
|
getAccountVideoChannelsList,
|
||||||
|
getVideoChannelsList,
|
||||||
|
immutableAssign,
|
||||||
|
killallServers,
|
||||||
|
makeGetRequest,
|
||||||
|
makePostBodyRequest,
|
||||||
|
makePutBodyRequest,
|
||||||
|
runServer,
|
||||||
|
ServerInfo,
|
||||||
|
setAccessTokensToServers,
|
||||||
|
userLogin
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params'
|
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params'
|
||||||
|
import { getAccountsList } from '../../utils/users/accounts'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
describe('Test videos API validator', function () {
|
describe('Test videos API validator', function () {
|
||||||
const path = '/api/v1/videos/channels'
|
const videoChannelPath = '/api/v1/video-channels'
|
||||||
|
const accountPath = '/api/v1/accounts/'
|
||||||
let server: ServerInfo
|
let server: ServerInfo
|
||||||
let accessTokenUser: string
|
let accessTokenUser: string
|
||||||
|
|
||||||
|
@ -37,15 +51,15 @@ describe('Test videos API validator', function () {
|
||||||
|
|
||||||
describe('When listing a video channels', function () {
|
describe('When listing a video channels', function () {
|
||||||
it('Should fail with a bad start pagination', async function () {
|
it('Should fail with a bad start pagination', async function () {
|
||||||
await checkBadStartPagination(server.url, path, server.accessToken)
|
await checkBadStartPagination(server.url, videoChannelPath, server.accessToken)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a bad count pagination', async function () {
|
it('Should fail with a bad count pagination', async function () {
|
||||||
await checkBadCountPagination(server.url, path, server.accessToken)
|
await checkBadCountPagination(server.url, videoChannelPath, server.accessToken)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an incorrect sort', async function () {
|
it('Should fail with an incorrect sort', async function () {
|
||||||
await checkBadSortPagination(server.url, path, server.accessToken)
|
await checkBadSortPagination(server.url, videoChannelPath, server.accessToken)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -60,12 +74,20 @@ describe('Test videos API validator', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When adding a video channel', function () {
|
describe('When adding a video channel', function () {
|
||||||
|
let path: string
|
||||||
|
|
||||||
const baseCorrectParams = {
|
const baseCorrectParams = {
|
||||||
name: 'hello',
|
name: 'hello',
|
||||||
description: 'super description',
|
description: 'super description',
|
||||||
support: 'super support text'
|
support: 'super support text'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
const res = await getAccountsList(server.url)
|
||||||
|
const accountId = res.body.data[0].id
|
||||||
|
path = accountPath + accountId + '/video-channels'
|
||||||
|
})
|
||||||
|
|
||||||
it('Should fail with a non authenticated user', async function () {
|
it('Should fail with a non authenticated user', async function () {
|
||||||
await makePostBodyRequest({ url: server.url, path, token: 'none', fields: baseCorrectParams, statusCodeExpected: 401 })
|
await makePostBodyRequest({ url: server.url, path, token: 'none', fields: baseCorrectParams, statusCodeExpected: 401 })
|
||||||
})
|
})
|
||||||
|
@ -107,22 +129,27 @@ describe('Test videos API validator', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When updating a video channel', function () {
|
describe('When updating a video channel', function () {
|
||||||
|
let path: string
|
||||||
|
|
||||||
const baseCorrectParams = {
|
const baseCorrectParams = {
|
||||||
name: 'hello',
|
name: 'hello',
|
||||||
description: 'super description'
|
description: 'super description'
|
||||||
}
|
}
|
||||||
|
|
||||||
let videoChannelId
|
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
const res = await getVideoChannelsList(server.url, 0, 1)
|
const res1 = await getVideoChannelsList(server.url, 0, 1)
|
||||||
videoChannelId = res.body.data[0].id
|
const videoChannelId = res1.body.data[0].id
|
||||||
|
|
||||||
|
const res2 = await getAccountsList(server.url)
|
||||||
|
const accountId = res2.body.data[0].id
|
||||||
|
|
||||||
|
path = accountPath + accountId + '/video-channels/' + videoChannelId
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a non authenticated user', async function () {
|
it('Should fail with a non authenticated user', async function () {
|
||||||
await makePutBodyRequest({
|
await makePutBodyRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path: path + '/' + videoChannelId,
|
path,
|
||||||
token: 'hi',
|
token: 'hi',
|
||||||
fields: baseCorrectParams,
|
fields: baseCorrectParams,
|
||||||
statusCodeExpected: 401
|
statusCodeExpected: 401
|
||||||
|
@ -132,7 +159,7 @@ describe('Test videos API validator', function () {
|
||||||
it('Should fail with another authenticated user', async function () {
|
it('Should fail with another authenticated user', async function () {
|
||||||
await makePutBodyRequest({
|
await makePutBodyRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path: path + '/' + videoChannelId,
|
path,
|
||||||
token: accessTokenUser,
|
token: accessTokenUser,
|
||||||
fields: baseCorrectParams,
|
fields: baseCorrectParams,
|
||||||
statusCodeExpected: 403
|
statusCodeExpected: 403
|
||||||
|
@ -141,23 +168,23 @@ describe('Test videos API validator', function () {
|
||||||
|
|
||||||
it('Should fail with a long name', async function () {
|
it('Should fail with a long name', async function () {
|
||||||
const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(25) })
|
const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(25) })
|
||||||
await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields })
|
await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a long description', async function () {
|
it('Should fail with a long description', async function () {
|
||||||
const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(60) })
|
const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(60) })
|
||||||
await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields })
|
await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a long support text', async function () {
|
it('Should fail with a long support text', async function () {
|
||||||
const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) })
|
const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) })
|
||||||
await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields })
|
await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed with the correct parameters', async function () {
|
it('Should succeed with the correct parameters', async function () {
|
||||||
await makePutBodyRequest({
|
await makePutBodyRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path: path + '/' + videoChannelId,
|
path,
|
||||||
token: server.accessToken,
|
token: server.accessToken,
|
||||||
fields: baseCorrectParams,
|
fields: baseCorrectParams,
|
||||||
statusCodeExpected: 204
|
statusCodeExpected: 204
|
||||||
|
@ -166,17 +193,23 @@ describe('Test videos API validator', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When getting a video channel', function () {
|
describe('When getting a video channel', function () {
|
||||||
|
let basePath: string
|
||||||
let videoChannelId: number
|
let videoChannelId: number
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
const res = await getVideoChannelsList(server.url, 0, 1)
|
const res1 = await getVideoChannelsList(server.url, 0, 1)
|
||||||
videoChannelId = res.body.data[0].id
|
videoChannelId = res1.body.data[0].id
|
||||||
|
|
||||||
|
const res2 = await getAccountsList(server.url)
|
||||||
|
const accountId = res2.body.data[0].id
|
||||||
|
|
||||||
|
basePath = accountPath + accountId + '/video-channels'
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should return the list of the video channels with nothing', async function () {
|
it('Should return the list of the video channels with nothing', async function () {
|
||||||
const res = await makeGetRequest({
|
const res = await makeGetRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path,
|
path: basePath,
|
||||||
statusCodeExpected: 200
|
statusCodeExpected: 200
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -186,7 +219,7 @@ describe('Test videos API validator', function () {
|
||||||
it('Should fail without a correct uuid', async function () {
|
it('Should fail without a correct uuid', async function () {
|
||||||
await makeGetRequest({
|
await makeGetRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path: path + '/coucou',
|
path: basePath + '/coucou',
|
||||||
statusCodeExpected: 400
|
statusCodeExpected: 400
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -194,7 +227,7 @@ describe('Test videos API validator', function () {
|
||||||
it('Should return 404 with an incorrect video channel', async function () {
|
it('Should return 404 with an incorrect video channel', async function () {
|
||||||
await makeGetRequest({
|
await makeGetRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path: path + '/4da6fde3-88f7-4d16-b119-108df5630b06',
|
path: basePath + '/4da6fde3-88f7-4d16-b119-108df5630b06',
|
||||||
statusCodeExpected: 404
|
statusCodeExpected: 404
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -202,7 +235,7 @@ describe('Test videos API validator', function () {
|
||||||
it('Should succeed with the correct parameters', async function () {
|
it('Should succeed with the correct parameters', async function () {
|
||||||
await makeGetRequest({
|
await makeGetRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path: path + '/' + videoChannelId,
|
path: basePath + '/' + videoChannelId,
|
||||||
statusCodeExpected: 200
|
statusCodeExpected: 200
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -210,33 +243,41 @@ describe('Test videos API validator', function () {
|
||||||
|
|
||||||
describe('When deleting a video channel', function () {
|
describe('When deleting a video channel', function () {
|
||||||
let videoChannelId: number
|
let videoChannelId: number
|
||||||
|
let accountId: number
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
const res = await getVideoChannelsList(server.url, 0, 1)
|
const res1 = await getVideoChannelsList(server.url, 0, 1)
|
||||||
videoChannelId = res.body.data[0].id
|
videoChannelId = res1.body.data[0].id
|
||||||
|
|
||||||
|
const res2 = await getAccountsList(server.url)
|
||||||
|
accountId = res2.body.data[0].id
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a non authenticated user', async function () {
|
it('Should fail with a non authenticated user', async function () {
|
||||||
await deleteVideoChannel(server.url, 'coucou', videoChannelId, 401)
|
await deleteVideoChannel(server.url, 'coucou', accountId, videoChannelId, 401)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with another authenticated user', async function () {
|
it('Should fail with another authenticated user', async function () {
|
||||||
await deleteVideoChannel(server.url, accessTokenUser, videoChannelId, 403)
|
await deleteVideoChannel(server.url, accessTokenUser, accountId, videoChannelId, 403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an unknown id', async function () {
|
it('Should fail with an unknown account id', async function () {
|
||||||
await deleteVideoChannel(server.url, server.accessToken, 454554, 404)
|
await deleteVideoChannel(server.url, server.accessToken, 454554,videoChannelId, 404)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an unknown video channel id', async function () {
|
||||||
|
await deleteVideoChannel(server.url, server.accessToken, accountId,454554, 404)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed with the correct parameters', async function () {
|
it('Should succeed with the correct parameters', async function () {
|
||||||
await deleteVideoChannel(server.url, server.accessToken, videoChannelId)
|
await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail to delete the last user video channel', async function () {
|
it('Should fail to delete the last user video channel', async function () {
|
||||||
const res = await getVideoChannelsList(server.url, 0, 1)
|
const res = await getVideoChannelsList(server.url, 0, 1)
|
||||||
videoChannelId = res.body.data[0].id
|
videoChannelId = res.body.data[0].id
|
||||||
|
|
||||||
await deleteVideoChannel(server.url, server.accessToken, videoChannelId, 409)
|
await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId, 409)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ import {
|
||||||
getVideoCommentThreads,
|
getVideoCommentThreads,
|
||||||
getVideoThreadComments
|
getVideoThreadComments
|
||||||
} from '../../utils/videos/video-comments'
|
} from '../../utils/videos/video-comments'
|
||||||
|
import { getAccountsList } from '../../utils/users/accounts'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@ describe('Test multiple servers', function () {
|
||||||
let servers: ServerInfo[] = []
|
let servers: ServerInfo[] = []
|
||||||
const toRemove = []
|
const toRemove = []
|
||||||
let videoUUID = ''
|
let videoUUID = ''
|
||||||
|
let accountId: number
|
||||||
let videoChannelId: number
|
let videoChannelId: number
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -56,13 +58,20 @@ describe('Test multiple servers', function () {
|
||||||
// Get the access tokens
|
// Get the access tokens
|
||||||
await setAccessTokensToServers(servers)
|
await setAccessTokensToServers(servers)
|
||||||
|
|
||||||
const videoChannel = {
|
{
|
||||||
name: 'my channel',
|
const res = await getAccountsList(servers[0].url)
|
||||||
description: 'super channel'
|
accountId = res.body.data[0].id
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const videoChannel = {
|
||||||
|
name: 'my channel',
|
||||||
|
description: 'super channel'
|
||||||
|
}
|
||||||
|
await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, accountId, videoChannel)
|
||||||
|
const channelRes = await getVideoChannelsList(servers[ 0 ].url, 0, 1)
|
||||||
|
videoChannelId = channelRes.body.data[ 0 ].id
|
||||||
}
|
}
|
||||||
await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
|
|
||||||
const channelRes = await getVideoChannelsList(servers[0].url, 0, 1)
|
|
||||||
videoChannelId = channelRes.body.data[0].id
|
|
||||||
|
|
||||||
// Server 1 and server 2 follow each other
|
// Server 1 and server 2 follow each other
|
||||||
await doubleFollow(servers[0], servers[1])
|
await doubleFollow(servers[0], servers[1])
|
||||||
|
|
|
@ -17,12 +17,14 @@ import {
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
updateVideoChannel
|
updateVideoChannel
|
||||||
} from '../../utils/index'
|
} from '../../utils/index'
|
||||||
|
import { getAccountsList } from '../../utils/users/accounts'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
describe('Test video channels', function () {
|
describe('Test video channels', function () {
|
||||||
let servers: ServerInfo[]
|
let servers: ServerInfo[]
|
||||||
let userInfo: User
|
let userInfo: User
|
||||||
|
let accountId: number
|
||||||
let videoChannelId: number
|
let videoChannelId: number
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -35,6 +37,11 @@ describe('Test video channels', function () {
|
||||||
await setAccessTokensToServers(servers)
|
await setAccessTokensToServers(servers)
|
||||||
await doubleFollow(servers[0], servers[1])
|
await doubleFollow(servers[0], servers[1])
|
||||||
|
|
||||||
|
{
|
||||||
|
const res = await getAccountsList(servers[0].url)
|
||||||
|
accountId = res.body.data[0].id
|
||||||
|
}
|
||||||
|
|
||||||
await wait(5000)
|
await wait(5000)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -54,7 +61,7 @@ describe('Test video channels', function () {
|
||||||
description: 'super video channel description',
|
description: 'super video channel description',
|
||||||
support: 'super video channel support text'
|
support: 'super video channel support text'
|
||||||
}
|
}
|
||||||
const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
|
const res = await addVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannel)
|
||||||
videoChannelId = res.body.videoChannel.id
|
videoChannelId = res.body.videoChannel.id
|
||||||
|
|
||||||
// The channel is 1 is propagated to servers 2
|
// The channel is 1 is propagated to servers 2
|
||||||
|
@ -120,7 +127,7 @@ describe('Test video channels', function () {
|
||||||
support: 'video channel support text updated'
|
support: 'video channel support text updated'
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId, videoChannelAttributes)
|
await updateVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId, videoChannelAttributes)
|
||||||
|
|
||||||
await wait(3000)
|
await wait(3000)
|
||||||
})
|
})
|
||||||
|
@ -139,7 +146,7 @@ describe('Test video channels', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should get video channel', async function () {
|
it('Should get video channel', async function () {
|
||||||
const res = await getVideoChannel(servers[0].url, videoChannelId)
|
const res = await getVideoChannel(servers[0].url, accountId, videoChannelId)
|
||||||
|
|
||||||
const videoChannel = res.body
|
const videoChannel = res.body
|
||||||
expect(videoChannel.displayName).to.equal('video channel updated')
|
expect(videoChannel.displayName).to.equal('video channel updated')
|
||||||
|
@ -148,7 +155,7 @@ describe('Test video channels', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should delete video channel', async function () {
|
it('Should delete video channel', async function () {
|
||||||
await deleteVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId)
|
await deleteVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have video channel deleted', async function () {
|
it('Should have video channel deleted', async function () {
|
||||||
|
|
|
@ -7,7 +7,7 @@ type VideoChannelAttributes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVideoChannelsList (url: string, start: number, count: number, sort?: string) {
|
function getVideoChannelsList (url: string, start: number, count: number, sort?: string) {
|
||||||
const path = '/api/v1/videos/channels'
|
const path = '/api/v1/video-channels'
|
||||||
|
|
||||||
const req = request(url)
|
const req = request(url)
|
||||||
.get(path)
|
.get(path)
|
||||||
|
@ -22,7 +22,7 @@ function getVideoChannelsList (url: string, start: number, count: number, sort?:
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAccountVideoChannelsList (url: string, accountId: number | string, specialStatus = 200) {
|
function getAccountVideoChannelsList (url: string, accountId: number | string, specialStatus = 200) {
|
||||||
const path = '/api/v1/videos/accounts/' + accountId + '/channels'
|
const path = '/api/v1/accounts/' + accountId + '/video-channels'
|
||||||
|
|
||||||
return request(url)
|
return request(url)
|
||||||
.get(path)
|
.get(path)
|
||||||
|
@ -31,8 +31,14 @@ function getAccountVideoChannelsList (url: string, accountId: number | string, s
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addVideoChannel (url: string, token: string, videoChannelAttributesArg: VideoChannelAttributes, expectedStatus = 200) {
|
function addVideoChannel (
|
||||||
const path = '/api/v1/videos/channels'
|
url: string,
|
||||||
|
token: string,
|
||||||
|
accountId: number,
|
||||||
|
videoChannelAttributesArg: VideoChannelAttributes,
|
||||||
|
expectedStatus = 200
|
||||||
|
) {
|
||||||
|
const path = '/api/v1/accounts/' + accountId + '/video-channels/'
|
||||||
|
|
||||||
// Default attributes
|
// Default attributes
|
||||||
let attributes = {
|
let attributes = {
|
||||||
|
@ -50,9 +56,16 @@ function addVideoChannel (url: string, token: string, videoChannelAttributesArg:
|
||||||
.expect(expectedStatus)
|
.expect(expectedStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateVideoChannel (url: string, token: string, channelId: number, attributes: VideoChannelAttributes, expectedStatus = 204) {
|
function updateVideoChannel (
|
||||||
|
url: string,
|
||||||
|
token: string,
|
||||||
|
accountId: number,
|
||||||
|
channelId: number,
|
||||||
|
attributes: VideoChannelAttributes,
|
||||||
|
expectedStatus = 204
|
||||||
|
) {
|
||||||
const body = {}
|
const body = {}
|
||||||
const path = '/api/v1/videos/channels/' + channelId
|
const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
|
||||||
|
|
||||||
if (attributes.name) body['name'] = attributes.name
|
if (attributes.name) body['name'] = attributes.name
|
||||||
if (attributes.description) body['description'] = attributes.description
|
if (attributes.description) body['description'] = attributes.description
|
||||||
|
@ -66,18 +79,18 @@ function updateVideoChannel (url: string, token: string, channelId: number, attr
|
||||||
.expect(expectedStatus)
|
.expect(expectedStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteVideoChannel (url: string, token: string, channelId: number, expectedStatus = 204) {
|
function deleteVideoChannel (url: string, token: string, accountId: number, channelId: number, expectedStatus = 204) {
|
||||||
const path = '/api/v1/videos/channels/'
|
const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
|
||||||
|
|
||||||
return request(url)
|
return request(url)
|
||||||
.delete(path + channelId)
|
.delete(path)
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.set('Authorization', 'Bearer ' + token)
|
.set('Authorization', 'Bearer ' + token)
|
||||||
.expect(expectedStatus)
|
.expect(expectedStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVideoChannel (url: string, channelId: number) {
|
function getVideoChannel (url: string, accountId: number, channelId: number) {
|
||||||
const path = '/api/v1/videos/channels/' + channelId
|
const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
|
||||||
|
|
||||||
return request(url)
|
return request(url)
|
||||||
.get(path)
|
.get(path)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -91,7 +91,7 @@ paths:
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
enum: ['xml', 'atom' 'json']
|
enum: [ 'xml', 'atom', 'json']
|
||||||
default: 'xml'
|
default: 'xml'
|
||||||
description: 'The format expected (xml defaults to RSS 2.0, atom to ATOM 1.0 and json to JSON FEED 1.0'
|
description: 'The format expected (xml defaults to RSS 2.0, atom to ATOM 1.0 and json to JSON FEED 1.0'
|
||||||
- name: accountId
|
- name: accountId
|
||||||
|
@ -967,7 +967,7 @@ paths:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/VideoBlacklist'
|
$ref: '#/definitions/VideoBlacklist'
|
||||||
/videos/channels:
|
/video-channels:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- VideoChannel
|
- VideoChannel
|
||||||
|
@ -998,83 +998,7 @@ paths:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/VideoChannel'
|
$ref: '#/definitions/VideoChannel'
|
||||||
post:
|
/accounts/{accountId}/video-channels:
|
||||||
security:
|
|
||||||
- OAuth2: [ ]
|
|
||||||
tags:
|
|
||||||
- VideoChannel
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/VideoChannelInput'
|
|
||||||
responses:
|
|
||||||
'204':
|
|
||||||
description: successful operation
|
|
||||||
"/videos/channels/{id}":
|
|
||||||
get:
|
|
||||||
tags:
|
|
||||||
- VideoChannel
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
description: 'The video id '
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: successful operation
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/VideoChannel'
|
|
||||||
put:
|
|
||||||
security:
|
|
||||||
- OAuth2: [ ]
|
|
||||||
tags:
|
|
||||||
- VideoChannel
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
description: 'The video id '
|
|
||||||
- in: body
|
|
||||||
name: body
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/VideoChannelInput'
|
|
||||||
responses:
|
|
||||||
'204':
|
|
||||||
description: successful operation
|
|
||||||
delete:
|
|
||||||
security:
|
|
||||||
- OAuth2: [ ]
|
|
||||||
tags:
|
|
||||||
- VideoChannel
|
|
||||||
consumes:
|
|
||||||
- application/json
|
|
||||||
produces:
|
|
||||||
- application/json
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
description: 'The video id '
|
|
||||||
responses:
|
|
||||||
'204':
|
|
||||||
description: successful operation
|
|
||||||
/videos/accounts/{accountId}/channels:
|
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- VideoChannel
|
- VideoChannel
|
||||||
|
@ -1095,6 +1019,102 @@ paths:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/VideoChannel'
|
$ref: '#/definitions/VideoChannel'
|
||||||
|
post:
|
||||||
|
security:
|
||||||
|
- OAuth2: [ ]
|
||||||
|
tags:
|
||||||
|
- VideoChannel
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
parameters:
|
||||||
|
- name: accountId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: 'The account id '
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/VideoChannelInput'
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: successful operation
|
||||||
|
"/account/{accountId}/video-channels/{id}":
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- VideoChannel
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
parameters:
|
||||||
|
- name: accountId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: 'The account id '
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: 'The video channel id '
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/VideoChannel'
|
||||||
|
put:
|
||||||
|
security:
|
||||||
|
- OAuth2: [ ]
|
||||||
|
tags:
|
||||||
|
- VideoChannel
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
parameters:
|
||||||
|
- name: accountId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: 'The account id '
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: 'The video channel id '
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/VideoChannelInput'
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: successful operation
|
||||||
|
delete:
|
||||||
|
security:
|
||||||
|
- OAuth2: [ ]
|
||||||
|
tags:
|
||||||
|
- VideoChannel
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
parameters:
|
||||||
|
- name: accountId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: 'The account id '
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: 'The video channel id '
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: successful operation
|
||||||
"/videos/{videoId}/comment-threads":
|
"/videos/{videoId}/comment-threads":
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
|
|
Loading…
Reference in New Issue