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