diff options
Diffstat (limited to 'server/models/account')
-rw-r--r-- | server/models/account/account-blocklist.ts | 8 | ||||
-rw-r--r-- | server/models/account/account-video-rate.ts | 28 | ||||
-rw-r--r-- | server/models/account/account.ts | 27 | ||||
-rw-r--r-- | server/models/account/user-notification-setting.ts | 15 | ||||
-rw-r--r-- | server/models/account/user-notification.ts | 29 | ||||
-rw-r--r-- | server/models/account/user-video-history.ts | 7 | ||||
-rw-r--r-- | server/models/account/user.ts | 94 |
7 files changed, 147 insertions, 61 deletions
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts index d5746ad76..8bcaca828 100644 --- a/server/models/account/account-blocklist.ts +++ b/server/models/account/account-blocklist.ts | |||
@@ -3,6 +3,8 @@ import { AccountModel } from './account' | |||
3 | import { getSort } from '../utils' | 3 | import { getSort } from '../utils' |
4 | import { AccountBlock } from '../../../shared/models/blocklist' | 4 | import { AccountBlock } from '../../../shared/models/blocklist' |
5 | import { Op } from 'sequelize' | 5 | import { Op } from 'sequelize' |
6 | import * as Bluebird from 'bluebird' | ||
7 | import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/typings/models' | ||
6 | 8 | ||
7 | enum ScopeNames { | 9 | enum ScopeNames { |
8 | WITH_ACCOUNTS = 'WITH_ACCOUNTS' | 10 | WITH_ACCOUNTS = 'WITH_ACCOUNTS' |
@@ -103,7 +105,7 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> { | |||
103 | }) | 105 | }) |
104 | } | 106 | } |
105 | 107 | ||
106 | static loadByAccountAndTarget (accountId: number, targetAccountId: number) { | 108 | static loadByAccountAndTarget (accountId: number, targetAccountId: number): Bluebird<MAccountBlocklist> { |
107 | const query = { | 109 | const query = { |
108 | where: { | 110 | where: { |
109 | accountId, | 111 | accountId, |
@@ -126,13 +128,13 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> { | |||
126 | 128 | ||
127 | return AccountBlocklistModel | 129 | return AccountBlocklistModel |
128 | .scope([ ScopeNames.WITH_ACCOUNTS ]) | 130 | .scope([ ScopeNames.WITH_ACCOUNTS ]) |
129 | .findAndCountAll(query) | 131 | .findAndCountAll<MAccountBlocklistAccounts>(query) |
130 | .then(({ rows, count }) => { | 132 | .then(({ rows, count }) => { |
131 | return { total: count, data: rows } | 133 | return { total: count, data: rows } |
132 | }) | 134 | }) |
133 | } | 135 | } |
134 | 136 | ||
135 | toFormattedJSON (): AccountBlock { | 137 | toFormattedJSON (this: MAccountBlocklistFormattable): AccountBlock { |
136 | return { | 138 | return { |
137 | byAccount: this.ByAccount.toFormattedJSON(), | 139 | byAccount: this.ByAccount.toFormattedJSON(), |
138 | blockedAccount: this.BlockedAccount.toFormattedJSON(), | 140 | blockedAccount: this.BlockedAccount.toFormattedJSON(), |
diff --git a/server/models/account/account-video-rate.ts b/server/models/account/account-video-rate.ts index 4bd8114cf..a6edbeee8 100644 --- a/server/models/account/account-video-rate.ts +++ b/server/models/account/account-video-rate.ts | |||
@@ -10,6 +10,13 @@ import { buildLocalAccountIdsIn, getSort, throwIfNotValid } from '../utils' | |||
10 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 10 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
11 | import { AccountVideoRate } from '../../../shared' | 11 | import { AccountVideoRate } from '../../../shared' |
12 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel' | 12 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel' |
13 | import * as Bluebird from 'bluebird' | ||
14 | import { | ||
15 | MAccountVideoRate, | ||
16 | MAccountVideoRateAccountUrl, | ||
17 | MAccountVideoRateAccountVideo, | ||
18 | MAccountVideoRateFormattable | ||
19 | } from '@server/typings/models/video/video-rate' | ||
13 | 20 | ||
14 | /* | 21 | /* |
15 | Account rates per video. | 22 | Account rates per video. |
@@ -77,7 +84,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
77 | }) | 84 | }) |
78 | Account: AccountModel | 85 | Account: AccountModel |
79 | 86 | ||
80 | static load (accountId: number, videoId: number, transaction?: Transaction) { | 87 | static load (accountId: number, videoId: number, transaction?: Transaction): Bluebird<MAccountVideoRate> { |
81 | const options: FindOptions = { | 88 | const options: FindOptions = { |
82 | where: { | 89 | where: { |
83 | accountId, | 90 | accountId, |
@@ -89,7 +96,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
89 | return AccountVideoRateModel.findOne(options) | 96 | return AccountVideoRateModel.findOne(options) |
90 | } | 97 | } |
91 | 98 | ||
92 | static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, transaction?: Transaction) { | 99 | static loadByAccountAndVideoOrUrl (accountId: number, videoId: number, url: string, t?: Transaction): Bluebird<MAccountVideoRate> { |
93 | const options: FindOptions = { | 100 | const options: FindOptions = { |
94 | where: { | 101 | where: { |
95 | [ Op.or]: [ | 102 | [ Op.or]: [ |
@@ -103,7 +110,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
103 | ] | 110 | ] |
104 | } | 111 | } |
105 | } | 112 | } |
106 | if (transaction) options.transaction = transaction | 113 | if (t) options.transaction = t |
107 | 114 | ||
108 | return AccountVideoRateModel.findOne(options) | 115 | return AccountVideoRateModel.findOne(options) |
109 | } | 116 | } |
@@ -140,7 +147,12 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
140 | return AccountVideoRateModel.findAndCountAll(query) | 147 | return AccountVideoRateModel.findAndCountAll(query) |
141 | } | 148 | } |
142 | 149 | ||
143 | static loadLocalAndPopulateVideo (rateType: VideoRateType, accountName: string, videoId: number, transaction?: Transaction) { | 150 | static loadLocalAndPopulateVideo ( |
151 | rateType: VideoRateType, | ||
152 | accountName: string, | ||
153 | videoId: number, | ||
154 | t?: Transaction | ||
155 | ): Bluebird<MAccountVideoRateAccountVideo> { | ||
144 | const options: FindOptions = { | 156 | const options: FindOptions = { |
145 | where: { | 157 | where: { |
146 | videoId, | 158 | videoId, |
@@ -152,7 +164,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
152 | required: true, | 164 | required: true, |
153 | include: [ | 165 | include: [ |
154 | { | 166 | { |
155 | attributes: [ 'id', 'url', 'preferredUsername' ], | 167 | attributes: [ 'id', 'url', 'followersUrl', 'preferredUsername' ], |
156 | model: ActorModel.unscoped(), | 168 | model: ActorModel.unscoped(), |
157 | required: true, | 169 | required: true, |
158 | where: { | 170 | where: { |
@@ -167,7 +179,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
167 | } | 179 | } |
168 | ] | 180 | ] |
169 | } | 181 | } |
170 | if (transaction) options.transaction = transaction | 182 | if (t) options.transaction = t |
171 | 183 | ||
172 | return AccountVideoRateModel.findOne(options) | 184 | return AccountVideoRateModel.findOne(options) |
173 | } | 185 | } |
@@ -208,7 +220,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
208 | ] | 220 | ] |
209 | } | 221 | } |
210 | 222 | ||
211 | return AccountVideoRateModel.findAndCountAll(query) | 223 | return AccountVideoRateModel.findAndCountAll<MAccountVideoRateAccountUrl>(query) |
212 | } | 224 | } |
213 | 225 | ||
214 | static cleanOldRatesOf (videoId: number, type: VideoRateType, beforeUpdatedAt: Date) { | 226 | static cleanOldRatesOf (videoId: number, type: VideoRateType, beforeUpdatedAt: Date) { |
@@ -241,7 +253,7 @@ export class AccountVideoRateModel extends Model<AccountVideoRateModel> { | |||
241 | }) | 253 | }) |
242 | } | 254 | } |
243 | 255 | ||
244 | toFormattedJSON (): AccountVideoRate { | 256 | toFormattedJSON (this: MAccountVideoRateFormattable): AccountVideoRate { |
245 | return { | 257 | return { |
246 | video: this.Video.toFormattedJSON(), | 258 | video: this.Video.toFormattedJSON(), |
247 | rating: this.type | 259 | rating: this.type |
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 4dc412301..ba1094536 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -3,7 +3,8 @@ import { | |||
3 | BeforeDestroy, | 3 | BeforeDestroy, |
4 | BelongsTo, | 4 | BelongsTo, |
5 | Column, | 5 | Column, |
6 | CreatedAt, DataType, | 6 | CreatedAt, |
7 | DataType, | ||
7 | Default, | 8 | Default, |
8 | DefaultScope, | 9 | DefaultScope, |
9 | ForeignKey, | 10 | ForeignKey, |
@@ -31,6 +32,8 @@ import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequ | |||
31 | import { AccountBlocklistModel } from './account-blocklist' | 32 | import { AccountBlocklistModel } from './account-blocklist' |
32 | import { ServerBlocklistModel } from '../server/server-blocklist' | 33 | import { ServerBlocklistModel } from '../server/server-blocklist' |
33 | import { ActorFollowModel } from '../activitypub/actor-follow' | 34 | import { ActorFollowModel } from '../activitypub/actor-follow' |
35 | import { MAccountActor, MAccountDefault, MAccountSummaryFormattable, MAccountFormattable, MAccountAP } from '../../typings/models' | ||
36 | import * as Bluebird from 'bluebird' | ||
34 | 37 | ||
35 | export enum ScopeNames { | 38 | export enum ScopeNames { |
36 | SUMMARY = 'SUMMARY' | 39 | SUMMARY = 'SUMMARY' |
@@ -229,11 +232,11 @@ export class AccountModel extends Model<AccountModel> { | |||
229 | return undefined | 232 | return undefined |
230 | } | 233 | } |
231 | 234 | ||
232 | static load (id: number, transaction?: Transaction) { | 235 | static load (id: number, transaction?: Transaction): Bluebird<MAccountDefault> { |
233 | return AccountModel.findByPk(id, { transaction }) | 236 | return AccountModel.findByPk(id, { transaction }) |
234 | } | 237 | } |
235 | 238 | ||
236 | static loadByNameWithHost (nameWithHost: string) { | 239 | static loadByNameWithHost (nameWithHost: string): Bluebird<MAccountDefault> { |
237 | const [ accountName, host ] = nameWithHost.split('@') | 240 | const [ accountName, host ] = nameWithHost.split('@') |
238 | 241 | ||
239 | if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName) | 242 | if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName) |
@@ -241,7 +244,7 @@ export class AccountModel extends Model<AccountModel> { | |||
241 | return AccountModel.loadByNameAndHost(accountName, host) | 244 | return AccountModel.loadByNameAndHost(accountName, host) |
242 | } | 245 | } |
243 | 246 | ||
244 | static loadLocalByName (name: string) { | 247 | static loadLocalByName (name: string): Bluebird<MAccountDefault> { |
245 | const query = { | 248 | const query = { |
246 | where: { | 249 | where: { |
247 | [ Op.or ]: [ | 250 | [ Op.or ]: [ |
@@ -271,7 +274,7 @@ export class AccountModel extends Model<AccountModel> { | |||
271 | return AccountModel.findOne(query) | 274 | return AccountModel.findOne(query) |
272 | } | 275 | } |
273 | 276 | ||
274 | static loadByNameAndHost (name: string, host: string) { | 277 | static loadByNameAndHost (name: string, host: string): Bluebird<MAccountDefault> { |
275 | const query = { | 278 | const query = { |
276 | include: [ | 279 | include: [ |
277 | { | 280 | { |
@@ -296,7 +299,7 @@ export class AccountModel extends Model<AccountModel> { | |||
296 | return AccountModel.findOne(query) | 299 | return AccountModel.findOne(query) |
297 | } | 300 | } |
298 | 301 | ||
299 | static loadByUrl (url: string, transaction?: Transaction) { | 302 | static loadByUrl (url: string, transaction?: Transaction): Bluebird<MAccountDefault> { |
300 | const query = { | 303 | const query = { |
301 | include: [ | 304 | include: [ |
302 | { | 305 | { |
@@ -329,7 +332,7 @@ export class AccountModel extends Model<AccountModel> { | |||
329 | }) | 332 | }) |
330 | } | 333 | } |
331 | 334 | ||
332 | static listLocalsForSitemap (sort: string) { | 335 | static listLocalsForSitemap (sort: string): Bluebird<MAccountActor[]> { |
333 | const query = { | 336 | const query = { |
334 | attributes: [ ], | 337 | attributes: [ ], |
335 | offset: 0, | 338 | offset: 0, |
@@ -350,7 +353,7 @@ export class AccountModel extends Model<AccountModel> { | |||
350 | .findAll(query) | 353 | .findAll(query) |
351 | } | 354 | } |
352 | 355 | ||
353 | toFormattedJSON (): Account { | 356 | toFormattedJSON (this: MAccountFormattable): Account { |
354 | const actor = this.Actor.toFormattedJSON() | 357 | const actor = this.Actor.toFormattedJSON() |
355 | const account = { | 358 | const account = { |
356 | id: this.id, | 359 | id: this.id, |
@@ -364,8 +367,8 @@ export class AccountModel extends Model<AccountModel> { | |||
364 | return Object.assign(actor, account) | 367 | return Object.assign(actor, account) |
365 | } | 368 | } |
366 | 369 | ||
367 | toFormattedSummaryJSON (): AccountSummary { | 370 | toFormattedSummaryJSON (this: MAccountSummaryFormattable): AccountSummary { |
368 | const actor = this.Actor.toFormattedJSON() | 371 | const actor = this.Actor.toFormattedSummaryJSON() |
369 | 372 | ||
370 | return { | 373 | return { |
371 | id: this.id, | 374 | id: this.id, |
@@ -377,8 +380,8 @@ export class AccountModel extends Model<AccountModel> { | |||
377 | } | 380 | } |
378 | } | 381 | } |
379 | 382 | ||
380 | toActivityPubObject () { | 383 | toActivityPubObject (this: MAccountAP) { |
381 | const obj = this.Actor.toActivityPubObject(this.name, 'Account') | 384 | const obj = this.Actor.toActivityPubObject(this.name) |
382 | 385 | ||
383 | return Object.assign(obj, { | 386 | return Object.assign(obj, { |
384 | summary: this.description | 387 | summary: this.description |
diff --git a/server/models/account/user-notification-setting.ts b/server/models/account/user-notification-setting.ts index c2fbc6d23..dc69a17fd 100644 --- a/server/models/account/user-notification-setting.ts +++ b/server/models/account/user-notification-setting.ts | |||
@@ -17,6 +17,7 @@ import { UserModel } from './user' | |||
17 | import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' | 17 | import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' |
18 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model' | 18 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model' |
19 | import { clearCacheByUserId } from '../../lib/oauth-model' | 19 | import { clearCacheByUserId } from '../../lib/oauth-model' |
20 | import { MNotificationSettingFormattable } from '@server/typings/models' | ||
20 | 21 | ||
21 | @Table({ | 22 | @Table({ |
22 | tableName: 'userNotificationSetting', | 23 | tableName: 'userNotificationSetting', |
@@ -113,6 +114,15 @@ export class UserNotificationSettingModel extends Model<UserNotificationSettingM | |||
113 | @AllowNull(false) | 114 | @AllowNull(false) |
114 | @Default(null) | 115 | @Default(null) |
115 | @Is( | 116 | @Is( |
117 | 'UserNotificationSettingNewInstanceFollower', | ||
118 | value => throwIfNotValid(value, isUserNotificationSettingValid, 'autoInstanceFollowing') | ||
119 | ) | ||
120 | @Column | ||
121 | autoInstanceFollowing: UserNotificationSettingValue | ||
122 | |||
123 | @AllowNull(false) | ||
124 | @Default(null) | ||
125 | @Is( | ||
116 | 'UserNotificationSettingNewFollow', | 126 | 'UserNotificationSettingNewFollow', |
117 | value => throwIfNotValid(value, isUserNotificationSettingValid, 'newFollow') | 127 | value => throwIfNotValid(value, isUserNotificationSettingValid, 'newFollow') |
118 | ) | 128 | ) |
@@ -152,7 +162,7 @@ export class UserNotificationSettingModel extends Model<UserNotificationSettingM | |||
152 | return clearCacheByUserId(instance.userId) | 162 | return clearCacheByUserId(instance.userId) |
153 | } | 163 | } |
154 | 164 | ||
155 | toFormattedJSON (): UserNotificationSetting { | 165 | toFormattedJSON (this: MNotificationSettingFormattable): UserNotificationSetting { |
156 | return { | 166 | return { |
157 | newCommentOnMyVideo: this.newCommentOnMyVideo, | 167 | newCommentOnMyVideo: this.newCommentOnMyVideo, |
158 | newVideoFromSubscription: this.newVideoFromSubscription, | 168 | newVideoFromSubscription: this.newVideoFromSubscription, |
@@ -164,7 +174,8 @@ export class UserNotificationSettingModel extends Model<UserNotificationSettingM | |||
164 | newUserRegistration: this.newUserRegistration, | 174 | newUserRegistration: this.newUserRegistration, |
165 | commentMention: this.commentMention, | 175 | commentMention: this.commentMention, |
166 | newFollow: this.newFollow, | 176 | newFollow: this.newFollow, |
167 | newInstanceFollower: this.newInstanceFollower | 177 | newInstanceFollower: this.newInstanceFollower, |
178 | autoInstanceFollowing: this.autoInstanceFollowing | ||
168 | } | 179 | } |
169 | } | 180 | } |
170 | } | 181 | } |
diff --git a/server/models/account/user-notification.ts b/server/models/account/user-notification.ts index f38cd7e78..ccb81b891 100644 --- a/server/models/account/user-notification.ts +++ b/server/models/account/user-notification.ts | |||
@@ -16,6 +16,7 @@ import { ActorModel } from '../activitypub/actor' | |||
16 | import { ActorFollowModel } from '../activitypub/actor-follow' | 16 | import { ActorFollowModel } from '../activitypub/actor-follow' |
17 | import { AvatarModel } from '../avatar/avatar' | 17 | import { AvatarModel } from '../avatar/avatar' |
18 | import { ServerModel } from '../server/server' | 18 | import { ServerModel } from '../server/server' |
19 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/typings/models/user' | ||
19 | 20 | ||
20 | enum ScopeNames { | 21 | enum ScopeNames { |
21 | WITH_ALL = 'WITH_ALL' | 22 | WITH_ALL = 'WITH_ALL' |
@@ -134,13 +135,18 @@ function buildAccountInclude (required: boolean, withActor = false) { | |||
134 | ] | 135 | ] |
135 | }, | 136 | }, |
136 | { | 137 | { |
137 | attributes: [ 'preferredUsername' ], | 138 | attributes: [ 'preferredUsername', 'type' ], |
138 | model: ActorModel.unscoped(), | 139 | model: ActorModel.unscoped(), |
139 | required: true, | 140 | required: true, |
140 | as: 'ActorFollowing', | 141 | as: 'ActorFollowing', |
141 | include: [ | 142 | include: [ |
142 | buildChannelInclude(false), | 143 | buildChannelInclude(false), |
143 | buildAccountInclude(false) | 144 | buildAccountInclude(false), |
145 | { | ||
146 | attributes: [ 'host' ], | ||
147 | model: ServerModel.unscoped(), | ||
148 | required: false | ||
149 | } | ||
144 | ] | 150 | ] |
145 | } | 151 | } |
146 | ] | 152 | ] |
@@ -371,7 +377,7 @@ export class UserNotificationModel extends Model<UserNotificationModel> { | |||
371 | return UserNotificationModel.update({ read: true }, query) | 377 | return UserNotificationModel.update({ read: true }, query) |
372 | } | 378 | } |
373 | 379 | ||
374 | toFormattedJSON (): UserNotification { | 380 | toFormattedJSON (this: UserNotificationModelForApi): UserNotification { |
375 | const video = this.Video | 381 | const video = this.Video |
376 | ? 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) }) |
377 | : undefined | 383 | : undefined |
@@ -403,6 +409,11 @@ export class UserNotificationModel extends Model<UserNotificationModel> { | |||
403 | 409 | ||
404 | const account = this.Account ? this.formatActor(this.Account) : undefined | 410 | const account = this.Account ? this.formatActor(this.Account) : undefined |
405 | 411 | ||
412 | const actorFollowingType = { | ||
413 | Application: 'instance' as 'instance', | ||
414 | Group: 'channel' as 'channel', | ||
415 | Person: 'account' as 'account' | ||
416 | } | ||
406 | const actorFollow = this.ActorFollow ? { | 417 | const actorFollow = this.ActorFollow ? { |
407 | id: this.ActorFollow.id, | 418 | id: this.ActorFollow.id, |
408 | state: this.ActorFollow.state, | 419 | state: this.ActorFollow.state, |
@@ -414,9 +425,10 @@ export class UserNotificationModel extends Model<UserNotificationModel> { | |||
414 | host: this.ActorFollow.ActorFollower.getHost() | 425 | host: this.ActorFollow.ActorFollower.getHost() |
415 | }, | 426 | }, |
416 | following: { | 427 | following: { |
417 | type: this.ActorFollow.ActorFollowing.VideoChannel ? 'channel' as 'channel' : 'account' as 'account', | 428 | type: actorFollowingType[this.ActorFollow.ActorFollowing.type], |
418 | displayName: (this.ActorFollow.ActorFollowing.VideoChannel || this.ActorFollow.ActorFollowing.Account).getDisplayName(), | 429 | displayName: (this.ActorFollow.ActorFollowing.VideoChannel || this.ActorFollow.ActorFollowing.Account).getDisplayName(), |
419 | name: this.ActorFollow.ActorFollowing.preferredUsername | 430 | name: this.ActorFollow.ActorFollowing.preferredUsername, |
431 | host: this.ActorFollow.ActorFollowing.getHost() | ||
420 | } | 432 | } |
421 | } : undefined | 433 | } : undefined |
422 | 434 | ||
@@ -436,7 +448,7 @@ export class UserNotificationModel extends Model<UserNotificationModel> { | |||
436 | } | 448 | } |
437 | } | 449 | } |
438 | 450 | ||
439 | private formatVideo (video: VideoModel) { | 451 | formatVideo (this: UserNotificationModelForApi, video: UserNotificationIncludes.VideoInclude) { |
440 | return { | 452 | return { |
441 | id: video.id, | 453 | id: video.id, |
442 | uuid: video.uuid, | 454 | uuid: video.uuid, |
@@ -444,7 +456,10 @@ export class UserNotificationModel extends Model<UserNotificationModel> { | |||
444 | } | 456 | } |
445 | } | 457 | } |
446 | 458 | ||
447 | private formatActor (accountOrChannel: AccountModel | VideoChannelModel) { | 459 | formatActor ( |
460 | this: UserNotificationModelForApi, | ||
461 | accountOrChannel: UserNotificationIncludes.AccountIncludeActor | UserNotificationIncludes.VideoChannelIncludeActor | ||
462 | ) { | ||
448 | const avatar = accountOrChannel.Actor.Avatar | 463 | const avatar = accountOrChannel.Actor.Avatar |
449 | ? { path: accountOrChannel.Actor.Avatar.getStaticPath() } | 464 | ? { path: accountOrChannel.Actor.Avatar.getStaticPath() } |
450 | : undefined | 465 | : undefined |
diff --git a/server/models/account/user-video-history.ts b/server/models/account/user-video-history.ts index a862fc45f..3fe4c8db1 100644 --- a/server/models/account/user-video-history.ts +++ b/server/models/account/user-video-history.ts | |||
@@ -1,7 +1,8 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { VideoModel } from '../video/video' | 2 | import { VideoModel } from '../video/video' |
3 | import { UserModel } from './user' | 3 | import { UserModel } from './user' |
4 | import { Transaction, Op, DestroyOptions } from 'sequelize' | 4 | import { DestroyOptions, Op, Transaction } from 'sequelize' |
5 | import { MUserAccountId, MUserId } from '@server/typings/models' | ||
5 | 6 | ||
6 | @Table({ | 7 | @Table({ |
7 | tableName: 'userVideoHistory', | 8 | tableName: 'userVideoHistory', |
@@ -54,7 +55,7 @@ export class UserVideoHistoryModel extends Model<UserVideoHistoryModel> { | |||
54 | }) | 55 | }) |
55 | User: UserModel | 56 | User: UserModel |
56 | 57 | ||
57 | static listForApi (user: UserModel, start: number, count: number) { | 58 | static listForApi (user: MUserAccountId, start: number, count: number) { |
58 | return VideoModel.listForApi({ | 59 | return VideoModel.listForApi({ |
59 | start, | 60 | start, |
60 | count, | 61 | count, |
@@ -67,7 +68,7 @@ export class UserVideoHistoryModel extends Model<UserVideoHistoryModel> { | |||
67 | }) | 68 | }) |
68 | } | 69 | } |
69 | 70 | ||
70 | static removeUserHistoryBefore (user: UserModel, beforeDate: string, t: Transaction) { | 71 | static removeUserHistoryBefore (user: MUserId, beforeDate: string, t: Transaction) { |
71 | const query: DestroyOptions = { | 72 | const query: DestroyOptions = { |
72 | where: { | 73 | where: { |
73 | userId: user.id | 74 | userId: user.id |
diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 0041bf577..451e1fd6b 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts | |||
@@ -22,6 +22,7 @@ import { | |||
22 | import { hasUserRight, USER_ROLE_LABELS, UserRight } from '../../../shared' | 22 | import { hasUserRight, USER_ROLE_LABELS, UserRight } from '../../../shared' |
23 | import { User, UserRole } from '../../../shared/models/users' | 23 | import { User, UserRole } from '../../../shared/models/users' |
24 | import { | 24 | import { |
25 | isNoInstanceConfigWarningModal, | ||
25 | isUserAdminFlagsValid, | 26 | isUserAdminFlagsValid, |
26 | isUserAutoPlayVideoValid, | 27 | isUserAutoPlayVideoValid, |
27 | isUserBlockedReasonValid, | 28 | isUserBlockedReasonValid, |
@@ -35,7 +36,8 @@ import { | |||
35 | isUserVideoQuotaDailyValid, | 36 | isUserVideoQuotaDailyValid, |
36 | isUserVideoQuotaValid, | 37 | isUserVideoQuotaValid, |
37 | isUserVideosHistoryEnabledValid, | 38 | isUserVideosHistoryEnabledValid, |
38 | isUserWebTorrentEnabledValid | 39 | isUserWebTorrentEnabledValid, |
40 | isNoWelcomeModal | ||
39 | } from '../../helpers/custom-validators/users' | 41 | } from '../../helpers/custom-validators/users' |
40 | import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' | 42 | import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' |
41 | import { OAuthTokenModel } from '../oauth/oauth-token' | 43 | import { OAuthTokenModel } from '../oauth/oauth-token' |
@@ -54,6 +56,14 @@ import { VideoImportModel } from '../video/video-import' | |||
54 | import { UserAdminFlag } from '../../../shared/models/users/user-flag.model' | 56 | import { UserAdminFlag } from '../../../shared/models/users/user-flag.model' |
55 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' | 57 | import { isThemeNameValid } from '../../helpers/custom-validators/plugins' |
56 | import { getThemeOrDefault } from '../../lib/plugins/theme-utils' | 58 | import { getThemeOrDefault } from '../../lib/plugins/theme-utils' |
59 | import * as Bluebird from 'bluebird' | ||
60 | import { | ||
61 | MUserDefault, | ||
62 | MUserFormattable, | ||
63 | MUserId, | ||
64 | MUserNotifSettingChannelDefault, | ||
65 | MUserWithNotificationSetting | ||
66 | } from '@server/typings/models' | ||
57 | 67 | ||
58 | enum ScopeNames { | 68 | enum ScopeNames { |
59 | WITH_VIDEO_CHANNEL = 'WITH_VIDEO_CHANNEL' | 69 | WITH_VIDEO_CHANNEL = 'WITH_VIDEO_CHANNEL' |
@@ -195,6 +205,24 @@ export class UserModel extends Model<UserModel> { | |||
195 | @Column | 205 | @Column |
196 | theme: string | 206 | theme: string |
197 | 207 | ||
208 | @AllowNull(false) | ||
209 | @Default(false) | ||
210 | @Is( | ||
211 | 'UserNoInstanceConfigWarningModal', | ||
212 | value => throwIfNotValid(value, isNoInstanceConfigWarningModal, 'no instance config warning modal') | ||
213 | ) | ||
214 | @Column | ||
215 | noInstanceConfigWarningModal: boolean | ||
216 | |||
217 | @AllowNull(false) | ||
218 | @Default(false) | ||
219 | @Is( | ||
220 | 'UserNoInstanceConfigWarningModal', | ||
221 | value => throwIfNotValid(value, isNoWelcomeModal, 'no welcome modal') | ||
222 | ) | ||
223 | @Column | ||
224 | noWelcomeModal: boolean | ||
225 | |||
198 | @CreatedAt | 226 | @CreatedAt |
199 | createdAt: Date | 227 | createdAt: Date |
200 | 228 | ||
@@ -303,7 +331,7 @@ export class UserModel extends Model<UserModel> { | |||
303 | }) | 331 | }) |
304 | } | 332 | } |
305 | 333 | ||
306 | static listWithRight (right: UserRight) { | 334 | static listWithRight (right: UserRight): Bluebird<MUserDefault[]> { |
307 | const roles = Object.keys(USER_ROLE_LABELS) | 335 | const roles = Object.keys(USER_ROLE_LABELS) |
308 | .map(k => parseInt(k, 10) as UserRole) | 336 | .map(k => parseInt(k, 10) as UserRole) |
309 | .filter(role => hasUserRight(role, right)) | 337 | .filter(role => hasUserRight(role, right)) |
@@ -319,7 +347,7 @@ export class UserModel extends Model<UserModel> { | |||
319 | return UserModel.findAll(query) | 347 | return UserModel.findAll(query) |
320 | } | 348 | } |
321 | 349 | ||
322 | static listUserSubscribersOf (actorId: number) { | 350 | static listUserSubscribersOf (actorId: number): Bluebird<MUserWithNotificationSetting[]> { |
323 | const query = { | 351 | const query = { |
324 | include: [ | 352 | include: [ |
325 | { | 353 | { |
@@ -358,7 +386,7 @@ export class UserModel extends Model<UserModel> { | |||
358 | return UserModel.unscoped().findAll(query) | 386 | return UserModel.unscoped().findAll(query) |
359 | } | 387 | } |
360 | 388 | ||
361 | static listByUsernames (usernames: string[]) { | 389 | static listByUsernames (usernames: string[]): Bluebird<MUserDefault[]> { |
362 | const query = { | 390 | const query = { |
363 | where: { | 391 | where: { |
364 | username: usernames | 392 | username: usernames |
@@ -368,11 +396,11 @@ export class UserModel extends Model<UserModel> { | |||
368 | return UserModel.findAll(query) | 396 | return UserModel.findAll(query) |
369 | } | 397 | } |
370 | 398 | ||
371 | static loadById (id: number) { | 399 | static loadById (id: number): Bluebird<MUserDefault> { |
372 | return UserModel.findByPk(id) | 400 | return UserModel.findByPk(id) |
373 | } | 401 | } |
374 | 402 | ||
375 | static loadByUsername (username: string) { | 403 | static loadByUsername (username: string): Bluebird<MUserDefault> { |
376 | const query = { | 404 | const query = { |
377 | where: { | 405 | where: { |
378 | username: { [ Op.iLike ]: username } | 406 | username: { [ Op.iLike ]: username } |
@@ -382,7 +410,7 @@ export class UserModel extends Model<UserModel> { | |||
382 | return UserModel.findOne(query) | 410 | return UserModel.findOne(query) |
383 | } | 411 | } |
384 | 412 | ||
385 | static loadByUsernameAndPopulateChannels (username: string) { | 413 | static loadByUsernameAndPopulateChannels (username: string): Bluebird<MUserNotifSettingChannelDefault> { |
386 | const query = { | 414 | const query = { |
387 | where: { | 415 | where: { |
388 | username: { [ Op.iLike ]: username } | 416 | username: { [ Op.iLike ]: username } |
@@ -392,7 +420,7 @@ export class UserModel extends Model<UserModel> { | |||
392 | return UserModel.scope(ScopeNames.WITH_VIDEO_CHANNEL).findOne(query) | 420 | return UserModel.scope(ScopeNames.WITH_VIDEO_CHANNEL).findOne(query) |
393 | } | 421 | } |
394 | 422 | ||
395 | static loadByEmail (email: string) { | 423 | static loadByEmail (email: string): Bluebird<MUserDefault> { |
396 | const query = { | 424 | const query = { |
397 | where: { | 425 | where: { |
398 | 426 | ||
@@ -402,7 +430,7 @@ export class UserModel extends Model<UserModel> { | |||
402 | return UserModel.findOne(query) | 430 | return UserModel.findOne(query) |
403 | } | 431 | } |
404 | 432 | ||
405 | static loadByUsernameOrEmail (username: string, email?: string) { | 433 | static loadByUsernameOrEmail (username: string, email?: string): Bluebird<MUserDefault> { |
406 | if (!email) email = username | 434 | if (!email) email = username |
407 | 435 | ||
408 | const query = { | 436 | const query = { |
@@ -414,7 +442,7 @@ export class UserModel extends Model<UserModel> { | |||
414 | return UserModel.findOne(query) | 442 | return UserModel.findOne(query) |
415 | } | 443 | } |
416 | 444 | ||
417 | static loadByVideoId (videoId: number) { | 445 | static loadByVideoId (videoId: number): Bluebird<MUserDefault> { |
418 | const query = { | 446 | const query = { |
419 | include: [ | 447 | include: [ |
420 | { | 448 | { |
@@ -445,7 +473,7 @@ export class UserModel extends Model<UserModel> { | |||
445 | return UserModel.findOne(query) | 473 | return UserModel.findOne(query) |
446 | } | 474 | } |
447 | 475 | ||
448 | static loadByVideoImportId (videoImportId: number) { | 476 | static loadByVideoImportId (videoImportId: number): Bluebird<MUserDefault> { |
449 | const query = { | 477 | const query = { |
450 | include: [ | 478 | include: [ |
451 | { | 479 | { |
@@ -462,7 +490,7 @@ export class UserModel extends Model<UserModel> { | |||
462 | return UserModel.findOne(query) | 490 | return UserModel.findOne(query) |
463 | } | 491 | } |
464 | 492 | ||
465 | static loadByChannelActorId (videoChannelActorId: number) { | 493 | static loadByChannelActorId (videoChannelActorId: number): Bluebird<MUserDefault> { |
466 | const query = { | 494 | const query = { |
467 | include: [ | 495 | include: [ |
468 | { | 496 | { |
@@ -486,7 +514,7 @@ export class UserModel extends Model<UserModel> { | |||
486 | return UserModel.findOne(query) | 514 | return UserModel.findOne(query) |
487 | } | 515 | } |
488 | 516 | ||
489 | static loadByAccountActorId (accountActorId: number) { | 517 | static loadByAccountActorId (accountActorId: number): Bluebird<MUserDefault> { |
490 | const query = { | 518 | const query = { |
491 | include: [ | 519 | include: [ |
492 | { | 520 | { |
@@ -503,7 +531,7 @@ export class UserModel extends Model<UserModel> { | |||
503 | return UserModel.findOne(query) | 531 | return UserModel.findOne(query) |
504 | } | 532 | } |
505 | 533 | ||
506 | static getOriginalVideoFileTotalFromUser (user: UserModel) { | 534 | static getOriginalVideoFileTotalFromUser (user: MUserId) { |
507 | // Don't use sequelize because we need to use a sub query | 535 | // Don't use sequelize because we need to use a sub query |
508 | const query = UserModel.generateUserQuotaBaseSQL() | 536 | const query = UserModel.generateUserQuotaBaseSQL() |
509 | 537 | ||
@@ -511,7 +539,7 @@ export class UserModel extends Model<UserModel> { | |||
511 | } | 539 | } |
512 | 540 | ||
513 | // Returns cumulative size of all video files uploaded in the last 24 hours. | 541 | // Returns cumulative size of all video files uploaded in the last 24 hours. |
514 | static getOriginalVideoFileTotalDailyFromUser (user: UserModel) { | 542 | static getOriginalVideoFileTotalDailyFromUser (user: MUserId) { |
515 | // Don't use sequelize because we need to use a sub query | 543 | // Don't use sequelize because we need to use a sub query |
516 | const query = UserModel.generateUserQuotaBaseSQL('"video"."createdAt" > now() - interval \'24 hours\'') | 544 | const query = UserModel.generateUserQuotaBaseSQL('"video"."createdAt" > now() - interval \'24 hours\'') |
517 | 545 | ||
@@ -552,38 +580,52 @@ export class UserModel extends Model<UserModel> { | |||
552 | return comparePassword(password, this.password) | 580 | return comparePassword(password, this.password) |
553 | } | 581 | } |
554 | 582 | ||
555 | toFormattedJSON (parameters: { withAdminFlags?: boolean } = {}): User { | 583 | toFormattedJSON (this: MUserFormattable, parameters: { withAdminFlags?: boolean } = {}): User { |
556 | const videoQuotaUsed = this.get('videoQuotaUsed') | 584 | const videoQuotaUsed = this.get('videoQuotaUsed') |
557 | const videoQuotaUsedDaily = this.get('videoQuotaUsedDaily') | 585 | const videoQuotaUsedDaily = this.get('videoQuotaUsedDaily') |
558 | 586 | ||
559 | const json = { | 587 | const json: User = { |
560 | id: this.id, | 588 | id: this.id, |
561 | username: this.username, | 589 | username: this.username, |
562 | email: this.email, | 590 | email: this.email, |
591 | theme: getThemeOrDefault(this.theme, DEFAULT_USER_THEME_NAME), | ||
592 | |||
563 | pendingEmail: this.pendingEmail, | 593 | pendingEmail: this.pendingEmail, |
564 | emailVerified: this.emailVerified, | 594 | emailVerified: this.emailVerified, |
595 | |||
565 | nsfwPolicy: this.nsfwPolicy, | 596 | nsfwPolicy: this.nsfwPolicy, |
566 | webTorrentEnabled: this.webTorrentEnabled, | 597 | webTorrentEnabled: this.webTorrentEnabled, |
567 | videosHistoryEnabled: this.videosHistoryEnabled, | 598 | videosHistoryEnabled: this.videosHistoryEnabled, |
568 | autoPlayVideo: this.autoPlayVideo, | 599 | autoPlayVideo: this.autoPlayVideo, |
569 | videoLanguages: this.videoLanguages, | 600 | videoLanguages: this.videoLanguages, |
601 | |||
570 | role: this.role, | 602 | role: this.role, |
571 | theme: getThemeOrDefault(this.theme, DEFAULT_USER_THEME_NAME), | ||
572 | roleLabel: USER_ROLE_LABELS[ this.role ], | 603 | roleLabel: USER_ROLE_LABELS[ this.role ], |
604 | |||
573 | videoQuota: this.videoQuota, | 605 | videoQuota: this.videoQuota, |
574 | videoQuotaDaily: this.videoQuotaDaily, | 606 | videoQuotaDaily: this.videoQuotaDaily, |
575 | createdAt: this.createdAt, | 607 | videoQuotaUsed: videoQuotaUsed !== undefined |
608 | ? parseInt(videoQuotaUsed + '', 10) | ||
609 | : undefined, | ||
610 | videoQuotaUsedDaily: videoQuotaUsedDaily !== undefined | ||
611 | ? parseInt(videoQuotaUsedDaily + '', 10) | ||
612 | : undefined, | ||
613 | |||
614 | noInstanceConfigWarningModal: this.noInstanceConfigWarningModal, | ||
615 | noWelcomeModal: this.noWelcomeModal, | ||
616 | |||
576 | blocked: this.blocked, | 617 | blocked: this.blocked, |
577 | blockedReason: this.blockedReason, | 618 | blockedReason: this.blockedReason, |
619 | |||
578 | account: this.Account.toFormattedJSON(), | 620 | account: this.Account.toFormattedJSON(), |
579 | notificationSettings: this.NotificationSetting ? this.NotificationSetting.toFormattedJSON() : undefined, | 621 | |
622 | notificationSettings: this.NotificationSetting | ||
623 | ? this.NotificationSetting.toFormattedJSON() | ||
624 | : undefined, | ||
625 | |||
580 | videoChannels: [], | 626 | videoChannels: [], |
581 | videoQuotaUsed: videoQuotaUsed !== undefined | 627 | |
582 | ? parseInt(videoQuotaUsed + '', 10) | 628 | createdAt: this.createdAt |
583 | : undefined, | ||
584 | videoQuotaUsedDaily: videoQuotaUsedDaily !== undefined | ||
585 | ? parseInt(videoQuotaUsedDaily + '', 10) | ||
586 | : undefined | ||
587 | } | 629 | } |
588 | 630 | ||
589 | if (parameters.withAdminFlags) { | 631 | if (parameters.withAdminFlags) { |