aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/account/user.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/account/user.ts')
-rw-r--r--server/models/account/user.ts68
1 files changed, 59 insertions, 9 deletions
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 0150df4ce..178012eae 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -27,7 +27,8 @@ import {
27 isUserPasswordValid, 27 isUserPasswordValid,
28 isUserRoleValid, 28 isUserRoleValid,
29 isUserUsernameValid, 29 isUserUsernameValid,
30 isUserVideoQuotaValid 30 isUserVideoQuotaValid,
31 isUserVideoQuotaDailyValid
31} from '../../helpers/custom-validators/users' 32} from '../../helpers/custom-validators/users'
32import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' 33import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto'
33import { OAuthTokenModel } from '../oauth/oauth-token' 34import { OAuthTokenModel } from '../oauth/oauth-token'
@@ -124,6 +125,11 @@ export class UserModel extends Model<UserModel> {
124 @Column(DataType.BIGINT) 125 @Column(DataType.BIGINT)
125 videoQuota: number 126 videoQuota: number
126 127
128 @AllowNull(false)
129 @Is('UserVideoQuotaDaily', value => throwIfNotValid(value, isUserVideoQuotaDailyValid, 'video quota daily'))
130 @Column(DataType.BIGINT)
131 videoQuotaDaily: number
132
127 @CreatedAt 133 @CreatedAt
128 createdAt: Date 134 createdAt: Date
129 135
@@ -271,7 +277,32 @@ export class UserModel extends Model<UserModel> {
271 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" ' + 277 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" ' +
272 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + 278 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
273 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' + 279 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' +
274 'WHERE "account"."userId" = $userId GROUP BY "video"."id") t' 280 'WHERE "account"."userId" = $userId ' +
281 'GROUP BY "video"."id") t'
282
283 const options = {
284 bind: { userId: user.id },
285 type: Sequelize.QueryTypes.SELECT
286 }
287 return UserModel.sequelize.query(query, options)
288 .then(([ { total } ]) => {
289 if (total === null) return 0
290
291 return parseInt(total, 10)
292 })
293 }
294
295 // Returns comulative size of all video files uploaded in the last 24 hours.
296 static getOriginalVideoFileTotalDailyFromUser (user: UserModel) {
297 // Don't use sequelize because we need to use a sub query
298 const query = 'SELECT SUM("size") AS "total" FROM ' +
299 '(SELECT MAX("videoFile"."size") AS "size" FROM "videoFile" ' +
300 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" ' +
301 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
302 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' +
303 'WHERE "account"."userId" = $userId ' +
304 'AND "video"."createdAt" > now() - interval \'24 hours\'' +
305 'GROUP BY "video"."id") t'
275 306
276 const options = { 307 const options = {
277 bind: { userId: user.id }, 308 bind: { userId: user.id },
@@ -303,6 +334,7 @@ export class UserModel extends Model<UserModel> {
303 334
304 toFormattedJSON (): User { 335 toFormattedJSON (): User {
305 const videoQuotaUsed = this.get('videoQuotaUsed') 336 const videoQuotaUsed = this.get('videoQuotaUsed')
337 const videoQuotaUsedDaily = this.get('videoQuotaUsedDaily')
306 338
307 const json = { 339 const json = {
308 id: this.id, 340 id: this.id,
@@ -313,12 +345,18 @@ export class UserModel extends Model<UserModel> {
313 role: this.role, 345 role: this.role,
314 roleLabel: USER_ROLE_LABELS[ this.role ], 346 roleLabel: USER_ROLE_LABELS[ this.role ],
315 videoQuota: this.videoQuota, 347 videoQuota: this.videoQuota,
348 videoQuotaDaily: this.videoQuotaDaily,
316 createdAt: this.createdAt, 349 createdAt: this.createdAt,
317 blocked: this.blocked, 350 blocked: this.blocked,
318 blockedReason: this.blockedReason, 351 blockedReason: this.blockedReason,
319 account: this.Account.toFormattedJSON(), 352 account: this.Account.toFormattedJSON(),
320 videoChannels: [], 353 videoChannels: [],
321 videoQuotaUsed: videoQuotaUsed !== undefined ? parseInt(videoQuotaUsed, 10) : undefined 354 videoQuotaUsed: videoQuotaUsed !== undefined
355 ? parseInt(videoQuotaUsed, 10)
356 : undefined,
357 videoQuotaUsedDaily: videoQuotaUsedDaily !== undefined
358 ? parseInt(videoQuotaUsedDaily, 10)
359 : undefined
322 } 360 }
323 361
324 if (Array.isArray(this.Account.VideoChannels) === true) { 362 if (Array.isArray(this.Account.VideoChannels) === true) {
@@ -335,12 +373,24 @@ export class UserModel extends Model<UserModel> {
335 return json 373 return json
336 } 374 }
337 375
338 isAbleToUploadVideo (videoFile: { size: number }) { 376 async isAbleToUploadVideo (videoFile: { size: number }) {
339 if (this.videoQuota === -1) return Promise.resolve(true) 377 if (this.videoQuota === -1 && this.videoQuotaDaily === -1) return Promise.resolve(true)
340 378
341 return UserModel.getOriginalVideoFileTotalFromUser(this) 379 const [ totalBytes, totalBytesDaily ] = await Promise.all([
342 .then(totalBytes => { 380 UserModel.getOriginalVideoFileTotalFromUser(this),
343 return (videoFile.size + totalBytes) < this.videoQuota 381 UserModel.getOriginalVideoFileTotalDailyFromUser(this)
344 }) 382 ])
383
384 const uploadedTotal = videoFile.size + totalBytes
385 const uploadedDaily = videoFile.size + totalBytesDaily
386 if (this.videoQuotaDaily === -1) {
387 return uploadedTotal < this.videoQuota
388 }
389 if (this.videoQuota === -1) {
390 return uploadedDaily < this.videoQuotaDaily
391 }
392
393 return (uploadedTotal < this.videoQuota) &&
394 (uploadedDaily < this.videoQuotaDaily)
345 } 395 }
346} 396}