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