aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models
diff options
context:
space:
mode:
Diffstat (limited to 'server/models')
-rw-r--r--server/models/abuse/abuse.ts2
-rw-r--r--server/models/abuse/sql/abuse-query-builder.ts (renamed from server/models/abuse/abuse-query-builder.ts)2
-rw-r--r--server/models/account/account.ts14
-rw-r--r--server/models/actor/actor-follow.ts14
-rw-r--r--server/models/actor/actor-image.ts14
-rw-r--r--server/models/actor/actor.ts25
-rw-r--r--server/models/actor/sql/shared/actor-follow-table-attributes.ts65
-rw-r--r--server/models/server/server.ts14
-rw-r--r--server/models/utils.ts52
-rw-r--r--server/models/video/sql/comment/video-comment-table-attributes.ts71
-rw-r--r--server/models/video/video-comment.ts14
11 files changed, 151 insertions, 136 deletions
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts
index 4c6a96a86..5610077c9 100644
--- a/server/models/abuse/abuse.ts
+++ b/server/models/abuse/abuse.ts
@@ -40,7 +40,7 @@ import { ScopeNames as VideoScopeNames, VideoModel } from '../video/video'
40import { VideoBlacklistModel } from '../video/video-blacklist' 40import { VideoBlacklistModel } from '../video/video-blacklist'
41import { ScopeNames as VideoChannelScopeNames, SummaryOptions as ChannelSummaryOptions, VideoChannelModel } from '../video/video-channel' 41import { ScopeNames as VideoChannelScopeNames, SummaryOptions as ChannelSummaryOptions, VideoChannelModel } from '../video/video-channel'
42import { ScopeNames as CommentScopeNames, VideoCommentModel } from '../video/video-comment' 42import { ScopeNames as CommentScopeNames, VideoCommentModel } from '../video/video-comment'
43import { buildAbuseListQuery, BuildAbusesQueryOptions } from './abuse-query-builder' 43import { buildAbuseListQuery, BuildAbusesQueryOptions } from './sql/abuse-query-builder'
44import { VideoAbuseModel } from './video-abuse' 44import { VideoAbuseModel } from './video-abuse'
45import { VideoCommentAbuseModel } from './video-comment-abuse' 45import { VideoCommentAbuseModel } from './video-comment-abuse'
46 46
diff --git a/server/models/abuse/abuse-query-builder.ts b/server/models/abuse/sql/abuse-query-builder.ts
index 74f4542e5..854f0cda8 100644
--- a/server/models/abuse/abuse-query-builder.ts
+++ b/server/models/abuse/sql/abuse-query-builder.ts
@@ -2,7 +2,7 @@
2import { exists } from '@server/helpers/custom-validators/misc' 2import { exists } from '@server/helpers/custom-validators/misc'
3import { forceNumber } from '@shared/core-utils' 3import { forceNumber } from '@shared/core-utils'
4import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models' 4import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models'
5import { buildBlockedAccountSQL, buildDirectionAndField } from '../utils' 5import { buildBlockedAccountSQL, buildDirectionAndField } from '../../utils'
6 6
7export type BuildAbusesQueryOptions = { 7export type BuildAbusesQueryOptions = {
8 start: number 8 start: number
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index 8a7dfba94..fca1b7b6d 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -38,7 +38,7 @@ import { ApplicationModel } from '../application/application'
38import { ServerModel } from '../server/server' 38import { ServerModel } from '../server/server'
39import { ServerBlocklistModel } from '../server/server-blocklist' 39import { ServerBlocklistModel } from '../server/server-blocklist'
40import { UserModel } from '../user/user' 40import { UserModel } from '../user/user'
41import { getSort, throwIfNotValid } from '../utils' 41import { buildSQLAttributes, getSort, throwIfNotValid } from '../utils'
42import { VideoModel } from '../video/video' 42import { VideoModel } from '../video/video'
43import { VideoChannelModel } from '../video/video-channel' 43import { VideoChannelModel } from '../video/video-channel'
44import { VideoCommentModel } from '../video/video-comment' 44import { VideoCommentModel } from '../video/video-comment'
@@ -251,6 +251,18 @@ export class AccountModel extends Model<Partial<AttributesOnly<AccountModel>>> {
251 return undefined 251 return undefined
252 } 252 }
253 253
254 // ---------------------------------------------------------------------------
255
256 static getSQLAttributes (tableName: string, aliasPrefix = '') {
257 return buildSQLAttributes({
258 model: this,
259 tableName,
260 aliasPrefix
261 })
262 }
263
264 // ---------------------------------------------------------------------------
265
254 static load (id: number, transaction?: Transaction): Promise<MAccountDefault> { 266 static load (id: number, transaction?: Transaction): Promise<MAccountDefault> {
255 return AccountModel.findByPk(id, { transaction }) 267 return AccountModel.findByPk(id, { transaction })
256 } 268 }
diff --git a/server/models/actor/actor-follow.ts b/server/models/actor/actor-follow.ts
index 9615229dd..a849817d5 100644
--- a/server/models/actor/actor-follow.ts
+++ b/server/models/actor/actor-follow.ts
@@ -38,7 +38,7 @@ import { ACTOR_FOLLOW_SCORE, CONSTRAINTS_FIELDS, FOLLOW_STATES, SERVER_ACTOR_NAM
38import { AccountModel } from '../account/account' 38import { AccountModel } from '../account/account'
39import { ServerModel } from '../server/server' 39import { ServerModel } from '../server/server'
40import { doesExist } from '../shared/query' 40import { doesExist } from '../shared/query'
41import { createSafeIn, getSort, searchAttribute, throwIfNotValid } from '../utils' 41import { buildSQLAttributes, createSafeIn, getSort, searchAttribute, throwIfNotValid } from '../utils'
42import { VideoChannelModel } from '../video/video-channel' 42import { VideoChannelModel } from '../video/video-channel'
43import { ActorModel, unusedActorAttributesForAPI } from './actor' 43import { ActorModel, unusedActorAttributesForAPI } from './actor'
44import { InstanceListFollowersQueryBuilder, ListFollowersOptions } from './sql/instance-list-followers-query-builder' 44import { InstanceListFollowersQueryBuilder, ListFollowersOptions } from './sql/instance-list-followers-query-builder'
@@ -140,6 +140,18 @@ export class ActorFollowModel extends Model<Partial<AttributesOnly<ActorFollowMo
140 }) 140 })
141 } 141 }
142 142
143 // ---------------------------------------------------------------------------
144
145 static getSQLAttributes (tableName: string, aliasPrefix = '') {
146 return buildSQLAttributes({
147 model: this,
148 tableName,
149 aliasPrefix
150 })
151 }
152
153 // ---------------------------------------------------------------------------
154
143 /* 155 /*
144 * @deprecated Use `findOrCreateCustom` instead 156 * @deprecated Use `findOrCreateCustom` instead
145 */ 157 */
diff --git a/server/models/actor/actor-image.ts b/server/models/actor/actor-image.ts
index f2b3b2f4b..83898cd38 100644
--- a/server/models/actor/actor-image.ts
+++ b/server/models/actor/actor-image.ts
@@ -22,7 +22,7 @@ import { isActivityPubUrlValid } from '../../helpers/custom-validators/activityp
22import { logger } from '../../helpers/logger' 22import { logger } from '../../helpers/logger'
23import { CONFIG } from '../../initializers/config' 23import { CONFIG } from '../../initializers/config'
24import { LAZY_STATIC_PATHS, MIMETYPES, WEBSERVER } from '../../initializers/constants' 24import { LAZY_STATIC_PATHS, MIMETYPES, WEBSERVER } from '../../initializers/constants'
25import { throwIfNotValid } from '../utils' 25import { buildSQLAttributes, throwIfNotValid } from '../utils'
26import { ActorModel } from './actor' 26import { ActorModel } from './actor'
27 27
28@Table({ 28@Table({
@@ -94,6 +94,18 @@ export class ActorImageModel extends Model<Partial<AttributesOnly<ActorImageMode
94 .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, { err })) 94 .catch(err => logger.error('Cannot remove actor image file %s.', instance.filename, { err }))
95 } 95 }
96 96
97 // ---------------------------------------------------------------------------
98
99 static getSQLAttributes (tableName: string, aliasPrefix = '') {
100 return buildSQLAttributes({
101 model: this,
102 tableName,
103 aliasPrefix
104 })
105 }
106
107 // ---------------------------------------------------------------------------
108
97 static loadByName (filename: string) { 109 static loadByName (filename: string) {
98 const query = { 110 const query = {
99 where: { 111 where: {
diff --git a/server/models/actor/actor.ts b/server/models/actor/actor.ts
index d7afa727d..a62e6030a 100644
--- a/server/models/actor/actor.ts
+++ b/server/models/actor/actor.ts
@@ -55,7 +55,7 @@ import {
55import { AccountModel } from '../account/account' 55import { AccountModel } from '../account/account'
56import { getServerActor } from '../application/application' 56import { getServerActor } from '../application/application'
57import { ServerModel } from '../server/server' 57import { ServerModel } from '../server/server'
58import { isOutdated, throwIfNotValid } from '../utils' 58import { buildSQLAttributes, isOutdated, throwIfNotValid } from '../utils'
59import { VideoModel } from '../video/video' 59import { VideoModel } from '../video/video'
60import { VideoChannelModel } from '../video/video-channel' 60import { VideoChannelModel } from '../video/video-channel'
61import { ActorFollowModel } from './actor-follow' 61import { ActorFollowModel } from './actor-follow'
@@ -65,7 +65,7 @@ enum ScopeNames {
65 FULL = 'FULL' 65 FULL = 'FULL'
66} 66}
67 67
68export const unusedActorAttributesForAPI = [ 68export const unusedActorAttributesForAPI: (keyof AttributesOnly<ActorModel>)[] = [
69 'publicKey', 69 'publicKey',
70 'privateKey', 70 'privateKey',
71 'inboxUrl', 71 'inboxUrl',
@@ -306,6 +306,27 @@ export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> {
306 }) 306 })
307 VideoChannel: VideoChannelModel 307 VideoChannel: VideoChannelModel
308 308
309 // ---------------------------------------------------------------------------
310
311 static getSQLAttributes (tableName: string, aliasPrefix = '') {
312 return buildSQLAttributes({
313 model: this,
314 tableName,
315 aliasPrefix
316 })
317 }
318
319 static getSQLAPIAttributes (tableName: string, aliasPrefix = '') {
320 return buildSQLAttributes({
321 model: this,
322 tableName,
323 aliasPrefix,
324 excludeAttributes: unusedActorAttributesForAPI
325 })
326 }
327
328 // ---------------------------------------------------------------------------
329
309 static async load (id: number): Promise<MActor> { 330 static async load (id: number): Promise<MActor> {
310 const actorServer = await getServerActor() 331 const actorServer = await getServerActor()
311 if (id === actorServer.id) return actorServer 332 if (id === actorServer.id) return actorServer
diff --git a/server/models/actor/sql/shared/actor-follow-table-attributes.ts b/server/models/actor/sql/shared/actor-follow-table-attributes.ts
index 156b37d44..7dd908ece 100644
--- a/server/models/actor/sql/shared/actor-follow-table-attributes.ts
+++ b/server/models/actor/sql/shared/actor-follow-table-attributes.ts
@@ -1,62 +1,31 @@
1import { logger } from '@server/helpers/logger'
2import { Memoize } from '@server/helpers/memoize'
3import { ServerModel } from '@server/models/server/server'
4import { ActorModel } from '../../actor'
5import { ActorFollowModel } from '../../actor-follow'
6import { ActorImageModel } from '../../actor-image'
7
1export class ActorFollowTableAttributes { 8export class ActorFollowTableAttributes {
2 9
10 @Memoize()
3 getFollowAttributes () { 11 getFollowAttributes () {
4 return [ 12 logger.error('coucou')
5 '"ActorFollowModel"."id"', 13
6 '"ActorFollowModel"."state"', 14 return ActorFollowModel.getSQLAttributes('ActorFollowModel').join(', ')
7 '"ActorFollowModel"."score"',
8 '"ActorFollowModel"."url"',
9 '"ActorFollowModel"."actorId"',
10 '"ActorFollowModel"."targetActorId"',
11 '"ActorFollowModel"."createdAt"',
12 '"ActorFollowModel"."updatedAt"'
13 ].join(', ')
14 } 15 }
15 16
17 @Memoize()
16 getActorAttributes (actorTableName: string) { 18 getActorAttributes (actorTableName: string) {
17 return [ 19 return ActorModel.getSQLAttributes(actorTableName, `${actorTableName}.`).join(', ')
18 `"${actorTableName}"."id" AS "${actorTableName}.id"`,
19 `"${actorTableName}"."type" AS "${actorTableName}.type"`,
20 `"${actorTableName}"."preferredUsername" AS "${actorTableName}.preferredUsername"`,
21 `"${actorTableName}"."url" AS "${actorTableName}.url"`,
22 `"${actorTableName}"."publicKey" AS "${actorTableName}.publicKey"`,
23 `"${actorTableName}"."privateKey" AS "${actorTableName}.privateKey"`,
24 `"${actorTableName}"."followersCount" AS "${actorTableName}.followersCount"`,
25 `"${actorTableName}"."followingCount" AS "${actorTableName}.followingCount"`,
26 `"${actorTableName}"."inboxUrl" AS "${actorTableName}.inboxUrl"`,
27 `"${actorTableName}"."outboxUrl" AS "${actorTableName}.outboxUrl"`,
28 `"${actorTableName}"."sharedInboxUrl" AS "${actorTableName}.sharedInboxUrl"`,
29 `"${actorTableName}"."followersUrl" AS "${actorTableName}.followersUrl"`,
30 `"${actorTableName}"."followingUrl" AS "${actorTableName}.followingUrl"`,
31 `"${actorTableName}"."remoteCreatedAt" AS "${actorTableName}.remoteCreatedAt"`,
32 `"${actorTableName}"."serverId" AS "${actorTableName}.serverId"`,
33 `"${actorTableName}"."createdAt" AS "${actorTableName}.createdAt"`,
34 `"${actorTableName}"."updatedAt" AS "${actorTableName}.updatedAt"`
35 ].join(', ')
36 } 20 }
37 21
22 @Memoize()
38 getServerAttributes (actorTableName: string) { 23 getServerAttributes (actorTableName: string) {
39 return [ 24 return ServerModel.getSQLAttributes(`${actorTableName}->Server`, `${actorTableName}.Server.`).join(', ')
40 `"${actorTableName}->Server"."id" AS "${actorTableName}.Server.id"`,
41 `"${actorTableName}->Server"."host" AS "${actorTableName}.Server.host"`,
42 `"${actorTableName}->Server"."redundancyAllowed" AS "${actorTableName}.Server.redundancyAllowed"`,
43 `"${actorTableName}->Server"."createdAt" AS "${actorTableName}.Server.createdAt"`,
44 `"${actorTableName}->Server"."updatedAt" AS "${actorTableName}.Server.updatedAt"`
45 ].join(', ')
46 } 25 }
47 26
27 @Memoize()
48 getAvatarAttributes (actorTableName: string) { 28 getAvatarAttributes (actorTableName: string) {
49 return [ 29 return ActorImageModel.getSQLAttributes(`${actorTableName}->Avatars`, `${actorTableName}.Avatars.`).join(', ')
50 `"${actorTableName}->Avatars"."id" AS "${actorTableName}.Avatars.id"`,
51 `"${actorTableName}->Avatars"."filename" AS "${actorTableName}.Avatars.filename"`,
52 `"${actorTableName}->Avatars"."height" AS "${actorTableName}.Avatars.height"`,
53 `"${actorTableName}->Avatars"."width" AS "${actorTableName}.Avatars.width"`,
54 `"${actorTableName}->Avatars"."fileUrl" AS "${actorTableName}.Avatars.fileUrl"`,
55 `"${actorTableName}->Avatars"."onDisk" AS "${actorTableName}.Avatars.onDisk"`,
56 `"${actorTableName}->Avatars"."type" AS "${actorTableName}.Avatars.type"`,
57 `"${actorTableName}->Avatars"."actorId" AS "${actorTableName}.Avatars.actorId"`,
58 `"${actorTableName}->Avatars"."createdAt" AS "${actorTableName}.Avatars.createdAt"`,
59 `"${actorTableName}->Avatars"."updatedAt" AS "${actorTableName}.Avatars.updatedAt"`
60 ].join(', ')
61 } 30 }
62} 31}
diff --git a/server/models/server/server.ts b/server/models/server/server.ts
index ef42de090..f6cb40f60 100644
--- a/server/models/server/server.ts
+++ b/server/models/server/server.ts
@@ -4,7 +4,7 @@ import { MServer, MServerFormattable } from '@server/types/models/server'
4import { AttributesOnly } from '@shared/typescript-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { isHostValid } from '../../helpers/custom-validators/servers' 5import { isHostValid } from '../../helpers/custom-validators/servers'
6import { ActorModel } from '../actor/actor' 6import { ActorModel } from '../actor/actor'
7import { throwIfNotValid } from '../utils' 7import { buildSQLAttributes, throwIfNotValid } from '../utils'
8import { ServerBlocklistModel } from './server-blocklist' 8import { ServerBlocklistModel } from './server-blocklist'
9 9
10@Table({ 10@Table({
@@ -52,6 +52,18 @@ export class ServerModel extends Model<Partial<AttributesOnly<ServerModel>>> {
52 }) 52 })
53 BlockedBy: ServerBlocklistModel[] 53 BlockedBy: ServerBlocklistModel[]
54 54
55 // ---------------------------------------------------------------------------
56
57 static getSQLAttributes (tableName: string, aliasPrefix = '') {
58 return buildSQLAttributes({
59 model: this,
60 tableName,
61 aliasPrefix
62 })
63 }
64
65 // ---------------------------------------------------------------------------
66
55 static load (id: number, transaction?: Transaction): Promise<MServer> { 67 static load (id: number, transaction?: Transaction): Promise<MServer> {
56 const query = { 68 const query = {
57 where: { 69 where: {
diff --git a/server/models/utils.ts b/server/models/utils.ts
index 0b6ac8340..69ad123ac 100644
--- a/server/models/utils.ts
+++ b/server/models/utils.ts
@@ -1,6 +1,7 @@
1import { literal, Op, OrderItem, Sequelize } from 'sequelize' 1import { literal, Model, ModelStatic, Op, OrderItem, Sequelize } from 'sequelize'
2import validator from 'validator' 2import validator from 'validator'
3import { forceNumber } from '@shared/core-utils' 3import { forceNumber } from '@shared/core-utils'
4import { AttributesOnly } from '@shared/typescript-utils'
4 5
5type SortType = { sortModel: string, sortValue: string } 6type SortType = { sortModel: string, sortValue: string }
6 7
@@ -178,30 +179,6 @@ function buildBlockedAccountSQL (blockerIds: number[]) {
178 'WHERE "serverBlocklist"."accountId" IN (' + blockerIdsString + ')' 179 'WHERE "serverBlocklist"."accountId" IN (' + blockerIdsString + ')'
179} 180}
180 181
181function buildBlockedAccountSQLOptimized (columnNameJoin: string, blockerIds: number[]) {
182 const blockerIdsString = blockerIds.join(', ')
183
184 return [
185 literal(
186 `NOT EXISTS (` +
187 ` SELECT 1 FROM "accountBlocklist" ` +
188 ` WHERE "targetAccountId" = ${columnNameJoin} ` +
189 ` AND "accountId" IN (${blockerIdsString})` +
190 `)`
191 ),
192
193 literal(
194 `NOT EXISTS (` +
195 ` SELECT 1 FROM "account" ` +
196 ` INNER JOIN "actor" ON account."actorId" = actor.id ` +
197 ` INNER JOIN "serverBlocklist" ON "actor"."serverId" = "serverBlocklist"."targetServerId" ` +
198 ` WHERE "account"."id" = ${columnNameJoin} ` +
199 ` AND "serverBlocklist"."accountId" IN (${blockerIdsString})` +
200 `)`
201 )
202 ]
203}
204
205function buildServerIdsFollowedBy (actorId: any) { 182function buildServerIdsFollowedBy (actorId: any) {
206 const actorIdNumber = forceNumber(actorId) 183 const actorIdNumber = forceNumber(actorId)
207 184
@@ -277,11 +254,34 @@ function searchAttribute (sourceField?: string, targetField?: string) {
277 } 254 }
278} 255}
279 256
257function buildSQLAttributes <M extends Model> (options: {
258 model: ModelStatic<M>
259 tableName: string
260
261 excludeAttributes?: (keyof AttributesOnly<M>)[]
262 aliasPrefix?: string
263}) {
264 const { model, tableName, aliasPrefix, excludeAttributes } = options
265
266 const attributes = Object.keys(model.getAttributes())
267
268 return attributes
269 .filter(a => {
270 if (!excludeAttributes) return true
271 if (excludeAttributes.includes(a)) return false
272
273 return true
274 })
275 .map(a => {
276 return `"${tableName}"."${a}" AS "${aliasPrefix || ''}${a}"`
277 })
278}
279
280// --------------------------------------------------------------------------- 280// ---------------------------------------------------------------------------
281 281
282export { 282export {
283 buildSQLAttributes,
283 buildBlockedAccountSQL, 284 buildBlockedAccountSQL,
284 buildBlockedAccountSQLOptimized,
285 buildLocalActorIdsIn, 285 buildLocalActorIdsIn,
286 getPlaylistSort, 286 getPlaylistSort,
287 SortType, 287 SortType,
diff --git a/server/models/video/sql/comment/video-comment-table-attributes.ts b/server/models/video/sql/comment/video-comment-table-attributes.ts
index cae3c1683..10e635e41 100644
--- a/server/models/video/sql/comment/video-comment-table-attributes.ts
+++ b/server/models/video/sql/comment/video-comment-table-attributes.ts
@@ -1,33 +1,23 @@
1import { Memoize } from '@server/helpers/memoize'
2import { AccountModel } from '@server/models/account/account'
3import { ActorModel } from '@server/models/actor/actor'
4import { ActorImageModel } from '@server/models/actor/actor-image'
5import { ServerModel } from '@server/models/server/server'
6import { VideoCommentModel } from '../../video-comment'
7
1export class VideoCommentTableAttributes { 8export class VideoCommentTableAttributes {
2 9
10 @Memoize()
3 getVideoCommentAttributes () { 11 getVideoCommentAttributes () {
4 return [ 12 return VideoCommentModel.getSQLAttributes('VideoCommentModel').join(', ')
5 '"VideoCommentModel"."id"',
6 '"VideoCommentModel"."url"',
7 '"VideoCommentModel"."deletedAt"',
8 '"VideoCommentModel"."updatedAt"',
9 '"VideoCommentModel"."createdAt"',
10 '"VideoCommentModel"."text"',
11 '"VideoCommentModel"."originCommentId"',
12 '"VideoCommentModel"."inReplyToCommentId"',
13 '"VideoCommentModel"."videoId"',
14 '"VideoCommentModel"."accountId"'
15 ].join(', ')
16 } 13 }
17 14
15 @Memoize()
18 getAccountAttributes () { 16 getAccountAttributes () {
19 return [ 17 return AccountModel.getSQLAttributes('Account', 'Account.').join(', ')
20 `"Account"."id" AS "Account.id"`,
21 `"Account"."name" AS "Account.name"`,
22 `"Account"."description" AS "Account.description"`,
23 `"Account"."createdAt" AS "Account.createdAt"`,
24 `"Account"."updatedAt" AS "Account.updatedAt"`,
25 `"Account"."actorId" AS "Account.actorId"`,
26 `"Account"."userId" AS "Account.userId"`,
27 `"Account"."applicationId" AS "Account.applicationId"`
28 ].join(', ')
29 } 18 }
30 19
20 @Memoize()
31 getVideoAttributes () { 21 getVideoAttributes () {
32 return [ 22 return [
33 `"Video"."id" AS "Video.id"`, 23 `"Video"."id" AS "Video.id"`,
@@ -36,43 +26,18 @@ export class VideoCommentTableAttributes {
36 ].join(', ') 26 ].join(', ')
37 } 27 }
38 28
29 @Memoize()
39 getActorAttributes () { 30 getActorAttributes () {
40 return [ 31 return ActorModel.getSQLAPIAttributes('Account->Actor', `Account.Actor.`).join(', ')
41 `"Account->Actor"."id" AS "Account.Actor.id"`,
42 `"Account->Actor"."type" AS "Account.Actor.type"`,
43 `"Account->Actor"."preferredUsername" AS "Account.Actor.preferredUsername"`,
44 `"Account->Actor"."url" AS "Account.Actor.url"`,
45 `"Account->Actor"."followersCount" AS "Account.Actor.followersCount"`,
46 `"Account->Actor"."followingCount" AS "Account.Actor.followingCount"`,
47 `"Account->Actor"."remoteCreatedAt" AS "Account.Actor.remoteCreatedAt"`,
48 `"Account->Actor"."serverId" AS "Account.Actor.serverId"`,
49 `"Account->Actor"."createdAt" AS "Account.Actor.createdAt"`,
50 `"Account->Actor"."updatedAt" AS "Account.Actor.updatedAt"`
51 ].join(', ')
52 } 32 }
53 33
34 @Memoize()
54 getServerAttributes () { 35 getServerAttributes () {
55 return [ 36 return ServerModel.getSQLAttributes('Account->Actor->Server', `Account.Actor.Server.`).join(', ')
56 `"Account->Actor->Server"."id" AS "Account.Actor.Server.id"`,
57 `"Account->Actor->Server"."host" AS "Account.Actor.Server.host"`,
58 `"Account->Actor->Server"."redundancyAllowed" AS "Account.Actor.Server.redundancyAllowed"`,
59 `"Account->Actor->Server"."createdAt" AS "Account.Actor.Server.createdAt"`,
60 `"Account->Actor->Server"."updatedAt" AS "Account.Actor.Server.updatedAt"`
61 ].join(', ')
62 } 37 }
63 38
39 @Memoize()
64 getAvatarAttributes () { 40 getAvatarAttributes () {
65 return [ 41 return ActorImageModel.getSQLAttributes('Account->Actor->Avatars', 'Account.Actor.Avatars.id').join(', ')
66 `"Account->Actor->Avatars"."id" AS "Account.Actor.Avatars.id"`,
67 `"Account->Actor->Avatars"."filename" AS "Account.Actor.Avatars.filename"`,
68 `"Account->Actor->Avatars"."height" AS "Account.Actor.Avatars.height"`,
69 `"Account->Actor->Avatars"."width" AS "Account.Actor.Avatars.width"`,
70 `"Account->Actor->Avatars"."fileUrl" AS "Account.Actor.Avatars.fileUrl"`,
71 `"Account->Actor->Avatars"."onDisk" AS "Account.Actor.Avatars.onDisk"`,
72 `"Account->Actor->Avatars"."type" AS "Account.Actor.Avatars.type"`,
73 `"Account->Actor->Avatars"."actorId" AS "Account.Actor.Avatars.actorId"`,
74 `"Account->Actor->Avatars"."createdAt" AS "Account.Actor.Avatars.createdAt"`,
75 `"Account->Actor->Avatars"."updatedAt" AS "Account.Actor.Avatars.updatedAt"`
76 ].join(', ')
77 } 42 }
78} 43}
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts
index fb9d15e55..28a3d723d 100644
--- a/server/models/video/video-comment.ts
+++ b/server/models/video/video-comment.ts
@@ -40,7 +40,7 @@ import {
40import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' 40import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse'
41import { AccountModel } from '../account/account' 41import { AccountModel } from '../account/account'
42import { ActorModel } from '../actor/actor' 42import { ActorModel } from '../actor/actor'
43import { buildLocalAccountIdsIn, throwIfNotValid } from '../utils' 43import { buildLocalAccountIdsIn, buildSQLAttributes, throwIfNotValid } from '../utils'
44import { ListVideoCommentsOptions, VideoCommentListQueryBuilder } from './sql/comment/video-comment-list-query-builder' 44import { ListVideoCommentsOptions, VideoCommentListQueryBuilder } from './sql/comment/video-comment-list-query-builder'
45import { VideoModel } from './video' 45import { VideoModel } from './video'
46import { VideoChannelModel } from './video-channel' 46import { VideoChannelModel } from './video-channel'
@@ -192,6 +192,18 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment
192 }) 192 })
193 CommentAbuses: VideoCommentAbuseModel[] 193 CommentAbuses: VideoCommentAbuseModel[]
194 194
195 // ---------------------------------------------------------------------------
196
197 static getSQLAttributes (tableName: string, aliasPrefix = '') {
198 return buildSQLAttributes({
199 model: this,
200 tableName,
201 aliasPrefix
202 })
203 }
204
205 // ---------------------------------------------------------------------------
206
195 static loadById (id: number, t?: Transaction): Promise<MComment> { 207 static loadById (id: number, t?: Transaction): Promise<MComment> {
196 const query: FindOptions = { 208 const query: FindOptions = {
197 where: { 209 where: {