Add user moderation in the account page
[oweals/peertube.git] / server / models / account / account.ts
1 import * as Sequelize from 'sequelize'
2 import {
3   AllowNull,
4   BeforeDestroy,
5   BelongsTo,
6   Column,
7   CreatedAt,
8   Default,
9   DefaultScope,
10   ForeignKey,
11   HasMany,
12   Is,
13   Model,
14   Table,
15   UpdatedAt
16 } from 'sequelize-typescript'
17 import { Account } from '../../../shared/models/actors'
18 import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts'
19 import { sendDeleteActor } from '../../lib/activitypub/send'
20 import { ActorModel } from '../activitypub/actor'
21 import { ApplicationModel } from '../application/application'
22 import { ServerModel } from '../server/server'
23 import { getSort, throwIfNotValid } from '../utils'
24 import { VideoChannelModel } from '../video/video-channel'
25 import { VideoCommentModel } from '../video/video-comment'
26 import { UserModel } from './user'
27
28 @DefaultScope({
29   include: [
30     {
31       model: () => ActorModel, // Default scope includes avatar and server
32       required: true
33     }
34   ]
35 })
36 @Table({
37   tableName: 'account',
38   indexes: [
39     {
40       fields: [ 'actorId' ],
41       unique: true
42     },
43     {
44       fields: [ 'applicationId' ]
45     },
46     {
47       fields: [ 'userId' ]
48     }
49   ]
50 })
51 export class AccountModel extends Model<AccountModel> {
52
53   @AllowNull(false)
54   @Column
55   name: string
56
57   @AllowNull(true)
58   @Default(null)
59   @Is('AccountDescription', value => throwIfNotValid(value, isAccountDescriptionValid, 'description'))
60   @Column
61   description: string
62
63   @CreatedAt
64   createdAt: Date
65
66   @UpdatedAt
67   updatedAt: Date
68
69   @ForeignKey(() => ActorModel)
70   @Column
71   actorId: number
72
73   @BelongsTo(() => ActorModel, {
74     foreignKey: {
75       allowNull: false
76     },
77     onDelete: 'cascade'
78   })
79   Actor: ActorModel
80
81   @ForeignKey(() => UserModel)
82   @Column
83   userId: number
84
85   @BelongsTo(() => UserModel, {
86     foreignKey: {
87       allowNull: true
88     },
89     onDelete: 'cascade'
90   })
91   User: UserModel
92
93   @ForeignKey(() => ApplicationModel)
94   @Column
95   applicationId: number
96
97   @BelongsTo(() => ApplicationModel, {
98     foreignKey: {
99       allowNull: true
100     },
101     onDelete: 'cascade'
102   })
103   Application: ApplicationModel
104
105   @HasMany(() => VideoChannelModel, {
106     foreignKey: {
107       allowNull: false
108     },
109     onDelete: 'cascade',
110     hooks: true
111   })
112   VideoChannels: VideoChannelModel[]
113
114   @HasMany(() => VideoCommentModel, {
115     foreignKey: {
116       allowNull: false
117     },
118     onDelete: 'cascade',
119     hooks: true
120   })
121   VideoComments: VideoCommentModel[]
122
123   @BeforeDestroy
124   static async sendDeleteIfOwned (instance: AccountModel, options) {
125     if (!instance.Actor) {
126       instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) as ActorModel
127     }
128
129     if (instance.isOwned()) {
130       return sendDeleteActor(instance.Actor, options.transaction)
131     }
132
133     return undefined
134   }
135
136   static load (id: number, transaction?: Sequelize.Transaction) {
137     return AccountModel.findById(id, { transaction })
138   }
139
140   static loadByUUID (uuid: string) {
141     const query = {
142       include: [
143         {
144           model: ActorModel,
145           required: true,
146           where: {
147             uuid
148           }
149         }
150       ]
151     }
152
153     return AccountModel.findOne(query)
154   }
155
156   static loadLocalByName (name: string) {
157     const query = {
158       where: {
159         [ Sequelize.Op.or ]: [
160           {
161             userId: {
162               [ Sequelize.Op.ne ]: null
163             }
164           },
165           {
166             applicationId: {
167               [ Sequelize.Op.ne ]: null
168             }
169           }
170         ]
171       },
172       include: [
173         {
174           model: ActorModel,
175           required: true,
176           where: {
177             preferredUsername: name
178           }
179         }
180       ]
181     }
182
183     return AccountModel.findOne(query)
184   }
185
186   static loadByNameAndHost (name: string, host: string) {
187     const query = {
188       include: [
189         {
190           model: ActorModel,
191           required: true,
192           where: {
193             preferredUsername: name
194           },
195           include: [
196             {
197               model: ServerModel,
198               required: true,
199               where: {
200                 host
201               }
202             }
203           ]
204         }
205       ]
206     }
207
208     return AccountModel.findOne(query)
209   }
210
211   static loadByUrl (url: string, transaction?: Sequelize.Transaction) {
212     const query = {
213       include: [
214         {
215           model: ActorModel,
216           required: true,
217           where: {
218             url
219           }
220         }
221       ],
222       transaction
223     }
224
225     return AccountModel.findOne(query)
226   }
227
228   static listForApi (start: number, count: number, sort: string) {
229     const query = {
230       offset: start,
231       limit: count,
232       order: getSort(sort)
233     }
234
235     return AccountModel.findAndCountAll(query)
236       .then(({ rows, count }) => {
237         return {
238           data: rows,
239           total: count
240         }
241       })
242   }
243
244   toFormattedJSON (): Account {
245     const actor = this.Actor.toFormattedJSON()
246     const account = {
247       id: this.id,
248       displayName: this.getDisplayName(),
249       description: this.description,
250       createdAt: this.createdAt,
251       updatedAt: this.updatedAt,
252       userId: this.userId ? this.userId : undefined
253     }
254
255     return Object.assign(actor, account)
256   }
257
258   toActivityPubObject () {
259     const obj = this.Actor.toActivityPubObject(this.name, 'Account')
260
261     return Object.assign(obj, {
262       summary: this.description
263     })
264   }
265
266   isOwned () {
267     return this.Actor.isOwned()
268   }
269
270   getDisplayName () {
271     return this.name
272   }
273 }