Users can change ownership of their video [#510] (#888)
[oweals/peertube.git] / server / controllers / api / videos / ownership.ts
1 import * as express from 'express'
2 import { logger } from '../../../helpers/logger'
3 import { sequelizeTypescript } from '../../../initializers'
4 import {
5   asyncMiddleware,
6   asyncRetryTransactionMiddleware,
7   authenticate,
8   paginationValidator,
9   setDefaultPagination,
10   videosAcceptChangeOwnershipValidator,
11   videosChangeOwnershipValidator,
12   videosTerminateChangeOwnershipValidator
13 } from '../../../middlewares'
14 import { AccountModel } from '../../../models/account/account'
15 import { VideoModel } from '../../../models/video/video'
16 import { VideoChangeOwnershipModel } from '../../../models/video/video-change-ownership'
17 import { VideoChangeOwnershipStatus } from '../../../../shared/models/videos'
18 import { VideoChannelModel } from '../../../models/video/video-channel'
19 import { getFormattedObjects } from '../../../helpers/utils'
20
21 const ownershipVideoRouter = express.Router()
22
23 ownershipVideoRouter.post('/:videoId/give-ownership',
24   authenticate,
25   asyncMiddleware(videosChangeOwnershipValidator),
26   asyncRetryTransactionMiddleware(giveVideoOwnership)
27 )
28
29 ownershipVideoRouter.get('/ownership',
30   authenticate,
31   paginationValidator,
32   setDefaultPagination,
33   asyncRetryTransactionMiddleware(listVideoOwnership)
34 )
35
36 ownershipVideoRouter.post('/ownership/:id/accept',
37   authenticate,
38   asyncMiddleware(videosTerminateChangeOwnershipValidator),
39   asyncMiddleware(videosAcceptChangeOwnershipValidator),
40   asyncRetryTransactionMiddleware(acceptOwnership)
41 )
42
43 ownershipVideoRouter.post('/ownership/:id/refuse',
44   authenticate,
45   asyncMiddleware(videosTerminateChangeOwnershipValidator),
46   asyncRetryTransactionMiddleware(refuseOwnership)
47 )
48
49 // ---------------------------------------------------------------------------
50
51 export {
52   ownershipVideoRouter
53 }
54
55 // ---------------------------------------------------------------------------
56
57 async function giveVideoOwnership (req: express.Request, res: express.Response) {
58   const videoInstance = res.locals.video as VideoModel
59   const initiatorAccount = res.locals.oauth.token.User.Account as AccountModel
60   const nextOwner = res.locals.nextOwner as AccountModel
61
62   await sequelizeTypescript.transaction(async t => {
63     await VideoChangeOwnershipModel.findOrCreate({
64       where: {
65         initiatorAccountId: initiatorAccount.id,
66         nextOwnerAccountId: nextOwner.id,
67         videoId: videoInstance.id,
68         status: VideoChangeOwnershipStatus.WAITING
69       },
70       defaults: {
71         initiatorAccountId: initiatorAccount.id,
72         nextOwnerAccountId: nextOwner.id,
73         videoId: videoInstance.id,
74         status: VideoChangeOwnershipStatus.WAITING
75       }
76     })
77     logger.info('Ownership change for video %s created.', videoInstance.name)
78     return res.type('json').status(204).end()
79   })
80 }
81
82 async function listVideoOwnership (req: express.Request, res: express.Response) {
83   const currentAccount = res.locals.oauth.token.User.Account as AccountModel
84   const resultList = await VideoChangeOwnershipModel.listForApi(
85     currentAccount.id,
86     req.query.start || 0,
87     req.query.count || 10,
88     req.query.sort || 'createdAt'
89   )
90
91   return res.json(getFormattedObjects(resultList.data, resultList.total))
92 }
93
94 async function acceptOwnership (req: express.Request, res: express.Response) {
95   return sequelizeTypescript.transaction(async t => {
96     const videoChangeOwnership = res.locals.videoChangeOwnership as VideoChangeOwnershipModel
97     const targetVideo = videoChangeOwnership.Video
98     const channel = res.locals.videoChannel as VideoChannelModel
99
100     targetVideo.set('channelId', channel.id)
101
102     await targetVideo.save()
103     videoChangeOwnership.set('status', VideoChangeOwnershipStatus.ACCEPTED)
104     await videoChangeOwnership.save()
105
106     return res.sendStatus(204)
107   })
108 }
109
110 async function refuseOwnership (req: express.Request, res: express.Response) {
111   return sequelizeTypescript.transaction(async t => {
112     const videoChangeOwnership = res.locals.videoChangeOwnership as VideoChangeOwnershipModel
113     videoChangeOwnership.set('status', VideoChangeOwnershipStatus.REFUSED)
114     await videoChangeOwnership.save()
115     return res.sendStatus(204)
116   })
117 }