1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-06 03:50:26 +02:00

Type models

This commit is contained in:
Chocobozzz 2017-05-22 20:58:25 +02:00
parent 65fcc3119c
commit e02643f32e
76 changed files with 1710 additions and 816 deletions

View file

@ -2,7 +2,7 @@ import express = require('express')
import { CONFIG } from '../../initializers';
import { logger } from '../../helpers'
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
const clientsRouter = express.Router()

View file

@ -1,6 +1,6 @@
import express = require('express')
import { CONFIG } from '../../initializers';
import { CONFIG } from '../../initializers'
const configRouter = express.Router()

View file

@ -1,7 +1,7 @@
import express = require('express')
import { waterfall } from 'async'
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { CONFIG } from '../../initializers'
import {
logger,
@ -35,12 +35,12 @@ podsRouter.post('/makefriends',
ensureIsAdmin,
makeFriendsValidator,
setBodyHostsPort,
makeFriends
makeFriendsController
)
podsRouter.get('/quitfriends',
authenticate,
ensureIsAdmin,
quitFriends
quitFriendsController
)
// ---------------------------------------------------------------------------

View file

@ -1,7 +1,7 @@
import express = require('express')
import { waterfall } from 'async/waterfall'
import * as waterfall from 'async/waterfall'
const db = require('../../../initializers/database')
import { database as db } from '../../../initializers/database'
import { checkSignature, signatureValidator } from '../../../middlewares'
const remotePodsRouter = express.Router()

View file

@ -1,7 +1,7 @@
import express = require('express')
import { eachSeries, waterfall } from 'async'
const db = require('../../../initializers/database')
import { database as db } from '../../../initializers/database'
import {
REQUEST_ENDPOINT_ACTIONS,
REQUEST_ENDPOINTS,

View file

@ -1,7 +1,7 @@
import express = require('express')
import { waterfall } from 'async'
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { CONFIG, USER_ROLES } from '../../initializers'
import { logger, getFormatedObjects } from '../../helpers'
import {
@ -114,7 +114,7 @@ function getUserVideoRating (req, res, next) {
const videoId = req.params.videoId
const userId = res.locals.oauth.token.User.id
db.UserVideoRate.load(userId, videoId, function (err, ratingObj) {
db.UserVideoRate.load(userId, videoId, null, function (err, ratingObj) {
if (err) return next(err)
const rating = ratingObj ? ratingObj.type : 'none'

View file

@ -1,7 +1,7 @@
import express = require('express')
import { waterfall } from 'async'
const db = require('../../../initializers/database')
import { database as db } from '../../../initializers/database'
import friends = require('../../../lib/friends')
import {
logger,

View file

@ -1,6 +1,6 @@
import express = require('express')
const db = require('../../../initializers/database')
import { database as db } from '../../../initializers/database'
import { logger } from '../../../helpers'
import {
authenticate,

View file

@ -4,7 +4,7 @@ import multer = require('multer')
import path = require('path')
import { waterfall } from 'async'
const db = require('../../../initializers/database')
import { database as db } from '../../../initializers/database'
import {
CONFIG,
REQUEST_VIDEO_QADU_TYPES,

View file

@ -1,7 +1,7 @@
import express = require('express')
import { waterfall } from 'async'
const db = require('../../../initializers/database')
import { database as db } from '../../../initializers/database'
import {
logger,
retryTransactionWrapper,

View file

@ -6,20 +6,21 @@ import expressValidator = require('express-validator')
// TODO: use .validator when express-validator typing will have validator field
const validator = expressValidator['validator']
const db = require('../initializers/database')
import { database as db } from '../initializers/database'
import {
CONFIG,
REMOTE_SCHEME,
STATIC_PATHS,
STATIC_MAX_AGE
} from '../initializers'
import { root } from '../helpers'
const clientsRouter = express.Router()
// TODO: move to constants
const opengraphComment = '<!-- opengraph tags -->'
const distPath = join(__dirname, '..', '..', 'client/dist')
const embedPath = join(distPath, 'standalone/videos/embed.html')
const distPath = join(root(), 'client', 'dist')
const embedPath = join(distPath, 'standalone', 'videos', 'embed.html')
const indexPath = join(distPath, 'index.html')
// Special route that add OpenGraph tags

View file

@ -1,7 +1,7 @@
// TODO: import from ES6 when retry typing file will include errorFilter function
import retry = require('async/retry')
const db = require('../initializers/database')
import { database as db } from '../initializers/database'
import { logger } from './logger'
function commitTransaction (t, callback) {
@ -52,7 +52,7 @@ function transactionRetryer (func, callback) {
}
function startSerializableTransaction (callback) {
db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) {
db.sequelize.transaction(/* { isolationLevel: 'SERIALIZABLE' } */).asCallback(function (err, t) {
// We force to return only two parameters
return callback(err, t)
})

View file

@ -36,13 +36,6 @@ const logger = new winston.Logger({
exitOnError: true
})
// TODO: useful?
// logger.stream = {
// write: function (message) {
// logger.info(message)
// }
// }
// ---------------------------------------------------------------------------
export { logger }

View file

@ -1,4 +1,5 @@
import { pseudoRandomBytes } from 'crypto'
import { join } from 'path'
import { logger } from './logger'
@ -42,6 +43,11 @@ function getFormatedObjects (objects, objectsTotal) {
}
}
function root () {
// We are in /dist/helpers/utils.js
return join(__dirname, '..', '..', '..')
}
// ---------------------------------------------------------------------------
export {
@ -50,5 +56,6 @@ export {
cleanForExit,
generateRandomString,
isTestInstance,
getFormatedObjects
getFormatedObjects,
root
}

View file

@ -1,6 +1,6 @@
import config = require('config')
const db = require('./database')
import { database as db } from './database'
import { CONFIG } from './constants'
// Some checks on configuration files

View file

@ -1,6 +1,9 @@
import config = require('config')
import { join } from 'path'
// Do not use barrels, remain constants as independent as possible
import { root, isTestInstance } from '../helpers/utils'
// ---------------------------------------------------------------------------
const LAST_MIGRATION_VERSION = 50
@ -44,12 +47,12 @@ const CONFIG = {
PASSWORD: config.get<string>('database.password')
},
STORAGE: {
CERT_DIR: join(__dirname, '..', '..', config.get<string>('storage.certs')),
LOG_DIR: join(__dirname, '..', '..', config.get<string>('storage.logs')),
VIDEOS_DIR: join(__dirname, '..', '..', config.get<string>('storage.videos')),
THUMBNAILS_DIR: join(__dirname, '..', '..', config.get<string>('storage.thumbnails')),
PREVIEWS_DIR: join(__dirname, '..', '..', config.get<string>('storage.previews')),
TORRENTS_DIR: join(__dirname, '..', '..', config.get<string>('storage.torrents'))
CERT_DIR: join(root(), config.get<string>('storage.certs')),
LOG_DIR: join(root(), config.get<string>('storage.logs')),
VIDEOS_DIR: join(root(), config.get<string>('storage.videos')),
THUMBNAILS_DIR: join(root(), config.get<string>('storage.thumbnails')),
PREVIEWS_DIR: join(root(), config.get<string>('storage.previews')),
TORRENTS_DIR: join(root(), config.get<string>('storage.torrents'))
},
WEBSERVER: {
SCHEME: config.get<boolean>('webserver.https') === true ? 'https' : 'http',
@ -334,10 +337,3 @@ export {
VIDEO_LICENCES,
VIDEO_RATE_TYPES
}
// ---------------------------------------------------------------------------
// This method exists in utils module but we want to let the constants module independent
function isTestInstance () {
return (process.env.NODE_ENV === 'test')
}

View file

@ -6,12 +6,52 @@ import { CONFIG } from './constants'
// Do not use barrel, we need to load database first
import { logger } from '../helpers/logger'
import { isTestInstance } from '../helpers/utils'
import {
ApplicationModel,
AuthorModel,
JobModel,
OAuthClientModel,
OAuthTokenModel,
PodModel,
RequestModel,
RequestToPodModel,
RequestVideoEventModel,
RequestVideoQaduModel,
TagModel,
UserModel,
UserVideoRateModel,
VideoAbuseModel,
BlacklistedVideoModel,
VideoTagModel,
VideoModel
} from '../models'
const dbname = CONFIG.DATABASE.DBNAME
const username = CONFIG.DATABASE.USERNAME
const password = CONFIG.DATABASE.PASSWORD
const database: any = {}
const database: {
sequelize?: Sequelize.Sequelize,
init?: (silent: any, callback: any) => void,
Application?: ApplicationModel,
Author?: AuthorModel,
Job?: JobModel,
OAuthClient?: OAuthClientModel,
OAuthToken?: OAuthTokenModel,
Pod?: PodModel,
RequestToPod?: RequestToPodModel,
RequestVideoEvent?: RequestVideoEventModel,
RequestVideoQadu?: RequestVideoQaduModel,
Request?: RequestModel,
Tag?: TagModel,
UserVideoRate?: UserVideoRateModel,
User?: UserModel,
VideoAbuse?: VideoAbuseModel,
BlacklistedVideo?: BlacklistedVideoModel,
VideoTag?: VideoTagModel,
Video?: VideoModel
} = {}
const sequelize = new Sequelize(dbname, username, password, {
dialect: 'postgres',
@ -32,12 +72,6 @@ const sequelize = new Sequelize(dbname, username, password, {
database.sequelize = sequelize
database.init = function (silent, callback) {
if (!callback) {
callback = silent
silent = false
}
if (!callback) callback = function () { /* empty */ }
const modelDirectory = join(__dirname, '..', 'models')
fs.readdir(modelDirectory, function (err, files) {
@ -45,7 +79,12 @@ database.init = function (silent, callback) {
files.filter(function (file) {
// For all models but not utils.js
if (file === 'utils.js') return false
if (
file === 'index.js' ||
file === 'utils.js' ||
file.endsWith('-interface.js') ||
file.endsWith('.js.map')
) return false
return true
})
@ -69,4 +108,6 @@ database.init = function (silent, callback) {
// ---------------------------------------------------------------------------
module.exports = database
export {
database
}

View file

@ -4,10 +4,10 @@ import { each, series } from 'async'
import mkdirp = require('mkdirp')
import passwordGenerator = require('password-generator')
const db = require('./database')
import { database as db } from './database'
import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants'
import { clientsExist, usersExist } from './checker'
import { logger, createCertsIfNotExist } from '../helpers'
import { logger, createCertsIfNotExist, root } from '../helpers'
function installApplication (callback) {
series([
@ -47,7 +47,7 @@ function createDirectoriesIfNotExist (callback) {
each(Object.keys(storages), function (key, callbackEach) {
const dir = storages[key]
mkdirp(join(__dirname, '..', '..', dir), callbackEach)
mkdirp(join(root(), dir), callbackEach)
}, callback)
}
@ -65,7 +65,8 @@ function createOAuthClientIfNotExist (callback) {
const client = db.OAuthClient.build({
clientId: id,
clientSecret: secret,
grants: [ 'password', 'refresh_token' ]
grants: [ 'password', 'refresh_token' ],
redirectUris: null
})
client.save().asCallback(function (err, createdClient) {

View file

@ -1,10 +1,12 @@
import { waterfall, eachSeries } from 'async'
import fs = require('fs')
import path = require('path')
import * as Sequelize from 'sequelize'
const db = require('./database')
import { database as db } from './database'
import { LAST_MIGRATION_VERSION } from './constants'
import { logger } from '../helpers'
import { ApplicationInstance } from '../models'
function migrate (finalCallback) {
waterfall([
@ -94,7 +96,7 @@ function getMigrationScripts (callback) {
}
function executeMigration (actualVersion, entity, callback) {
const versionScript = parseInt(entity.version)
const versionScript = parseInt(entity.version, 10)
// Do not execute old migration scripts
if (versionScript <= actualVersion) return callback(null)
@ -112,7 +114,7 @@ function executeMigration (actualVersion, entity, callback) {
transaction: t,
queryInterface: db.sequelize.getQueryInterface(),
sequelize: db.sequelize,
Sequelize: db.Sequelize
Sequelize: Sequelize
}
migrationScript.up(options, function (err) {
if (err) {

View file

@ -1,7 +1,7 @@
import { each, eachLimit, eachSeries, series, waterfall } from 'async'
import request = require('request')
const db = require('../initializers/database')
import { database as db } from '../initializers/database'
import {
API_VERSION,
CONFIG,
@ -329,7 +329,7 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
// Flush pool requests
requestScheduler.forceSend()
eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: any, callbackEach) {
eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: { host: string }, callbackEach) {
const params = {
url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/',
method: 'POST',
@ -340,7 +340,7 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
}
}
makeRetryRequest(params, function (err, res, body) {
makeRetryRequest(params, function (err, res, body: { cert: string, email: string }) {
if (err) {
logger.error('Error with adding %s pod.', pod.host, { error: err })
// Don't break the process

View file

@ -1,4 +1,4 @@
const db = require('../../../initializers/database')
import { database as db } from '../../../initializers/database'
import { logger } from '../../../helpers'
import { addVideoToFriends } from '../../../lib'

View file

@ -1,6 +1,6 @@
import { forever, queue } from 'async'
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import {
JOBS_FETCHING_INTERVAL,
JOBS_FETCH_LIMIT_PER_CYCLE,
@ -24,7 +24,7 @@ class JobScheduler {
logger.info('Jobs scheduler activated.')
const jobsQueue = queue(this.processJob)
const jobsQueue = queue(this.processJob.bind(this))
// Finish processing jobs from a previous start
const state = JOB_STATES.PROCESSING
@ -58,7 +58,7 @@ class JobScheduler {
})
}
createJob (transaction, handlerName, handlerInputData, callback) {
createJob (transaction, handlerName: string, handlerInputData: object, callback) {
const createQuery = {
state: JOB_STATES.PENDING,
handlerName,

View file

@ -1,4 +1,4 @@
const db = require('../initializers/database')
import { database as db } from '../initializers/database'
import { logger } from '../helpers'
// ---------------------------------------------------------------------------
@ -72,7 +72,7 @@ function saveToken (token, client, user) {
userId: user.id
}
return db.OAuthToken.create(tokenToCreate).then(function (tokenCreated) {
return db.OAuthToken.create(tokenToCreate).then(function (tokenCreated: any) {
tokenCreated.client = client
tokenCreated.user = user

View file

@ -1,6 +1,6 @@
import { eachLimit } from 'async/eachLimit'
import * as eachLimit from 'async/eachLimit'
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { logger, makeSecureRequest } from '../../helpers'
import {
API_VERSION,

View file

@ -1,4 +1,4 @@
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { BaseRequestScheduler } from './base-request-scheduler'
import { logger } from '../../helpers'
import {
@ -59,13 +59,14 @@ class RequestScheduler extends BaseRequestScheduler {
const toIds = options.toIds
const transaction = options.transaction
const pods = []
// TODO: check the setPods works
const podIds = []
// If there are no destination pods abort
if (toIds.length === 0) return callback(null)
toIds.forEach(toPod => {
pods.push(db.Pod.build({ id: toPod }))
podIds.push(toPod)
})
const createQuery = {
@ -83,7 +84,7 @@ class RequestScheduler extends BaseRequestScheduler {
return db.Request.create(createQuery, dbRequestOptions).asCallback((err, request) => {
if (err) return callback(err)
return request.setPods(pods, dbRequestOptions).asCallback(callback)
return request.setPods(podIds, dbRequestOptions).asCallback(callback)
})
}

View file

@ -1,4 +1,4 @@
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { BaseRequestScheduler } from './base-request-scheduler'
import {
REQUESTS_VIDEO_EVENT_LIMIT_PODS,

View file

@ -1,4 +1,4 @@
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { BaseRequestScheduler } from './base-request-scheduler'
import { logger } from '../../helpers'
import {

View file

@ -1,4 +1,4 @@
const logger = require('../helpers/logger')
import { logger } from '../helpers'
function ensureIsAdmin (req, res, next) {
const user = res.locals.oauth.token.user

View file

@ -1,11 +1,11 @@
import OAuthServer = require('express-oauth-server')
const constants = require('../initializers/constants')
const logger = require('../helpers/logger')
import { OAUTH_LIFETIME } from '../initializers'
import { logger } from '../helpers'
const oAuthServer = new OAuthServer({
accessTokenLifetime: constants.OAUTH_LIFETIME.ACCESS_TOKEN,
refreshTokenLifetime: constants.OAUTH_LIFETIME.REFRESH_TOKEN,
accessTokenLifetime: OAUTH_LIFETIME.ACCESS_TOKEN,
refreshTokenLifetime: OAUTH_LIFETIME.REFRESH_TOKEN,
model: require('../lib/oauth-model')
})

View file

@ -1,10 +1,10 @@
const constants = require('../initializers/constants')
import { PAGINATION_COUNT_DEFAULT } from '../initializers'
function setPagination (req, res, next) {
if (!req.query.start) req.query.start = 0
else req.query.start = parseInt(req.query.start, 10)
if (!req.query.count) req.query.count = constants.PAGINATION_COUNT_DEFAULT
if (!req.query.count) req.query.count = PAGINATION_COUNT_DEFAULT
else req.query.count = parseInt(req.query.count, 10)
return next()

View file

@ -1,6 +1,4 @@
'use strict'
const constants = require('../initializers/constants')
import { REMOTE_SCHEME } from '../initializers'
function setBodyHostsPort (req, res, next) {
if (!req.body.hosts) return next()
@ -48,7 +46,7 @@ function getHostWithPort (host) {
// The port was not specified
if (splitted.length === 1) {
if (constants.REMOTE_SCHEME.HTTP === 'https') return host + ':443'
if (REMOTE_SCHEME.HTTP === 'https') return host + ':443'
return host + ':80'
}

View file

@ -1,6 +1,8 @@
const db = require('../initializers/database')
const logger = require('../helpers/logger')
const peertubeCrypto = require('../helpers/peertube-crypto')
import { database as db } from '../initializers'
import {
logger,
checkSignature as peertubeCryptoCheckSignature
} from '../helpers'
function checkSignature (req, res, next) {
const host = req.body.signature.host
@ -26,7 +28,7 @@ function checkSignature (req, res, next) {
signatureShouldBe = host
}
const signatureOk = peertubeCrypto.checkSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
if (signatureOk === true) {
res.locals.secure = {

View file

@ -1,4 +1,4 @@
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { checkErrors } from './utils'
import { logger } from '../../helpers'
import { CONFIG } from '../../initializers'

View file

@ -1,4 +1,4 @@
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { checkErrors } from './utils'
import { logger } from '../../helpers'

View file

@ -1,4 +1,4 @@
const db = require('../../initializers/database')
import { database as db } from '../../initializers/database'
import { checkErrors } from './utils'
import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
import { logger, isVideoDurationValid } from '../../helpers'

View file

@ -0,0 +1,23 @@
import * as Sequelize from 'sequelize'
export namespace ApplicationMethods {
export type LoadMigrationVersion = (callback: (err: Error, version: number) => void) => void
export type UpdateMigrationVersion = (newVersion: number, transaction: any, callback: any) => void
}
export interface ApplicationClass {
loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
}
export interface ApplicationAttributes {
migrationVersion: number
}
export interface ApplicationInstance extends ApplicationClass, ApplicationAttributes, Sequelize.Instance<ApplicationAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface ApplicationModel extends ApplicationClass, Sequelize.Model<ApplicationInstance, ApplicationAttributes> {}

View file

@ -1,5 +1,20 @@
module.exports = function (sequelize, DataTypes) {
const Application = sequelize.define('Application',
import * as Sequelize from 'sequelize'
import { addMethodsToModel } from './utils'
import {
ApplicationClass,
ApplicationAttributes,
ApplicationInstance,
ApplicationMethods
} from './application-interface'
let Application: Sequelize.Model<ApplicationInstance, ApplicationAttributes>
let loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
let updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
export default function defineApplication (sequelize: Sequelize.Sequelize, DataTypes) {
Application = sequelize.define<ApplicationInstance, ApplicationAttributes>('Application',
{
migrationVersion: {
type: DataTypes.INTEGER,
@ -9,34 +24,31 @@ module.exports = function (sequelize, DataTypes) {
isInt: true
}
}
},
{
classMethods: {
loadMigrationVersion,
updateMigrationVersion
}
}
)
const classMethods = [ loadMigrationVersion, updateMigrationVersion ]
addMethodsToModel(Application, classMethods)
return Application
}
// ---------------------------------------------------------------------------
function loadMigrationVersion (callback) {
loadMigrationVersion = function (callback: (err: Error, version: number) => void) {
const query = {
attributes: [ 'migrationVersion' ]
}
return this.findOne(query).asCallback(function (err, data) {
return Application.findOne(query).asCallback(function (err, data) {
const version = data ? data.migrationVersion : null
return callback(err, version)
})
}
function updateMigrationVersion (newVersion, transaction, callback) {
const options: { where?: any, transaction?: any } = {
updateMigrationVersion = function (newVersion: number, transaction: any, callback: any) {
const options: Sequelize.UpdateOptions = {
where: {}
}
@ -46,5 +58,5 @@ function updateMigrationVersion (newVersion, transaction, callback) {
options.transaction = transaction
}
return this.update({ migrationVersion: newVersion }, options).asCallback(callback)
return Application.update({ migrationVersion: newVersion }, options).asCallback(callback)
}

View file

@ -0,0 +1,21 @@
import * as Sequelize from 'sequelize'
export namespace AuthorMethods {
export type FindOrCreateAuthor = (name, podId, userId, transaction, callback) => void
}
export interface AuthorClass {
findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
}
export interface AuthorAttributes {
name: string
}
export interface AuthorInstance extends AuthorClass, AuthorAttributes, Sequelize.Instance<AuthorAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface AuthorModel extends AuthorClass, Sequelize.Model<AuthorInstance, AuthorAttributes> {}

View file

@ -1,7 +1,21 @@
import * as Sequelize from 'sequelize'
import { isUserUsernameValid } from '../helpers'
module.exports = function (sequelize, DataTypes) {
const Author = sequelize.define('Author',
import { addMethodsToModel } from './utils'
import {
AuthorClass,
AuthorInstance,
AuthorAttributes,
AuthorMethods
} from './author-interface'
let Author: Sequelize.Model<AuthorInstance, AuthorAttributes>
let findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
export default function defineAuthor (sequelize: Sequelize.Sequelize, DataTypes) {
Author = sequelize.define<AuthorInstance, AuthorAttributes>('Author',
{
name: {
type: DataTypes.STRING,
@ -30,22 +44,20 @@ module.exports = function (sequelize, DataTypes) {
fields: [ 'name', 'podId' ],
unique: true
}
],
classMethods: {
associate,
findOrCreateAuthor
}
]
}
)
const classMethods = [ associate, findOrCreateAuthor ]
addMethodsToModel(Author, classMethods)
return Author
}
// ---------------------------------------------------------------------------
function associate (models) {
this.belongsTo(models.Pod, {
Author.belongsTo(models.Pod, {
foreignKey: {
name: 'podId',
allowNull: true
@ -53,7 +65,7 @@ function associate (models) {
onDelete: 'cascade'
})
this.belongsTo(models.User, {
Author.belongsTo(models.User, {
foreignKey: {
name: 'userId',
allowNull: true
@ -62,7 +74,7 @@ function associate (models) {
})
}
function findOrCreateAuthor (name, podId, userId, transaction, callback) {
findOrCreateAuthor = function (name, podId, userId, transaction, callback) {
if (!callback) {
callback = transaction
transaction = null
@ -81,7 +93,7 @@ function findOrCreateAuthor (name, podId, userId, transaction, callback) {
if (transaction) query.transaction = transaction
this.findOrCreate(query).asCallback(function (err, result) {
Author.findOrCreate(query).asCallback(function (err, result) {
if (err) return callback(err)
// [ instance, wasCreated ]

17
server/models/index.ts Normal file
View file

@ -0,0 +1,17 @@
export * from './application-interface'
export * from './author-interface'
export * from './job-interface'
export * from './oauth-client-interface'
export * from './oauth-token-interface'
export * from './pod-interface'
export * from './request-interface'
export * from './request-to-pod-interface'
export * from './request-video-event-interface'
export * from './request-video-qadu-interface'
export * from './tag-interface'
export * from './user-video-rate-interface'
export * from './user-interface'
export * from './video-abuse-interface'
export * from './video-blacklist-interface'
export * from './video-tag-interface'
export * from './video-interface'

View file

@ -0,0 +1,23 @@
import * as Sequelize from 'sequelize'
export namespace JobMethods {
export type ListWithLimit = (limit, state, callback) => void
}
export interface JobClass {
listWithLimit: JobMethods.ListWithLimit
}
export interface JobAttributes {
state: string
handlerName: string
handlerInputData: object
}
export interface JobInstance extends JobClass, JobAttributes, Sequelize.Instance<JobAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface JobModel extends JobClass, Sequelize.Model<JobInstance, JobAttributes> {}

View file

@ -1,11 +1,22 @@
import { values } from 'lodash'
import * as Sequelize from 'sequelize'
import { JOB_STATES } from '../initializers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
JobClass,
JobInstance,
JobAttributes,
module.exports = function (sequelize, DataTypes) {
const Job = sequelize.define('Job',
JobMethods
} from './job-interface'
let Job: Sequelize.Model<JobInstance, JobAttributes>
let listWithLimit: JobMethods.ListWithLimit
export default function defineJob (sequelize: Sequelize.Sequelize, DataTypes) {
Job = sequelize.define<JobInstance, JobAttributes>('Job',
{
state: {
type: DataTypes.ENUM(values(JOB_STATES)),
@ -25,19 +36,19 @@ module.exports = function (sequelize, DataTypes) {
{
fields: [ 'state' ]
}
],
classMethods: {
listWithLimit
}
]
}
)
const classMethods = [ listWithLimit ]
addMethodsToModel(Job, classMethods)
return Job
}
// ---------------------------------------------------------------------------
function listWithLimit (limit, state, callback) {
listWithLimit = function (limit, state, callback) {
const query = {
order: [
[ 'id', 'ASC' ]
@ -48,5 +59,5 @@ function listWithLimit (limit, state, callback) {
}
}
return this.findAll(query).asCallback(callback)
return Job.findAll(query).asCallback(callback)
}

View file

@ -0,0 +1,28 @@
import * as Sequelize from 'sequelize'
export namespace OAuthClientMethods {
export type CountTotal = (callback) => void
export type LoadFirstClient = (callback) => void
export type GetByIdAndSecret = (clientId, clientSecret) => void
}
export interface OAuthClientClass {
countTotal: OAuthClientMethods.CountTotal
loadFirstClient: OAuthClientMethods.LoadFirstClient
getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
}
export interface OAuthClientAttributes {
clientId: string
clientSecret: string
grants: string[]
redirectUris: string[]
}
export interface OAuthClientInstance extends OAuthClientClass, OAuthClientAttributes, Sequelize.Instance<OAuthClientAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface OAuthClientModel extends OAuthClientClass, Sequelize.Model<OAuthClientInstance, OAuthClientAttributes> {}

View file

@ -1,5 +1,21 @@
module.exports = function (sequelize, DataTypes) {
const OAuthClient = sequelize.define('OAuthClient',
import * as Sequelize from 'sequelize'
import { addMethodsToModel } from './utils'
import {
OAuthClientClass,
OAuthClientInstance,
OAuthClientAttributes,
OAuthClientMethods
} from './oauth-client-interface'
let OAuthClient: Sequelize.Model<OAuthClientInstance, OAuthClientAttributes>
let countTotal: OAuthClientMethods.CountTotal
let loadFirstClient: OAuthClientMethods.LoadFirstClient
let getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
export default function (sequelize, DataTypes) {
OAuthClient = sequelize.define('OAuthClient',
{
clientId: {
type: DataTypes.STRING,
@ -26,29 +42,40 @@ module.exports = function (sequelize, DataTypes) {
fields: [ 'clientId', 'clientSecret' ],
unique: true
}
],
classMethods: {
countTotal,
getByIdAndSecret,
loadFirstClient
}
]
}
)
const classMethods = [
associate,
countTotal,
getByIdAndSecret,
loadFirstClient
]
addMethodsToModel(OAuthClient, classMethods)
return OAuthClient
}
// ---------------------------------------------------------------------------
function countTotal (callback) {
return this.count().asCallback(callback)
function associate (models) {
OAuthClient.hasMany(models.OAuthToken, {
foreignKey: 'oAuthClientId',
onDelete: 'cascade'
})
}
function loadFirstClient (callback) {
return this.findOne().asCallback(callback)
countTotal = function (callback) {
return OAuthClient.count().asCallback(callback)
}
function getByIdAndSecret (clientId, clientSecret) {
loadFirstClient = function (callback) {
return OAuthClient.findOne().asCallback(callback)
}
getByIdAndSecret = function (clientId, clientSecret) {
const query = {
where: {
clientId: clientId,
@ -56,5 +83,5 @@ function getByIdAndSecret (clientId, clientSecret) {
}
}
return this.findOne(query)
return OAuthClient.findOne(query)
}

View file

@ -0,0 +1,34 @@
import * as Sequelize from 'sequelize'
import { UserModel } from './user-interface'
export namespace OAuthTokenMethods {
export type GetByRefreshTokenAndPopulateClient = (refreshToken) => void
export type GetByTokenAndPopulateUser = (bearerToken) => void
export type GetByRefreshTokenAndPopulateUser = (refreshToken) => any
export type RemoveByUserId = (userId, callback) => void
}
export interface OAuthTokenClass {
getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
removeByUserId: OAuthTokenMethods.RemoveByUserId
}
export interface OAuthTokenAttributes {
accessToken: string
accessTokenExpiresAt: Date
refreshToken: string
refreshTokenExpiresAt: Date
User?: UserModel
}
export interface OAuthTokenInstance extends OAuthTokenClass, OAuthTokenAttributes, Sequelize.Instance<OAuthTokenAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface OAuthTokenModel extends OAuthTokenClass, Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes> {}

View file

@ -1,9 +1,24 @@
import * as Sequelize from 'sequelize'
import { logger } from '../helpers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
OAuthTokenClass,
OAuthTokenInstance,
OAuthTokenAttributes,
module.exports = function (sequelize, DataTypes) {
const OAuthToken = sequelize.define('OAuthToken',
OAuthTokenMethods
} from './oauth-token-interface'
let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes>
let getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
let getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
let getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
let removeByUserId: OAuthTokenMethods.RemoveByUserId
export default function (sequelize, DataTypes) {
OAuthToken = sequelize.define('OAuthToken',
{
accessToken: {
type: DataTypes.STRING,
@ -38,25 +53,27 @@ module.exports = function (sequelize, DataTypes) {
{
fields: [ 'oAuthClientId' ]
}
],
classMethods: {
associate,
getByRefreshTokenAndPopulateClient,
getByTokenAndPopulateUser,
getByRefreshTokenAndPopulateUser,
removeByUserId
}
]
}
)
const classMethods = [
associate,
getByRefreshTokenAndPopulateClient,
getByTokenAndPopulateUser,
getByRefreshTokenAndPopulateUser,
removeByUserId
]
addMethodsToModel(OAuthToken, classMethods)
return OAuthToken
}
// ---------------------------------------------------------------------------
function associate (models) {
this.belongsTo(models.User, {
OAuthToken.belongsTo(models.User, {
foreignKey: {
name: 'userId',
allowNull: false
@ -64,7 +81,7 @@ function associate (models) {
onDelete: 'cascade'
})
this.belongsTo(models.OAuthClient, {
OAuthToken.belongsTo(models.OAuthClient, {
foreignKey: {
name: 'oAuthClientId',
allowNull: false
@ -73,25 +90,25 @@ function associate (models) {
})
}
function getByRefreshTokenAndPopulateClient (refreshToken) {
getByRefreshTokenAndPopulateClient = function (refreshToken) {
const query = {
where: {
refreshToken: refreshToken
},
include: [ this.associations.OAuthClient ]
include: [ OAuthToken['sequelize'].models.OAuthClient ]
}
return this.findOne(query).then(function (token) {
return OAuthToken.findOne(query).then(function (token) {
if (!token) return token
const tokenInfos = {
refreshToken: token.refreshToken,
refreshTokenExpiresAt: token.refreshTokenExpiresAt,
client: {
id: token.client.id
id: token['client'].id
},
user: {
id: token.user
id: token['user']
}
}
@ -101,42 +118,42 @@ function getByRefreshTokenAndPopulateClient (refreshToken) {
})
}
function getByTokenAndPopulateUser (bearerToken) {
getByTokenAndPopulateUser = function (bearerToken) {
const query = {
where: {
accessToken: bearerToken
},
include: [ this.sequelize.models.User ]
include: [ OAuthToken['sequelize'].models.User ]
}
return this.findOne(query).then(function (token) {
if (token) token.user = token.User
return OAuthToken.findOne(query).then(function (token) {
if (token) token['user'] = token.User
return token
})
}
function getByRefreshTokenAndPopulateUser (refreshToken) {
getByRefreshTokenAndPopulateUser = function (refreshToken) {
const query = {
where: {
refreshToken: refreshToken
},
include: [ this.sequelize.models.User ]
include: [ OAuthToken['sequelize'].models.User ]
}
return this.findOne(query).then(function (token) {
token.user = token.User
return OAuthToken.findOne(query).then(function (token) {
token['user'] = token.User
return token
})
}
function removeByUserId (userId, callback) {
removeByUserId = function (userId, callback) {
const query = {
where: {
userId: userId
}
}
return this.destroy(query).asCallback(callback)
return OAuthToken.destroy(query).asCallback(callback)
}

View file

@ -0,0 +1,46 @@
import * as Sequelize from 'sequelize'
export namespace PodMethods {
export type ToFormatedJSON = () => void
export type CountAll = (callback) => void
export type IncrementScores = (ids, value, callback) => void
export type List = (callback) => void
export type ListAllIds = (transaction, callback) => void
export type ListRandomPodIdsWithRequest = (limit, tableWithPods, tableWithPodsJoins, callback) => void
export type ListBadPods = (callback) => void
export type Load = (id, callback) => void
export type LoadByHost = (host, callback) => void
export type RemoveAll = (callback) => void
export type UpdatePodsScore = (goodPods, badPods) => void
}
export interface PodClass {
countAll: PodMethods.CountAll
incrementScores: PodMethods.IncrementScores
list: PodMethods.List
listAllIds: PodMethods.ListAllIds
listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
listBadPods: PodMethods.ListBadPods
load: PodMethods.Load
loadByHost: PodMethods.LoadByHost
removeAll: PodMethods.RemoveAll
updatePodsScore: PodMethods.UpdatePodsScore
}
export interface PodAttributes {
host?: string
publicKey?: string
score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
email?: string
}
export interface PodInstance extends PodClass, PodAttributes, Sequelize.Instance<PodAttributes> {
id: number
createdAt: Date
updatedAt: Date
toFormatedJSON: PodMethods.ToFormatedJSON,
}
export interface PodModel extends PodClass, Sequelize.Model<PodInstance, PodAttributes> {}

View file

@ -1,13 +1,34 @@
import { each, waterfall } from 'async'
import { map } from 'lodash'
import * as Sequelize from 'sequelize'
import { FRIEND_SCORE, PODS_SCORE } from '../initializers'
import { logger, isHostValid } from '../helpers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
PodClass,
PodInstance,
PodAttributes,
module.exports = function (sequelize, DataTypes) {
const Pod = sequelize.define('Pod',
PodMethods
} from './pod-interface'
let Pod: Sequelize.Model<PodInstance, PodAttributes>
let toFormatedJSON: PodMethods.ToFormatedJSON
let countAll: PodMethods.CountAll
let incrementScores: PodMethods.IncrementScores
let list: PodMethods.List
let listAllIds: PodMethods.ListAllIds
let listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
let listBadPods: PodMethods.ListBadPods
let load: PodMethods.Load
let loadByHost: PodMethods.LoadByHost
let removeAll: PodMethods.RemoveAll
let updatePodsScore: PodMethods.UpdatePodsScore
export default function (sequelize, DataTypes) {
Pod = sequelize.define('Pod',
{
host: {
type: DataTypes.STRING,
@ -49,33 +70,33 @@ module.exports = function (sequelize, DataTypes) {
{
fields: [ 'score' ]
}
],
classMethods: {
associate,
countAll,
incrementScores,
list,
listAllIds,
listRandomPodIdsWithRequest,
listBadPods,
load,
loadByHost,
updatePodsScore,
removeAll
},
instanceMethods: {
toFormatedJSON
}
]
}
)
const classMethods = [
associate,
countAll,
incrementScores,
list,
listAllIds,
listRandomPodIdsWithRequest,
listBadPods,
load,
loadByHost,
updatePodsScore,
removeAll
]
const instanceMethods = [ toFormatedJSON ]
addMethodsToModel(Pod, classMethods, instanceMethods)
return Pod
}
// ------------------------------ METHODS ------------------------------
function toFormatedJSON () {
toFormatedJSON = function () {
const json = {
id: this.id,
host: this.host,
@ -90,22 +111,22 @@ function toFormatedJSON () {
// ------------------------------ Statics ------------------------------
function associate (models) {
this.belongsToMany(models.Request, {
Pod.belongsToMany(models.Request, {
foreignKey: 'podId',
through: models.RequestToPod,
onDelete: 'cascade'
})
}
function countAll (callback) {
return this.count().asCallback(callback)
countAll = function (callback) {
return Pod.count().asCallback(callback)
}
function incrementScores (ids, value, callback) {
incrementScores = function (ids, value, callback) {
if (!callback) callback = function () { /* empty */ }
const update = {
score: this.sequelize.literal('score +' + value)
score: Sequelize.literal('score +' + value)
}
const options = {
@ -118,14 +139,14 @@ function incrementScores (ids, value, callback) {
validate: false
}
return this.update(update, options).asCallback(callback)
return Pod.update(update, options).asCallback(callback)
}
function list (callback) {
return this.findAll().asCallback(callback)
list = function (callback) {
return Pod.findAll().asCallback(callback)
}
function listAllIds (transaction, callback) {
listAllIds = function (transaction, callback) {
if (!callback) {
callback = transaction
transaction = null
@ -137,22 +158,20 @@ function listAllIds (transaction, callback) {
if (transaction) query.transaction = transaction
return this.findAll(query).asCallback(function (err, pods) {
return Pod.findAll(query).asCallback(function (err, pods) {
if (err) return callback(err)
return callback(null, map(pods, 'id'))
})
}
function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins, callback) {
listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins, callback) {
if (!callback) {
callback = tableWithPodsJoins
tableWithPodsJoins = ''
}
const self = this
self.count().asCallback(function (err, count) {
Pod.count().asCallback(function (err, count) {
if (err) return callback(err)
// Optimization...
@ -171,13 +190,13 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
where: {
id: {
$in: [
this.sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`)
Sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`)
]
}
}
}
return this.findAll(query).asCallback(function (err, pods) {
return Pod.findAll(query).asCallback(function (err, pods) {
if (err) return callback(err)
return callback(null, map(pods, 'id'))
@ -185,49 +204,47 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
})
}
function listBadPods (callback) {
listBadPods = function (callback) {
const query = {
where: {
score: { $lte: 0 }
}
}
return this.findAll(query).asCallback(callback)
return Pod.findAll(query).asCallback(callback)
}
function load (id, callback) {
return this.findById(id).asCallback(callback)
load = function (id, callback) {
return Pod.findById(id).asCallback(callback)
}
function loadByHost (host, callback) {
loadByHost = function (host, callback) {
const query = {
where: {
host: host
}
}
return this.findOne(query).asCallback(callback)
return Pod.findOne(query).asCallback(callback)
}
function removeAll (callback) {
return this.destroy().asCallback(callback)
removeAll = function (callback) {
return Pod.destroy().asCallback(callback)
}
function updatePodsScore (goodPods, badPods) {
const self = this
updatePodsScore = function (goodPods, badPods) {
logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
if (goodPods.length !== 0) {
this.incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
if (err) logger.error('Cannot increment scores of good pods.', { error: err })
})
}
if (badPods.length !== 0) {
this.incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
if (err) logger.error('Cannot decrement scores of bad pods.', { error: err })
removeBadPods.call(self)
removeBadPods()
})
}
}
@ -236,11 +253,9 @@ function updatePodsScore (goodPods, badPods) {
// Remove pods with a score of 0 (too many requests where they were unreachable)
function removeBadPods () {
const self = this
waterfall([
function findBadPods (callback) {
self.sequelize.models.Pod.listBadPods(function (err, pods) {
listBadPods(function (err, pods) {
if (err) {
logger.error('Cannot find bad pods.', { error: err })
return callback(err)

View file

@ -0,0 +1,32 @@
import * as Sequelize from 'sequelize'
import { PodAttributes } from './pod-interface'
export namespace RequestMethods {
export type CountTotalRequests = (callback) => void
export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
export type RemoveWithEmptyTo = (callback) => void
export type RemoveAll = (callback) => void
}
export interface RequestClass {
countTotalRequests: RequestMethods.CountTotalRequests
listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
removeAll: RequestMethods.RemoveAll
}
export interface RequestAttributes {
request: object
endpoint: string
}
export interface RequestInstance extends Sequelize.Instance<RequestAttributes> {
id: number
createdAt: Date
updatedAt: Date
setPods: Sequelize.HasManySetAssociationsMixin<PodAttributes, number>
}
export interface RequestModel extends RequestClass, Sequelize.Model<RequestInstance, RequestAttributes> {}

View file

@ -0,0 +1,20 @@
import * as Sequelize from 'sequelize'
export namespace RequestToPodMethods {
export type RemoveByRequestIdsAndPod = (requestsIds, podId, callback) => void
}
export interface RequestToPodClass {
removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
}
export interface RequestToPodAttributes {
}
export interface RequestToPodInstance extends Sequelize.Instance<RequestToPodAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface RequestToPodModel extends RequestToPodClass, Sequelize.Model<RequestToPodInstance, RequestToPodAttributes> {}

View file

@ -1,5 +1,19 @@
module.exports = function (sequelize, DataTypes) {
const RequestToPod = sequelize.define('RequestToPod', {}, {
import * as Sequelize from 'sequelize'
import { addMethodsToModel } from './utils'
import {
RequestToPodClass,
RequestToPodInstance,
RequestToPodAttributes,
RequestToPodMethods
} from './request-to-pod-interface'
let RequestToPod: Sequelize.Model<RequestToPodInstance, RequestToPodAttributes>
let removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
export default function (sequelize, DataTypes) {
RequestToPod = sequelize.define('RequestToPod', {}, {
indexes: [
{
fields: [ 'requestId' ]
@ -11,18 +25,20 @@ module.exports = function (sequelize, DataTypes) {
fields: [ 'requestId', 'podId' ],
unique: true
}
],
classMethods: {
removeByRequestIdsAndPod
}
]
})
const classMethods = [
removeByRequestIdsAndPod
]
addMethodsToModel(RequestToPod, classMethods)
return RequestToPod
}
// ---------------------------------------------------------------------------
function removeByRequestIdsAndPod (requestsIds, podId, callback) {
removeByRequestIdsAndPod = function (requestsIds, podId, callback) {
if (!callback) callback = function () { /* empty */ }
const query = {
@ -34,5 +50,5 @@ function removeByRequestIdsAndPod (requestsIds, podId, callback) {
}
}
this.destroy(query).asCallback(callback)
RequestToPod.destroy(query).asCallback(callback)
}

View file

@ -0,0 +1,26 @@
import * as Sequelize from 'sequelize'
export namespace RequestVideoEventMethods {
export type CountTotalRequests = (callback) => void
export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
export type RemoveAll = (callback) => void
}
export interface RequestVideoEventClass {
countTotalRequests: RequestVideoEventMethods.CountTotalRequests
listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
removeAll: RequestVideoEventMethods.RemoveAll
}
export interface RequestVideoEventAttributes {
type: string
count: number
}
export interface RequestVideoEventInstance extends Sequelize.Instance<RequestVideoEventAttributes> {
id: number
}
export interface RequestVideoEventModel extends RequestVideoEventClass, Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> {}

View file

@ -3,14 +3,28 @@
*/
import { values } from 'lodash'
import * as Sequelize from 'sequelize'
import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers'
import { isVideoEventCountValid } from '../helpers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
RequestVideoEventClass,
RequestVideoEventInstance,
RequestVideoEventAttributes,
module.exports = function (sequelize, DataTypes) {
const RequestVideoEvent = sequelize.define('RequestVideoEvent',
RequestVideoEventMethods
} from './request-video-event-interface'
let RequestVideoEvent: Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes>
let countTotalRequests: RequestVideoEventMethods.CountTotalRequests
let listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
let removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
let removeAll: RequestVideoEventMethods.RemoveAll
export default function (sequelize, DataTypes) {
RequestVideoEvent = sequelize.define('RequestVideoEvent',
{
type: {
type: DataTypes.ENUM(values(REQUEST_VIDEO_EVENT_TYPES)),
@ -33,26 +47,27 @@ module.exports = function (sequelize, DataTypes) {
{
fields: [ 'videoId' ]
}
],
classMethods: {
associate,
listWithLimitAndRandom,
countTotalRequests,
removeAll,
removeByRequestIdsAndPod
}
]
}
)
const classMethods = [
associate,
listWithLimitAndRandom,
countTotalRequests,
removeAll,
removeByRequestIdsAndPod
]
addMethodsToModel(RequestVideoEvent, classMethods)
return RequestVideoEvent
}
// ------------------------------ STATICS ------------------------------
function associate (models) {
this.belongsTo(models.Video, {
RequestVideoEvent.belongsTo(models.Video, {
foreignKey: {
name: 'videoId',
allowNull: false
@ -61,14 +76,13 @@ function associate (models) {
})
}
function countTotalRequests (callback) {
countTotalRequests = function (callback) {
const query = {}
return this.count(query).asCallback(callback)
return RequestVideoEvent.count(query).asCallback(callback)
}
function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
const self = this
const Pod = this.sequelize.models.Pod
listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
const Pod = RequestVideoEvent['sequelize'].models.Pod
// We make a join between videos and authors to find the podId of our video event requests
const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' +
@ -86,13 +100,13 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
],
include: [
{
model: self.sequelize.models.Video,
model: RequestVideoEvent['sequelize'].models.Video,
include: [
{
model: self.sequelize.models.Author,
model: RequestVideoEvent['sequelize'].models.Author,
include: [
{
model: self.sequelize.models.Pod,
model: RequestVideoEvent['sequelize'].models.Pod,
where: {
id: {
$in: podIds
@ -106,7 +120,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
]
}
self.findAll(query).asCallback(function (err, requests) {
RequestVideoEvent.findAll(query).asCallback(function (err, requests) {
if (err) return callback(err)
const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@ -115,7 +129,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
})
}
function removeByRequestIdsAndPod (ids, podId, callback) {
removeByRequestIdsAndPod = function (ids, podId, callback) {
const query = {
where: {
id: {
@ -124,10 +138,10 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
},
include: [
{
model: this.sequelize.models.Video,
model: RequestVideoEvent['sequelize'].models.Video,
include: [
{
model: this.sequelize.models.Author,
model: RequestVideoEvent['sequelize'].models.Author,
where: {
podId
}
@ -137,12 +151,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
]
}
this.destroy(query).asCallback(callback)
RequestVideoEvent.destroy(query).asCallback(callback)
}
function removeAll (callback) {
removeAll = function (callback) {
// Delete all requests
this.truncate({ cascade: true }).asCallback(callback)
RequestVideoEvent.truncate({ cascade: true }).asCallback(callback)
}
// ---------------------------------------------------------------------------

View file

@ -0,0 +1,25 @@
import * as Sequelize from 'sequelize'
export namespace RequestVideoQaduMethods {
export type CountTotalRequests = (callback) => void
export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
export type RemoveAll = (callback) => void
}
export interface RequestVideoQaduClass {
countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
removeAll: RequestVideoQaduMethods.RemoveAll
}
export interface RequestVideoQaduAttributes {
type: string
}
export interface RequestVideoQaduInstance extends Sequelize.Instance<RequestVideoQaduAttributes> {
id: number
}
export interface RequestVideoQaduModel extends RequestVideoQaduClass, Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes> {}

View file

@ -10,13 +10,27 @@
*/
import { values } from 'lodash'
import * as Sequelize from 'sequelize'
import { REQUEST_VIDEO_QADU_TYPES } from '../initializers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
RequestVideoQaduClass,
RequestVideoQaduInstance,
RequestVideoQaduAttributes,
module.exports = function (sequelize, DataTypes) {
const RequestVideoQadu = sequelize.define('RequestVideoQadu',
RequestVideoQaduMethods
} from './request-video-qadu-interface'
let RequestVideoQadu: Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes>
let countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
let listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
let removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
let removeAll: RequestVideoQaduMethods.RemoveAll
export default function (sequelize, DataTypes) {
RequestVideoQadu = sequelize.define('RequestVideoQadu',
{
type: {
type: DataTypes.ENUM(values(REQUEST_VIDEO_QADU_TYPES)),
@ -32,26 +46,27 @@ module.exports = function (sequelize, DataTypes) {
{
fields: [ 'videoId' ]
}
],
classMethods: {
associate,
listWithLimitAndRandom,
countTotalRequests,
removeAll,
removeByRequestIdsAndPod
}
]
}
)
const classMethods = [
associate,
listWithLimitAndRandom,
countTotalRequests,
removeAll,
removeByRequestIdsAndPod
]
addMethodsToModel(RequestVideoQadu, classMethods)
return RequestVideoQadu
}
// ------------------------------ STATICS ------------------------------
function associate (models) {
this.belongsTo(models.Pod, {
RequestVideoQadu.belongsTo(models.Pod, {
foreignKey: {
name: 'podId',
allowNull: false
@ -59,7 +74,7 @@ function associate (models) {
onDelete: 'CASCADE'
})
this.belongsTo(models.Video, {
RequestVideoQadu.belongsTo(models.Video, {
foreignKey: {
name: 'videoId',
allowNull: false
@ -68,14 +83,13 @@ function associate (models) {
})
}
function countTotalRequests (callback) {
countTotalRequests = function (callback) {
const query = {}
return this.count(query).asCallback(callback)
return RequestVideoQadu.count(query).asCallback(callback)
}
function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
const self = this
const Pod = this.sequelize.models.Pod
listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
const Pod = RequestVideoQadu['sequelize'].models.Pod
Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) {
if (err) return callback(err)
@ -86,7 +100,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
const query = {
include: [
{
model: self.sequelize.models.Pod,
model: RequestVideoQadu['sequelize'].models.Pod,
where: {
id: {
$in: podIds
@ -94,12 +108,12 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
}
},
{
model: self.sequelize.models.Video
model: RequestVideoQadu['sequelize'].models.Video
}
]
}
self.findAll(query).asCallback(function (err, requests) {
RequestVideoQadu.findAll(query).asCallback(function (err, requests) {
if (err) return callback(err)
const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@ -108,7 +122,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
})
}
function removeByRequestIdsAndPod (ids, podId, callback) {
removeByRequestIdsAndPod = function (ids, podId, callback) {
const query = {
where: {
id: {
@ -118,12 +132,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
}
}
this.destroy(query).asCallback(callback)
RequestVideoQadu.destroy(query).asCallback(callback)
}
function removeAll (callback) {
removeAll = function (callback) {
// Delete all requests
this.truncate({ cascade: true }).asCallback(callback)
RequestVideoQadu.truncate({ cascade: true }).asCallback(callback)
}
// ---------------------------------------------------------------------------

View file

@ -1,11 +1,25 @@
import { values } from 'lodash'
import * as Sequelize from 'sequelize'
import { REQUEST_ENDPOINTS } from '../initializers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
RequestClass,
RequestInstance,
RequestAttributes,
module.exports = function (sequelize, DataTypes) {
const Request = sequelize.define('Request',
RequestMethods
} from './request-interface'
let Request: Sequelize.Model<RequestInstance, RequestAttributes>
let countTotalRequests: RequestMethods.CountTotalRequests
let listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
let removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
let removeAll: RequestMethods.RemoveAll
export default function (sequelize, DataTypes) {
Request = sequelize.define('Request',
{
request: {
type: DataTypes.JSON,
@ -15,27 +29,27 @@ module.exports = function (sequelize, DataTypes) {
type: DataTypes.ENUM(values(REQUEST_ENDPOINTS)),
allowNull: false
}
},
{
classMethods: {
associate,
listWithLimitAndRandom,
countTotalRequests,
removeAll,
removeWithEmptyTo
}
}
)
const classMethods = [
associate,
listWithLimitAndRandom,
countTotalRequests,
removeAll,
removeWithEmptyTo
]
addMethodsToModel(Request, classMethods)
return Request
}
// ------------------------------ STATICS ------------------------------
function associate (models) {
this.belongsToMany(models.Pod, {
Request.belongsToMany(models.Pod, {
foreignKey: {
name: 'requestId',
allowNull: false
@ -45,19 +59,18 @@ function associate (models) {
})
}
function countTotalRequests (callback) {
countTotalRequests = function (callback) {
// We need to include Pod because there are no cascade delete when a pod is removed
// So we could count requests that do not have existing pod anymore
const query = {
include: [ this.sequelize.models.Pod ]
include: [ Request['sequelize'].models.Pod ]
}
return this.count(query).asCallback(callback)
return Request.count(query).asCallback(callback)
}
function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
const self = this
const Pod = this.sequelize.models.Pod
listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
const Pod = Request['sequelize'].models.Pod
Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) {
if (err) return callback(err)
@ -73,7 +86,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
],
include: [
{
model: self.sequelize.models.Pod,
model: Request['sequelize'].models.Pod,
where: {
id: {
$in: podIds
@ -83,7 +96,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
]
}
self.findAll(query).asCallback(function (err, requests) {
Request.findAll(query).asCallback(function (err, requests) {
if (err) return callback(err)
const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@ -92,25 +105,25 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
})
}
function removeAll (callback) {
removeAll = function (callback) {
// Delete all requests
this.truncate({ cascade: true }).asCallback(callback)
Request.truncate({ cascade: true }).asCallback(callback)
}
function removeWithEmptyTo (callback) {
removeWithEmptyTo = function (callback) {
if (!callback) callback = function () { /* empty */ }
const query = {
where: {
id: {
$notIn: [
this.sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
Sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
]
}
}
}
this.destroy(query).asCallback(callback)
Request.destroy(query).asCallback(callback)
}
// ---------------------------------------------------------------------------

View file

@ -0,0 +1,19 @@
import * as Sequelize from 'sequelize'
export namespace TagMethods {
export type FindOrCreateTags = (tags, transaction, callback) => void
}
export interface TagClass {
findOrCreateTags: TagMethods.FindOrCreateTags
}
export interface TagAttributes {
name: string
}
export interface TagInstance extends TagClass, TagAttributes, Sequelize.Instance<TagAttributes> {
id: number
}
export interface TagModel extends TagClass, Sequelize.Model<TagInstance, TagAttributes> {}

View file

@ -1,9 +1,20 @@
import { each } from 'async'
import * as Sequelize from 'sequelize'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
TagClass,
TagInstance,
TagAttributes,
module.exports = function (sequelize, DataTypes) {
const Tag = sequelize.define('Tag',
TagMethods
} from './tag-interface'
let Tag: Sequelize.Model<TagInstance, TagAttributes>
let findOrCreateTags: TagMethods.FindOrCreateTags
export default function (sequelize, DataTypes) {
Tag = sequelize.define('Tag',
{
name: {
type: DataTypes.STRING,
@ -17,35 +28,36 @@ module.exports = function (sequelize, DataTypes) {
fields: [ 'name' ],
unique: true
}
],
classMethods: {
associate,
findOrCreateTags
}
]
}
)
const classMethods = [
associate,
findOrCreateTags
]
addMethodsToModel(Tag, classMethods)
return Tag
}
// ---------------------------------------------------------------------------
function associate (models) {
this.belongsToMany(models.Video, {
Tag.belongsToMany(models.Video, {
foreignKey: 'tagId',
through: models.VideoTag,
onDelete: 'cascade'
})
}
function findOrCreateTags (tags, transaction, callback) {
findOrCreateTags = function (tags, transaction, callback) {
if (!callback) {
callback = transaction
transaction = null
}
const self = this
const tagInstances = []
each(tags, function (tag, callbackEach) {
@ -60,7 +72,7 @@ function findOrCreateTags (tags, transaction, callback) {
if (transaction) query.transaction = transaction
self.findOrCreate(query).asCallback(function (err, res) {
Tag.findOrCreate(query).asCallback(function (err, res) {
if (err) return callbackEach(err)
// res = [ tag, isCreated ]

View file

@ -0,0 +1,45 @@
import * as Sequelize from 'sequelize'
export namespace UserMethods {
export type IsPasswordMatch = (password, callback) => void
export type ToFormatedJSON = () => void
export type IsAdmin = () => boolean
export type CountTotal = (callback) => void
export type GetByUsername = (username) => any
export type List = (callback) => void
export type ListForApi = (start, count, sort, callback) => void
export type LoadById = (id, callback) => void
export type LoadByUsername = (username, callback) => void
export type LoadByUsernameOrEmail = (username, email, callback) => void
}
export interface UserClass {
isPasswordMatch: UserMethods.IsPasswordMatch,
toFormatedJSON: UserMethods.ToFormatedJSON,
isAdmin: UserMethods.IsAdmin,
countTotal: UserMethods.CountTotal,
getByUsername: UserMethods.GetByUsername,
list: UserMethods.List,
listForApi: UserMethods.ListForApi,
loadById: UserMethods.LoadById,
loadByUsername: UserMethods.LoadByUsername,
loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
}
export interface UserAttributes {
password: string
username: string
email: string
displayNSFW?: boolean
role: string
}
export interface UserInstance extends UserClass, UserAttributes, Sequelize.Instance<UserAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface UserModel extends UserClass, Sequelize.Model<UserInstance, UserAttributes> {}

View file

@ -0,0 +1,21 @@
import * as Sequelize from 'sequelize'
export namespace UserVideoRateMethods {
export type Load = (userId, videoId, transaction, callback) => void
}
export interface UserVideoRateClass {
load: UserVideoRateMethods.Load
}
export interface UserVideoRateAttributes {
type: string
}
export interface UserVideoRateInstance extends Sequelize.Instance<UserVideoRateAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface UserVideoRateModel extends UserVideoRateClass, Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes> {}

View file

@ -3,13 +3,24 @@
*/
import { values } from 'lodash'
import * as Sequelize from 'sequelize'
import { VIDEO_RATE_TYPES } from '../initializers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
UserVideoRateClass,
UserVideoRateInstance,
UserVideoRateAttributes,
module.exports = function (sequelize, DataTypes) {
const UserVideoRate = sequelize.define('UserVideoRate',
UserVideoRateMethods
} from './user-video-rate-interface'
let UserVideoRate: Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes>
let load: UserVideoRateMethods.Load
export default function (sequelize, DataTypes) {
UserVideoRate = sequelize.define('UserVideoRate',
{
type: {
type: DataTypes.ENUM(values(VIDEO_RATE_TYPES)),
@ -22,22 +33,24 @@ module.exports = function (sequelize, DataTypes) {
fields: [ 'videoId', 'userId', 'type' ],
unique: true
}
],
classMethods: {
associate,
load
}
]
}
)
const classMethods = [
associate,
load
]
addMethodsToModel(UserVideoRate, classMethods)
return UserVideoRate
}
// ------------------------------ STATICS ------------------------------
function associate (models) {
this.belongsTo(models.Video, {
UserVideoRate.belongsTo(models.Video, {
foreignKey: {
name: 'videoId',
allowNull: false
@ -45,7 +58,7 @@ function associate (models) {
onDelete: 'CASCADE'
})
this.belongsTo(models.User, {
UserVideoRate.belongsTo(models.User, {
foreignKey: {
name: 'userId',
allowNull: false
@ -54,21 +67,14 @@ function associate (models) {
})
}
function load (userId, videoId, transaction, callback) {
if (!callback) {
callback = transaction
transaction = null
}
const query = {
load = function (userId, videoId, transaction, callback) {
const options: Sequelize.FindOptions = {
where: {
userId,
videoId
}
}
const options: any = {}
if (transaction) options.transaction = transaction
return this.findOne(query, options).asCallback(callback)
return UserVideoRate.findOne(options).asCallback(callback)
}

View file

@ -1,4 +1,5 @@
import { values } from 'lodash'
import * as Sequelize from 'sequelize'
import { getSort } from './utils'
import { USER_ROLES } from '../initializers'
@ -10,10 +11,29 @@ import {
isUserDisplayNSFWValid
} from '../helpers'
// ---------------------------------------------------------------------------
import { addMethodsToModel } from './utils'
import {
UserClass,
UserInstance,
UserAttributes,
module.exports = function (sequelize, DataTypes) {
const User = sequelize.define('User',
UserMethods
} from './user-interface'
let User: Sequelize.Model<UserInstance, UserAttributes>
let isPasswordMatch: UserMethods.IsPasswordMatch
let toFormatedJSON: UserMethods.ToFormatedJSON
let isAdmin: UserMethods.IsAdmin
let countTotal: UserMethods.CountTotal
let getByUsername: UserMethods.GetByUsername
let list: UserMethods.List
let listForApi: UserMethods.ListForApi
let loadById: UserMethods.LoadById
let loadByUsername: UserMethods.LoadByUsername
let loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
export default function (sequelize, DataTypes) {
User = sequelize.define('User',
{
password: {
type: DataTypes.STRING,
@ -69,22 +89,6 @@ module.exports = function (sequelize, DataTypes) {
unique: true
}
],
classMethods: {
associate,
countTotal,
getByUsername,
list,
listForApi,
loadById,
loadByUsername,
loadByUsernameOrEmail
},
instanceMethods: {
isPasswordMatch,
toFormatedJSON,
isAdmin
},
hooks: {
beforeCreate: beforeCreateOrUpdate,
beforeUpdate: beforeCreateOrUpdate
@ -92,26 +96,46 @@ module.exports = function (sequelize, DataTypes) {
}
)
const classMethods = [
associate,
countTotal,
getByUsername,
list,
listForApi,
loadById,
loadByUsername,
loadByUsernameOrEmail
]
const instanceMethods = [
isPasswordMatch,
toFormatedJSON,
isAdmin
]
addMethodsToModel(User, classMethods, instanceMethods)
return User
}
function beforeCreateOrUpdate (user, options, next) {
cryptPassword(user.password, function (err, hash) {
if (err) return next(err)
function beforeCreateOrUpdate (user, options) {
return new Promise(function (resolve, reject) {
cryptPassword(user.password, function (err, hash) {
if (err) return reject(err)
user.password = hash
user.password = hash
return next()
return resolve()
})
})
}
// ------------------------------ METHODS ------------------------------
function isPasswordMatch (password, callback) {
isPasswordMatch = function (password, callback) {
return comparePassword(password, this.password, callback)
}
function toFormatedJSON () {
toFormatedJSON = function () {
return {
id: this.id,
username: this.username,
@ -122,76 +146,76 @@ function toFormatedJSON () {
}
}
function isAdmin () {
isAdmin = function () {
return this.role === USER_ROLES.ADMIN
}
// ------------------------------ STATICS ------------------------------
function associate (models) {
this.hasOne(models.Author, {
User.hasOne(models.Author, {
foreignKey: 'userId',
onDelete: 'cascade'
})
this.hasMany(models.OAuthToken, {
User.hasMany(models.OAuthToken, {
foreignKey: 'userId',
onDelete: 'cascade'
})
}
function countTotal (callback) {
countTotal = function (callback) {
return this.count().asCallback(callback)
}
function getByUsername (username) {
getByUsername = function (username) {
const query = {
where: {
username: username
}
}
return this.findOne(query)
return User.findOne(query)
}
function list (callback) {
return this.find().asCallback(callback)
list = function (callback) {
return User.find().asCallback(callback)
}
function listForApi (start, count, sort, callback) {
listForApi = function (start, count, sort, callback) {
const query = {
offset: start,
limit: count,
order: [ getSort(sort) ]
}
return this.findAndCountAll(query).asCallback(function (err, result) {
return User.findAndCountAll(query).asCallback(function (err, result) {
if (err) return callback(err)
return callback(null, result.rows, result.count)
})
}
function loadById (id, callback) {
return this.findById(id).asCallback(callback)
loadById = function (id, callback) {
return User.findById(id).asCallback(callback)
}
function loadByUsername (username, callback) {
loadByUsername = function (username, callback) {
const query = {
where: {
username: username
}
}
return this.findOne(query).asCallback(callback)
return User.findOne(query).asCallback(callback)
}
function loadByUsernameOrEmail (username, email, callback) {
loadByUsernameOrEmail = function (username, email, callback) {
const query = {
where: {
$or: [ { username }, { email } ]
}
}
return this.findOne(query).asCallback(callback)
return User.findOne(query).asCallback(callback)
}

View file

@ -14,8 +14,14 @@ function getSort (value) {
return [ field, direction ]
}
function addMethodsToModel (model: any, classMethods: Function[], instanceMethods: Function[] = []) {
classMethods.forEach(m => model[m.name] = m)
instanceMethods.forEach(m => model.prototype[m.name] = m)
}
// ---------------------------------------------------------------------------
export {
addMethodsToModel,
getSort
}

View file

@ -0,0 +1,24 @@
import * as Sequelize from 'sequelize'
export namespace VideoAbuseMethods {
export type toFormatedJSON = () => void
export type ListForApi = (start, count, sort, callback) => void
}
export interface VideoAbuseClass {
listForApi: VideoAbuseMethods.ListForApi
}
export interface VideoAbuseAttributes {
reporterUsername: string
reason: string
}
export interface VideoAbuseInstance extends Sequelize.Instance<VideoAbuseAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface VideoAbuseModel extends VideoAbuseClass, Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes> {}

View file

@ -1,9 +1,22 @@
import * as Sequelize from 'sequelize'
import { CONFIG } from '../initializers'
import { isVideoAbuseReporterUsernameValid, isVideoAbuseReasonValid } from '../helpers'
import { getSort } from './utils'
module.exports = function (sequelize, DataTypes) {
const VideoAbuse = sequelize.define('VideoAbuse',
import { addMethodsToModel, getSort } from './utils'
import {
VideoAbuseClass,
VideoAbuseInstance,
VideoAbuseAttributes,
VideoAbuseMethods
} from './video-abuse-interface'
let VideoAbuse: Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes>
let listForApi: VideoAbuseMethods.ListForApi
export default function (sequelize, DataTypes) {
VideoAbuse = sequelize.define('VideoAbuse',
{
reporterUsername: {
type: DataTypes.STRING,
@ -34,60 +47,24 @@ module.exports = function (sequelize, DataTypes) {
{
fields: [ 'reporterPodId' ]
}
],
classMethods: {
associate,
listForApi
},
instanceMethods: {
toFormatedJSON
}
]
}
)
const classMethods = [
associate,
listForApi
]
const instanceMethods = [
toFormatedJSON
]
addMethodsToModel(VideoAbuse, classMethods, instanceMethods)
return VideoAbuse
}
// ---------------------------------------------------------------------------
function associate (models) {
this.belongsTo(models.Pod, {
foreignKey: {
name: 'reporterPodId',
allowNull: true
},
onDelete: 'cascade'
})
this.belongsTo(models.Video, {
foreignKey: {
name: 'videoId',
allowNull: false
},
onDelete: 'cascade'
})
}
function listForApi (start, count, sort, callback) {
const query = {
offset: start,
limit: count,
order: [ getSort(sort) ],
include: [
{
model: this.sequelize.models.Pod,
required: false
}
]
}
return this.findAndCountAll(query).asCallback(function (err, result) {
if (err) return callback(err)
return callback(null, result.rows, result.count)
})
}
// ------------------------------ METHODS ------------------------------
function toFormatedJSON () {
let reporterPodHost
@ -110,3 +87,45 @@ function toFormatedJSON () {
return json
}
// ------------------------------ STATICS ------------------------------
function associate (models) {
VideoAbuse.belongsTo(models.Pod, {
foreignKey: {
name: 'reporterPodId',
allowNull: true
},
onDelete: 'cascade'
})
VideoAbuse.belongsTo(models.Video, {
foreignKey: {
name: 'videoId',
allowNull: false
},
onDelete: 'cascade'
})
}
listForApi = function (start, count, sort, callback) {
const query = {
offset: start,
limit: count,
order: [ getSort(sort) ],
include: [
{
model: VideoAbuse['sequelize'].models.Pod,
required: false
}
]
}
return VideoAbuse.findAndCountAll(query).asCallback(function (err, result) {
if (err) return callback(err)
return callback(null, result.rows, result.count)
})
}

View file

@ -0,0 +1,31 @@
import * as Sequelize from 'sequelize'
export namespace BlacklistedVideoMethods {
export type ToFormatedJSON = () => void
export type CountTotal = (callback) => void
export type List = (callback) => void
export type ListForApi = (start, count, sort, callback) => void
export type LoadById = (id, callback) => void
export type LoadByVideoId = (id, callback) => void
}
export interface BlacklistedVideoClass {
toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
countTotal: BlacklistedVideoMethods.CountTotal
list: BlacklistedVideoMethods.List
listForApi: BlacklistedVideoMethods.ListForApi
loadById: BlacklistedVideoMethods.LoadById
loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
}
export interface BlacklistedVideoAttributes {
}
export interface BlacklistedVideoInstance extends BlacklistedVideoClass, BlacklistedVideoAttributes, Sequelize.Instance<BlacklistedVideoAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface BlacklistedVideoModel extends BlacklistedVideoClass, Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes> {}

View file

@ -1,9 +1,24 @@
import { getSort } from './utils'
import * as Sequelize from 'sequelize'
// ---------------------------------------------------------------------------
import { addMethodsToModel, getSort } from './utils'
import {
BlacklistedVideoClass,
BlacklistedVideoInstance,
BlacklistedVideoAttributes,
module.exports = function (sequelize, DataTypes) {
const BlacklistedVideo = sequelize.define('BlacklistedVideo',
BlacklistedVideoMethods
} from './video-blacklist-interface'
let BlacklistedVideo: Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes>
let toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
let countTotal: BlacklistedVideoMethods.CountTotal
let list: BlacklistedVideoMethods.List
let listForApi: BlacklistedVideoMethods.ListForApi
let loadById: BlacklistedVideoMethods.LoadById
let loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
export default function (sequelize, DataTypes) {
BlacklistedVideo = sequelize.define('BlacklistedVideo',
{},
{
indexes: [
@ -11,29 +26,30 @@ module.exports = function (sequelize, DataTypes) {
fields: [ 'videoId' ],
unique: true
}
],
classMethods: {
associate,
countTotal,
list,
listForApi,
loadById,
loadByVideoId
},
instanceMethods: {
toFormatedJSON
},
hooks: {}
]
}
)
const classMethods = [
associate,
countTotal,
list,
listForApi,
loadById,
loadByVideoId
]
const instanceMethods = [
toFormatedJSON
]
addMethodsToModel(BlacklistedVideo, classMethods, instanceMethods)
return BlacklistedVideo
}
// ------------------------------ METHODS ------------------------------
function toFormatedJSON () {
toFormatedJSON = function () {
return {
id: this.id,
videoId: this.videoId,
@ -44,44 +60,44 @@ function toFormatedJSON () {
// ------------------------------ STATICS ------------------------------
function associate (models) {
this.belongsTo(models.Video, {
BlacklistedVideo.belongsTo(models.Video, {
foreignKey: 'videoId',
onDelete: 'cascade'
})
}
function countTotal (callback) {
return this.count().asCallback(callback)
countTotal = function (callback) {
return BlacklistedVideo.count().asCallback(callback)
}
function list (callback) {
return this.findAll().asCallback(callback)
list = function (callback) {
return BlacklistedVideo.findAll().asCallback(callback)
}
function listForApi (start, count, sort, callback) {
listForApi = function (start, count, sort, callback) {
const query = {
offset: start,
limit: count,
order: [ getSort(sort) ]
}
return this.findAndCountAll(query).asCallback(function (err, result) {
return BlacklistedVideo.findAndCountAll(query).asCallback(function (err, result) {
if (err) return callback(err)
return callback(null, result.rows, result.count)
})
}
function loadById (id, callback) {
return this.findById(id).asCallback(callback)
loadById = function (id, callback) {
return BlacklistedVideo.findById(id).asCallback(callback)
}
function loadByVideoId (id, callback) {
loadByVideoId = function (id, callback) {
const query = {
where: {
videoId: id
}
}
return this.find(query).asCallback(callback)
return BlacklistedVideo.find(query).asCallback(callback)
}

View file

@ -0,0 +1,75 @@
import * as Sequelize from 'sequelize'
export namespace VideoMethods {
export type GenerateMagnetUri = () => void
export type GetVideoFilename = () => void
export type GetThumbnailName = () => void
export type GetPreviewName = () => void
export type GetTorrentName = () => void
export type IsOwned = () => void
export type ToFormatedJSON = () => void
export type ToAddRemoteJSON = (callback) => void
export type ToUpdateRemoteJSON = (callback) => void
export type TranscodeVideofile = (callback) => void
export type GenerateThumbnailFromData = (video, thumbnailData, callback) => void
export type GetDurationFromFile = (videoPath, callback) => void
export type List = (callback) => void
export type ListForApi = (start, count, sort, callback) => void
export type LoadByHostAndRemoteId = (fromHost, remoteId, callback) => void
export type ListOwnedAndPopulateAuthorAndTags = (callback) => void
export type ListOwnedByAuthor = (author, callback) => void
export type Load = (id, callback) => void
export type LoadAndPopulateAuthor = (id, callback) => void
export type LoadAndPopulateAuthorAndPodAndTags = (id, callback) => void
export type SearchAndPopulateAuthorAndPodAndTags = (value, field, start, count, sort, callback) => void
}
export interface VideoClass {
generateMagnetUri: VideoMethods.GenerateMagnetUri
getVideoFilename: VideoMethods.GetVideoFilename
getThumbnailName: VideoMethods.GetThumbnailName
getPreviewName: VideoMethods.GetPreviewName
getTorrentName: VideoMethods.GetTorrentName
isOwned: VideoMethods.IsOwned
toFormatedJSON: VideoMethods.ToFormatedJSON
toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
transcodeVideofile: VideoMethods.TranscodeVideofile
generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
getDurationFromFile: VideoMethods.GetDurationFromFile
list: VideoMethods.List
listForApi: VideoMethods.ListForApi
loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
load: VideoMethods.Load
loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
}
export interface VideoAttributes {
name: string
extname: string
remoteId: string
category: number
licence: number
language: number
nsfw: boolean
description: string
infoHash?: string
duration: number
views?: number
likes?: number
dislikes?: number
}
export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> {
id: string
createdAt: Date
updatedAt: Date
}
export interface VideoModel extends VideoClass, Sequelize.Model<VideoInstance, VideoAttributes> {}

View file

@ -0,0 +1,18 @@
import * as Sequelize from 'sequelize'
export namespace VideoTagMethods {
}
export interface VideoTagClass {
}
export interface VideoTagAttributes {
}
export interface VideoTagInstance extends Sequelize.Instance<VideoTagAttributes> {
id: number
createdAt: Date
updatedAt: Date
}
export interface VideoTagModel extends VideoTagClass, Sequelize.Model<VideoTagInstance, VideoTagAttributes> {}

View file

@ -1,5 +1,18 @@
module.exports = function (sequelize, DataTypes) {
const VideoTag = sequelize.define('VideoTag', {}, {
import * as Sequelize from 'sequelize'
import { addMethodsToModel } from './utils'
import {
VideoTagClass,
VideoTagInstance,
VideoTagAttributes,
VideoTagMethods
} from './video-tag-interface'
let VideoTag: Sequelize.Model<VideoTagInstance, VideoTagAttributes>
export default function (sequelize, DataTypes) {
VideoTag = sequelize.define('VideoTag', {}, {
indexes: [
{
fields: [ 'videoId' ]

View file

@ -8,8 +8,9 @@ import { map, values } from 'lodash'
import { parallel, series } from 'async'
import parseTorrent = require('parse-torrent')
import { join } from 'path'
import * as Sequelize from 'sequelize'
const db = require('../initializers/database')
import { database as db } from '../initializers/database'
import {
logger,
isVideoNameValid,
@ -32,12 +33,42 @@ import {
THUMBNAILS_SIZE
} from '../initializers'
import { JobScheduler, removeVideoToFriends } from '../lib'
import { getSort } from './utils'
// ---------------------------------------------------------------------------
import { addMethodsToModel, getSort } from './utils'
import {
VideoClass,
VideoInstance,
VideoAttributes,
module.exports = function (sequelize, DataTypes) {
const Video = sequelize.define('Video',
VideoMethods
} from './video-interface'
let Video: Sequelize.Model<VideoInstance, VideoAttributes>
let generateMagnetUri: VideoMethods.GenerateMagnetUri
let getVideoFilename: VideoMethods.GetVideoFilename
let getThumbnailName: VideoMethods.GetThumbnailName
let getPreviewName: VideoMethods.GetPreviewName
let getTorrentName: VideoMethods.GetTorrentName
let isOwned: VideoMethods.IsOwned
let toFormatedJSON: VideoMethods.ToFormatedJSON
let toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
let toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
let transcodeVideofile: VideoMethods.TranscodeVideofile
let generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
let getDurationFromFile: VideoMethods.GetDurationFromFile
let list: VideoMethods.List
let listForApi: VideoMethods.ListForApi
let loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
let listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
let listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
let load: VideoMethods.Load
let loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
let loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
let searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
export default function (sequelize, DataTypes) {
Video = sequelize.define('Video',
{
id: {
type: DataTypes.UUID,
@ -194,34 +225,6 @@ module.exports = function (sequelize, DataTypes) {
fields: [ 'likes' ]
}
],
classMethods: {
associate,
generateThumbnailFromData,
getDurationFromFile,
list,
listForApi,
listOwnedAndPopulateAuthorAndTags,
listOwnedByAuthor,
load,
loadByHostAndRemoteId,
loadAndPopulateAuthor,
loadAndPopulateAuthorAndPodAndTags,
searchAndPopulateAuthorAndPodAndTags
},
instanceMethods: {
generateMagnetUri,
getVideoFilename,
getThumbnailName,
getPreviewName,
getTorrentName,
isOwned,
toFormatedJSON,
toAddRemoteJSON,
toUpdateRemoteJSON,
transcodeVideofile,
removeFromBlacklist
},
hooks: {
beforeValidate,
beforeCreate,
@ -230,99 +233,139 @@ module.exports = function (sequelize, DataTypes) {
}
)
const classMethods = [
associate,
generateThumbnailFromData,
getDurationFromFile,
list,
listForApi,
listOwnedAndPopulateAuthorAndTags,
listOwnedByAuthor,
load,
loadByHostAndRemoteId,
loadAndPopulateAuthor,
loadAndPopulateAuthorAndPodAndTags,
searchAndPopulateAuthorAndPodAndTags
]
const instanceMethods = [
generateMagnetUri,
getVideoFilename,
getThumbnailName,
getPreviewName,
getTorrentName,
isOwned,
toFormatedJSON,
toAddRemoteJSON,
toUpdateRemoteJSON,
transcodeVideofile,
removeFromBlacklist
]
addMethodsToModel(Video, classMethods, instanceMethods)
return Video
}
function beforeValidate (video, options, next) {
function beforeValidate (video, options) {
// Put a fake infoHash if it does not exists yet
if (video.isOwned() && !video.infoHash) {
// 40 hexa length
video.infoHash = '0123456789abcdef0123456789abcdef01234567'
}
return next(null)
}
function beforeCreate (video, options, next) {
const tasks = []
function beforeCreate (video, options) {
return new Promise(function (resolve, reject) {
const tasks = []
if (video.isOwned()) {
const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
if (video.isOwned()) {
const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
tasks.push(
function createVideoTorrent (callback) {
createTorrentFromVideo(video, videoPath, callback)
},
function createVideoThumbnail (callback) {
createThumbnail(video, videoPath, callback)
},
function createVideoPreview (callback) {
createPreview(video, videoPath, callback)
}
)
if (CONFIG.TRANSCODING.ENABLED === true) {
tasks.push(
function createVideoTranscoderJob (callback) {
const dataInput = {
id: video.id
}
JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback)
}
)
}
return parallel(tasks, function (err) {
if (err) return reject(err)
return resolve()
})
}
return resolve()
})
}
function afterDestroy (video, options) {
return new Promise(function (resolve, reject) {
const tasks = []
tasks.push(
function createVideoTorrent (callback) {
createTorrentFromVideo(video, videoPath, callback)
},
function createVideoThumbnail (callback) {
createThumbnail(video, videoPath, callback)
},
function createVideoPreview (callback) {
createPreview(video, videoPath, callback)
function (callback) {
removeThumbnail(video, callback)
}
)
if (CONFIG.TRANSCODING.ENABLED === true) {
if (video.isOwned()) {
tasks.push(
function createVideoTranscoderJob (callback) {
const dataInput = {
id: video.id
function removeVideoFile (callback) {
removeFile(video, callback)
},
function removeVideoTorrent (callback) {
removeTorrent(video, callback)
},
function removeVideoPreview (callback) {
removePreview(video, callback)
},
function notifyFriends (callback) {
const params = {
remoteId: video.id
}
JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback)
removeVideoToFriends(params)
return callback()
}
)
}
return parallel(tasks, next)
}
parallel(tasks, function (err) {
if (err) return reject(err)
return next()
}
function afterDestroy (video, options, next) {
const tasks = []
tasks.push(
function (callback) {
removeThumbnail(video, callback)
}
)
if (video.isOwned()) {
tasks.push(
function removeVideoFile (callback) {
removeFile(video, callback)
},
function removeVideoTorrent (callback) {
removeTorrent(video, callback)
},
function removeVideoPreview (callback) {
removePreview(video, callback)
},
function removeVideoToFriends (callback) {
const params = {
remoteId: video.id
}
removeVideoToFriends(params)
return callback()
}
)
}
parallel(tasks, next)
return resolve()
})
})
}
// ------------------------------ METHODS ------------------------------
function associate (models) {
this.belongsTo(models.Author, {
Video.belongsTo(models.Author, {
foreignKey: {
name: 'authorId',
allowNull: false
@ -330,13 +373,13 @@ function associate (models) {
onDelete: 'cascade'
})
this.belongsToMany(models.Tag, {
Video.belongsToMany(models.Tag, {
foreignKey: 'videoId',
through: models.VideoTag,
onDelete: 'cascade'
})
this.hasMany(models.VideoAbuse, {
Video.hasMany(models.VideoAbuse, {
foreignKey: {
name: 'videoId',
allowNull: false
@ -345,7 +388,7 @@ function associate (models) {
})
}
function generateMagnetUri () {
generateMagnetUri = function () {
let baseUrlHttp
let baseUrlWs
@ -372,18 +415,18 @@ function generateMagnetUri () {
return magnetUtil.encode(magnetHash)
}
function getVideoFilename () {
getVideoFilename = function () {
if (this.isOwned()) return this.id + this.extname
return this.remoteId + this.extname
}
function getThumbnailName () {
getThumbnailName = function () {
// We always have a copy of the thumbnail
return this.id + '.jpg'
}
function getPreviewName () {
getPreviewName = function () {
const extension = '.jpg'
if (this.isOwned()) return this.id + extension
@ -391,7 +434,7 @@ function getPreviewName () {
return this.remoteId + extension
}
function getTorrentName () {
getTorrentName = function () {
const extension = '.torrent'
if (this.isOwned()) return this.id + extension
@ -399,11 +442,11 @@ function getTorrentName () {
return this.remoteId + extension
}
function isOwned () {
isOwned = function () {
return this.remoteId === null
}
function toFormatedJSON () {
toFormatedJSON = function () {
let podHost
if (this.Author.Pod) {
@ -453,43 +496,41 @@ function toFormatedJSON () {
return json
}
function toAddRemoteJSON (callback) {
const self = this
toAddRemoteJSON = function (callback) {
// Get thumbnail data to send to the other pod
const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
fs.readFile(thumbnailPath, function (err, thumbnailData) {
fs.readFile(thumbnailPath, (err, thumbnailData) => {
if (err) {
logger.error('Cannot read the thumbnail of the video')
return callback(err)
}
const remoteVideo = {
name: self.name,
category: self.category,
licence: self.licence,
language: self.language,
nsfw: self.nsfw,
description: self.description,
infoHash: self.infoHash,
remoteId: self.id,
author: self.Author.name,
duration: self.duration,
name: this.name,
category: this.category,
licence: this.licence,
language: this.language,
nsfw: this.nsfw,
description: this.description,
infoHash: this.infoHash,
remoteId: this.id,
author: this.Author.name,
duration: this.duration,
thumbnailData: thumbnailData.toString('binary'),
tags: map(self.Tags, 'name'),
createdAt: self.createdAt,
updatedAt: self.updatedAt,
extname: self.extname,
views: self.views,
likes: self.likes,
dislikes: self.dislikes
tags: map(this.Tags, 'name'),
createdAt: this.createdAt,
updatedAt: this.updatedAt,
extname: this.extname,
views: this.views,
likes: this.likes,
dislikes: this.dislikes
}
return callback(null, remoteVideo)
})
}
function toUpdateRemoteJSON (callback) {
toUpdateRemoteJSON = function (callback) {
const json = {
name: this.name,
category: this.category,
@ -513,7 +554,7 @@ function toUpdateRemoteJSON (callback) {
return json
}
function transcodeVideofile (finalCallback) {
transcodeVideofile = function (finalCallback) {
const video = this
const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
@ -568,7 +609,7 @@ function transcodeVideofile (finalCallback) {
// ------------------------------ STATICS ------------------------------
function generateThumbnailFromData (video, thumbnailData, callback) {
generateThumbnailFromData = function (video, thumbnailData, callback) {
// Creating the thumbnail for a remote video
const thumbnailName = video.getThumbnailName()
@ -580,7 +621,7 @@ function generateThumbnailFromData (video, thumbnailData, callback) {
})
}
function getDurationFromFile (videoPath, callback) {
getDurationFromFile = function (videoPath, callback) {
ffmpeg.ffprobe(videoPath, function (err, metadata) {
if (err) return callback(err)
@ -588,46 +629,46 @@ function getDurationFromFile (videoPath, callback) {
})
}
function list (callback) {
return this.findAll().asCallback(callback)
list = function (callback) {
return Video.findAll().asCallback(callback)
}
function listForApi (start, count, sort, callback) {
listForApi = function (start, count, sort, callback) {
// Exclude Blakclisted videos from the list
const query = {
distinct: true,
offset: start,
limit: count,
distinct: true, // For the count, a video can have many tags
order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ],
order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ],
include: [
{
model: this.sequelize.models.Author,
include: [ { model: this.sequelize.models.Pod, required: false } ]
model: Video['sequelize'].models.Author,
include: [ { model: Video['sequelize'].models.Pod, required: false } ]
},
this.sequelize.models.Tag
Video['sequelize'].models.Tag
],
where: createBaseVideosWhere.call(this)
where: createBaseVideosWhere()
}
return this.findAndCountAll(query).asCallback(function (err, result) {
return Video.findAndCountAll(query).asCallback(function (err, result) {
if (err) return callback(err)
return callback(null, result.rows, result.count)
})
}
function loadByHostAndRemoteId (fromHost, remoteId, callback) {
loadByHostAndRemoteId = function (fromHost, remoteId, callback) {
const query = {
where: {
remoteId: remoteId
},
include: [
{
model: this.sequelize.models.Author,
model: Video['sequelize'].models.Author,
include: [
{
model: this.sequelize.models.Pod,
model: Video['sequelize'].models.Pod,
required: true,
where: {
host: fromHost
@ -638,29 +679,29 @@ function loadByHostAndRemoteId (fromHost, remoteId, callback) {
]
}
return this.findOne(query).asCallback(callback)
return Video.findOne(query).asCallback(callback)
}
function listOwnedAndPopulateAuthorAndTags (callback) {
listOwnedAndPopulateAuthorAndTags = function (callback) {
// If remoteId is null this is *our* video
const query = {
where: {
remoteId: null
},
include: [ this.sequelize.models.Author, this.sequelize.models.Tag ]
include: [ Video['sequelize'].models.Author, Video['sequelize'].models.Tag ]
}
return this.findAll(query).asCallback(callback)
return Video.findAll(query).asCallback(callback)
}
function listOwnedByAuthor (author, callback) {
listOwnedByAuthor = function (author, callback) {
const query = {
where: {
remoteId: null
},
include: [
{
model: this.sequelize.models.Author,
model: Video['sequelize'].models.Author,
where: {
name: author
}
@ -668,58 +709,58 @@ function listOwnedByAuthor (author, callback) {
]
}
return this.findAll(query).asCallback(callback)
return Video.findAll(query).asCallback(callback)
}
function load (id, callback) {
return this.findById(id).asCallback(callback)
load = function (id, callback) {
return Video.findById(id).asCallback(callback)
}
function loadAndPopulateAuthor (id, callback) {
loadAndPopulateAuthor = function (id, callback) {
const options = {
include: [ this.sequelize.models.Author ]
include: [ Video['sequelize'].models.Author ]
}
return this.findById(id, options).asCallback(callback)
return Video.findById(id, options).asCallback(callback)
}
function loadAndPopulateAuthorAndPodAndTags (id, callback) {
loadAndPopulateAuthorAndPodAndTags = function (id, callback) {
const options = {
include: [
{
model: this.sequelize.models.Author,
include: [ { model: this.sequelize.models.Pod, required: false } ]
model: Video['sequelize'].models.Author,
include: [ { model: Video['sequelize'].models.Pod, required: false } ]
},
this.sequelize.models.Tag
Video['sequelize'].models.Tag
]
}
return this.findById(id, options).asCallback(callback)
return Video.findById(id, options).asCallback(callback)
}
function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort, callback) {
searchAndPopulateAuthorAndPodAndTags = function (value, field, start, count, sort, callback) {
const podInclude: any = {
model: this.sequelize.models.Pod,
model: Video['sequelize'].models.Pod,
required: false
}
const authorInclude: any = {
model: this.sequelize.models.Author,
model: Video['sequelize'].models.Author,
include: [
podInclude
]
}
const tagInclude: any = {
model: this.sequelize.models.Tag
model: Video['sequelize'].models.Tag
}
const query: any = {
where: createBaseVideosWhere.call(this),
distinct: true,
where: createBaseVideosWhere(),
offset: start,
limit: count,
distinct: true, // For the count, a video can have many tags
order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ]
order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ]
}
// Make an exact search with the magnet
@ -727,8 +768,8 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
const infoHash = magnetUtil.decode(value).infoHash
query.where.infoHash = infoHash
} else if (field === 'tags') {
const escapedValue = this.sequelize.escape('%' + value + '%')
query.where.id.$in = this.sequelize.literal(
const escapedValue = Video['sequelize'].escape('%' + value + '%')
query.where.id.$in = Video['sequelize'].literal(
'(SELECT "VideoTags"."videoId" FROM "Tags" INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" WHERE name LIKE ' + escapedValue + ')'
)
} else if (field === 'host') {
@ -758,10 +799,10 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
]
if (tagInclude.where) {
// query.include.push([ this.sequelize.models.Tag ])
// query.include.push([ Video['sequelize'].models.Tag ])
}
return this.findAndCountAll(query).asCallback(function (err, result) {
return Video.findAndCountAll(query).asCallback(function (err, result) {
if (err) return callback(err)
return callback(null, result.rows, result.count)
@ -773,7 +814,7 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
function createBaseVideosWhere () {
return {
id: {
$notIn: this.sequelize.literal(
$notIn: Video['sequelize'].literal(
'(SELECT "BlacklistedVideos"."videoId" FROM "BlacklistedVideos")'
)
}

View file

@ -12,7 +12,7 @@ const loginUtils = require('../utils/login')
const serversUtils = require('../utils/servers')
const videosUtils = require('../utils/videos')
describe('Test video blacklists', function () {
describe('Test video transcoding', function () {
let servers = []
before(function (done) {

View file

@ -82,7 +82,7 @@ function runServer (number, callback) {
detached: true
}
server.app = fork(pathUtils.join(__dirname, '..', '..', '..', 'server.js'), [], options)
server.app = fork(pathUtils.join(__dirname, '..', '..', '..', 'dist', 'server.js'), [], options)
server.app.stdout.on('data', function onStdout (data) {
let dontContinue = false