video-channels.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import express from 'express'
  2. import { body, param, query } from 'express-validator'
  3. import { CONFIG } from '@server/initializers/config'
  4. import { MChannelAccountDefault } from '@server/types/models'
  5. import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
  6. import { isBooleanValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc'
  7. import {
  8. isVideoChannelDescriptionValid,
  9. isVideoChannelDisplayNameValid,
  10. isVideoChannelSupportValid,
  11. isVideoChannelUsernameValid
  12. } from '../../../helpers/custom-validators/video-channels'
  13. import { logger } from '../../../helpers/logger'
  14. import { ActorModel } from '../../../models/actor/actor'
  15. import { VideoChannelModel } from '../../../models/video/video-channel'
  16. import { areValidationErrors, doesVideoChannelNameWithHostExist } from '../shared'
  17. const videoChannelsAddValidator = [
  18. body('name').custom(isVideoChannelUsernameValid).withMessage('Should have a valid channel name'),
  19. body('displayName').custom(isVideoChannelDisplayNameValid).withMessage('Should have a valid display name'),
  20. body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
  21. body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
  22. async (req: express.Request, res: express.Response, next: express.NextFunction) => {
  23. logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body })
  24. if (areValidationErrors(req, res)) return
  25. const actor = await ActorModel.loadLocalByName(req.body.name)
  26. if (actor) {
  27. res.fail({
  28. status: HttpStatusCode.CONFLICT_409,
  29. message: 'Another actor (account/channel) with this name on this instance already exists or has already existed.'
  30. })
  31. return false
  32. }
  33. const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id)
  34. if (count >= CONFIG.VIDEO_CHANNELS.MAX_PER_USER) {
  35. res.fail({ message: `You cannot create more than ${CONFIG.VIDEO_CHANNELS.MAX_PER_USER} channels` })
  36. return false
  37. }
  38. return next()
  39. }
  40. ]
  41. const videoChannelsUpdateValidator = [
  42. param('nameWithHost').exists().withMessage('Should have an video channel name with host'),
  43. body('displayName')
  44. .optional()
  45. .custom(isVideoChannelDisplayNameValid).withMessage('Should have a valid display name'),
  46. body('description')
  47. .optional()
  48. .custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
  49. body('support')
  50. .optional()
  51. .custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
  52. body('bulkVideosSupportUpdate')
  53. .optional()
  54. .custom(isBooleanValid).withMessage('Should have a valid bulkVideosSupportUpdate boolean field'),
  55. (req: express.Request, res: express.Response, next: express.NextFunction) => {
  56. logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
  57. if (areValidationErrors(req, res)) return
  58. return next()
  59. }
  60. ]
  61. const videoChannelsRemoveValidator = [
  62. async (req: express.Request, res: express.Response, next: express.NextFunction) => {
  63. logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
  64. if (!await checkVideoChannelIsNotTheLastOne(res.locals.videoChannel, res)) return
  65. return next()
  66. }
  67. ]
  68. const videoChannelsNameWithHostValidator = [
  69. param('nameWithHost').exists().withMessage('Should have an video channel name with host'),
  70. async (req: express.Request, res: express.Response, next: express.NextFunction) => {
  71. logger.debug('Checking videoChannelsNameWithHostValidator parameters', { parameters: req.params })
  72. if (areValidationErrors(req, res)) return
  73. if (!await doesVideoChannelNameWithHostExist(req.params.nameWithHost, res)) return
  74. return next()
  75. }
  76. ]
  77. const ensureIsLocalChannel = [
  78. (req: express.Request, res: express.Response, next: express.NextFunction) => {
  79. if (res.locals.videoChannel.Actor.isOwned() === false) {
  80. return res.fail({
  81. status: HttpStatusCode.FORBIDDEN_403,
  82. message: 'This channel is not owned.'
  83. })
  84. }
  85. return next()
  86. }
  87. ]
  88. const videoChannelStatsValidator = [
  89. query('withStats')
  90. .optional()
  91. .customSanitizer(toBooleanOrNull)
  92. .custom(isBooleanValid).withMessage('Should have a valid stats flag'),
  93. (req: express.Request, res: express.Response, next: express.NextFunction) => {
  94. if (areValidationErrors(req, res)) return
  95. return next()
  96. }
  97. ]
  98. const videoChannelsListValidator = [
  99. query('search').optional().not().isEmpty().withMessage('Should have a valid search'),
  100. (req: express.Request, res: express.Response, next: express.NextFunction) => {
  101. logger.debug('Checking video channels search query', { parameters: req.query })
  102. if (areValidationErrors(req, res)) return
  103. return next()
  104. }
  105. ]
  106. // ---------------------------------------------------------------------------
  107. export {
  108. videoChannelsAddValidator,
  109. videoChannelsUpdateValidator,
  110. videoChannelsRemoveValidator,
  111. videoChannelsNameWithHostValidator,
  112. ensureIsLocalChannel,
  113. videoChannelsListValidator,
  114. videoChannelStatsValidator
  115. }
  116. // ---------------------------------------------------------------------------
  117. async function checkVideoChannelIsNotTheLastOne (videoChannel: MChannelAccountDefault, res: express.Response) {
  118. const count = await VideoChannelModel.countByAccount(videoChannel.Account.id)
  119. if (count <= 1) {
  120. res.fail({
  121. status: HttpStatusCode.CONFLICT_409,
  122. message: 'Cannot remove the last channel of this user'
  123. })
  124. return false
  125. }
  126. return true
  127. }