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