From d48ff09d27d234425c3e9f091ae9072d8e6d8b7a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 14 Dec 2017 10:07:57 +0100 Subject: [PATCH] Use sequelize scopes --- .../app/shared/video/video-details.model.ts | 1 + client/src/app/shared/video/video.model.ts | 2 - .../middlewares/validators/video-channels.ts | 2 +- server/models/account/user.ts | 50 ++-- server/models/application/application.ts | 18 -- server/models/oauth/oauth-token.ts | 59 +++-- server/models/video/video-channel-share.ts | 43 +++- server/models/video/video-channel.ts | 115 +++------ server/models/video/video-share.ts | 36 ++- server/models/video/video.ts | 243 ++++++++---------- server/tests/api/single-server.ts | 3 - server/tests/api/video-abuse.ts | 2 +- shared/models/videos/video.model.ts | 2 +- 13 files changed, 264 insertions(+), 312 deletions(-) diff --git a/client/src/app/shared/video/video-details.model.ts b/client/src/app/shared/video/video-details.model.ts index b96f8f6c8..d51bc01a7 100644 --- a/client/src/app/shared/video/video-details.model.ts +++ b/client/src/app/shared/video/video-details.model.ts @@ -58,6 +58,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel { this.files = hash.files this.channel = hash.channel this.account = hash.account + this.tags = hash.tags this.likesPercent = (this.likes / (this.likes + this.dislikes)) * 100 this.dislikesPercent = (this.dislikes / (this.likes + this.dislikes)) * 100 diff --git a/client/src/app/shared/video/video.model.ts b/client/src/app/shared/video/video.model.ts index 32c33829d..c3759cb65 100644 --- a/client/src/app/shared/video/video.model.ts +++ b/client/src/app/shared/video/video.model.ts @@ -22,7 +22,6 @@ export class Video implements VideoServerModel { isLocal: boolean name: string serverHost: string - tags: string[] thumbnailPath: string thumbnailUrl: string previewPath: string @@ -71,7 +70,6 @@ export class Video implements VideoServerModel { this.isLocal = hash.isLocal this.name = hash.name this.serverHost = hash.serverHost - this.tags = hash.tags this.thumbnailPath = hash.thumbnailPath this.thumbnailUrl = absoluteAPIUrl + hash.thumbnailPath this.previewPath = hash.previewPath diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts index 660390080..068fd210f 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/video-channels.ts @@ -78,7 +78,7 @@ const videoChannelsRemoveValidator = [ if (!await isVideoChannelExist(req.params.id, res)) return // Check if the user who did the request is able to delete the video - if (!checkUserCanDeleteVideoChannel(res.locals.user, res.locals.videoChannel, res)) return + if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return if (!await checkVideoChannelIsNotTheLastOne(res)) return return next() diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 84adad96e..26f04dcb5 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts @@ -5,12 +5,12 @@ import { BeforeUpdate, Column, CreatedAt, DataType, - Default, + Default, DefaultScope, HasMany, HasOne, Is, IsEmail, - Model, + Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { hasUserRight, USER_ROLE_LABELS, UserRight } from '../../../shared' @@ -27,6 +27,25 @@ import { getSort, throwIfNotValid } from '../utils' import { VideoChannelModel } from '../video/video-channel' import { AccountModel } from './account' +@DefaultScope({ + include: [ + { + model: () => AccountModel, + required: true + } + ] +}) +@Scopes({ + withVideoChannel: { + include: [ + { + model: () => AccountModel, + required: true, + include: [ () => VideoChannelModel ] + } + ] + } +}) @Table({ tableName: 'user', indexes: [ @@ -122,8 +141,7 @@ export class UserModel extends Model { const query = { offset: start, limit: count, - order: [ getSort(sort) ], - include: [ { model: AccountModel, required: true } ] + order: [ getSort(sort) ] } return UserModel.findAndCountAll(query) @@ -136,19 +154,14 @@ export class UserModel extends Model { } static loadById (id: number) { - const options = { - include: [ { model: AccountModel, required: true } ] - } - - return UserModel.findById(id, options) + return UserModel.findById(id) } static loadByUsername (username: string) { const query = { where: { username - }, - include: [ { model: AccountModel, required: true } ] + } } return UserModel.findOne(query) @@ -158,29 +171,20 @@ export class UserModel extends Model { const query = { where: { username - }, - include: [ - { - model: AccountModel, - required: true, - include: [ VideoChannelModel ] - } - ] + } } - return UserModel.findOne(query) + return UserModel.scope('withVideoChannel').findOne(query) } static loadByUsernameOrEmail (username: string, email: string) { const query = { - include: [ { model: AccountModel, required: true } ], where: { [ Sequelize.Op.or ]: [ { username }, { email } ] } } - // FIXME: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18387 - return (UserModel as any).findOne(query) + return UserModel.findOne(query) } private static getOriginalVideoFileTotalFromUser (user: UserModel) { diff --git a/server/models/application/application.ts b/server/models/application/application.ts index f3c0f1052..9fc07e850 100644 --- a/server/models/application/application.ts +++ b/server/models/application/application.ts @@ -1,4 +1,3 @@ -import { Transaction } from 'sequelize' import { AllowNull, Column, Default, IsInt, Model, Table } from 'sequelize-typescript' @Table({ @@ -15,21 +14,4 @@ export class ApplicationModel extends Model { static countTotal () { return ApplicationModel.count() } - - static loadMigrationVersion () { - const query = { - attributes: [ 'migrationVersion' ] - } - - return ApplicationModel.findOne(query).then(data => data ? data.migrationVersion : null) - } - - static updateMigrationVersion (newVersion: number, transaction: Transaction) { - const options = { - where: {}, - transaction: transaction - } - - return ApplicationModel.update({ migrationVersion: newVersion }, options) - } } diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts index 0d21c42fd..995fa33d5 100644 --- a/server/models/oauth/oauth-token.ts +++ b/server/models/oauth/oauth-token.ts @@ -1,4 +1,4 @@ -import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' +import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { logger } from '../../helpers' import { AccountModel } from '../account/account' import { UserModel } from '../account/user' @@ -15,6 +15,25 @@ export type OAuthTokenInfo = { } } +enum ScopeNames { + WITH_ACCOUNT = 'WITH_ACCOUNT' +} + +@Scopes({ + [ScopeNames.WITH_ACCOUNT]: { + include: [ + { + model: () => UserModel, + include: [ + { + model: () => AccountModel, + required: true + } + ] + } + ] + } +}) @Table({ tableName: 'oAuthToken', indexes: [ @@ -115,21 +134,10 @@ export class OAuthTokenModel extends Model { const query = { where: { accessToken: bearerToken - }, - include: [ - { - model: UserModel, - include: [ - { - model: AccountModel, - required: true - } - ] - } - ] + } } - return OAuthTokenModel.findOne(query).then(token => { + return OAuthTokenModel.scope(ScopeNames.WITH_ACCOUNT).findOne(query).then(token => { if (token) token['user'] = token.User return token @@ -140,24 +148,15 @@ export class OAuthTokenModel extends Model { const query = { where: { refreshToken: refreshToken - }, - include: [ - { - model: UserModel, - include: [ - { - model: AccountModel, - required: true - } - ] - } - ] + } } - return OAuthTokenModel.findOne(query).then(token => { - token['user'] = token.User + return OAuthTokenModel.scope(ScopeNames.WITH_ACCOUNT) + .findOne(query) + .then(token => { + token['user'] = token.User - return token - }) + return token + }) } } 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) { + static loadByUrl (url: string, t?: Sequelize.Transaction) { const query: IFindOptions = { where: { - uuid + url } } 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 { diff --git a/server/tests/api/single-server.ts b/server/tests/api/single-server.ts index 174fb480d..7f4351f5e 100644 --- a/server/tests/api/single-server.ts +++ b/server/tests/api/single-server.ts @@ -132,7 +132,6 @@ describe('Test a single server', function () { expect(video.serverHost).to.equal('localhost:9001') expect(video.accountName).to.equal('root') expect(video.isLocal).to.be.true - expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) expect(dateIsValid(video.createdAt)).to.be.true expect(dateIsValid(video.updatedAt)).to.be.true @@ -181,7 +180,6 @@ describe('Test a single server', function () { expect(video.serverHost).to.equal('localhost:9001') expect(video.accountName).to.equal('root') expect(video.isLocal).to.be.true - expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) expect(dateIsValid(video.createdAt)).to.be.true expect(dateIsValid(video.updatedAt)).to.be.true expect(video.channel.name).to.equal('Default root channel') @@ -248,7 +246,6 @@ describe('Test a single server', function () { expect(video.serverHost).to.equal('localhost:9001') expect(video.accountName).to.equal('root') expect(video.isLocal).to.be.true - expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'tag3' ]) expect(dateIsValid(video.createdAt)).to.be.true expect(dateIsValid(video.updatedAt)).to.be.true diff --git a/server/tests/api/video-abuse.ts b/server/tests/api/video-abuse.ts index 60bee9c3d..4a0b6b504 100644 --- a/server/tests/api/video-abuse.ts +++ b/server/tests/api/video-abuse.ts @@ -47,7 +47,7 @@ describe('Test video abuses', function () { await uploadVideo(servers[1].url, servers[1].accessToken, video2Attributes) // Wait videos propagation, server 2 has transcoding enabled - await wait(10000) + await wait(15000) const res = await getVideosList(servers[0].url) const videos = res.body.data diff --git a/shared/models/videos/video.model.ts b/shared/models/videos/video.model.ts index dc12a05d9..3a378419f 100644 --- a/shared/models/videos/video.model.ts +++ b/shared/models/videos/video.model.ts @@ -28,7 +28,6 @@ export interface Video { isLocal: boolean name: string serverHost: string - tags: string[] thumbnailPath: string previewPath: string embedPath: string @@ -43,6 +42,7 @@ export interface VideoDetails extends Video { privacyLabel: string descriptionPath: string channel: VideoChannel + tags: string[] files: VideoFile[] account: Account }