]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/models/account/account.ts
2eed66fc2696641fbcbf785581adc7d64270c28a
[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 { logger } from '../../helpers/logger'
20 import { sendDeleteActor } from '../../lib/activitypub/send'
21 import { ActorModel } from '../activitypub/actor'
22 import { ApplicationModel } from '../application/application'
23 import { AvatarModel } from '../avatar/avatar'
24 import { ServerModel } from '../server/server'
25 import { getSort, throwIfNotValid } from '../utils'
26 import { VideoChannelModel } from '../video/video-channel'
27 import { VideoCommentModel } from '../video/video-comment'
28 import { UserModel } from './user'
29
30 @DefaultScope({
31 include: [
32 {
33 model: () => ActorModel,
34 required: true,
35 include: [
36 {
37 model: () => ServerModel,
38 required: false
39 },
40 {
41 model: () => AvatarModel,
42 required: false
43 }
44 ]
45 }
46 ]
47 })
48 @Table({
49 tableName: 'account',
50 indexes: [
51 {
52 fields: [ 'actorId' ],
53 unique: true
54 },
55 {
56 fields: [ 'applicationId' ]
57 },
58 {
59 fields: [ 'userId' ]
60 }
61 ]
62 })
63 export class AccountModel extends Model<AccountModel> {
64
65 @AllowNull(false)
66 @Column
67 name: string
68
69 @AllowNull(true)
70 @Default(null)
71 @Is('AccountDescription', value => throwIfNotValid(value, isAccountDescriptionValid, 'description'))
72 @Column
73 description: string
74
75 @CreatedAt
76 createdAt: Date
77
78 @UpdatedAt
79 updatedAt: Date
80
81 @ForeignKey(() => ActorModel)
82 @Column
83 actorId: number
84
85 @BelongsTo(() => ActorModel, {
86 foreignKey: {
87 allowNull: false
88 },
89 onDelete: 'cascade'
90 })
91 Actor: ActorModel
92
93 @ForeignKey(() => UserModel)
94 @Column
95 userId: number
96
97 @BelongsTo(() => UserModel, {
98 foreignKey: {
99 allowNull: true
100 },
101 onDelete: 'cascade'
102 })
103 User: UserModel
104
105 @ForeignKey(() => ApplicationModel)
106 @Column
107 applicationId: number
108
109 @BelongsTo(() => ApplicationModel, {
110 foreignKey: {
111 allowNull: true
112 },
113 onDelete: 'cascade'
114 })
115 Application: ApplicationModel
116
117 @HasMany(() => VideoChannelModel, {
118 foreignKey: {
119 allowNull: false
120 },
121 onDelete: 'cascade',
122 hooks: true
123 })
124 VideoChannels: VideoChannelModel[]
125
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
141 if (instance.isOwned()) {
142 logger.debug('Sending delete of actor of account %s.', instance.Actor.url)
143 return sendDeleteActor(instance.Actor, options.transaction)
144 }
145
146 return undefined
147 }
148
149 static load (id: number) {
150 return AccountModel.findById(id)
151 }
152
153 static loadByUUID (uuid: string) {
154 const query = {
155 include: [
156 {
157 model: ActorModel,
158 required: true,
159 where: {
160 uuid
161 }
162 }
163 ]
164 }
165
166 return AccountModel.findOne(query)
167 }
168
169 static loadLocalByName (name: string) {
170 const query = {
171 where: {
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 ]
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 ]
219 }
220
221 return AccountModel.findOne(query)
222 }
223
224 static loadByUrl (url: string, transaction?: Sequelize.Transaction) {
225 const query = {
226 include: [
227 {
228 model: ActorModel,
229 required: true,
230 where: {
231 url
232 }
233 }
234 ],
235 transaction
236 }
237
238 return AccountModel.findOne(query)
239 }
240
241 static listForApi (start: number, count: number, sort: string) {
242 const query = {
243 offset: start,
244 limit: count,
245 order: getSort(sort)
246 }
247
248 return AccountModel.findAndCountAll(query)
249 .then(({ rows, count }) => {
250 return {
251 data: rows,
252 total: count
253 }
254 })
255 }
256
257 toFormattedJSON (): Account {
258 const actor = this.Actor.toFormattedJSON()
259 const account = {
260 id: this.id,
261 displayName: this.getDisplayName(),
262 description: this.description,
263 createdAt: this.createdAt,
264 updatedAt: this.updatedAt
265 }
266
267 return Object.assign(actor, account)
268 }
269
270 toActivityPubObject () {
271 const obj = this.Actor.toActivityPubObject(this.name, 'Account')
272
273 return Object.assign(obj, {
274 summary: this.description
275 })
276 }
277
278 isOwned () {
279 return this.Actor.isOwned()
280 }
281
282 getDisplayName () {
283 return this.name
284 }
285 }