123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- import { FindOptions, Op, WhereOptions } from 'sequelize'
- import {
- AllowNull,
- BeforeCreate,
- BelongsTo,
- Column,
- CreatedAt,
- DataType,
- ForeignKey,
- Is,
- IsEmail,
- Model,
- Table,
- UpdatedAt
- } from 'sequelize-typescript'
- import {
- isRegistrationModerationResponseValid,
- isRegistrationReasonValid,
- isRegistrationStateValid
- } from '@server/helpers/custom-validators/user-registration'
- import { isVideoChannelDisplayNameValid } from '@server/helpers/custom-validators/video-channels'
- import { cryptPassword } from '@server/helpers/peertube-crypto'
- import { USER_REGISTRATION_STATES } from '@server/initializers/constants'
- import { MRegistration, MRegistrationFormattable } from '@server/types/models'
- import { UserRegistration, UserRegistrationState } from '@shared/models'
- import { AttributesOnly } from '@shared/typescript-utils'
- import { isUserDisplayNameValid, isUserEmailVerifiedValid, isUserPasswordValid } from '../../helpers/custom-validators/users'
- import { getSort, throwIfNotValid } from '../shared'
- import { UserModel } from './user'
- @Table({
- tableName: 'userRegistration',
- indexes: [
- {
- fields: [ 'username' ],
- unique: true
- },
- {
- fields: [ 'email' ],
- unique: true
- },
- {
- fields: [ 'channelHandle' ],
- unique: true
- },
- {
- fields: [ 'userId' ],
- unique: true
- }
- ]
- })
- export class UserRegistrationModel extends Model<Partial<AttributesOnly<UserRegistrationModel>>> {
- @AllowNull(false)
- @Is('RegistrationState', value => throwIfNotValid(value, isRegistrationStateValid, 'state'))
- @Column
- state: UserRegistrationState
- @AllowNull(false)
- @Is('RegistrationReason', value => throwIfNotValid(value, isRegistrationReasonValid, 'registration reason'))
- @Column(DataType.TEXT)
- registrationReason: string
- @AllowNull(true)
- @Is('RegistrationModerationResponse', value => throwIfNotValid(value, isRegistrationModerationResponseValid, 'moderation response', true))
- @Column(DataType.TEXT)
- moderationResponse: string
- @AllowNull(true)
- @Is('RegistrationPassword', value => throwIfNotValid(value, isUserPasswordValid, 'registration password', true))
- @Column
- password: string
- @AllowNull(false)
- @Column
- username: string
- @AllowNull(false)
- @IsEmail
- @Column(DataType.STRING(400))
- email: string
- @AllowNull(true)
- @Is('RegistrationEmailVerified', value => throwIfNotValid(value, isUserEmailVerifiedValid, 'email verified boolean', true))
- @Column
- emailVerified: boolean
- @AllowNull(true)
- @Is('RegistrationAccountDisplayName', value => throwIfNotValid(value, isUserDisplayNameValid, 'account display name', true))
- @Column
- accountDisplayName: string
- @AllowNull(true)
- @Is('ChannelHandle', value => throwIfNotValid(value, isVideoChannelDisplayNameValid, 'channel handle', true))
- @Column
- channelHandle: string
- @AllowNull(true)
- @Is('ChannelDisplayName', value => throwIfNotValid(value, isVideoChannelDisplayNameValid, 'channel display name', true))
- @Column
- channelDisplayName: string
- @CreatedAt
- createdAt: Date
- @UpdatedAt
- updatedAt: Date
- @ForeignKey(() => UserModel)
- @Column
- userId: number
- @BelongsTo(() => UserModel, {
- foreignKey: {
- allowNull: true
- },
- onDelete: 'SET NULL'
- })
- User: UserModel
- @BeforeCreate
- static async cryptPasswordIfNeeded (instance: UserRegistrationModel) {
- instance.password = await cryptPassword(instance.password)
- }
- static load (id: number): Promise<MRegistration> {
- return UserRegistrationModel.findByPk(id)
- }
- static loadByEmail (email: string): Promise<MRegistration> {
- const query = {
- where: { email }
- }
- return UserRegistrationModel.findOne(query)
- }
- static loadByEmailOrUsername (emailOrUsername: string): Promise<MRegistration> {
- const query = {
- where: {
- [Op.or]: [
- { email: emailOrUsername },
- { username: emailOrUsername }
- ]
- }
- }
- return UserRegistrationModel.findOne(query)
- }
- static loadByEmailOrHandle (options: {
- email: string
- username: string
- channelHandle?: string
- }): Promise<MRegistration> {
- const { email, username, channelHandle } = options
- let or: WhereOptions = [
- { email },
- { channelHandle: username },
- { username }
- ]
- if (channelHandle) {
- or = or.concat([
- { username: channelHandle },
- { channelHandle }
- ])
- }
- const query = {
- where: {
- [Op.or]: or
- }
- }
- return UserRegistrationModel.findOne(query)
- }
- // ---------------------------------------------------------------------------
- static listForApi (options: {
- start: number
- count: number
- sort: string
- search?: string
- }) {
- const { start, count, sort, search } = options
- const where: WhereOptions = {}
- if (search) {
- Object.assign(where, {
- [Op.or]: [
- {
- email: {
- [Op.iLike]: '%' + search + '%'
- }
- },
- {
- username: {
- [Op.iLike]: '%' + search + '%'
- }
- }
- ]
- })
- }
- const query: FindOptions = {
- offset: start,
- limit: count,
- order: getSort(sort),
- where,
- include: [
- {
- model: UserModel.unscoped(),
- required: false
- }
- ]
- }
- return Promise.all([
- UserRegistrationModel.count(query),
- UserRegistrationModel.findAll<MRegistrationFormattable>(query)
- ]).then(([ total, data ]) => ({ total, data }))
- }
- // ---------------------------------------------------------------------------
- toFormattedJSON (this: MRegistrationFormattable): UserRegistration {
- return {
- id: this.id,
- state: {
- id: this.state,
- label: USER_REGISTRATION_STATES[this.state]
- },
- registrationReason: this.registrationReason,
- moderationResponse: this.moderationResponse,
- username: this.username,
- email: this.email,
- emailVerified: this.emailVerified,
- accountDisplayName: this.accountDisplayName,
- channelHandle: this.channelHandle,
- channelDisplayName: this.channelDisplayName,
- createdAt: this.createdAt,
- updatedAt: this.updatedAt,
- user: this.User
- ? { id: this.User.id }
- : null
- }
- }
- }
|