From 3fd3ab2d34d512b160a5e6084d7609be7b4f4452 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 12 Dec 2017 17:53:50 +0100 Subject: Move models to typescript-sequelize --- server/models/video/video-channel.ts | 572 +++++++++++++++++------------------ 1 file changed, 271 insertions(+), 301 deletions(-) (limited to 'server/models/video/video-channel.ts') diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 54f12dce3..9b545a4ef 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -1,371 +1,341 @@ import * as Sequelize from 'sequelize' -import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../../helpers' -import { CONSTRAINTS_FIELDS } from '../../initializers/constants' -import { sendDeleteVideoChannel } from '../../lib/activitypub/send/send-delete' - -import { addMethodsToModel, getSort } from '../utils' -import { VideoChannelAttributes, VideoChannelInstance, VideoChannelMethods } from './video-channel-interface' -import { getAnnounceActivityPubUrl } from '../../lib/activitypub/url' -import { activityPubCollection } from '../../helpers/activitypub' -import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' - -let VideoChannel: Sequelize.Model -let toFormattedJSON: VideoChannelMethods.ToFormattedJSON -let toActivityPubObject: VideoChannelMethods.ToActivityPubObject -let isOwned: VideoChannelMethods.IsOwned -let countByAccount: VideoChannelMethods.CountByAccount -let listForApi: VideoChannelMethods.ListForApi -let listByAccount: VideoChannelMethods.ListByAccount -let loadByIdAndAccount: VideoChannelMethods.LoadByIdAndAccount -let loadByUUID: VideoChannelMethods.LoadByUUID -let loadAndPopulateAccount: VideoChannelMethods.LoadAndPopulateAccount -let loadByUUIDAndPopulateAccount: VideoChannelMethods.LoadByUUIDAndPopulateAccount -let loadByHostAndUUID: VideoChannelMethods.LoadByHostAndUUID -let loadAndPopulateAccountAndVideos: VideoChannelMethods.LoadAndPopulateAccountAndVideos -let loadByUrl: VideoChannelMethods.LoadByUrl -let loadByUUIDOrUrl: VideoChannelMethods.LoadByUUIDOrUrl - -export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { - VideoChannel = sequelize.define('VideoChannel', +import { + AfterDestroy, + AllowNull, + BelongsTo, + Column, + CreatedAt, + DataType, + Default, + ForeignKey, + HasMany, + Is, + IsUUID, + Model, + Table, + UpdatedAt +} from 'sequelize-typescript' +import { IFindOptions } from 'sequelize-typescript/lib/interfaces/IFindOptions' +import { activityPubCollection } from '../../helpers' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub' +import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels' +import { CONSTRAINTS_FIELDS } from '../../initializers' +import { getAnnounceActivityPubUrl } from '../../lib/activitypub' +import { sendDeleteVideoChannel } from '../../lib/activitypub/send' +import { AccountModel } from '../account/account' +import { ServerModel } from '../server/server' +import { getSort, throwIfNotValid } from '../utils' +import { VideoModel } from './video' +import { VideoChannelShareModel } from './video-channel-share' + +@Table({ + tableName: 'videoChannel', + indexes: [ { - uuid: { - type: DataTypes.UUID, - defaultValue: DataTypes.UUIDV4, - allowNull: false, - validate: { - isUUID: 4 - } - }, - name: { - type: DataTypes.STRING, - allowNull: false, - validate: { - nameValid: value => { - const res = isVideoChannelNameValid(value) - if (res === false) throw new Error('Video channel name is not valid.') - } - } - }, - description: { - type: DataTypes.STRING, - allowNull: true, - validate: { - descriptionValid: value => { - const res = isVideoChannelDescriptionValid(value) - if (res === false) throw new Error('Video channel description is not valid.') - } - } - }, - remote: { - type: DataTypes.BOOLEAN, - allowNull: false, - defaultValue: false - }, - url: { - type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNELS.URL.max), - allowNull: false, - validate: { - urlValid: value => { - const res = isActivityPubUrlValid(value) - if (res === false) throw new Error('Video channel URL is not valid.') - } - } - } - }, - { - indexes: [ - { - fields: [ 'accountId' ] - } - ], - hooks: { - afterDestroy - } + fields: [ 'accountId' ] } - ) - - const classMethods = [ - associate, - - listForApi, - listByAccount, - loadByIdAndAccount, - loadAndPopulateAccount, - loadByUUIDAndPopulateAccount, - loadByUUID, - loadByHostAndUUID, - loadAndPopulateAccountAndVideos, - countByAccount, - loadByUrl, - loadByUUIDOrUrl ] - const instanceMethods = [ - isOwned, - toFormattedJSON, - toActivityPubObject - ] - addMethodsToModel(VideoChannel, classMethods, instanceMethods) +}) +export class VideoChannelModel extends Model { - return VideoChannel -} + @AllowNull(false) + @Default(DataType.UUIDV4) + @IsUUID(4) + @Column(DataType.UUID) + uuid: string -// ------------------------------ METHODS ------------------------------ + @AllowNull(false) + @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name')) + @Column + name: string -isOwned = function (this: VideoChannelInstance) { - return this.remote === false -} - -toFormattedJSON = function (this: VideoChannelInstance) { - const json = { - id: this.id, - uuid: this.uuid, - name: this.name, - description: this.description, - isLocal: this.isOwned(), - createdAt: this.createdAt, - updatedAt: this.updatedAt - } + @AllowNull(true) + @Is('VideoChannelDescription', value => throwIfNotValid(value, isVideoChannelDescriptionValid, 'description')) + @Column + description: string - if (this.Account !== undefined) { - json['owner'] = { - name: this.Account.name, - uuid: this.Account.uuid - } - } + @AllowNull(false) + @Column + remote: boolean - if (Array.isArray(this.Videos)) { - json['videos'] = this.Videos.map(v => v.toFormattedJSON()) - } + @AllowNull(false) + @Is('VideoChannelUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) + @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_CHANNELS.URL.max)) + url: string - return json -} + @CreatedAt + createdAt: Date -toActivityPubObject = function (this: VideoChannelInstance) { - let sharesObject - if (Array.isArray(this.VideoChannelShares)) { - const shares: string[] = [] + @UpdatedAt + updatedAt: Date - for (const videoChannelShare of this.VideoChannelShares) { - const shareUrl = getAnnounceActivityPubUrl(this.url, videoChannelShare.Account) - shares.push(shareUrl) - } + @ForeignKey(() => AccountModel) + @Column + accountId: number - sharesObject = activityPubCollection(shares) - } - - const json = { - type: 'VideoChannel' as 'VideoChannel', - id: this.url, - uuid: this.uuid, - content: this.description, - name: this.name, - published: this.createdAt.toISOString(), - updated: this.updatedAt.toISOString(), - shares: sharesObject - } - - return json -} - -// ------------------------------ STATICS ------------------------------ + @BelongsTo(() => AccountModel, { + foreignKey: { + allowNull: false + }, + onDelete: 'CASCADE' + }) + Account: AccountModel -function associate (models) { - VideoChannel.belongsTo(models.Account, { + @HasMany(() => VideoModel, { foreignKey: { - name: 'accountId', + name: 'channelId', allowNull: false }, onDelete: 'CASCADE' }) + Videos: VideoModel[] - VideoChannel.hasMany(models.Video, { + @HasMany(() => VideoChannelShareModel, { foreignKey: { name: 'channelId', allowNull: false }, onDelete: 'CASCADE' }) -} + VideoChannelShares: VideoChannelShareModel[] -function afterDestroy (videoChannel: VideoChannelInstance) { - if (videoChannel.isOwned()) { - return sendDeleteVideoChannel(videoChannel, undefined) - } + @AfterDestroy + static sendDeleteIfOwned (instance: VideoChannelModel) { + if (instance.isOwned()) { + return sendDeleteVideoChannel(instance, undefined) + } - return undefined -} + return undefined + } -countByAccount = function (accountId: number) { - const query = { - where: { - accountId + static countByAccount (accountId: number) { + const query = { + where: { + accountId + } } + + return VideoChannelModel.count(query) } - return VideoChannel.count(query) -} + static listForApi (start: number, count: number, sort: string) { + const query = { + offset: start, + limit: count, + order: [ getSort(sort) ], + include: [ + { + model: AccountModel, + required: true, + include: [ { model: ServerModel, required: false } ] + } + ] + } -listForApi = function (start: number, count: number, sort: string) { - const query = { - offset: start, - limit: count, - order: [ getSort(sort) ], - include: [ - { - model: VideoChannel['sequelize'].models.Account, - required: true, - include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ] - } - ] + return VideoChannelModel.findAndCountAll(query) + .then(({ rows, count }) => { + return { total: count, data: rows } + }) } - return VideoChannel.findAndCountAll(query).then(({ rows, count }) => { - return { total: count, data: rows } - }) -} + static listByAccount (accountId: number) { + const query = { + order: [ getSort('createdAt') ], + include: [ + { + model: AccountModel, + where: { + id: accountId + }, + required: true, + include: [ { model: ServerModel, required: false } ] + } + ] + } -listByAccount = function (accountId: number) { - const query = { - order: [ getSort('createdAt') ], - include: [ - { - model: VideoChannel['sequelize'].models.Account, - where: { - id: accountId - }, - required: true, - include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ] - } - ] + return VideoChannelModel.findAndCountAll(query) + .then(({ rows, count }) => { + return { total: count, data: rows } + }) } - return VideoChannel.findAndCountAll(query).then(({ rows, count }) => { - return { total: count, data: rows } - }) -} + static loadByUUID (uuid: string, t?: Sequelize.Transaction) { + const query: IFindOptions = { + where: { + uuid + } + } + + if (t !== undefined) query.transaction = t -loadByUUID = function (uuid: string, t?: Sequelize.Transaction) { - const query: Sequelize.FindOptions = { - where: { - uuid + return VideoChannelModel.findOne(query) + } + + static loadByUrl (url: string, t?: Sequelize.Transaction) { + const query: IFindOptions = { + where: { + url + }, + include: [ AccountModel ] } + + if (t !== undefined) query.transaction = t + + return VideoChannelModel.findOne(query) } - if (t !== undefined) query.transaction = t + static loadByUUIDOrUrl (uuid: string, url: string, t?: Sequelize.Transaction) { + const query: IFindOptions = { + where: { + [ Sequelize.Op.or ]: [ + { uuid }, + { url } + ] + } + } - return VideoChannel.findOne(query) -} + if (t !== undefined) query.transaction = t -loadByUrl = function (url: string, t?: Sequelize.Transaction) { - const query: Sequelize.FindOptions = { - where: { - url - }, - include: [ VideoChannel['sequelize'].models.Account ] + return VideoChannelModel.findOne(query) } - if (t !== undefined) query.transaction = t + static loadByHostAndUUID (fromHost: string, uuid: string, t?: Sequelize.Transaction) { + const query: IFindOptions = { + where: { + uuid + }, + include: [ + { + model: AccountModel, + include: [ + { + model: ServerModel, + required: true, + where: { + host: fromHost + } + } + ] + } + ] + } - return VideoChannel.findOne(query) -} + if (t !== undefined) query.transaction = t + + return VideoChannelModel.findOne(query) + } -loadByUUIDOrUrl = function (uuid: string, url: string, t?: Sequelize.Transaction) { - const query: Sequelize.FindOptions = { - where: { - [Sequelize.Op.or]: [ - { uuid }, - { url } + static loadByIdAndAccount (id: number, accountId: number) { + const options = { + where: { + id, + accountId + }, + include: [ + { + model: AccountModel, + include: [ { model: ServerModel, required: false } ] + } ] } + + return VideoChannelModel.findOne(options) } - if (t !== undefined) query.transaction = t + static loadAndPopulateAccount (id: number) { + const options = { + include: [ + { + model: AccountModel, + include: [ { model: ServerModel, required: false } ] + } + ] + } - return VideoChannel.findOne(query) -} + return VideoChannelModel.findById(id, options) + } -loadByHostAndUUID = function (fromHost: string, uuid: string, t?: Sequelize.Transaction) { - const query: Sequelize.FindOptions = { - where: { - uuid - }, - include: [ - { - model: VideoChannel['sequelize'].models.Account, - include: [ - { - model: VideoChannel['sequelize'].models.Server, - required: true, - where: { - host: fromHost - } - } - ] - } - ] + static loadByUUIDAndPopulateAccount (uuid: string) { + const options = { + where: { + uuid + }, + include: [ + { + model: AccountModel, + include: [ { model: ServerModel, required: false } ] + } + ] + } + + return VideoChannelModel.findOne(options) } - if (t !== undefined) query.transaction = t + static loadAndPopulateAccountAndVideos (id: number) { + const options = { + include: [ + { + model: AccountModel, + include: [ { model: ServerModel, required: false } ] + }, + VideoModel + ] + } - return VideoChannel.findOne(query) -} + return VideoChannelModel.findById(id, options) + } -loadByIdAndAccount = function (id: number, accountId: number) { - const options = { - where: { - id, - accountId - }, - include: [ - { - model: VideoChannel['sequelize'].models.Account, - include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ] - } - ] + isOwned () { + return this.remote === false } - return VideoChannel.findOne(options) -} + toFormattedJSON () { + const json = { + id: this.id, + uuid: this.uuid, + name: this.name, + description: this.description, + isLocal: this.isOwned(), + createdAt: this.createdAt, + updatedAt: this.updatedAt + } -loadAndPopulateAccount = function (id: number) { - const options = { - include: [ - { - model: VideoChannel['sequelize'].models.Account, - include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ] + if (this.Account !== undefined) { + json[ 'owner' ] = { + name: this.Account.name, + uuid: this.Account.uuid } - ] + } + + if (Array.isArray(this.Videos)) { + json[ 'videos' ] = this.Videos.map(v => v.toFormattedJSON()) + } + + return json } - return VideoChannel.findById(id, options) -} + toActivityPubObject () { + let sharesObject + if (Array.isArray(this.VideoChannelShares)) { + const shares: string[] = [] -loadByUUIDAndPopulateAccount = function (uuid: string) { - const options = { - where: { - uuid - }, - include: [ - { - model: VideoChannel['sequelize'].models.Account, - include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ] + for (const videoChannelShare of this.VideoChannelShares) { + const shareUrl = getAnnounceActivityPubUrl(this.url, videoChannelShare.Account) + shares.push(shareUrl) } - ] - } - return VideoChannel.findOne(options) -} + sharesObject = activityPubCollection(shares) + } -loadAndPopulateAccountAndVideos = function (id: number) { - const options = { - include: [ - { - model: VideoChannel['sequelize'].models.Account, - include: [ { model: VideoChannel['sequelize'].models.Server, required: false } ] - }, - VideoChannel['sequelize'].models.Video - ] + return { + type: 'VideoChannel' as 'VideoChannel', + id: this.url, + uuid: this.uuid, + content: this.description, + name: this.name, + published: this.createdAt.toISOString(), + updated: this.updatedAt.toISOString(), + shares: sharesObject + } } - - return VideoChannel.findById(id, options) } -- cgit v1.2.3