From cc918ac3f45e32f031cce7b6e0473e5c2c34b8ae Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 25 Apr 2018 16:15:39 +0200 Subject: Update video-channel routes (again) Use /video-channels now, it's more simple for clients --- server/controllers/api/accounts.ts | 168 +------------------------------ server/controllers/api/video-channel.ts | 173 +++++++++++++++++++++++++++++++- 2 files changed, 173 insertions(+), 168 deletions(-) (limited to 'server/controllers') diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 85987c912..ccae0436b 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts @@ -1,30 +1,18 @@ import * as express from 'express' -import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils' +import { getFormattedObjects } from '../../helpers/utils' import { asyncMiddleware, - authenticate, listVideoAccountChannelsValidator, optionalAuthenticate, paginationValidator, setDefaultPagination, - setDefaultSort, - videoChannelsAddValidator, - videoChannelsGetValidator, - videoChannelsRemoveValidator, - videoChannelsUpdateValidator + setDefaultSort } from '../../middlewares' import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators' import { AccountModel } from '../../models/account/account' import { VideoModel } from '../../models/video/video' 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() @@ -56,39 +44,6 @@ accountsRouter.get('/:accountId/video-channels', 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) -) - // --------------------------------------------------------------------------- export { @@ -115,125 +70,6 @@ async function listVideoAccountChannels (req: express.Request, res: express.Resp 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, - uuid: videoChannel.Actor.uuid - } - }).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 diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index d57273747..6241aaa5c 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts @@ -1,13 +1,30 @@ import * as express from 'express' -import { getFormattedObjects } from '../../helpers/utils' +import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils' import { asyncMiddleware, + authenticate, + optionalAuthenticate, paginationValidator, setDefaultPagination, setDefaultSort, - videoChannelsSortValidator + videoChannelsAddValidator, + videoChannelsGetValidator, + videoChannelsRemoveValidator, + videoChannelsSortValidator, + videoChannelsUpdateValidator } from '../../middlewares' import { VideoChannelModel } from '../../models/video/video-channel' +import { videosSortValidator } from '../../middlewares/validators' +import { sendUpdateActor } from '../../lib/activitypub/send' +import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' +import { createVideoChannel } from '../../lib/video-channel' +import { isNSFWHidden } from '../../helpers/express-utils' +import { setAsyncActorKeys } from '../../lib/activitypub' +import { retryTransactionWrapper } from '../../helpers/database-utils' +import { AccountModel } from '../../models/account/account' +import { sequelizeTypescript } from '../../initializers' +import { logger } from '../../helpers/logger' +import { VideoModel } from '../../models/video/video' const videoChannelRouter = express.Router() @@ -19,6 +36,39 @@ videoChannelRouter.get('/', asyncMiddleware(listVideoChannels) ) +videoChannelRouter.post('/', + authenticate, + videoChannelsAddValidator, + asyncMiddleware(addVideoChannelRetryWrapper) +) + +videoChannelRouter.put('/:id', + authenticate, + asyncMiddleware(videoChannelsUpdateValidator), + updateVideoChannelRetryWrapper +) + +videoChannelRouter.delete('/:id', + authenticate, + asyncMiddleware(videoChannelsRemoveValidator), + asyncMiddleware(removeVideoChannelRetryWrapper) +) + +videoChannelRouter.get('/:id', + asyncMiddleware(videoChannelsGetValidator), + asyncMiddleware(getVideoChannel) +) + +videoChannelRouter.get('/:id/videos', + asyncMiddleware(videoChannelsGetValidator), + paginationValidator, + videosSortValidator, + setDefaultSort, + setDefaultPagination, + optionalAuthenticate, + asyncMiddleware(listVideoChannelVideos) +) + // --------------------------------------------------------------------------- export { @@ -32,3 +82,122 @@ async function listVideoChannels (req: express.Request, res: express.Response, n 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, + uuid: videoChannel.Actor.uuid + } + }).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)) +} -- cgit v1.2.3