From d48ff09d27d234425c3e9f091ae9072d8e6d8b7a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 14 Dec 2017 10:07:57 +0100 Subject: Use sequelize scopes --- server/models/video/video-channel-share.ts | 43 +++-- server/models/video/video-channel.ts | 113 ++++---------- server/models/video/video-share.ts | 36 ++++- server/models/video/video.ts | 243 +++++++++++++---------------- 4 files changed, 203 insertions(+), 232 deletions(-) (limited to 'server/models/video') diff --git a/server/models/video/video-channel-share.ts b/server/models/video/video-channel-share.ts index cdba32fcd..f5b7a7cd5 100644 --- a/server/models/video/video-channel-share.ts +++ b/server/models/video/video-channel-share.ts @@ -1,8 +1,35 @@ import * as Sequelize from 'sequelize' -import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' +import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { AccountModel } from '../account/account' import { VideoChannelModel } from './video-channel' +enum ScopeNames { + FULL = 'FULL', + WITH_ACCOUNT = 'WITH_ACCOUNT' +} + +@Scopes({ + [ScopeNames.FULL]: { + include: [ + { + model: () => AccountModel, + required: true + }, + { + model: () => VideoChannelModel, + required: true + } + ] + }, + [ScopeNames.WITH_ACCOUNT]: { + include: [ + { + model: () => AccountModel, + required: true + } + ] + } +}) @Table({ tableName: 'videoChannelShare', indexes: [ @@ -46,15 +73,11 @@ export class VideoChannelShareModel extends Model { VideoChannel: VideoChannelModel static load (accountId: number, videoChannelId: number, t: Sequelize.Transaction) { - return VideoChannelShareModel.findOne({ + return VideoChannelShareModel.scope(ScopeNames.FULL).findOne({ where: { accountId, videoChannelId }, - include: [ - AccountModel, - VideoChannelModel - ], transaction: t }) } @@ -64,16 +87,10 @@ export class VideoChannelShareModel extends Model { where: { videoChannelId }, - include: [ - { - model: AccountModel, - required: true - } - ], transaction: t } - return VideoChannelShareModel.findAll(query) + return VideoChannelShareModel.scope(ScopeNames.WITH_ACCOUNT).findAll(query) .then(res => res.map(r => r.Account)) } } diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 9b545a4ef..068c8029d 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -11,7 +11,7 @@ import { HasMany, Is, IsUUID, - Model, + Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' @@ -28,6 +28,26 @@ import { getSort, throwIfNotValid } from '../utils' import { VideoModel } from './video' import { VideoChannelShareModel } from './video-channel-share' +enum ScopeNames { + WITH_ACCOUNT = 'WITH_ACCOUNT', + WITH_VIDEOS = 'WITH_VIDEOS' +} + +@Scopes({ + [ScopeNames.WITH_ACCOUNT]: { + include: [ + { + model: () => AccountModel, + include: [ { model: () => ServerModel, required: false } ] + } + ] + }, + [ScopeNames.WITH_VIDEOS]: { + include: [ + () => VideoModel + ] + } +}) @Table({ tableName: 'videoChannel', indexes: [ @@ -122,17 +142,10 @@ export class VideoChannelModel extends Model { const query = { offset: start, limit: count, - order: [ getSort(sort) ], - include: [ - { - model: AccountModel, - required: true, - include: [ { model: ServerModel, required: false } ] - } - ] + order: [ getSort(sort) ] } - return VideoChannelModel.findAndCountAll(query) + return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findAndCountAll(query) .then(({ rows, count }) => { return { total: count, data: rows } }) @@ -159,29 +172,16 @@ export class VideoChannelModel extends Model { }) } - static loadByUUID (uuid: string, t?: Sequelize.Transaction) { - const query: IFindOptions = { - where: { - uuid - } - } - - if (t !== undefined) query.transaction = t - - 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) + return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findOne(query) } static loadByUUIDOrUrl (uuid: string, url: string, t?: Sequelize.Transaction) { @@ -199,90 +199,39 @@ export class VideoChannelModel extends Model { return VideoChannelModel.findOne(query) } - 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 - } - } - ] - } - ] - } - - if (t !== undefined) query.transaction = t - - return VideoChannelModel.findOne(query) - } - static loadByIdAndAccount (id: number, accountId: number) { const options = { where: { id, accountId - }, - include: [ - { - model: AccountModel, - include: [ { model: ServerModel, required: false } ] - } - ] + } } - return VideoChannelModel.findOne(options) + return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findOne(options) } static loadAndPopulateAccount (id: number) { - const options = { - include: [ - { - model: AccountModel, - include: [ { model: ServerModel, required: false } ] - } - ] - } - - return VideoChannelModel.findById(id, options) + return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findById(id) } static loadByUUIDAndPopulateAccount (uuid: string) { const options = { where: { uuid - }, - include: [ - { - model: AccountModel, - include: [ { model: ServerModel, required: false } ] - } - ] + } } - return VideoChannelModel.findOne(options) + return VideoChannelModel.scope(ScopeNames.WITH_ACCOUNT).findOne(options) } static loadAndPopulateAccountAndVideos (id: number) { const options = { include: [ - { - model: AccountModel, - include: [ { model: ServerModel, required: false } ] - }, VideoModel ] } - return VideoChannelModel.findById(id, options) + return VideoChannelModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEOS ]).findById(id, options) } isOwned () { diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts index 01b6d3d34..e1733b3a7 100644 --- a/server/models/video/video-share.ts +++ b/server/models/video/video-share.ts @@ -1,8 +1,35 @@ import * as Sequelize from 'sequelize' -import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' +import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { AccountModel } from '../account/account' import { VideoModel } from './video' +enum ScopeNames { + FULL = 'FULL', + WITH_ACCOUNT = 'WITH_ACCOUNT' +} + +@Scopes({ + [ScopeNames.FULL]: { + include: [ + { + model: () => AccountModel, + required: true + }, + { + model: () => VideoModel, + required: true + } + ] + }, + [ScopeNames.WITH_ACCOUNT]: { + include: [ + { + model: () => AccountModel, + required: true + } + ] + } +}) @Table({ tableName: 'videoShare', indexes: [ @@ -46,14 +73,11 @@ export class VideoShareModel extends Model { Video: VideoModel static load (accountId: number, videoId: number, t: Sequelize.Transaction) { - return VideoShareModel.findOne({ + return VideoShareModel.scope(ScopeNames.WITH_ACCOUNT).findOne({ where: { accountId, videoId }, - include: [ - AccountModel - ], transaction: t }) } @@ -72,7 +96,7 @@ export class VideoShareModel extends Model { transaction: t } - return VideoShareModel.findAll(query) + return VideoShareModel.scope(ScopeNames.FULL).findAll(query) .then(res => res.map(r => r.Account)) } } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 9e26f9bbe..1f940a50d 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -21,12 +21,14 @@ import { IsUUID, Min, Model, + Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { IIncludeOptions } from 'sequelize-typescript/lib/interfaces/IIncludeOptions' import { VideoPrivacy, VideoResolution } from '../../../shared' import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' +import { Video, VideoDetails } from '../../../shared/models/videos' import { activityPubCollection, createTorrentPromise, @@ -76,6 +78,79 @@ import { VideoFileModel } from './video-file' import { VideoShareModel } from './video-share' import { VideoTagModel } from './video-tag' +enum ScopeNames { + NOT_IN_BLACKLIST = 'NOT_IN_BLACKLIST', + PUBLIC = 'PUBLIC', + WITH_ACCOUNT = 'WITH_ACCOUNT', + WITH_TAGS = 'WITH_TAGS', + WITH_FILES = 'WITH_FILES', + WITH_SHARES = 'WITH_SHARES', + WITH_RATES = 'WITH_RATES' +} + +@Scopes({ + [ScopeNames.NOT_IN_BLACKLIST]: { + where: { + id: { + [Sequelize.Op.notIn]: Sequelize.literal( + '(SELECT "videoBlacklist"."videoId" FROM "videoBlacklist")' + ) + } + } + }, + [ScopeNames.PUBLIC]: { + where: { + privacy: VideoPrivacy.PUBLIC + } + }, + [ScopeNames.WITH_ACCOUNT]: { + include: [ + { + model: () => VideoChannelModel, + required: true, + include: [ + { + model: () => AccountModel, + required: true, + include: [ + { + model: () => ServerModel, + required: false + } + ] + } + ] + } + ] + }, + [ScopeNames.WITH_TAGS]: { + include: [ () => TagModel ] + }, + [ScopeNames.WITH_FILES]: { + include: [ + { + model: () => VideoFileModel, + required: true + } + ] + }, + [ScopeNames.WITH_SHARES]: { + include: [ + { + model: () => VideoShareModel, + include: [ () => AccountModel ] + } + ] + }, + [ScopeNames.WITH_RATES]: { + include: [ + { + model: () => AccountVideoRateModel, + include: [ () => AccountModel ] + } + ] + } +}) @Table({ tableName: 'video', indexes: [ @@ -273,11 +348,7 @@ export class VideoModel extends Model { } static list () { - const query = { - include: [ VideoFileModel ] - } - - return VideoModel.findAll(query) + return VideoModel.scope(ScopeNames.WITH_FILES).findAll() } static listAllAndSharedByAccountForOutbox (accountId: number, start: number, count: number) { @@ -363,10 +434,9 @@ export class VideoModel extends Model { static listUserVideosForApi (userId: number, start: number, count: number, sort: string) { const query = { - distinct: true, offset: start, limit: count, - order: [ getSort(sort), [ 'Tags', 'name', 'ASC' ] ], + order: [ getSort(sort) ], include: [ { model: VideoChannelModel, @@ -380,8 +450,7 @@ export class VideoModel extends Model { required: true } ] - }, - TagModel + } ] } @@ -395,74 +464,35 @@ export class VideoModel extends Model { static listForApi (start: number, count: number, sort: string) { const query = { - distinct: true, offset: start, limit: count, - order: [ getSort(sort), [ 'Tags', 'name', 'ASC' ] ], - include: [ - { - model: VideoChannelModel, - required: true, - include: [ - { - model: AccountModel, - required: true, - include: [ - { - model: ServerModel, - required: false - } - ] - } - ] - }, - TagModel - ], - where: this.createBaseVideosWhere() + order: [ getSort(sort) ] } - return VideoModel.findAndCountAll(query).then(({ rows, count }) => { - return { - data: rows, - total: count - } - }) + return VideoModel.scope([ ScopeNames.NOT_IN_BLACKLIST, ScopeNames.PUBLIC, ScopeNames.WITH_ACCOUNT ]) + .findAndCountAll(query) + .then(({ rows, count }) => { + return { + data: rows, + total: count + } + }) } static load (id: number) { return VideoModel.findById(id) } - static loadByUUID (uuid: string, t?: Sequelize.Transaction) { - const query: IFindOptions = { - where: { - uuid - }, - include: [ VideoFileModel ] - } - - if (t !== undefined) query.transaction = t - - return VideoModel.findOne(query) - } - static loadByUrlAndPopulateAccount (url: string, t?: Sequelize.Transaction) { const query: IFindOptions = { where: { url - }, - include: [ - VideoFileModel, - { - model: VideoChannelModel, - include: [ AccountModel ] - } - ] + } } if (t !== undefined) query.transaction = t - return VideoModel.findOne(query) + return VideoModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_FILES ]).findOne(query) } static loadByUUIDOrURL (uuid: string, url: string, t?: Sequelize.Transaction) { @@ -472,42 +502,22 @@ export class VideoModel extends Model { { uuid }, { url } ] - }, - include: [ VideoFileModel ] + } } if (t !== undefined) query.transaction = t - return VideoModel.findOne(query) + return VideoModel.scope(ScopeNames.WITH_FILES).findOne(query) } static loadAndPopulateAccountAndServerAndTags (id: number) { const options = { - order: [ [ 'Tags', 'name', 'ASC' ] ], - include: [ - { - model: VideoChannelModel, - include: [ - { - model: AccountModel, - include: [ { model: ServerModel, required: false } ] - } - ] - }, - { - model: AccountVideoRateModel, - include: [ AccountModel ] - }, - { - model: VideoShareModel, - include: [ AccountModel ] - }, - TagModel, - VideoFileModel - ] + order: [ [ 'Tags', 'name', 'ASC' ] ] } - return VideoModel.findById(id, options) + return VideoModel + .scope([ ScopeNames.WITH_RATES, ScopeNames.WITH_SHARES, ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT ]) + .findById(id, options) } static loadByUUIDAndPopulateAccountAndServerAndTags (uuid: string) { @@ -515,31 +525,12 @@ export class VideoModel extends Model { order: [ [ 'Tags', 'name', 'ASC' ] ], where: { uuid - }, - include: [ - { - model: VideoChannelModel, - include: [ - { - model: AccountModel, - include: [ { model: ServerModel, required: false } ] - } - ] - }, - { - model: AccountVideoRateModel, - include: [ AccountModel ] - }, - { - model: VideoShareModel, - include: [ AccountModel ] - }, - TagModel, - VideoFileModel - ] + } } - return VideoModel.findOne(options) + return VideoModel + .scope([ ScopeNames.WITH_RATES, ScopeNames.WITH_SHARES, ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT ]) + .findOne(options) } static searchAndPopulateAccountAndServerAndTags (value: string, start: number, count: number, sort: string) { @@ -564,11 +555,11 @@ export class VideoModel extends Model { } const query: IFindOptions = { - distinct: true, - where: this.createBaseVideosWhere(), + distinct: true, // Because we have tags offset: start, limit: count, - order: [ getSort(sort), [ 'Tags', 'name', 'ASC' ] ] + order: [ getSort(sort) ], + where: {} } // TODO: search on tags too @@ -595,23 +586,13 @@ export class VideoModel extends Model { videoChannelInclude, tagInclude ] - return VideoModel.findAndCountAll(query).then(({ rows, count }) => { - return { - data: rows, - total: count - } - }) - } - - private static createBaseVideosWhere () { - return { - id: { - [Sequelize.Op.notIn]: VideoModel.sequelize.literal( - '(SELECT "videoBlacklist"."videoId" FROM "videoBlacklist")' - ) - }, - privacy: VideoPrivacy.PUBLIC - } + return VideoModel.scope([ ScopeNames.NOT_IN_BLACKLIST, ScopeNames.PUBLIC ]) + .findAndCountAll(query).then(({ rows, count }) => { + return { + data: rows, + total: count + } + }) } getOriginalFile () { @@ -733,13 +714,12 @@ export class VideoModel extends Model { views: this.views, likes: this.likes, dislikes: this.dislikes, - tags: map(this.Tags, 'name'), thumbnailPath: this.getThumbnailPath(), previewPath: this.getPreviewPath(), embedPath: this.getEmbedPath(), createdAt: this.createdAt, updatedAt: this.updatedAt - } + } as Video } toFormattedDetailsJSON () { @@ -755,6 +735,7 @@ export class VideoModel extends Model { descriptionPath: this.getDescriptionPath(), channel: this.VideoChannel.toFormattedJSON(), account: this.VideoChannel.Account.toFormattedJSON(), + tags: map(this.Tags, 'name'), files: [] } @@ -779,7 +760,7 @@ export class VideoModel extends Model { return -1 }) - return Object.assign(formattedJson, detailsJson) + return Object.assign(formattedJson, detailsJson) as VideoDetails } toActivityPubObject (): VideoTorrentObject { -- cgit v1.2.3