MUserWithNotificationSetting,
MVideoWithRights
} from '@server/types/models'
+import { AttributesOnly } from '@shared/typescript-utils'
import { hasUserRight, USER_ROLE_LABELS } from '../../../shared/core-utils/users'
import { AbuseState, MyUser, UserRight, VideoPlaylistType, VideoPrivacy } from '../../../shared/models'
import { User, UserRole } from '../../../shared/models/users'
import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type'
import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
import {
- isNoInstanceConfigWarningModal,
- isNoWelcomeModal,
isUserAdminFlagsValid,
isUserAutoPlayNextVideoPlaylistValid,
isUserAutoPlayNextVideoValid,
isUserBlockedReasonValid,
isUserBlockedValid,
isUserEmailVerifiedValid,
+ isUserNoModal,
isUserNSFWPolicyValid,
+ isUserP2PEnabledValid,
isUserPasswordValid,
isUserRoleValid,
isUserUsernameValid,
isUserVideoLanguages,
isUserVideoQuotaDailyValid,
isUserVideoQuotaValid,
- isUserVideosHistoryEnabledValid,
- isUserWebTorrentEnabledValid
+ isUserVideosHistoryEnabledValid
} from '../../helpers/custom-validators/users'
import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto'
import { DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants'
import { VideoLiveModel } from '../video/video-live'
import { VideoPlaylistModel } from '../video/video-playlist'
import { UserNotificationSettingModel } from './user-notification-setting'
+import { LiveQuotaStore } from '@server/lib/live'
+import { logger } from '@server/helpers/logger'
enum ScopeNames {
FOR_ME_API = 'FOR_ME_API',
WITH_VIDEOCHANNELS = 'WITH_VIDEOCHANNELS',
+ WITH_QUOTA = 'WITH_QUOTA',
WITH_STATS = 'WITH_STATS'
}
include: [
{
model: ActorImageModel,
- as: 'Banner',
+ as: 'Banners',
required: false
}
]
}
]
},
- [ScopeNames.WITH_STATS]: {
+ [ScopeNames.WITH_QUOTA]: {
attributes: {
include: [
[
'(' +
UserModel.generateUserQuotaBaseSQL({
withSelect: false,
- whereUserId: '"UserModel"."id"'
+ whereUserId: '"UserModel"."id"',
+ daily: false
}) +
')'
),
'videoQuotaUsed'
],
+ [
+ literal(
+ '(' +
+ UserModel.generateUserQuotaBaseSQL({
+ withSelect: false,
+ whereUserId: '"UserModel"."id"',
+ daily: true
+ }) +
+ ')'
+ ),
+ 'videoQuotaUsedDaily'
+ ]
+ ]
+ }
+ },
+ [ScopeNames.WITH_STATS]: {
+ attributes: {
+ include: [
[
literal(
'(' +
}
]
})
-export class UserModel extends Model {
+export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
@AllowNull(true)
@Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true))
nsfwPolicy: NSFWPolicyType
@AllowNull(false)
- @Default(true)
- @Is('UserWebTorrentEnabled', value => throwIfNotValid(value, isUserWebTorrentEnabledValid, 'WebTorrent enabled'))
+ @Is('p2pEnabled', value => throwIfNotValid(value, isUserP2PEnabledValid, 'P2P enabled'))
@Column
- webTorrentEnabled: boolean
+ p2pEnabled: boolean
@AllowNull(false)
@Default(true)
@Default(false)
@Is(
'UserNoInstanceConfigWarningModal',
- value => throwIfNotValid(value, isNoInstanceConfigWarningModal, 'no instance config warning modal')
+ value => throwIfNotValid(value, isUserNoModal, 'no instance config warning modal')
)
@Column
noInstanceConfigWarningModal: boolean
@AllowNull(false)
@Default(false)
@Is(
- 'UserNoInstanceConfigWarningModal',
- value => throwIfNotValid(value, isNoWelcomeModal, 'no welcome modal')
+ 'UserNoWelcomeModal',
+ value => throwIfNotValid(value, isUserNoModal, 'no welcome modal')
)
@Column
noWelcomeModal: boolean
+ @AllowNull(false)
+ @Default(false)
+ @Is(
+ 'UserNoAccountSetupWarningModal',
+ value => throwIfNotValid(value, isUserNoModal, 'no account setup warning modal')
+ )
+ @Column
+ noAccountSetupWarningModal: boolean
+
@AllowNull(true)
@Default(null)
@Column
}
const query: FindOptions = {
- attributes: {
- include: [
- [
- literal(
- '(' +
- UserModel.generateUserQuotaBaseSQL({
- withSelect: false,
- whereUserId: '"UserModel"."id"'
- }) +
- ')'
- ),
- 'videoQuotaUsed'
- ] as any // FIXME: typings
- ]
- },
offset: start,
limit: count,
order: getSort(sort),
where
}
- return UserModel.findAndCountAll(query)
- .then(({ rows, count }) => {
- return {
- data: rows,
- total: count
- }
- })
+ return Promise.all([
+ UserModel.unscoped().count(query),
+ UserModel.scope([ 'defaultScope', ScopeNames.WITH_QUOTA ]).findAll(query)
+ ]).then(([ total, data ]) => ({ total, data }))
}
static listWithRight (right: UserRight): Promise<MUserDefault[]> {
ScopeNames.WITH_VIDEOCHANNELS
]
- if (withStats) scopes.push(ScopeNames.WITH_STATS)
+ if (withStats) {
+ scopes.push(ScopeNames.WITH_QUOTA)
+ scopes.push(ScopeNames.WITH_STATS)
+ }
return UserModel.scope(scopes).findByPk(id)
}
const query = {
where: {
[Op.or]: [
- where(fn('lower', col('username')), fn('lower', username)),
+ where(fn('lower', col('username')), fn('lower', username) as any),
{ email }
]
static generateUserQuotaBaseSQL (options: {
whereUserId: '$userId' | '"UserModel"."id"'
withSelect: boolean
- where?: string
+ daily: boolean
}) {
- const andWhere = options.where
- ? 'AND ' + options.where
+ const andWhere = options.daily === true
+ ? 'AND "video"."createdAt" > now() - interval \'24 hours\''
: ''
const videoChannelJoin = 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
emailVerified: this.emailVerified,
nsfwPolicy: this.nsfwPolicy,
- webTorrentEnabled: this.webTorrentEnabled,
+
+ // FIXME: deprecated in 4.1
+ webTorrentEnabled: this.p2pEnabled,
+ p2pEnabled: this.p2pEnabled,
+
videosHistoryEnabled: this.videosHistoryEnabled,
autoPlayVideo: this.autoPlayVideo,
autoPlayNextVideo: this.autoPlayNextVideo,
videoQuota: this.videoQuota,
videoQuotaDaily: this.videoQuotaDaily,
+
videoQuotaUsed: videoQuotaUsed !== undefined
- ? parseInt(videoQuotaUsed + '', 10)
+ ? parseInt(videoQuotaUsed + '', 10) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id)
: undefined,
+
videoQuotaUsedDaily: videoQuotaUsedDaily !== undefined
- ? parseInt(videoQuotaUsedDaily + '', 10)
+ ? parseInt(videoQuotaUsedDaily + '', 10) + LiveQuotaStore.Instance.getLiveQuotaOf(this.id)
: undefined,
+
videosCount: videosCount !== undefined
? parseInt(videosCount + '', 10)
: undefined,
noInstanceConfigWarningModal: this.noInstanceConfigWarningModal,
noWelcomeModal: this.noWelcomeModal,
+ noAccountSetupWarningModal: this.noAccountSetupWarningModal,
blocked: this.blocked,
blockedReason: this.blockedReason,
}
toMeFormattedJSON (this: MMyUserFormattable): MyUser {
- const formatted = this.toFormattedJSON()
+ const formatted = this.toFormattedJSON({ withAdminFlags: true })
const specialPlaylists = this.Account.VideoPlaylists
.map(p => ({ id: p.id, name: p.name, type: p.type }))