From 499d6607236fb2c80beaf810ee5de22f6e09ae0e Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 24 Sep 2024 13:27:46 +0200 Subject: [PATCH] Faster get a user --- .../users/user-edit/user-edit.component.scss | 8 +- server/core/models/user/user.ts | 213 +++++++++--------- server/core/models/video/video-file.ts | 2 +- 3 files changed, 116 insertions(+), 107 deletions(-) diff --git a/client/src/app/+admin/overview/users/user-edit/user-edit.component.scss b/client/src/app/+admin/overview/users/user-edit/user-edit.component.scss index 1f17e0da0..efd1dd800 100644 --- a/client/src/app/+admin/overview/users/user-edit/user-edit.component.scss +++ b/client/src/app/+admin/overview/users/user-edit/user-edit.component.scss @@ -24,11 +24,9 @@ my-select-custom-value { @include responsive-width($form-base-input-width); } -.danger-zone { - button { - @include danger-button; - @include disable-outline; - } +.danger-zone button { + @include danger-button; + @include disable-outline; } .dashboard { diff --git a/server/core/models/user/user.ts b/server/core/models/user/user.ts index c2f8f81e0..dffaff4ed 100644 --- a/server/core/models/user/user.ts +++ b/server/core/models/user/user.ts @@ -21,7 +21,7 @@ import { MUserNotifSettingChannelDefault, MUserWithNotificationSetting } from '@server/types/models/index.js' -import { col, FindOptions, fn, literal, Op, QueryTypes, where, WhereOptions } from 'sequelize' +import { col, FindOptions, fn, literal, Op, QueryTypes, ScopeOptions, where, WhereOptions } from 'sequelize' import { AfterDestroy, AfterUpdate, @@ -85,6 +85,8 @@ enum ScopeNames { WITH_STATS = 'WITH_STATS' } +type WhereUserIdScopeOptions = { whereUserId?: '$userId' | '"UserModel"."id"' } + @DefaultScope(() => ({ include: [ { @@ -159,107 +161,113 @@ enum ScopeNames { } ] }, - [ScopeNames.WITH_QUOTA]: { - attributes: { - include: [ - [ - literal( - '(' + - UserModel.generateUserQuotaBaseSQL({ - whereUserId: '"UserModel"."id"', - daily: false, - onlyMaxResolution: true - }) + - ')' - ), - 'videoQuotaUsed' - ], - [ - literal( - '(' + - UserModel.generateUserQuotaBaseSQL({ - whereUserId: '"UserModel"."id"', - daily: true, - onlyMaxResolution: true - }) + - ')' - ), - 'videoQuotaUsedDaily' + [ScopeNames.WITH_QUOTA]: (options: WhereUserIdScopeOptions = {}) => { + return { + attributes: { + include: [ + [ + literal( + '(' + + UserModel.generateUserQuotaBaseSQL({ + whereUserId: options.whereUserId ?? '"UserModel"."id"', + daily: false, + onlyMaxResolution: true + }) + + ')' + ), + 'videoQuotaUsed' + ], + [ + literal( + '(' + + UserModel.generateUserQuotaBaseSQL({ + whereUserId: options.whereUserId ?? '"UserModel"."id"', + daily: true, + onlyMaxResolution: true + }) + + ')' + ), + 'videoQuotaUsedDaily' + ] ] - ] + } } }, - [ScopeNames.WITH_TOTAL_FILE_SIZES]: { - attributes: { - include: [ - [ - literal( - '(' + - UserModel.generateUserQuotaBaseSQL({ - whereUserId: '"UserModel"."id"', - daily: false, - onlyMaxResolution: false - }) + - ')' - ), - 'totalVideoFileSize' + [ScopeNames.WITH_TOTAL_FILE_SIZES]: (options: WhereUserIdScopeOptions = {}) => { + return { + attributes: { + include: [ + [ + literal( + '(' + + UserModel.generateUserQuotaBaseSQL({ + whereUserId: options.whereUserId ?? '"UserModel"."id"', + daily: false, + onlyMaxResolution: false + }) + + ')' + ), + 'totalVideoFileSize' + ] ] - ] + } } }, - [ScopeNames.WITH_STATS]: { - attributes: { - include: [ - [ - literal( - '(' + - 'SELECT COUNT("video"."id") ' + - 'FROM "video" ' + - 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + - 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + - 'WHERE "account"."userId" = "UserModel"."id"' + - ')' - ), - 'videosCount' - ], - [ - literal( - '(' + - `SELECT concat_ws(':', "abuses", "acceptedAbuses") ` + - 'FROM (' + - 'SELECT COUNT("abuse"."id") AS "abuses", ' + - `COUNT("abuse"."id") FILTER (WHERE "abuse"."state" = ${AbuseState.ACCEPTED}) AS "acceptedAbuses" ` + + [ScopeNames.WITH_STATS]: (options: WhereUserIdScopeOptions = {}) => { + return { + attributes: { + include: [ + [ + literal( + '(' + + 'SELECT COUNT("video"."id") ' + + 'FROM "video" ' + + 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + + 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + + `WHERE "account"."userId" = ${options.whereUserId}` + + ')' + ), + 'videosCount' + ], + [ + literal( + '(' + + `SELECT concat_ws(':', "abuses", "acceptedAbuses") ` + + 'FROM (' + + 'SELECT COUNT("abuse"."id") AS "abuses", ' + + `COUNT("abuse"."id") FILTER (WHERE "abuse"."state" = ${AbuseState.ACCEPTED}) AS "acceptedAbuses" ` + + 'FROM "abuse" ' + + 'INNER JOIN "account" ON "account"."id" = "abuse"."flaggedAccountId" ' + + `WHERE "account"."userId" = ${options.whereUserId}` + + ') t' + + ')' + ), + 'abusesCount' + ], + [ + literal( + '(' + + 'SELECT COUNT("abuse"."id") ' + 'FROM "abuse" ' + - 'INNER JOIN "account" ON "account"."id" = "abuse"."flaggedAccountId" ' + - 'WHERE "account"."userId" = "UserModel"."id"' + - ') t' + - ')' - ), - 'abusesCount' - ], - [ - literal( - '(' + - 'SELECT COUNT("abuse"."id") ' + - 'FROM "abuse" ' + - 'INNER JOIN "account" ON "account"."id" = "abuse"."reporterAccountId" ' + - 'WHERE "account"."userId" = "UserModel"."id"' + - ')' - ), - 'abusesCreatedCount' - ], - [ - literal( - '(' + - 'SELECT COUNT("videoComment"."id") ' + - 'FROM "videoComment" ' + - 'INNER JOIN "account" ON "account"."id" = "videoComment"."accountId" ' + - 'WHERE "account"."userId" = "UserModel"."id"' + - ')' - ), - 'videoCommentsCount' + 'INNER JOIN "account" ON "account"."id" = "abuse"."reporterAccountId" ' + + `WHERE "account"."userId" = ${options.whereUserId}` + + ')' + ), + 'abusesCreatedCount' + ], + [ + literal( + '(' + + 'SELECT COUNT("videoComment"."id") ' + + 'FROM "videoComment" ' + + 'INNER JOIN "account" ON "account"."id" = "videoComment"."accountId" ' + + `WHERE "account"."userId" = ${options.whereUserId}` + + ')' + ), + 'videoCommentsCount' + ] ] - ] + } } } })) @@ -619,17 +627,20 @@ export class UserModel extends SequelizeModel { } static loadByIdWithChannels (id: number, withStats = false): Promise { - const scopes = [ - ScopeNames.WITH_VIDEOCHANNELS - ] + const scopes: (string | ScopeOptions)[] = [ ScopeNames.WITH_VIDEOCHANNELS ] if (withStats) { - scopes.push(ScopeNames.WITH_QUOTA) - scopes.push(ScopeNames.WITH_STATS) - scopes.push(ScopeNames.WITH_TOTAL_FILE_SIZES) + const scopeOptions: WhereUserIdScopeOptions = { whereUserId: '$userId' } + + scopes.push({ method: [ ScopeNames.WITH_QUOTA, scopeOptions ] }) + scopes.push({ method: [ ScopeNames.WITH_STATS, scopeOptions ] }) + scopes.push({ method: [ ScopeNames.WITH_TOTAL_FILE_SIZES, scopeOptions ] }) } - return UserModel.scope(scopes).findByPk(id) + return UserModel.scope(scopes).findOne({ + where: { id }, + bind: { userId: id } + }) } static loadByUsername (username: string): Promise { diff --git a/server/core/models/video/video-file.ts b/server/core/models/video/video-file.ts index 4b79c57c0..6c5719231 100644 --- a/server/core/models/video/video-file.ts +++ b/server/core/models/video/video-file.ts @@ -349,7 +349,7 @@ export class VideoFileModel extends SequelizeModel { } } - return VideoFileModel.scope({ method: [ ScopeNames.WITH_VIDEO_OR_PLAYLIST, whereVideo ] }) + return VideoFileModel.scope({ method: [ ScopeNames.WITH_VIDEO_OR_PLAYLIST, { whereVideo } ] }) .findOne(options) .then(file => { if (!file) return null