aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/account
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/account')
-rw-r--r--server/models/account/account-blocklist.ts2
-rw-r--r--server/models/account/account-video-rate.ts12
-rw-r--r--server/models/account/account.ts69
-rw-r--r--server/models/account/user-notification.ts4
-rw-r--r--server/models/account/user.ts90
5 files changed, 89 insertions, 88 deletions
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts
index 6ebe32556..e2f66d733 100644
--- a/server/models/account/account-blocklist.ts
+++ b/server/models/account/account-blocklist.ts
@@ -80,7 +80,7 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
80 attributes: [ 'accountId', 'id' ], 80 attributes: [ 'accountId', 'id' ],
81 where: { 81 where: {
82 accountId: { 82 accountId: {
83 [Op.in]: accountIds // FIXME: sequelize ANY seems broken 83 [Op.in]: accountIds
84 }, 84 },
85 targetAccountId 85 targetAccountId
86 }, 86 },
diff --git a/server/models/account/account-video-rate.ts b/server/models/account/account-video-rate.ts
index c593595b2..8aeb486d1 100644
--- a/server/models/account/account-video-rate.ts
+++ b/server/models/account/account-video-rate.ts
@@ -99,7 +99,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
99 static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Bluebird<MAccountVideoRate> { 99 static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Bluebird<MAccountVideoRate> {
100 const options: FindOptions = { 100 const options: FindOptions = {
101 where: { 101 where: {
102 [ Op.or]: [ 102 [Op.or]: [
103 { 103 {
104 accountId, 104 accountId,
105 videoId 105 videoId
@@ -116,10 +116,10 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
116 } 116 }
117 117
118 static listByAccountForApi (options: { 118 static listByAccountForApi (options: {
119 start: number, 119 start: number
120 count: number, 120 count: number
121 sort: string, 121 sort: string
122 type?: string, 122 type?: string
123 accountId: number 123 accountId: number
124 }) { 124 }) {
125 const query: FindOptions = { 125 const query: FindOptions = {
@@ -135,7 +135,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> {
135 required: true, 135 required: true,
136 include: [ 136 include: [
137 { 137 {
138 model: VideoChannelModel.scope({ method: [VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }), 138 model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),
139 required: true 139 required: true
140 } 140 }
141 ] 141 ]
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index 8a0ffeb63..a0081f259 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -32,8 +32,9 @@ import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequ
32import { AccountBlocklistModel } from './account-blocklist' 32import { AccountBlocklistModel } from './account-blocklist'
33import { ServerBlocklistModel } from '../server/server-blocklist' 33import { ServerBlocklistModel } from '../server/server-blocklist'
34import { ActorFollowModel } from '../activitypub/actor-follow' 34import { ActorFollowModel } from '../activitypub/actor-follow'
35import { MAccountActor, MAccountDefault, MAccountSummaryFormattable, MAccountFormattable, MAccountAP } from '../../typings/models' 35import { MAccountActor, MAccountAP, MAccountDefault, MAccountFormattable, MAccountSummaryFormattable } from '../../typings/models'
36import * as Bluebird from 'bluebird' 36import * as Bluebird from 'bluebird'
37import { ModelCache } from '@server/models/model-cache'
37 38
38export enum ScopeNames { 39export enum ScopeNames {
39 SUMMARY = 'SUMMARY' 40 SUMMARY = 'SUMMARY'
@@ -53,7 +54,7 @@ export type SummaryOptions = {
53 ] 54 ]
54})) 55}))
55@Scopes(() => ({ 56@Scopes(() => ({
56 [ ScopeNames.SUMMARY ]: (options: SummaryOptions = {}) => { 57 [ScopeNames.SUMMARY]: (options: SummaryOptions = {}) => {
57 const whereActor = options.whereActor || undefined 58 const whereActor = options.whereActor || undefined
58 59
59 const serverInclude: IncludeOptions = { 60 const serverInclude: IncludeOptions = {
@@ -218,8 +219,6 @@ export class AccountModel extends Model<AccountModel> {
218 }) 219 })
219 BlockedAccounts: AccountBlocklistModel[] 220 BlockedAccounts: AccountBlocklistModel[]
220 221
221 private static cache: { [ id: string ]: any } = {}
222
223 @BeforeDestroy 222 @BeforeDestroy
224 static async sendDeleteIfOwned (instance: AccountModel, options) { 223 static async sendDeleteIfOwned (instance: AccountModel, options) {
225 if (!instance.Actor) { 224 if (!instance.Actor) {
@@ -247,45 +246,43 @@ export class AccountModel extends Model<AccountModel> {
247 } 246 }
248 247
249 static loadLocalByName (name: string): Bluebird<MAccountDefault> { 248 static loadLocalByName (name: string): Bluebird<MAccountDefault> {
250 // The server actor never change, so we can easily cache it 249 const fun = () => {
251 if (name === SERVER_ACTOR_NAME && AccountModel.cache[name]) { 250 const query = {
252 return Bluebird.resolve(AccountModel.cache[name]) 251 where: {
253 } 252 [Op.or]: [
254 253 {
255 const query = { 254 userId: {
256 where: { 255 [Op.ne]: null
257 [ Op.or ]: [ 256 }
258 { 257 },
259 userId: { 258 {
260 [ Op.ne ]: null 259 applicationId: {
260 [Op.ne]: null
261 }
261 } 262 }
262 }, 263 ]
264 },
265 include: [
263 { 266 {
264 applicationId: { 267 model: ActorModel,
265 [ Op.ne ]: null 268 required: true,
269 where: {
270 preferredUsername: name
266 } 271 }
267 } 272 }
268 ] 273 ]
269 }, 274 }
270 include: [
271 {
272 model: ActorModel,
273 required: true,
274 where: {
275 preferredUsername: name
276 }
277 }
278 ]
279 }
280 275
281 return AccountModel.findOne(query) 276 return AccountModel.findOne(query)
282 .then(account => { 277 }
283 if (name === SERVER_ACTOR_NAME) {
284 AccountModel.cache[name] = account
285 }
286 278
287 return account 279 return ModelCache.Instance.doCache({
288 }) 280 cacheType: 'local-account-name',
281 key: name,
282 fun,
283 // The server actor never change, so we can easily cache it
284 whitelist: () => name === SERVER_ACTOR_NAME
285 })
289 } 286 }
290 287
291 static loadByNameAndHost (name: string, host: string): Bluebird<MAccountDefault> { 288 static loadByNameAndHost (name: string, host: string): Bluebird<MAccountDefault> {
diff --git a/server/models/account/user-notification.ts b/server/models/account/user-notification.ts
index a05f30175..5a725187a 100644
--- a/server/models/account/user-notification.ts
+++ b/server/models/account/user-notification.ts
@@ -363,7 +363,7 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
363 where: { 363 where: {
364 userId, 364 userId,
365 id: { 365 id: {
366 [Op.in]: notificationIds // FIXME: sequelize ANY seems broken 366 [Op.in]: notificationIds
367 } 367 }
368 } 368 }
369 } 369 }
@@ -379,7 +379,7 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
379 379
380 toFormattedJSON (this: UserNotificationModelForApi): UserNotification { 380 toFormattedJSON (this: UserNotificationModelForApi): UserNotification {
381 const video = this.Video 381 const video = this.Video
382 ? Object.assign(this.formatVideo(this.Video),{ channel: this.formatActor(this.Video.VideoChannel) }) 382 ? Object.assign(this.formatVideo(this.Video), { channel: this.formatActor(this.Video.VideoChannel) })
383 : undefined 383 : undefined
384 384
385 const videoImport = this.VideoImport ? { 385 const videoImport = this.VideoImport ? {
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 4c2c5e278..777f09666 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -1,4 +1,4 @@
1import { FindOptions, literal, Op, QueryTypes, where, fn, col } from 'sequelize' 1import { FindOptions, literal, Op, QueryTypes, where, fn, col, WhereOptions } from 'sequelize'
2import { 2import {
3 AfterDestroy, 3 AfterDestroy,
4 AfterUpdate, 4 AfterUpdate,
@@ -49,7 +49,7 @@ import { VideoPlaylistModel } from '../video/video-playlist'
49import { AccountModel } from './account' 49import { AccountModel } from './account'
50import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type' 50import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type'
51import { values } from 'lodash' 51import { values } from 'lodash'
52import { DEFAULT_THEME_NAME, DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants' 52import { DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants'
53import { clearCacheByUserId } from '../../lib/oauth-model' 53import { clearCacheByUserId } from '../../lib/oauth-model'
54import { UserNotificationSettingModel } from './user-notification-setting' 54import { UserNotificationSettingModel } from './user-notification-setting'
55import { VideoModel } from '../video/video' 55import { VideoModel } from '../video/video'
@@ -101,7 +101,7 @@ enum ScopeNames {
101 required: true, 101 required: true,
102 where: { 102 where: {
103 type: { 103 type: {
104 [ Op.ne ]: VideoPlaylistType.REGULAR 104 [Op.ne]: VideoPlaylistType.REGULAR
105 } 105 }
106 } 106 }
107 } 107 }
@@ -186,7 +186,10 @@ export class UserModel extends Model<UserModel> {
186 186
187 @AllowNull(false) 187 @AllowNull(false)
188 @Default(true) 188 @Default(true)
189 @Is('UserAutoPlayNextVideoPlaylist', value => throwIfNotValid(value, isUserAutoPlayNextVideoPlaylistValid, 'auto play next video for playlists boolean')) 189 @Is(
190 'UserAutoPlayNextVideoPlaylist',
191 value => throwIfNotValid(value, isUserAutoPlayNextVideoPlaylistValid, 'auto play next video for playlists boolean')
192 )
190 @Column 193 @Column
191 autoPlayNextVideoPlaylist: boolean 194 autoPlayNextVideoPlaylist: boolean
192 195
@@ -230,7 +233,7 @@ export class UserModel extends Model<UserModel> {
230 videoQuotaDaily: number 233 videoQuotaDaily: number
231 234
232 @AllowNull(false) 235 @AllowNull(false)
233 @Default(DEFAULT_THEME_NAME) 236 @Default(DEFAULT_USER_THEME_NAME)
234 @Is('UserTheme', value => throwIfNotValid(value, isThemeNameValid, 'theme')) 237 @Is('UserTheme', value => throwIfNotValid(value, isThemeNameValid, 'theme'))
235 @Column 238 @Column
236 theme: string 239 theme: string
@@ -308,7 +311,8 @@ export class UserModel extends Model<UserModel> {
308 } 311 }
309 312
310 static listForApi (start: number, count: number, sort: string, search?: string) { 313 static listForApi (start: number, count: number, sort: string, search?: string) {
311 let where = undefined 314 let where: WhereOptions
315
312 if (search) { 316 if (search) {
313 where = { 317 where = {
314 [Op.or]: [ 318 [Op.or]: [
@@ -319,7 +323,7 @@ export class UserModel extends Model<UserModel> {
319 }, 323 },
320 { 324 {
321 username: { 325 username: {
322 [ Op.iLike ]: '%' + search + '%' 326 [Op.iLike]: '%' + search + '%'
323 } 327 }
324 } 328 }
325 ] 329 ]
@@ -332,14 +336,14 @@ export class UserModel extends Model<UserModel> {
332 [ 336 [
333 literal( 337 literal(
334 '(' + 338 '(' +
335 'SELECT COALESCE(SUM("size"), 0) ' + 339 'SELECT COALESCE(SUM("size"), 0) ' +
336 'FROM (' + 340 'FROM (' +
337 'SELECT MAX("videoFile"."size") AS "size" FROM "videoFile" ' + 341 'SELECT MAX("videoFile"."size") AS "size" FROM "videoFile" ' +
338 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" ' + 342 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" ' +
339 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + 343 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
340 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' + 344 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' +
341 'WHERE "account"."userId" = "UserModel"."id" GROUP BY "video"."id"' + 345 'WHERE "account"."userId" = "UserModel"."id" GROUP BY "video"."id"' +
342 ') t' + 346 ') t' +
343 ')' 347 ')'
344 ), 348 ),
345 'videoQuotaUsed' 349 'videoQuotaUsed'
@@ -353,18 +357,18 @@ export class UserModel extends Model<UserModel> {
353 } 357 }
354 358
355 return UserModel.findAndCountAll(query) 359 return UserModel.findAndCountAll(query)
356 .then(({ rows, count }) => { 360 .then(({ rows, count }) => {
357 return { 361 return {
358 data: rows, 362 data: rows,
359 total: count 363 total: count
360 } 364 }
361 }) 365 })
362 } 366 }
363 367
364 static listWithRight (right: UserRight): Bluebird<MUserDefault[]> { 368 static listWithRight (right: UserRight): Bluebird<MUserDefault[]> {
365 const roles = Object.keys(USER_ROLE_LABELS) 369 const roles = Object.keys(USER_ROLE_LABELS)
366 .map(k => parseInt(k, 10) as UserRole) 370 .map(k => parseInt(k, 10) as UserRole)
367 .filter(role => hasUserRight(role, right)) 371 .filter(role => hasUserRight(role, right))
368 372
369 const query = { 373 const query = {
370 where: { 374 where: {
@@ -390,7 +394,7 @@ export class UserModel extends Model<UserModel> {
390 required: true, 394 required: true,
391 include: [ 395 include: [
392 { 396 {
393 attributes: [ ], 397 attributes: [],
394 model: ActorModel.unscoped(), 398 model: ActorModel.unscoped(),
395 required: true, 399 required: true,
396 where: { 400 where: {
@@ -398,7 +402,7 @@ export class UserModel extends Model<UserModel> {
398 }, 402 },
399 include: [ 403 include: [
400 { 404 {
401 attributes: [ ], 405 attributes: [],
402 as: 'ActorFollowings', 406 as: 'ActorFollowings',
403 model: ActorFollowModel.unscoped(), 407 model: ActorFollowModel.unscoped(),
404 required: true, 408 required: true,
@@ -433,7 +437,7 @@ export class UserModel extends Model<UserModel> {
433 static loadByUsername (username: string): Bluebird<MUserDefault> { 437 static loadByUsername (username: string): Bluebird<MUserDefault> {
434 const query = { 438 const query = {
435 where: { 439 where: {
436 username: { [ Op.iLike ]: username } 440 username: { [Op.iLike]: username }
437 } 441 }
438 } 442 }
439 443
@@ -443,7 +447,7 @@ export class UserModel extends Model<UserModel> {
443 static loadForMeAPI (username: string): Bluebird<MUserNotifSettingChannelDefault> { 447 static loadForMeAPI (username: string): Bluebird<MUserNotifSettingChannelDefault> {
444 const query = { 448 const query = {
445 where: { 449 where: {
446 username: { [ Op.iLike ]: username } 450 username: { [Op.iLike]: username }
447 } 451 }
448 } 452 }
449 453
@@ -465,7 +469,7 @@ export class UserModel extends Model<UserModel> {
465 469
466 const query = { 470 const query = {
467 where: { 471 where: {
468 [ Op.or ]: [ 472 [Op.or]: [
469 where(fn('lower', col('username')), fn('lower', username)), 473 where(fn('lower', col('username')), fn('lower', username)),
470 474
471 { email } 475 { email }
@@ -592,7 +596,7 @@ export class UserModel extends Model<UserModel> {
592 const query = { 596 const query = {
593 where: { 597 where: {
594 username: { 598 username: {
595 [ Op.like ]: `%${search}%` 599 [Op.like]: `%${search}%`
596 } 600 }
597 }, 601 },
598 limit: 10 602 limit: 10
@@ -652,7 +656,7 @@ export class UserModel extends Model<UserModel> {
652 videoLanguages: this.videoLanguages, 656 videoLanguages: this.videoLanguages,
653 657
654 role: this.role, 658 role: this.role,
655 roleLabel: USER_ROLE_LABELS[ this.role ], 659 roleLabel: USER_ROLE_LABELS[this.role],
656 660
657 videoQuota: this.videoQuota, 661 videoQuota: this.videoQuota,
658 videoQuotaDaily: this.videoQuotaDaily, 662 videoQuotaDaily: this.videoQuotaDaily,
@@ -686,13 +690,13 @@ export class UserModel extends Model<UserModel> {
686 690
687 if (Array.isArray(this.Account.VideoChannels) === true) { 691 if (Array.isArray(this.Account.VideoChannels) === true) {
688 json.videoChannels = this.Account.VideoChannels 692 json.videoChannels = this.Account.VideoChannels
689 .map(c => c.toFormattedJSON()) 693 .map(c => c.toFormattedJSON())
690 .sort((v1, v2) => { 694 .sort((v1, v2) => {
691 if (v1.createdAt < v2.createdAt) return -1 695 if (v1.createdAt < v2.createdAt) return -1
692 if (v1.createdAt === v2.createdAt) return 0 696 if (v1.createdAt === v2.createdAt) return 0
693 697
694 return 1 698 return 1
695 }) 699 })
696 } 700 }
697 701
698 return json 702 return json
@@ -702,7 +706,7 @@ export class UserModel extends Model<UserModel> {
702 const formatted = this.toFormattedJSON() 706 const formatted = this.toFormattedJSON()
703 707
704 const specialPlaylists = this.Account.VideoPlaylists 708 const specialPlaylists = this.Account.VideoPlaylists
705 .map(p => ({ id: p.id, name: p.name, type: p.type })) 709 .map(p => ({ id: p.id, name: p.name, type: p.type }))
706 710
707 return Object.assign(formatted, { specialPlaylists }) 711 return Object.assign(formatted, { specialPlaylists })
708 } 712 }
@@ -729,12 +733,12 @@ export class UserModel extends Model<UserModel> {
729 733
730 return 'SELECT SUM("size") AS "total" ' + 734 return 'SELECT SUM("size") AS "total" ' +
731 'FROM (' + 735 'FROM (' +
732 'SELECT MAX("videoFile"."size") AS "size" FROM "videoFile" ' + 736 'SELECT MAX("videoFile"."size") AS "size" FROM "videoFile" ' +
733 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" ' + 737 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" ' +
734 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + 738 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
735 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' + 739 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' +
736 'WHERE "account"."userId" = $userId ' + andWhere + 740 'WHERE "account"."userId" = $userId ' + andWhere +
737 'GROUP BY "video"."id"' + 741 'GROUP BY "video"."id"' +
738 ') t' 742 ') t'
739 } 743 }
740 744