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.ts24
-rw-r--r--server/models/account/user-notification-setting.ts32
-rw-r--r--server/models/account/user-notification.ts95
-rw-r--r--server/models/account/user.ts51
4 files changed, 191 insertions, 11 deletions
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts
index 54ac290c4..efd6ed59e 100644
--- a/server/models/account/account-blocklist.ts
+++ b/server/models/account/account-blocklist.ts
@@ -2,6 +2,7 @@ import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, Updated
2import { AccountModel } from './account' 2import { AccountModel } from './account'
3import { getSort } from '../utils' 3import { getSort } from '../utils'
4import { AccountBlock } from '../../../shared/models/blocklist' 4import { AccountBlock } from '../../../shared/models/blocklist'
5import { Op } from 'sequelize'
5 6
6enum ScopeNames { 7enum ScopeNames {
7 WITH_ACCOUNTS = 'WITH_ACCOUNTS' 8 WITH_ACCOUNTS = 'WITH_ACCOUNTS'
@@ -73,18 +74,33 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
73 BlockedAccount: AccountModel 74 BlockedAccount: AccountModel
74 75
75 static isAccountMutedBy (accountId: number, targetAccountId: number) { 76 static isAccountMutedBy (accountId: number, targetAccountId: number) {
77 return AccountBlocklistModel.isAccountMutedByMulti([ accountId ], targetAccountId)
78 .then(result => result[accountId])
79 }
80
81 static isAccountMutedByMulti (accountIds: number[], targetAccountId: number) {
76 const query = { 82 const query = {
77 attributes: [ 'id' ], 83 attributes: [ 'accountId', 'id' ],
78 where: { 84 where: {
79 accountId, 85 accountId: {
86 [Op.any]: accountIds
87 },
80 targetAccountId 88 targetAccountId
81 }, 89 },
82 raw: true 90 raw: true
83 } 91 }
84 92
85 return AccountBlocklistModel.unscoped() 93 return AccountBlocklistModel.unscoped()
86 .findOne(query) 94 .findAll(query)
87 .then(a => !!a) 95 .then(rows => {
96 const result: { [accountId: number]: boolean } = {}
97
98 for (const accountId of accountIds) {
99 result[accountId] = !!rows.find(r => r.accountId === accountId)
100 }
101
102 return result
103 })
88 } 104 }
89 105
90 static loadByAccountAndTarget (accountId: number, targetAccountId: number) { 106 static loadByAccountAndTarget (accountId: number, targetAccountId: number) {
diff --git a/server/models/account/user-notification-setting.ts b/server/models/account/user-notification-setting.ts
index 6470defa7..f1c3ac223 100644
--- a/server/models/account/user-notification-setting.ts
+++ b/server/models/account/user-notification-setting.ts
@@ -83,6 +83,33 @@ export class UserNotificationSettingModel extends Model<UserNotificationSettingM
83 @Column 83 @Column
84 myVideoImportFinished: UserNotificationSettingValue 84 myVideoImportFinished: UserNotificationSettingValue
85 85
86 @AllowNull(false)
87 @Default(null)
88 @Is(
89 'UserNotificationSettingNewUserRegistration',
90 value => throwIfNotValid(value, isUserNotificationSettingValid, 'newUserRegistration')
91 )
92 @Column
93 newUserRegistration: UserNotificationSettingValue
94
95 @AllowNull(false)
96 @Default(null)
97 @Is(
98 'UserNotificationSettingNewFollow',
99 value => throwIfNotValid(value, isUserNotificationSettingValid, 'newFollow')
100 )
101 @Column
102 newFollow: UserNotificationSettingValue
103
104 @AllowNull(false)
105 @Default(null)
106 @Is(
107 'UserNotificationSettingCommentMention',
108 value => throwIfNotValid(value, isUserNotificationSettingValid, 'commentMention')
109 )
110 @Column
111 commentMention: UserNotificationSettingValue
112
86 @ForeignKey(() => UserModel) 113 @ForeignKey(() => UserModel)
87 @Column 114 @Column
88 userId: number 115 userId: number
@@ -114,7 +141,10 @@ export class UserNotificationSettingModel extends Model<UserNotificationSettingM
114 videoAbuseAsModerator: this.videoAbuseAsModerator, 141 videoAbuseAsModerator: this.videoAbuseAsModerator,
115 blacklistOnMyVideo: this.blacklistOnMyVideo, 142 blacklistOnMyVideo: this.blacklistOnMyVideo,
116 myVideoPublished: this.myVideoPublished, 143 myVideoPublished: this.myVideoPublished,
117 myVideoImportFinished: this.myVideoImportFinished 144 myVideoImportFinished: this.myVideoImportFinished,
145 newUserRegistration: this.newUserRegistration,
146 commentMention: this.commentMention,
147 newFollow: this.newFollow
118 } 148 }
119 } 149 }
120} 150}
diff --git a/server/models/account/user-notification.ts b/server/models/account/user-notification.ts
index 251244374..79afce600 100644
--- a/server/models/account/user-notification.ts
+++ b/server/models/account/user-notification.ts
@@ -25,6 +25,8 @@ import { AccountModel } from './account'
25import { VideoAbuseModel } from '../video/video-abuse' 25import { VideoAbuseModel } from '../video/video-abuse'
26import { VideoBlacklistModel } from '../video/video-blacklist' 26import { VideoBlacklistModel } from '../video/video-blacklist'
27import { VideoImportModel } from '../video/video-import' 27import { VideoImportModel } from '../video/video-import'
28import { ActorModel } from '../activitypub/actor'
29import { ActorFollowModel } from '../activitypub/actor-follow'
28 30
29enum ScopeNames { 31enum ScopeNames {
30 WITH_ALL = 'WITH_ALL' 32 WITH_ALL = 'WITH_ALL'
@@ -38,17 +40,17 @@ function buildVideoInclude (required: boolean) {
38 } 40 }
39} 41}
40 42
41function buildChannelInclude () { 43function buildChannelInclude (required: boolean) {
42 return { 44 return {
43 required: true, 45 required,
44 attributes: [ 'id', 'name' ], 46 attributes: [ 'id', 'name' ],
45 model: () => VideoChannelModel.unscoped() 47 model: () => VideoChannelModel.unscoped()
46 } 48 }
47} 49}
48 50
49function buildAccountInclude () { 51function buildAccountInclude (required: boolean) {
50 return { 52 return {
51 required: true, 53 required,
52 attributes: [ 'id', 'name' ], 54 attributes: [ 'id', 'name' ],
53 model: () => AccountModel.unscoped() 55 model: () => AccountModel.unscoped()
54 } 56 }
@@ -58,14 +60,14 @@ function buildAccountInclude () {
58 [ScopeNames.WITH_ALL]: { 60 [ScopeNames.WITH_ALL]: {
59 include: [ 61 include: [
60 Object.assign(buildVideoInclude(false), { 62 Object.assign(buildVideoInclude(false), {
61 include: [ buildChannelInclude() ] 63 include: [ buildChannelInclude(true) ]
62 }), 64 }),
63 { 65 {
64 attributes: [ 'id', 'originCommentId' ], 66 attributes: [ 'id', 'originCommentId' ],
65 model: () => VideoCommentModel.unscoped(), 67 model: () => VideoCommentModel.unscoped(),
66 required: false, 68 required: false,
67 include: [ 69 include: [
68 buildAccountInclude(), 70 buildAccountInclude(true),
69 buildVideoInclude(true) 71 buildVideoInclude(true)
70 ] 72 ]
71 }, 73 },
@@ -86,6 +88,42 @@ function buildAccountInclude () {
86 model: () => VideoImportModel.unscoped(), 88 model: () => VideoImportModel.unscoped(),
87 required: false, 89 required: false,
88 include: [ buildVideoInclude(false) ] 90 include: [ buildVideoInclude(false) ]
91 },
92 {
93 attributes: [ 'id', 'name' ],
94 model: () => AccountModel.unscoped(),
95 required: false,
96 include: [
97 {
98 attributes: [ 'id', 'preferredUsername' ],
99 model: () => ActorModel.unscoped(),
100 required: true
101 }
102 ]
103 },
104 {
105 attributes: [ 'id' ],
106 model: () => ActorFollowModel.unscoped(),
107 required: false,
108 include: [
109 {
110 attributes: [ 'preferredUsername' ],
111 model: () => ActorModel.unscoped(),
112 required: true,
113 as: 'ActorFollower',
114 include: [ buildAccountInclude(true) ]
115 },
116 {
117 attributes: [ 'preferredUsername' ],
118 model: () => ActorModel.unscoped(),
119 required: true,
120 as: 'ActorFollowing',
121 include: [
122 buildChannelInclude(false),
123 buildAccountInclude(false)
124 ]
125 }
126 ]
89 } 127 }
90 ] 128 ]
91 } 129 }
@@ -193,6 +231,30 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
193 }) 231 })
194 VideoImport: VideoImportModel 232 VideoImport: VideoImportModel
195 233
234 @ForeignKey(() => AccountModel)
235 @Column
236 accountId: number
237
238 @BelongsTo(() => AccountModel, {
239 foreignKey: {
240 allowNull: true
241 },
242 onDelete: 'cascade'
243 })
244 Account: AccountModel
245
246 @ForeignKey(() => ActorFollowModel)
247 @Column
248 actorFollowId: number
249
250 @BelongsTo(() => ActorFollowModel, {
251 foreignKey: {
252 allowNull: true
253 },
254 onDelete: 'cascade'
255 })
256 ActorFollow: ActorFollowModel
257
196 static listForApi (userId: number, start: number, count: number, sort: string, unread?: boolean) { 258 static listForApi (userId: number, start: number, count: number, sort: string, unread?: boolean) {
197 const query: IFindOptions<UserNotificationModel> = { 259 const query: IFindOptions<UserNotificationModel> = {
198 offset: start, 260 offset: start,
@@ -264,6 +326,25 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
264 video: this.formatVideo(this.VideoBlacklist.Video) 326 video: this.formatVideo(this.VideoBlacklist.Video)
265 } : undefined 327 } : undefined
266 328
329 const account = this.Account ? {
330 id: this.Account.id,
331 displayName: this.Account.getDisplayName(),
332 name: this.Account.Actor.preferredUsername
333 } : undefined
334
335 const actorFollow = this.ActorFollow ? {
336 id: this.ActorFollow.id,
337 follower: {
338 displayName: this.ActorFollow.ActorFollower.Account.getDisplayName(),
339 name: this.ActorFollow.ActorFollower.preferredUsername
340 },
341 following: {
342 type: this.ActorFollow.ActorFollowing.VideoChannel ? 'channel' as 'channel' : 'account' as 'account',
343 displayName: (this.ActorFollow.ActorFollowing.VideoChannel || this.ActorFollow.ActorFollowing.Account).getDisplayName(),
344 name: this.ActorFollow.ActorFollowing.preferredUsername
345 }
346 } : undefined
347
267 return { 348 return {
268 id: this.id, 349 id: this.id,
269 type: this.type, 350 type: this.type,
@@ -273,6 +354,8 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
273 comment, 354 comment,
274 videoAbuse, 355 videoAbuse,
275 videoBlacklist, 356 videoBlacklist,
357 account,
358 actorFollow,
276 createdAt: this.createdAt.toISOString(), 359 createdAt: this.createdAt.toISOString(),
277 updatedAt: this.updatedAt.toISOString() 360 updatedAt: this.updatedAt.toISOString()
278 } 361 }
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 33f56f641..017a96657 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -330,6 +330,16 @@ export class UserModel extends Model<UserModel> {
330 return UserModel.unscoped().findAll(query) 330 return UserModel.unscoped().findAll(query)
331 } 331 }
332 332
333 static listByUsernames (usernames: string[]) {
334 const query = {
335 where: {
336 username: usernames
337 }
338 }
339
340 return UserModel.findAll(query)
341 }
342
333 static loadById (id: number) { 343 static loadById (id: number) {
334 return UserModel.findById(id) 344 return UserModel.findById(id)
335 } 345 }
@@ -424,6 +434,47 @@ export class UserModel extends Model<UserModel> {
424 return UserModel.findOne(query) 434 return UserModel.findOne(query)
425 } 435 }
426 436
437 static loadByChannelActorId (videoChannelActorId: number) {
438 const query = {
439 include: [
440 {
441 required: true,
442 attributes: [ 'id' ],
443 model: AccountModel.unscoped(),
444 include: [
445 {
446 required: true,
447 attributes: [ 'id' ],
448 model: VideoChannelModel.unscoped(),
449 where: {
450 actorId: videoChannelActorId
451 }
452 }
453 ]
454 }
455 ]
456 }
457
458 return UserModel.findOne(query)
459 }
460
461 static loadByAccountActorId (accountActorId: number) {
462 const query = {
463 include: [
464 {
465 required: true,
466 attributes: [ 'id' ],
467 model: AccountModel.unscoped(),
468 where: {
469 actorId: accountActorId
470 }
471 }
472 ]
473 }
474
475 return UserModel.findOne(query)
476 }
477
427 static getOriginalVideoFileTotalFromUser (user: UserModel) { 478 static getOriginalVideoFileTotalFromUser (user: UserModel) {
428 // Don't use sequelize because we need to use a sub query 479 // Don't use sequelize because we need to use a sub query
429 const query = UserModel.generateUserQuotaBaseSQL() 480 const query = UserModel.generateUserQuotaBaseSQL()