Federate video abuses
[oweals/peertube.git] / server / models / video / video-abuse.ts
1 import * as Sequelize from 'sequelize'
2
3 import { CONFIG } from '../../initializers'
4 import { isVideoAbuseReasonValid } from '../../helpers'
5
6 import { addMethodsToModel, getSort } from '../utils'
7 import {
8   VideoAbuseInstance,
9   VideoAbuseAttributes,
10
11   VideoAbuseMethods
12 } from './video-abuse-interface'
13 import { VideoAbuseObject } from '../../../shared/models/activitypub/objects/video-abuse-object'
14
15 let VideoAbuse: Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes>
16 let toFormattedJSON: VideoAbuseMethods.ToFormattedJSON
17 let listForApi: VideoAbuseMethods.ListForApi
18 let toActivityPubObject: VideoAbuseMethods.ToActivityPubObject
19
20 export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
21   VideoAbuse = sequelize.define<VideoAbuseInstance, VideoAbuseAttributes>('VideoAbuse',
22     {
23       reason: {
24         type: DataTypes.STRING,
25         allowNull: false,
26         validate: {
27           reasonValid: value => {
28             const res = isVideoAbuseReasonValid(value)
29             if (res === false) throw new Error('Video abuse reason is not valid.')
30           }
31         }
32       }
33     },
34     {
35       indexes: [
36         {
37           fields: [ 'videoId' ]
38         },
39         {
40           fields: [ 'reporterAccountId' ]
41         }
42       ]
43     }
44   )
45
46   const classMethods = [
47     associate,
48
49     listForApi
50   ]
51   const instanceMethods = [
52     toFormattedJSON,
53     toActivityPubObject
54   ]
55   addMethodsToModel(VideoAbuse, classMethods, instanceMethods)
56
57   return VideoAbuse
58 }
59
60 // ------------------------------ METHODS ------------------------------
61
62 toFormattedJSON = function (this: VideoAbuseInstance) {
63   let reporterServerHost
64
65   if (this.Account.Server) {
66     reporterServerHost = this.Account.Server.host
67   } else {
68     // It means it's our video
69     reporterServerHost = CONFIG.WEBSERVER.HOST
70   }
71
72   const json = {
73     id: this.id,
74     reason: this.reason,
75     reporterUsername: this.Account.name,
76     reporterServerHost,
77     videoId: this.Video.id,
78     videoUUID: this.Video.uuid,
79     videoName: this.Video.name,
80     createdAt: this.createdAt
81   }
82
83   return json
84 }
85
86 toActivityPubObject = function (this: VideoAbuseInstance) {
87   const videoAbuseObject: VideoAbuseObject = {
88     type: 'Flag' as 'Flag',
89     content: this.reason,
90     object: this.Video.url
91   }
92
93   return videoAbuseObject
94 }
95
96 // ------------------------------ STATICS ------------------------------
97
98 function associate (models) {
99   VideoAbuse.belongsTo(models.Account, {
100     foreignKey: {
101       name: 'reporterAccountId',
102       allowNull: true
103     },
104     onDelete: 'CASCADE'
105   })
106
107   VideoAbuse.belongsTo(models.Video, {
108     foreignKey: {
109       name: 'videoId',
110       allowNull: false
111     },
112     onDelete: 'CASCADE'
113   })
114 }
115
116 listForApi = function (start: number, count: number, sort: string) {
117   const query = {
118     offset: start,
119     limit: count,
120     order: [ getSort(sort) ],
121     include: [
122       {
123         model: VideoAbuse['sequelize'].models.Account,
124         required: true,
125         include: [
126           {
127             model: VideoAbuse['sequelize'].models.Server,
128             required: false
129           }
130         ]
131       },
132       {
133         model: VideoAbuse['sequelize'].models.Video,
134         required: true
135       }
136     ]
137   }
138
139   return VideoAbuse.findAndCountAll(query).then(({ rows, count }) => {
140     return { total: count, data: rows }
141   })
142 }