2af7b386413ec33ee545a8adc30755ebb1c4958c
[oweals/peertube.git] / server / controllers / api / videos / abuse.ts
1 import * as express from 'express'
2 import { UserRight, VideoAbuseCreate, VideoAbuseState, VideoAbuse } from '../../../../shared'
3 import { logger } from '../../../helpers/logger'
4 import { getFormattedObjects } from '../../../helpers/utils'
5 import { sequelizeTypescript } from '../../../initializers/database'
6 import {
7   asyncMiddleware,
8   asyncRetryTransactionMiddleware,
9   authenticate,
10   ensureUserHasRight,
11   paginationValidator,
12   setDefaultPagination,
13   setDefaultSort,
14   videoAbuseGetValidator,
15   videoAbuseReportValidator,
16   videoAbusesSortValidator,
17   videoAbuseUpdateValidator,
18   videoAbuseListValidator
19 } from '../../../middlewares'
20 import { AccountModel } from '../../../models/account/account'
21 import { VideoAbuseModel } from '../../../models/video/video-abuse'
22 import { auditLoggerFactory, VideoAbuseAuditView } from '../../../helpers/audit-logger'
23 import { Notifier } from '../../../lib/notifier'
24 import { sendVideoAbuse } from '../../../lib/activitypub/send/send-flag'
25 import { MVideoAbuseAccountVideo } from '../../../typings/models/video'
26 import { getServerActor } from '@server/models/application/application'
27 import { MAccountDefault } from '@server/typings/models'
28
29 const auditLogger = auditLoggerFactory('abuse')
30 const abuseVideoRouter = express.Router()
31
32 abuseVideoRouter.get('/abuse',
33   authenticate,
34   ensureUserHasRight(UserRight.MANAGE_VIDEO_ABUSES),
35   paginationValidator,
36   videoAbusesSortValidator,
37   setDefaultSort,
38   setDefaultPagination,
39   videoAbuseListValidator,
40   asyncMiddleware(listVideoAbuses)
41 )
42 abuseVideoRouter.put('/:videoId/abuse/:id',
43   authenticate,
44   ensureUserHasRight(UserRight.MANAGE_VIDEO_ABUSES),
45   asyncMiddleware(videoAbuseUpdateValidator),
46   asyncRetryTransactionMiddleware(updateVideoAbuse)
47 )
48 abuseVideoRouter.post('/:videoId/abuse',
49   authenticate,
50   asyncMiddleware(videoAbuseReportValidator),
51   asyncRetryTransactionMiddleware(reportVideoAbuse)
52 )
53 abuseVideoRouter.delete('/:videoId/abuse/:id',
54   authenticate,
55   ensureUserHasRight(UserRight.MANAGE_VIDEO_ABUSES),
56   asyncMiddleware(videoAbuseGetValidator),
57   asyncRetryTransactionMiddleware(deleteVideoAbuse)
58 )
59
60 // ---------------------------------------------------------------------------
61
62 export {
63   abuseVideoRouter
64 }
65
66 // ---------------------------------------------------------------------------
67
68 async function listVideoAbuses (req: express.Request, res: express.Response) {
69   const user = res.locals.oauth.token.user
70   const serverActor = await getServerActor()
71
72   const resultList = await VideoAbuseModel.listForApi({
73     start: req.query.start,
74     count: req.query.count,
75     sort: req.query.sort,
76     id: req.query.id,
77     search: req.query.search,
78     state: req.query.state,
79     videoIs: req.query.videoIs,
80     searchReporter: req.query.searchReporter,
81     searchReportee: req.query.searchReportee,
82     searchVideo: req.query.searchVideo,
83     searchVideoChannel: req.query.searchVideoChannel,
84     serverAccountId: serverActor.Account.id,
85     user
86   })
87
88   return res.json(getFormattedObjects(resultList.data, resultList.total))
89 }
90
91 async function updateVideoAbuse (req: express.Request, res: express.Response) {
92   const videoAbuse = res.locals.videoAbuse
93
94   if (req.body.moderationComment !== undefined) videoAbuse.moderationComment = req.body.moderationComment
95   if (req.body.state !== undefined) videoAbuse.state = req.body.state
96
97   await sequelizeTypescript.transaction(t => {
98     return videoAbuse.save({ transaction: t })
99   })
100
101   // Do not send the delete to other instances, we updated OUR copy of this video abuse
102
103   return res.type('json').status(204).end()
104 }
105
106 async function deleteVideoAbuse (req: express.Request, res: express.Response) {
107   const videoAbuse = res.locals.videoAbuse
108
109   await sequelizeTypescript.transaction(t => {
110     return videoAbuse.destroy({ transaction: t })
111   })
112
113   // Do not send the delete to other instances, we delete OUR copy of this video abuse
114
115   return res.type('json').status(204).end()
116 }
117
118 async function reportVideoAbuse (req: express.Request, res: express.Response) {
119   const videoInstance = res.locals.videoAll
120   const body: VideoAbuseCreate = req.body
121   let reporterAccount: MAccountDefault
122   let videoAbuseJSON: VideoAbuse
123
124   const videoAbuseInstance = await sequelizeTypescript.transaction(async t => {
125     reporterAccount = await AccountModel.load(res.locals.oauth.token.User.Account.id, t)
126
127     const abuseToCreate = {
128       reporterAccountId: reporterAccount.id,
129       reason: body.reason,
130       videoId: videoInstance.id,
131       state: VideoAbuseState.PENDING
132     }
133
134     const videoAbuseInstance: MVideoAbuseAccountVideo = await VideoAbuseModel.create(abuseToCreate, { transaction: t })
135     videoAbuseInstance.Video = videoInstance
136     videoAbuseInstance.Account = reporterAccount
137
138     // We send the video abuse to the origin server
139     if (videoInstance.isOwned() === false) {
140       await sendVideoAbuse(reporterAccount.Actor, videoAbuseInstance, videoInstance, t)
141     }
142
143     videoAbuseJSON = videoAbuseInstance.toFormattedJSON()
144     auditLogger.create(reporterAccount.Actor.getIdentifier(), new VideoAbuseAuditView(videoAbuseJSON))
145
146     return videoAbuseInstance
147   })
148
149   Notifier.Instance.notifyOnNewVideoAbuse({
150     videoAbuse: videoAbuseJSON,
151     videoAbuseInstance,
152     reporter: reporterAccount.Actor.getIdentifier()
153   })
154
155   logger.info('Abuse report for video %s created.', videoInstance.name)
156
157   return res.json({ videoAbuse: videoAbuseJSON }).end()
158 }