1 import { FindOptions, Op, WhereOptions } from 'sequelize'
15 } from 'sequelize-typescript'
17 isRegistrationModerationResponseValid,
18 isRegistrationReasonValid,
19 isRegistrationStateValid
20 } from '@server/helpers/custom-validators/user-registration'
21 import { isVideoChannelDisplayNameValid } from '@server/helpers/custom-validators/video-channels'
22 import { cryptPassword } from '@server/helpers/peertube-crypto'
23 import { USER_REGISTRATION_STATES } from '@server/initializers/constants'
24 import { MRegistration, MRegistrationFormattable } from '@server/types/models'
25 import { UserRegistration, UserRegistrationState } from '@shared/models'
26 import { AttributesOnly } from '@shared/typescript-utils'
27 import { isUserDisplayNameValid, isUserEmailVerifiedValid, isUserPasswordValid } from '../../helpers/custom-validators/users'
28 import { getSort, throwIfNotValid } from '../shared'
29 import { UserModel } from './user'
32 tableName: 'userRegistration',
35 fields: [ 'username' ],
43 fields: [ 'channelHandle' ],
52 export class UserRegistrationModel extends Model<Partial<AttributesOnly<UserRegistrationModel>>> {
55 @Is('RegistrationState', value => throwIfNotValid(value, isRegistrationStateValid, 'state'))
57 state: UserRegistrationState
60 @Is('RegistrationReason', value => throwIfNotValid(value, isRegistrationReasonValid, 'registration reason'))
61 @Column(DataType.TEXT)
62 registrationReason: string
65 @Is('RegistrationModerationResponse', value => throwIfNotValid(value, isRegistrationModerationResponseValid, 'moderation response', true))
66 @Column(DataType.TEXT)
67 moderationResponse: string
70 @Is('RegistrationPassword', value => throwIfNotValid(value, isUserPasswordValid, 'registration password', true))
80 @Column(DataType.STRING(400))
84 @Is('RegistrationEmailVerified', value => throwIfNotValid(value, isUserEmailVerifiedValid, 'email verified boolean', true))
86 emailVerified: boolean
89 @Is('RegistrationAccountDisplayName', value => throwIfNotValid(value, isUserDisplayNameValid, 'account display name', true))
91 accountDisplayName: string
94 @Is('ChannelHandle', value => throwIfNotValid(value, isVideoChannelDisplayNameValid, 'channel handle', true))
99 @Is('ChannelDisplayName', value => throwIfNotValid(value, isVideoChannelDisplayNameValid, 'channel display name', true))
101 channelDisplayName: string
109 @ForeignKey(() => UserModel)
113 @BelongsTo(() => UserModel, {
122 static async cryptPasswordIfNeeded (instance: UserRegistrationModel) {
123 instance.password = await cryptPassword(instance.password)
126 static load (id: number): Promise<MRegistration> {
127 return UserRegistrationModel.findByPk(id)
130 static loadByEmail (email: string): Promise<MRegistration> {
135 return UserRegistrationModel.findOne(query)
138 static loadByEmailOrUsername (emailOrUsername: string): Promise<MRegistration> {
142 { email: emailOrUsername },
143 { username: emailOrUsername }
148 return UserRegistrationModel.findOne(query)
151 static loadByEmailOrHandle (options: {
154 channelHandle?: string
155 }): Promise<MRegistration> {
156 const { email, username, channelHandle } = options
158 let or: WhereOptions = [
160 { channelHandle: username },
166 { username: channelHandle },
177 return UserRegistrationModel.findOne(query)
180 // ---------------------------------------------------------------------------
182 static listForApi (options: {
188 const { start, count, sort, search } = options
190 const where: WhereOptions = {}
193 Object.assign(where, {
197 [Op.iLike]: '%' + search + '%'
202 [Op.iLike]: '%' + search + '%'
209 const query: FindOptions = {
212 order: getSort(sort),
216 model: UserModel.unscoped(),
223 UserRegistrationModel.count(query),
224 UserRegistrationModel.findAll<MRegistrationFormattable>(query)
225 ]).then(([ total, data ]) => ({ total, data }))
228 // ---------------------------------------------------------------------------
230 toFormattedJSON (this: MRegistrationFormattable): UserRegistration {
236 label: USER_REGISTRATION_STATES[this.state]
239 registrationReason: this.registrationReason,
240 moderationResponse: this.moderationResponse,
242 username: this.username,
244 emailVerified: this.emailVerified,
246 accountDisplayName: this.accountDisplayName,
248 channelHandle: this.channelHandle,
249 channelDisplayName: this.channelDisplayName,
251 createdAt: this.createdAt,
252 updatedAt: this.updatedAt,
255 ? { id: this.User.id }