ownership.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import express from 'express'
  2. import { MVideoFullLight } from '@server/types/models'
  3. import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
  4. import { VideoChangeOwnershipStatus, VideoState } from '../../../../shared/models/videos'
  5. import { logger } from '../../../helpers/logger'
  6. import { getFormattedObjects } from '../../../helpers/utils'
  7. import { sequelizeTypescript } from '../../../initializers/database'
  8. import { sendUpdateVideo } from '../../../lib/activitypub/send'
  9. import { changeVideoChannelShare } from '../../../lib/activitypub/share'
  10. import {
  11. asyncMiddleware,
  12. asyncRetryTransactionMiddleware,
  13. authenticate,
  14. paginationValidator,
  15. setDefaultPagination,
  16. videosAcceptChangeOwnershipValidator,
  17. videosChangeOwnershipValidator,
  18. videosTerminateChangeOwnershipValidator
  19. } from '../../../middlewares'
  20. import { VideoModel } from '../../../models/video/video'
  21. import { VideoChangeOwnershipModel } from '../../../models/video/video-change-ownership'
  22. import { VideoChannelModel } from '../../../models/video/video-channel'
  23. const ownershipVideoRouter = express.Router()
  24. ownershipVideoRouter.post('/:videoId/give-ownership',
  25. authenticate,
  26. asyncMiddleware(videosChangeOwnershipValidator),
  27. asyncRetryTransactionMiddleware(giveVideoOwnership)
  28. )
  29. ownershipVideoRouter.get('/ownership',
  30. authenticate,
  31. paginationValidator,
  32. setDefaultPagination,
  33. asyncRetryTransactionMiddleware(listVideoOwnership)
  34. )
  35. ownershipVideoRouter.post('/ownership/:id/accept',
  36. authenticate,
  37. asyncMiddleware(videosTerminateChangeOwnershipValidator),
  38. asyncMiddleware(videosAcceptChangeOwnershipValidator),
  39. asyncRetryTransactionMiddleware(acceptOwnership)
  40. )
  41. ownershipVideoRouter.post('/ownership/:id/refuse',
  42. authenticate,
  43. asyncMiddleware(videosTerminateChangeOwnershipValidator),
  44. asyncRetryTransactionMiddleware(refuseOwnership)
  45. )
  46. // ---------------------------------------------------------------------------
  47. export {
  48. ownershipVideoRouter
  49. }
  50. // ---------------------------------------------------------------------------
  51. async function giveVideoOwnership (req: express.Request, res: express.Response) {
  52. const videoInstance = res.locals.videoAll
  53. const initiatorAccountId = res.locals.oauth.token.User.Account.id
  54. const nextOwner = res.locals.nextOwner
  55. await sequelizeTypescript.transaction(t => {
  56. return VideoChangeOwnershipModel.findOrCreate({
  57. where: {
  58. initiatorAccountId,
  59. nextOwnerAccountId: nextOwner.id,
  60. videoId: videoInstance.id,
  61. status: VideoChangeOwnershipStatus.WAITING
  62. },
  63. defaults: {
  64. initiatorAccountId,
  65. nextOwnerAccountId: nextOwner.id,
  66. videoId: videoInstance.id,
  67. status: VideoChangeOwnershipStatus.WAITING
  68. },
  69. transaction: t
  70. })
  71. })
  72. logger.info('Ownership change for video %s created.', videoInstance.name)
  73. return res.type('json')
  74. .status(HttpStatusCode.NO_CONTENT_204)
  75. .end()
  76. }
  77. async function listVideoOwnership (req: express.Request, res: express.Response) {
  78. const currentAccountId = res.locals.oauth.token.User.Account.id
  79. const resultList = await VideoChangeOwnershipModel.listForApi(
  80. currentAccountId,
  81. req.query.start || 0,
  82. req.query.count || 10,
  83. req.query.sort || 'createdAt'
  84. )
  85. return res.json(getFormattedObjects(resultList.data, resultList.total))
  86. }
  87. function acceptOwnership (req: express.Request, res: express.Response) {
  88. return sequelizeTypescript.transaction(async t => {
  89. const videoChangeOwnership = res.locals.videoChangeOwnership
  90. const channel = res.locals.videoChannel
  91. // We need more attributes for federation
  92. const targetVideo = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoChangeOwnership.Video.id, t)
  93. const oldVideoChannel = await VideoChannelModel.loadAndPopulateAccount(targetVideo.channelId, t)
  94. targetVideo.channelId = channel.id
  95. const targetVideoUpdated = await targetVideo.save({ transaction: t }) as MVideoFullLight
  96. targetVideoUpdated.VideoChannel = channel
  97. if (targetVideoUpdated.hasPrivacyForFederation() && targetVideoUpdated.state === VideoState.PUBLISHED) {
  98. await changeVideoChannelShare(targetVideoUpdated, oldVideoChannel, t)
  99. await sendUpdateVideo(targetVideoUpdated, t, oldVideoChannel.Account.Actor)
  100. }
  101. videoChangeOwnership.status = VideoChangeOwnershipStatus.ACCEPTED
  102. await videoChangeOwnership.save({ transaction: t })
  103. return res.status(HttpStatusCode.NO_CONTENT_204).end()
  104. })
  105. }
  106. function refuseOwnership (req: express.Request, res: express.Response) {
  107. return sequelizeTypescript.transaction(async t => {
  108. const videoChangeOwnership = res.locals.videoChangeOwnership
  109. videoChangeOwnership.status = VideoChangeOwnershipStatus.REFUSED
  110. await videoChangeOwnership.save({ transaction: t })
  111. return res.status(HttpStatusCode.NO_CONTENT_204).end()
  112. })
  113. }