diff options
Diffstat (limited to 'server/models/account/user.ts')
-rw-r--r-- | server/models/account/user.ts | 180 |
1 files changed, 175 insertions, 5 deletions
diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 1843603f1..017a96657 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts | |||
@@ -32,6 +32,7 @@ import { | |||
32 | isUserUsernameValid, | 32 | isUserUsernameValid, |
33 | isUserVideoQuotaDailyValid, | 33 | isUserVideoQuotaDailyValid, |
34 | isUserVideoQuotaValid, | 34 | isUserVideoQuotaValid, |
35 | isUserVideosHistoryEnabledValid, | ||
35 | isUserWebTorrentEnabledValid | 36 | isUserWebTorrentEnabledValid |
36 | } from '../../helpers/custom-validators/users' | 37 | } from '../../helpers/custom-validators/users' |
37 | import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' | 38 | import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' |
@@ -43,6 +44,11 @@ import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type' | |||
43 | import { values } from 'lodash' | 44 | import { values } from 'lodash' |
44 | import { NSFW_POLICY_TYPES } from '../../initializers' | 45 | import { NSFW_POLICY_TYPES } from '../../initializers' |
45 | import { clearCacheByUserId } from '../../lib/oauth-model' | 46 | import { clearCacheByUserId } from '../../lib/oauth-model' |
47 | import { UserNotificationSettingModel } from './user-notification-setting' | ||
48 | import { VideoModel } from '../video/video' | ||
49 | import { ActorModel } from '../activitypub/actor' | ||
50 | import { ActorFollowModel } from '../activitypub/actor-follow' | ||
51 | import { VideoImportModel } from '../video/video-import' | ||
46 | 52 | ||
47 | enum ScopeNames { | 53 | enum ScopeNames { |
48 | WITH_VIDEO_CHANNEL = 'WITH_VIDEO_CHANNEL' | 54 | WITH_VIDEO_CHANNEL = 'WITH_VIDEO_CHANNEL' |
@@ -53,6 +59,10 @@ enum ScopeNames { | |||
53 | { | 59 | { |
54 | model: () => AccountModel, | 60 | model: () => AccountModel, |
55 | required: true | 61 | required: true |
62 | }, | ||
63 | { | ||
64 | model: () => UserNotificationSettingModel, | ||
65 | required: true | ||
56 | } | 66 | } |
57 | ] | 67 | ] |
58 | }) | 68 | }) |
@@ -63,6 +73,10 @@ enum ScopeNames { | |||
63 | model: () => AccountModel, | 73 | model: () => AccountModel, |
64 | required: true, | 74 | required: true, |
65 | include: [ () => VideoChannelModel ] | 75 | include: [ () => VideoChannelModel ] |
76 | }, | ||
77 | { | ||
78 | model: () => UserNotificationSettingModel, | ||
79 | required: true | ||
66 | } | 80 | } |
67 | ] | 81 | ] |
68 | } | 82 | } |
@@ -116,6 +130,12 @@ export class UserModel extends Model<UserModel> { | |||
116 | 130 | ||
117 | @AllowNull(false) | 131 | @AllowNull(false) |
118 | @Default(true) | 132 | @Default(true) |
133 | @Is('UserVideosHistoryEnabled', value => throwIfNotValid(value, isUserVideosHistoryEnabledValid, 'Videos history enabled')) | ||
134 | @Column | ||
135 | videosHistoryEnabled: boolean | ||
136 | |||
137 | @AllowNull(false) | ||
138 | @Default(true) | ||
119 | @Is('UserAutoPlayVideo', value => throwIfNotValid(value, isUserAutoPlayVideoValid, 'auto play video boolean')) | 139 | @Is('UserAutoPlayVideo', value => throwIfNotValid(value, isUserAutoPlayVideoValid, 'auto play video boolean')) |
120 | @Column | 140 | @Column |
121 | autoPlayVideo: boolean | 141 | autoPlayVideo: boolean |
@@ -160,6 +180,19 @@ export class UserModel extends Model<UserModel> { | |||
160 | }) | 180 | }) |
161 | Account: AccountModel | 181 | Account: AccountModel |
162 | 182 | ||
183 | @HasOne(() => UserNotificationSettingModel, { | ||
184 | foreignKey: 'userId', | ||
185 | onDelete: 'cascade', | ||
186 | hooks: true | ||
187 | }) | ||
188 | NotificationSetting: UserNotificationSettingModel | ||
189 | |||
190 | @HasMany(() => VideoImportModel, { | ||
191 | foreignKey: 'userId', | ||
192 | onDelete: 'cascade' | ||
193 | }) | ||
194 | VideoImports: VideoImportModel[] | ||
195 | |||
163 | @HasMany(() => OAuthTokenModel, { | 196 | @HasMany(() => OAuthTokenModel, { |
164 | foreignKey: 'userId', | 197 | foreignKey: 'userId', |
165 | onDelete: 'cascade' | 198 | onDelete: 'cascade' |
@@ -242,13 +275,12 @@ export class UserModel extends Model<UserModel> { | |||
242 | }) | 275 | }) |
243 | } | 276 | } |
244 | 277 | ||
245 | static listEmailsWithRight (right: UserRight) { | 278 | static listWithRight (right: UserRight) { |
246 | const roles = Object.keys(USER_ROLE_LABELS) | 279 | const roles = Object.keys(USER_ROLE_LABELS) |
247 | .map(k => parseInt(k, 10) as UserRole) | 280 | .map(k => parseInt(k, 10) as UserRole) |
248 | .filter(role => hasUserRight(role, right)) | 281 | .filter(role => hasUserRight(role, right)) |
249 | 282 | ||
250 | const query = { | 283 | const query = { |
251 | attribute: [ 'email' ], | ||
252 | where: { | 284 | where: { |
253 | role: { | 285 | role: { |
254 | [Sequelize.Op.in]: roles | 286 | [Sequelize.Op.in]: roles |
@@ -256,9 +288,56 @@ export class UserModel extends Model<UserModel> { | |||
256 | } | 288 | } |
257 | } | 289 | } |
258 | 290 | ||
259 | return UserModel.unscoped() | 291 | return UserModel.findAll(query) |
260 | .findAll(query) | 292 | } |
261 | .then(u => u.map(u => u.email)) | 293 | |
294 | static listUserSubscribersOf (actorId: number) { | ||
295 | const query = { | ||
296 | include: [ | ||
297 | { | ||
298 | model: UserNotificationSettingModel.unscoped(), | ||
299 | required: true | ||
300 | }, | ||
301 | { | ||
302 | attributes: [ 'userId' ], | ||
303 | model: AccountModel.unscoped(), | ||
304 | required: true, | ||
305 | include: [ | ||
306 | { | ||
307 | attributes: [ ], | ||
308 | model: ActorModel.unscoped(), | ||
309 | required: true, | ||
310 | where: { | ||
311 | serverId: null | ||
312 | }, | ||
313 | include: [ | ||
314 | { | ||
315 | attributes: [ ], | ||
316 | as: 'ActorFollowings', | ||
317 | model: ActorFollowModel.unscoped(), | ||
318 | required: true, | ||
319 | where: { | ||
320 | targetActorId: actorId | ||
321 | } | ||
322 | } | ||
323 | ] | ||
324 | } | ||
325 | ] | ||
326 | } | ||
327 | ] | ||
328 | } | ||
329 | |||
330 | return UserModel.unscoped().findAll(query) | ||
331 | } | ||
332 | |||
333 | static listByUsernames (usernames: string[]) { | ||
334 | const query = { | ||
335 | where: { | ||
336 | username: usernames | ||
337 | } | ||
338 | } | ||
339 | |||
340 | return UserModel.findAll(query) | ||
262 | } | 341 | } |
263 | 342 | ||
264 | static loadById (id: number) { | 343 | static loadById (id: number) { |
@@ -307,6 +386,95 @@ export class UserModel extends Model<UserModel> { | |||
307 | return UserModel.findOne(query) | 386 | return UserModel.findOne(query) |
308 | } | 387 | } |
309 | 388 | ||
389 | static loadByVideoId (videoId: number) { | ||
390 | const query = { | ||
391 | include: [ | ||
392 | { | ||
393 | required: true, | ||
394 | attributes: [ 'id' ], | ||
395 | model: AccountModel.unscoped(), | ||
396 | include: [ | ||
397 | { | ||
398 | required: true, | ||
399 | attributes: [ 'id' ], | ||
400 | model: VideoChannelModel.unscoped(), | ||
401 | include: [ | ||
402 | { | ||
403 | required: true, | ||
404 | attributes: [ 'id' ], | ||
405 | model: VideoModel.unscoped(), | ||
406 | where: { | ||
407 | id: videoId | ||
408 | } | ||
409 | } | ||
410 | ] | ||
411 | } | ||
412 | ] | ||
413 | } | ||
414 | ] | ||
415 | } | ||
416 | |||
417 | return UserModel.findOne(query) | ||
418 | } | ||
419 | |||
420 | static loadByVideoImportId (videoImportId: number) { | ||
421 | const query = { | ||
422 | include: [ | ||
423 | { | ||
424 | required: true, | ||
425 | attributes: [ 'id' ], | ||
426 | model: VideoImportModel.unscoped(), | ||
427 | where: { | ||
428 | id: videoImportId | ||
429 | } | ||
430 | } | ||
431 | ] | ||
432 | } | ||
433 | |||
434 | return UserModel.findOne(query) | ||
435 | } | ||
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 | |||
310 | static getOriginalVideoFileTotalFromUser (user: UserModel) { | 478 | static getOriginalVideoFileTotalFromUser (user: UserModel) { |
311 | // 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 |
312 | const query = UserModel.generateUserQuotaBaseSQL() | 480 | const query = UserModel.generateUserQuotaBaseSQL() |
@@ -363,6 +531,7 @@ export class UserModel extends Model<UserModel> { | |||
363 | emailVerified: this.emailVerified, | 531 | emailVerified: this.emailVerified, |
364 | nsfwPolicy: this.nsfwPolicy, | 532 | nsfwPolicy: this.nsfwPolicy, |
365 | webTorrentEnabled: this.webTorrentEnabled, | 533 | webTorrentEnabled: this.webTorrentEnabled, |
534 | videosHistoryEnabled: this.videosHistoryEnabled, | ||
366 | autoPlayVideo: this.autoPlayVideo, | 535 | autoPlayVideo: this.autoPlayVideo, |
367 | role: this.role, | 536 | role: this.role, |
368 | roleLabel: USER_ROLE_LABELS[ this.role ], | 537 | roleLabel: USER_ROLE_LABELS[ this.role ], |
@@ -372,6 +541,7 @@ export class UserModel extends Model<UserModel> { | |||
372 | blocked: this.blocked, | 541 | blocked: this.blocked, |
373 | blockedReason: this.blockedReason, | 542 | blockedReason: this.blockedReason, |
374 | account: this.Account.toFormattedJSON(), | 543 | account: this.Account.toFormattedJSON(), |
544 | notificationSettings: this.NotificationSetting ? this.NotificationSetting.toFormattedJSON() : undefined, | ||
375 | videoChannels: [], | 545 | videoChannels: [], |
376 | videoQuotaUsed: videoQuotaUsed !== undefined | 546 | videoQuotaUsed: videoQuotaUsed !== undefined |
377 | ? parseInt(videoQuotaUsed, 10) | 547 | ? parseInt(videoQuotaUsed, 10) |