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