Use sequelize scopes
This commit is contained in:
parent
94edfc3b2a
commit
d48ff09d27
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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<UserModel> {
|
|||
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<UserModel> {
|
|||
}
|
||||
|
||||
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<UserModel> {
|
|||
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) {
|
||||
|
|
|
@ -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<ApplicationModel> {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<OAuthTokenModel> {
|
|||
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<OAuthTokenModel> {
|
|||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VideoChannelShareModel> {
|
|||
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<VideoChannelShareModel> {
|
|||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VideoChannelModel> {
|
|||
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<VideoChannelModel> {
|
|||
})
|
||||
}
|
||||
|
||||
static loadByUUID (uuid: string, t?: Sequelize.Transaction) {
|
||||
static loadByUrl (url: string, t?: Sequelize.Transaction) {
|
||||
const query: IFindOptions<VideoChannelModel> = {
|
||||
where: {
|
||||
uuid
|
||||
url
|
||||
}
|
||||
}
|
||||
|
||||
if (t !== undefined) query.transaction = t
|
||||
|
||||
return VideoChannelModel.findOne(query)
|
||||
}
|
||||
|
||||
static loadByUrl (url: string, t?: Sequelize.Transaction) {
|
||||
const query: IFindOptions<VideoChannelModel> = {
|
||||
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<VideoChannelModel> {
|
|||
return VideoChannelModel.findOne(query)
|
||||
}
|
||||
|
||||
static loadByHostAndUUID (fromHost: string, uuid: string, t?: Sequelize.Transaction) {
|
||||
const query: IFindOptions<VideoChannelModel> = {
|
||||
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 () {
|
||||
|
|
|
@ -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<VideoShareModel> {
|
|||
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<VideoShareModel> {
|
|||
transaction: t
|
||||
}
|
||||
|
||||
return VideoShareModel.findAll(query)
|
||||
return VideoShareModel.scope(ScopeNames.FULL).findAll(query)
|
||||
.then(res => res.map(r => r.Account))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VideoModel> {
|
|||
}
|
||||
|
||||
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<VideoModel> {
|
|||
|
||||
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<VideoModel> {
|
|||
required: true
|
||||
}
|
||||
]
|
||||
},
|
||||
TagModel
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -395,74 +464,35 @@ export class VideoModel extends Model<VideoModel> {
|
|||
|
||||
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<VideoModel> = {
|
||||
where: {
|
||||
uuid
|
||||
},
|
||||
include: [ VideoFileModel ]
|
||||
}
|
||||
|
||||
if (t !== undefined) query.transaction = t
|
||||
|
||||
return VideoModel.findOne(query)
|
||||
}
|
||||
|
||||
static loadByUrlAndPopulateAccount (url: string, t?: Sequelize.Transaction) {
|
||||
const query: IFindOptions<VideoModel> = {
|
||||
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<VideoModel> {
|
|||
{ 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<VideoModel> {
|
|||
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<VideoModel> {
|
|||
}
|
||||
|
||||
const query: IFindOptions<VideoModel> = {
|
||||
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<VideoModel> {
|
|||
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<VideoModel> {
|
|||
views: this.views,
|
||||
likes: this.likes,
|
||||
dislikes: this.dislikes,
|
||||
tags: map<TagModel, string>(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<VideoModel> {
|
|||
descriptionPath: this.getDescriptionPath(),
|
||||
channel: this.VideoChannel.toFormattedJSON(),
|
||||
account: this.VideoChannel.Account.toFormattedJSON(),
|
||||
tags: map<TagModel, string>(this.Tags, 'name'),
|
||||
files: []
|
||||
}
|
||||
|
||||
|
@ -779,7 +760,7 @@ export class VideoModel extends Model<VideoModel> {
|
|||
return -1
|
||||
})
|
||||
|
||||
return Object.assign(formattedJson, detailsJson)
|
||||
return Object.assign(formattedJson, detailsJson) as VideoDetails
|
||||
}
|
||||
|
||||
toActivityPubObject (): VideoTorrentObject {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue