6ef1a915d85c9a4b5d5649949e8c3e1dd2f57200
[oweals/peertube.git] / server / models / video / video-abuse.ts
1 import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
2 import { VideoAbuseObject } from '../../../shared/models/activitypub/objects'
3 import { VideoAbuse } from '../../../shared/models/videos'
4 import {
5   isVideoAbuseModerationCommentValid,
6   isVideoAbuseReasonValid,
7   isVideoAbuseStateValid
8 } from '../../helpers/custom-validators/video-abuses'
9 import { AccountModel } from '../account/account'
10 import { getSort, throwIfNotValid } from '../utils'
11 import { VideoModel } from './video'
12 import { VideoAbuseState } from '../../../shared'
13 import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
14 import { MVideoAbuse, MVideoAbuseFormattable, MVideoAbuseVideo } from '../../typings/models'
15 import * as Bluebird from 'bluebird'
16
17 @Table({
18   tableName: 'videoAbuse',
19   indexes: [
20     {
21       fields: [ 'videoId' ]
22     },
23     {
24       fields: [ 'reporterAccountId' ]
25     }
26   ]
27 })
28 export class VideoAbuseModel extends Model<VideoAbuseModel> {
29
30   @AllowNull(false)
31   @Default(null)
32   @Is('VideoAbuseReason', value => throwIfNotValid(value, isVideoAbuseReasonValid, 'reason'))
33   @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_ABUSES.REASON.max))
34   reason: string
35
36   @AllowNull(false)
37   @Default(null)
38   @Is('VideoAbuseState', value => throwIfNotValid(value, isVideoAbuseStateValid, 'state'))
39   @Column
40   state: VideoAbuseState
41
42   @AllowNull(true)
43   @Default(null)
44   @Is('VideoAbuseModerationComment', value => throwIfNotValid(value, isVideoAbuseModerationCommentValid, 'moderationComment', true))
45   @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_ABUSES.MODERATION_COMMENT.max))
46   moderationComment: string
47
48   @CreatedAt
49   createdAt: Date
50
51   @UpdatedAt
52   updatedAt: Date
53
54   @ForeignKey(() => AccountModel)
55   @Column
56   reporterAccountId: number
57
58   @BelongsTo(() => AccountModel, {
59     foreignKey: {
60       allowNull: false
61     },
62     onDelete: 'cascade'
63   })
64   Account: AccountModel
65
66   @ForeignKey(() => VideoModel)
67   @Column
68   videoId: number
69
70   @BelongsTo(() => VideoModel, {
71     foreignKey: {
72       allowNull: false
73     },
74     onDelete: 'cascade'
75   })
76   Video: VideoModel
77
78   static loadByIdAndVideoId (id: number, videoId: number): Bluebird<MVideoAbuse> {
79     const query = {
80       where: {
81         id,
82         videoId
83       }
84     }
85     return VideoAbuseModel.findOne(query)
86   }
87
88   static listForApi (start: number, count: number, sort: string) {
89     const query = {
90       offset: start,
91       limit: count,
92       order: getSort(sort),
93       include: [
94         {
95           model: AccountModel,
96           required: true
97         },
98         {
99           model: VideoModel,
100           required: true
101         }
102       ]
103     }
104
105     return VideoAbuseModel.findAndCountAll(query)
106       .then(({ rows, count }) => {
107         return { total: count, data: rows }
108       })
109   }
110
111   toFormattedJSON (this: MVideoAbuseFormattable): VideoAbuse {
112     return {
113       id: this.id,
114       reason: this.reason,
115       reporterAccount: this.Account.toFormattedJSON(),
116       state: {
117         id: this.state,
118         label: VideoAbuseModel.getStateLabel(this.state)
119       },
120       moderationComment: this.moderationComment,
121       video: {
122         id: this.Video.id,
123         uuid: this.Video.uuid,
124         name: this.Video.name
125       },
126       createdAt: this.createdAt
127     }
128   }
129
130   toActivityPubObject (this: MVideoAbuseVideo): VideoAbuseObject {
131     return {
132       type: 'Flag' as 'Flag',
133       content: this.reason,
134       object: this.Video.url
135     }
136   }
137
138   private static getStateLabel (id: number) {
139     return VIDEO_ABUSE_STATES[id] || 'Unknown'
140   }
141 }