diff options
-rw-r--r-- | server/helpers/decache.ts | 2 | ||||
-rw-r--r-- | server/helpers/memoize.ts | 12 | ||||
-rw-r--r-- | server/models/abuse/abuse.ts | 2 | ||||
-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.ts | 14 | ||||
-rw-r--r-- | server/models/actor/actor-follow.ts | 14 | ||||
-rw-r--r-- | server/models/actor/actor-image.ts | 14 | ||||
-rw-r--r-- | server/models/actor/actor.ts | 25 | ||||
-rw-r--r-- | server/models/actor/sql/shared/actor-follow-table-attributes.ts | 65 | ||||
-rw-r--r-- | server/models/server/server.ts | 14 | ||||
-rw-r--r-- | server/models/utils.ts | 52 | ||||
-rw-r--r-- | server/models/video/sql/comment/video-comment-table-attributes.ts | 71 | ||||
-rw-r--r-- | server/models/video/video-comment.ts | 14 |
13 files changed, 164 insertions, 137 deletions
diff --git a/server/helpers/decache.ts b/server/helpers/decache.ts index e31973b7a..08ab545e4 100644 --- a/server/helpers/decache.ts +++ b/server/helpers/decache.ts | |||
@@ -68,7 +68,7 @@ function searchCache (moduleName: string, callback: (current: NodeModule) => voi | |||
68 | }; | 68 | }; |
69 | 69 | ||
70 | function removeCachedPath (pluginPath: string) { | 70 | function removeCachedPath (pluginPath: string) { |
71 | const pathCache = (module.constructor as any)._pathCache | 71 | const pathCache = (module.constructor as any)._pathCache as { [ id: string ]: string[] } |
72 | 72 | ||
73 | Object.keys(pathCache).forEach(function (cacheKey) { | 73 | Object.keys(pathCache).forEach(function (cacheKey) { |
74 | if (cacheKey.includes(pluginPath)) { | 74 | if (cacheKey.includes(pluginPath)) { |
diff --git a/server/helpers/memoize.ts b/server/helpers/memoize.ts new file mode 100644 index 000000000..aa20e7d73 --- /dev/null +++ b/server/helpers/memoize.ts | |||
@@ -0,0 +1,12 @@ | |||
1 | import memoizee from 'memoizee' | ||
2 | |||
3 | export function Memoize (config?: memoizee.Options<any>) { | ||
4 | return function (_target, _key, descriptor: PropertyDescriptor) { | ||
5 | const oldFunction = descriptor.value | ||
6 | const newFunction = memoizee(oldFunction, config) | ||
7 | |||
8 | descriptor.value = function () { | ||
9 | return newFunction.apply(this, arguments) | ||
10 | } | ||
11 | } | ||
12 | } | ||
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' | |||
40 | import { VideoBlacklistModel } from '../video/video-blacklist' | 40 | import { VideoBlacklistModel } from '../video/video-blacklist' |
41 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions as ChannelSummaryOptions, VideoChannelModel } from '../video/video-channel' | 41 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions as ChannelSummaryOptions, VideoChannelModel } from '../video/video-channel' |
42 | import { ScopeNames as CommentScopeNames, VideoCommentModel } from '../video/video-comment' | 42 | import { ScopeNames as CommentScopeNames, VideoCommentModel } from '../video/video-comment' |
43 | import { buildAbuseListQuery, BuildAbusesQueryOptions } from './abuse-query-builder' | 43 | import { buildAbuseListQuery, BuildAbusesQueryOptions } from './sql/abuse-query-builder' |
44 | import { VideoAbuseModel } from './video-abuse' | 44 | import { VideoAbuseModel } from './video-abuse' |
45 | import { VideoCommentAbuseModel } from './video-comment-abuse' | 45 | import { 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 @@ | |||
2 | import { exists } from '@server/helpers/custom-validators/misc' | 2 | import { exists } from '@server/helpers/custom-validators/misc' |
3 | import { forceNumber } from '@shared/core-utils' | 3 | import { forceNumber } from '@shared/core-utils' |
4 | import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models' | 4 | import { AbuseFilter, AbuseState, AbuseVideoIs } from '@shared/models' |
5 | import { buildBlockedAccountSQL, buildDirectionAndField } from '../utils' | 5 | import { buildBlockedAccountSQL, buildDirectionAndField } from '../../utils' |
6 | 6 | ||
7 | export type BuildAbusesQueryOptions = { | 7 | export 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' | |||
38 | import { ServerModel } from '../server/server' | 38 | import { ServerModel } from '../server/server' |
39 | import { ServerBlocklistModel } from '../server/server-blocklist' | 39 | import { ServerBlocklistModel } from '../server/server-blocklist' |
40 | import { UserModel } from '../user/user' | 40 | import { UserModel } from '../user/user' |
41 | import { getSort, throwIfNotValid } from '../utils' | 41 | import { buildSQLAttributes, getSort, throwIfNotValid } from '../utils' |
42 | import { VideoModel } from '../video/video' | 42 | import { VideoModel } from '../video/video' |
43 | import { VideoChannelModel } from '../video/video-channel' | 43 | import { VideoChannelModel } from '../video/video-channel' |
44 | import { VideoCommentModel } from '../video/video-comment' | 44 | import { 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 | |||
38 | import { AccountModel } from '../account/account' | 38 | import { AccountModel } from '../account/account' |
39 | import { ServerModel } from '../server/server' | 39 | import { ServerModel } from '../server/server' |
40 | import { doesExist } from '../shared/query' | 40 | import { doesExist } from '../shared/query' |
41 | import { createSafeIn, getSort, searchAttribute, throwIfNotValid } from '../utils' | 41 | import { buildSQLAttributes, createSafeIn, getSort, searchAttribute, throwIfNotValid } from '../utils' |
42 | import { VideoChannelModel } from '../video/video-channel' | 42 | import { VideoChannelModel } from '../video/video-channel' |
43 | import { ActorModel, unusedActorAttributesForAPI } from './actor' | 43 | import { ActorModel, unusedActorAttributesForAPI } from './actor' |
44 | import { InstanceListFollowersQueryBuilder, ListFollowersOptions } from './sql/instance-list-followers-query-builder' | 44 | import { 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 | |||
22 | import { logger } from '../../helpers/logger' | 22 | import { logger } from '../../helpers/logger' |
23 | import { CONFIG } from '../../initializers/config' | 23 | import { CONFIG } from '../../initializers/config' |
24 | import { LAZY_STATIC_PATHS, MIMETYPES, WEBSERVER } from '../../initializers/constants' | 24 | import { LAZY_STATIC_PATHS, MIMETYPES, WEBSERVER } from '../../initializers/constants' |
25 | import { throwIfNotValid } from '../utils' | 25 | import { buildSQLAttributes, throwIfNotValid } from '../utils' |
26 | import { ActorModel } from './actor' | 26 | import { 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 { | |||
55 | import { AccountModel } from '../account/account' | 55 | import { AccountModel } from '../account/account' |
56 | import { getServerActor } from '../application/application' | 56 | import { getServerActor } from '../application/application' |
57 | import { ServerModel } from '../server/server' | 57 | import { ServerModel } from '../server/server' |
58 | import { isOutdated, throwIfNotValid } from '../utils' | 58 | import { buildSQLAttributes, isOutdated, throwIfNotValid } from '../utils' |
59 | import { VideoModel } from '../video/video' | 59 | import { VideoModel } from '../video/video' |
60 | import { VideoChannelModel } from '../video/video-channel' | 60 | import { VideoChannelModel } from '../video/video-channel' |
61 | import { ActorFollowModel } from './actor-follow' | 61 | import { ActorFollowModel } from './actor-follow' |
@@ -65,7 +65,7 @@ enum ScopeNames { | |||
65 | FULL = 'FULL' | 65 | FULL = 'FULL' |
66 | } | 66 | } |
67 | 67 | ||
68 | export const unusedActorAttributesForAPI = [ | 68 | export 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 @@ | |||
1 | import { logger } from '@server/helpers/logger' | ||
2 | import { Memoize } from '@server/helpers/memoize' | ||
3 | import { ServerModel } from '@server/models/server/server' | ||
4 | import { ActorModel } from '../../actor' | ||
5 | import { ActorFollowModel } from '../../actor-follow' | ||
6 | import { ActorImageModel } from '../../actor-image' | ||
7 | |||
1 | export class ActorFollowTableAttributes { | 8 | export 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' | |||
4 | import { AttributesOnly } from '@shared/typescript-utils' | 4 | import { AttributesOnly } from '@shared/typescript-utils' |
5 | import { isHostValid } from '../../helpers/custom-validators/servers' | 5 | import { isHostValid } from '../../helpers/custom-validators/servers' |
6 | import { ActorModel } from '../actor/actor' | 6 | import { ActorModel } from '../actor/actor' |
7 | import { throwIfNotValid } from '../utils' | 7 | import { buildSQLAttributes, throwIfNotValid } from '../utils' |
8 | import { ServerBlocklistModel } from './server-blocklist' | 8 | import { 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 @@ | |||
1 | import { literal, Op, OrderItem, Sequelize } from 'sequelize' | 1 | import { literal, Model, ModelStatic, Op, OrderItem, Sequelize } from 'sequelize' |
2 | import validator from 'validator' | 2 | import validator from 'validator' |
3 | import { forceNumber } from '@shared/core-utils' | 3 | import { forceNumber } from '@shared/core-utils' |
4 | import { AttributesOnly } from '@shared/typescript-utils' | ||
4 | 5 | ||
5 | type SortType = { sortModel: string, sortValue: string } | 6 | type 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 | ||
181 | function 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 | |||
205 | function buildServerIdsFollowedBy (actorId: any) { | 182 | function 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 | ||
257 | function 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 | ||
282 | export { | 282 | export { |
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 @@ | |||
1 | import { Memoize } from '@server/helpers/memoize' | ||
2 | import { AccountModel } from '@server/models/account/account' | ||
3 | import { ActorModel } from '@server/models/actor/actor' | ||
4 | import { ActorImageModel } from '@server/models/actor/actor-image' | ||
5 | import { ServerModel } from '@server/models/server/server' | ||
6 | import { VideoCommentModel } from '../../video-comment' | ||
7 | |||
1 | export class VideoCommentTableAttributes { | 8 | export 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 { | |||
40 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' | 40 | import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse' |
41 | import { AccountModel } from '../account/account' | 41 | import { AccountModel } from '../account/account' |
42 | import { ActorModel } from '../actor/actor' | 42 | import { ActorModel } from '../actor/actor' |
43 | import { buildLocalAccountIdsIn, throwIfNotValid } from '../utils' | 43 | import { buildLocalAccountIdsIn, buildSQLAttributes, throwIfNotValid } from '../utils' |
44 | import { ListVideoCommentsOptions, VideoCommentListQueryBuilder } from './sql/comment/video-comment-list-query-builder' | 44 | import { ListVideoCommentsOptions, VideoCommentListQueryBuilder } from './sql/comment/video-comment-list-query-builder' |
45 | import { VideoModel } from './video' | 45 | import { VideoModel } from './video' |
46 | import { VideoChannelModel } from './video-channel' | 46 | import { 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: { |