Add blockedAccounts/blockedHosts support
This commit is contained in:
parent
3c603d2324
commit
0feb8973a8
2
PeerTube
2
PeerTube
|
@ -1 +1 @@
|
||||||
Subproject commit 68ca61941e3a7ca4c018566d2c496afd27dbd76d
|
Subproject commit 99139e7753e20ab0fba8eae5638d3dd3e792fe43
|
|
@ -48,6 +48,7 @@
|
||||||
"@types/body-parser": "^1.16.3",
|
"@types/body-parser": "^1.16.3",
|
||||||
"@types/config": "^0.0.36",
|
"@types/config": "^0.0.36",
|
||||||
"@types/express": "^4.16.1",
|
"@types/express": "^4.16.1",
|
||||||
|
"@types/fluent-ffmpeg": "^2.1.14",
|
||||||
"@types/lodash": "^4.14.149",
|
"@types/lodash": "^4.14.149",
|
||||||
"@types/mkdirp": "^1.0.0",
|
"@types/mkdirp": "^1.0.0",
|
||||||
"@types/morgan": "^1.7.32",
|
"@types/morgan": "^1.7.32",
|
||||||
|
|
|
@ -49,7 +49,7 @@ app.use(function (err, req, res, next) {
|
||||||
error = err.stack || err.message || err
|
error = err.stack || err.message || err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.error('Error in controller.', { error })
|
logger.error({ error }, 'Error in controller.')
|
||||||
return res.status(err.status || 500).end()
|
return res.status(err.status || 500).end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { asyncMiddleware } from '../../middlewares/async'
|
||||||
import { setDefaultPagination } from '../../middlewares/pagination'
|
import { setDefaultPagination } from '../../middlewares/pagination'
|
||||||
import { setDefaultSearchSort } from '../../middlewares/sort'
|
import { setDefaultSearchSort } from '../../middlewares/sort'
|
||||||
import { paginationValidator } from '../../middlewares/validators/pagination'
|
import { paginationValidator } from '../../middlewares/validators/pagination'
|
||||||
import { videoChannelsSearchValidator } from '../../middlewares/validators/search'
|
import { videoChannelsSearchValidator, commonFiltersValidators } from '../../middlewares/validators/search'
|
||||||
import { channelsSearchSortValidator } from '../../middlewares/validators/sort'
|
import { channelsSearchSortValidator } from '../../middlewares/validators/sort'
|
||||||
|
|
||||||
const searchChannelsRouter = express.Router()
|
const searchChannelsRouter = express.Router()
|
||||||
|
@ -15,6 +15,7 @@ searchChannelsRouter.get('/search/video-channels',
|
||||||
setDefaultPagination,
|
setDefaultPagination,
|
||||||
channelsSearchSortValidator,
|
channelsSearchSortValidator,
|
||||||
setDefaultSearchSort,
|
setDefaultSearchSort,
|
||||||
|
commonFiltersValidators,
|
||||||
videoChannelsSearchValidator,
|
videoChannelsSearchValidator,
|
||||||
asyncMiddleware(searchChannels)
|
asyncMiddleware(searchChannels)
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,8 +4,9 @@ import { setDefaultPagination } from '../../middlewares/pagination'
|
||||||
import { asyncMiddleware } from '../../middlewares/async'
|
import { asyncMiddleware } from '../../middlewares/async'
|
||||||
import { formatVideoForAPI, queryVideos } from '../../lib/elastic-search-videos'
|
import { formatVideoForAPI, queryVideos } from '../../lib/elastic-search-videos'
|
||||||
import { videosSearchSortValidator } from '../../middlewares/validators/sort'
|
import { videosSearchSortValidator } from '../../middlewares/validators/sort'
|
||||||
import { commonVideosFiltersValidator, videosSearchValidator } from '../../middlewares/validators/search'
|
import { commonVideosFiltersValidator, videosSearchValidator, commonFiltersValidators } from '../../middlewares/validators/search'
|
||||||
import { setDefaultSearchSort } from '../../middlewares/sort'
|
import { setDefaultSearchSort } from '../../middlewares/sort'
|
||||||
|
import { VideosSearchQuery } from 'server/types/video-search.model'
|
||||||
|
|
||||||
const searchVideosRouter = express.Router()
|
const searchVideosRouter = express.Router()
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ searchVideosRouter.get('/search/videos',
|
||||||
setDefaultPagination,
|
setDefaultPagination,
|
||||||
videosSearchSortValidator,
|
videosSearchSortValidator,
|
||||||
setDefaultSearchSort,
|
setDefaultSearchSort,
|
||||||
|
commonFiltersValidators,
|
||||||
commonVideosFiltersValidator,
|
commonVideosFiltersValidator,
|
||||||
videosSearchValidator,
|
videosSearchValidator,
|
||||||
asyncMiddleware(searchVideos)
|
asyncMiddleware(searchVideos)
|
||||||
|
@ -26,10 +28,12 @@ export { searchVideosRouter }
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
async function searchVideos (req: express.Request, res: express.Response) {
|
async function searchVideos (req: express.Request, res: express.Response) {
|
||||||
const resultList = await queryVideos(req.query)
|
const query = req.query as VideosSearchQuery
|
||||||
|
|
||||||
|
const resultList = await queryVideos(query)
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
total: resultList.total,
|
total: resultList.total,
|
||||||
data: resultList.data.map(v => formatVideoForAPI(v, req.query.fromHost as string))
|
data: resultList.data.map(v => formatVideoForAPI(v, query.fromHost))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ async function indexDocuments <T extends IndexableDoc> (options: {
|
||||||
|
|
||||||
if (resultBody.errors === true) {
|
if (resultBody.errors === true) {
|
||||||
const msg = 'Cannot insert data in elastic search.'
|
const msg = 'Cannot insert data in elastic search.'
|
||||||
logger.error(msg, { err: resultBody })
|
logger.error({ err: resultBody }, msg)
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ async function removeNotExistingChannels (host: string, existingChannels: Set<nu
|
||||||
|
|
||||||
const idsToRemove = difference(idsFromDB, Array.from(existingChannels))
|
const idsToRemove = difference(idsFromDB, Array.from(existingChannels))
|
||||||
|
|
||||||
logger.info('Will remove %d channels from %s.', idsToRemove.length, host, { idsToRemove })
|
logger.info({ idsToRemove }, 'Will remove %d channels from %s.', idsToRemove.length, host)
|
||||||
|
|
||||||
return elasticSearch.delete_by_query({
|
return elasticSearch.delete_by_query({
|
||||||
index: CONFIG.ELASTIC_SEARCH.INDEXES.CHANNELS,
|
index: CONFIG.ELASTIC_SEARCH.INDEXES.CHANNELS,
|
||||||
|
@ -56,6 +56,7 @@ async function removeNotExistingChannels (host: string, existingChannels: Set<nu
|
||||||
|
|
||||||
async function queryChannels (search: ChannelsSearchQuery) {
|
async function queryChannels (search: ChannelsSearchQuery) {
|
||||||
const bool: any = {}
|
const bool: any = {}
|
||||||
|
const mustNot: any[] = []
|
||||||
|
|
||||||
if (search.search) {
|
if (search.search) {
|
||||||
Object.assign(bool, {
|
Object.assign(bool, {
|
||||||
|
@ -71,6 +72,26 @@ async function queryChannels (search: ChannelsSearchQuery) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (search.blockedAccounts) {
|
||||||
|
mustNot.push({
|
||||||
|
terms: {
|
||||||
|
'ownerAccount.handle': search.blockedAccounts
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search.blockedHosts) {
|
||||||
|
mustNot.push({
|
||||||
|
terms: {
|
||||||
|
host: search.blockedHosts
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mustNot.length !== 0) {
|
||||||
|
Object.assign(bool, { must_not: mustNot })
|
||||||
|
}
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
from: search.start,
|
from: search.start,
|
||||||
size: search.count,
|
size: search.count,
|
||||||
|
@ -78,7 +99,7 @@ async function queryChannels (search: ChannelsSearchQuery) {
|
||||||
query: { bool }
|
query: { bool }
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('Will query Elastic Search for channels.', { body })
|
logger.debug({ body }, 'Will query Elastic Search for channels.')
|
||||||
|
|
||||||
const res = await elasticSearch.search({
|
const res = await elasticSearch.search({
|
||||||
index: CONFIG.ELASTIC_SEARCH.INDEXES.CHANNELS,
|
index: CONFIG.ELASTIC_SEARCH.INDEXES.CHANNELS,
|
||||||
|
@ -151,6 +172,8 @@ function formatChannelForDB (c: IndexableChannel): DBChannel {
|
||||||
description: c.description,
|
description: c.description,
|
||||||
support: c.support,
|
support: c.support,
|
||||||
|
|
||||||
|
handle: `${c.name}@${c.host}`,
|
||||||
|
|
||||||
ownerAccount: {
|
ownerAccount: {
|
||||||
id: c.ownerAccount.id,
|
id: c.ownerAccount.id,
|
||||||
url: c.ownerAccount.url,
|
url: c.ownerAccount.url,
|
||||||
|
@ -164,6 +187,8 @@ function formatChannelForDB (c: IndexableChannel): DBChannel {
|
||||||
createdAt: c.ownerAccount.createdAt,
|
createdAt: c.ownerAccount.createdAt,
|
||||||
updatedAt: c.ownerAccount.updatedAt,
|
updatedAt: c.ownerAccount.updatedAt,
|
||||||
|
|
||||||
|
handle: `${c.ownerAccount.name}@${c.ownerAccount.host}`,
|
||||||
|
|
||||||
avatar: formatAvatarForDB(c.ownerAccount)
|
avatar: formatAvatarForDB(c.ownerAccount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,6 +253,10 @@ function buildChannelOrAccountCommonMapping () {
|
||||||
type: 'keyword'
|
type: 'keyword'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handle: {
|
||||||
|
type: 'keyword'
|
||||||
|
},
|
||||||
|
|
||||||
displayName: {
|
displayName: {
|
||||||
type: 'text'
|
type: 'text'
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,7 +27,7 @@ function refreshVideosIndex () {
|
||||||
function removeVideosFromHosts (hosts: string[]) {
|
function removeVideosFromHosts (hosts: string[]) {
|
||||||
if (hosts.length === 0) return
|
if (hosts.length === 0) return
|
||||||
|
|
||||||
logger.info('Will remove videos from hosts.', { hosts })
|
logger.info({ hosts }, 'Will remove videos from hosts.')
|
||||||
|
|
||||||
return elasticSearch.delete_by_query({
|
return elasticSearch.delete_by_query({
|
||||||
index: CONFIG.ELASTIC_SEARCH.INDEXES.VIDEOS,
|
index: CONFIG.ELASTIC_SEARCH.INDEXES.VIDEOS,
|
||||||
|
@ -50,7 +50,7 @@ async function removeNotExistingVideos (host: string, existingVideos: Set<number
|
||||||
|
|
||||||
const idsToRemove = difference(idsFromDB, Array.from(existingVideos))
|
const idsToRemove = difference(idsFromDB, Array.from(existingVideos))
|
||||||
|
|
||||||
logger.info('Will remove %d videos from %s.', idsToRemove.length, host, { idsToRemove })
|
logger.info({ idsToRemove }, 'Will remove %d videos from %s.', idsToRemove.length, host)
|
||||||
|
|
||||||
return elasticSearch.delete_by_query({
|
return elasticSearch.delete_by_query({
|
||||||
index: CONFIG.ELASTIC_SEARCH.INDEXES.VIDEOS,
|
index: CONFIG.ELASTIC_SEARCH.INDEXES.VIDEOS,
|
||||||
|
@ -107,6 +107,7 @@ async function getVideoIdsOf (host: string) {
|
||||||
async function queryVideos (search: VideosSearchQuery) {
|
async function queryVideos (search: VideosSearchQuery) {
|
||||||
const bool: any = {}
|
const bool: any = {}
|
||||||
const filter: any[] = []
|
const filter: any[] = []
|
||||||
|
const mustNot: any[] = []
|
||||||
|
|
||||||
if (search.search) {
|
if (search.search) {
|
||||||
Object.assign(bool, {
|
Object.assign(bool, {
|
||||||
|
@ -122,6 +123,22 @@ async function queryVideos (search: VideosSearchQuery) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (search.blockedAccounts) {
|
||||||
|
mustNot.push({
|
||||||
|
terms: {
|
||||||
|
'account.handle': search.blockedAccounts
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search.blockedHosts) {
|
||||||
|
mustNot.push({
|
||||||
|
terms: {
|
||||||
|
host: search.blockedHosts
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (search.startDate) {
|
if (search.startDate) {
|
||||||
filter.push({
|
filter.push({
|
||||||
range: {
|
range: {
|
||||||
|
@ -234,6 +251,10 @@ async function queryVideos (search: VideosSearchQuery) {
|
||||||
|
|
||||||
Object.assign(bool, { filter })
|
Object.assign(bool, { filter })
|
||||||
|
|
||||||
|
if (mustNot.length !== 0) {
|
||||||
|
Object.assign(bool, { must_not: mustNot })
|
||||||
|
}
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
from: search.start,
|
from: search.start,
|
||||||
size: search.count,
|
size: search.count,
|
||||||
|
@ -241,7 +262,7 @@ async function queryVideos (search: VideosSearchQuery) {
|
||||||
query: { bool }
|
query: { bool }
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('Will query Elastic Search for videos.', { body })
|
logger.debug({ body }, 'Will query Elastic Search for videos.')
|
||||||
|
|
||||||
const res = await elasticSearch.search({
|
const res = await elasticSearch.search({
|
||||||
index: CONFIG.ELASTIC_SEARCH.INDEXES.VIDEOS,
|
index: CONFIG.ELASTIC_SEARCH.INDEXES.VIDEOS,
|
||||||
|
@ -314,6 +335,8 @@ function formatVideoForDB (v: IndexableVideo | IndexableVideoDetails): DBVideo |
|
||||||
url: v.account.url,
|
url: v.account.url,
|
||||||
host: v.account.host,
|
host: v.account.host,
|
||||||
|
|
||||||
|
handle: `${v.account.name}@${v.account.host}`,
|
||||||
|
|
||||||
avatar: formatAvatarForDB(v.account)
|
avatar: formatAvatarForDB(v.account)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -324,6 +347,8 @@ function formatVideoForDB (v: IndexableVideo | IndexableVideoDetails): DBVideo |
|
||||||
url: v.channel.url,
|
url: v.channel.url,
|
||||||
host: v.channel.host,
|
host: v.channel.host,
|
||||||
|
|
||||||
|
handle: `${v.channel.name}@${v.channel.host}`,
|
||||||
|
|
||||||
avatar: formatAvatarForDB(v.channel)
|
avatar: formatAvatarForDB(v.channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,6 +440,9 @@ function buildChannelOrAccountMapping () {
|
||||||
host: {
|
host: {
|
||||||
type: 'keyword'
|
type: 'keyword'
|
||||||
},
|
},
|
||||||
|
handle: {
|
||||||
|
type: 'keyword'
|
||||||
|
},
|
||||||
|
|
||||||
avatar: {
|
avatar: {
|
||||||
properties: buildAvatarMapping()
|
properties: buildAvatarMapping()
|
||||||
|
|
|
@ -26,7 +26,7 @@ export abstract class AbstractScheduler {
|
||||||
try {
|
try {
|
||||||
await this.internalExecute()
|
await this.internalExecute()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Cannot execute %s scheduler.', this.constructor.name, { err: inspect(err) })
|
logger.error({ err: inspect(err) }, 'Cannot execute %s scheduler.', this.constructor.name)
|
||||||
} finally {
|
} finally {
|
||||||
this.isRunning = false
|
this.isRunning = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class VideosIndexer extends AbstractScheduler {
|
||||||
this.indexSpecificVideo(task.host, task.uuid)
|
this.indexSpecificVideo(task.host, task.uuid)
|
||||||
.then(() => cb())
|
.then(() => cb())
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
logger.error('Error in index specific video %s of %s.', task.uuid, task.host, { err: inspect(err) })
|
logger.error({ err: inspect(err) }, 'Error in index specific video %s of %s.', task.uuid, task.host)
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}, INDEXER_QUEUE_CONCURRENCY)
|
}, INDEXER_QUEUE_CONCURRENCY)
|
||||||
|
@ -38,7 +38,7 @@ export class VideosIndexer extends AbstractScheduler {
|
||||||
this.indexSpecificChannel(task.host, task.name)
|
this.indexSpecificChannel(task.host, task.name)
|
||||||
.then(() => cb())
|
.then(() => cb())
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
logger.error('Error in index specific channel %s@%s.', task.name, task.host, { err: inspect(err) })
|
logger.error({ err: inspect(err) }, 'Error in index specific channel %s@%s.', task.name, task.host)
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
}, INDEXER_QUEUE_CONCURRENCY)
|
}, INDEXER_QUEUE_CONCURRENCY)
|
||||||
|
@ -72,7 +72,7 @@ export class VideosIndexer extends AbstractScheduler {
|
||||||
await this.indexHost(host)
|
await this.indexHost(host)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(inspect(err, { depth: 10 }))
|
console.error(inspect(err, { depth: 10 }))
|
||||||
logger.warn('Cannot index videos from %s.', host, { err })
|
logger.warn({ err: inspect(err) }, 'Cannot index videos from %s.', host)
|
||||||
}
|
}
|
||||||
}, { concurrency: INDEXER_CONCURRENCY })
|
}, { concurrency: INDEXER_CONCURRENCY })
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ const paginationValidator = [
|
||||||
query('count').optional().isInt({ min: 0 }).withMessage('Should have a number count'),
|
query('count').optional().isInt({ min: 0 }).withMessage('Should have a number count'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking pagination parameters', { parameters: req.query })
|
logger.debug({ parameters: req.query }, 'Checking pagination parameters')
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,25 @@ import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../helpers/cu
|
||||||
import { logger } from '../../helpers/logger'
|
import { logger } from '../../helpers/logger'
|
||||||
import { areValidationErrors } from './utils'
|
import { areValidationErrors } from './utils'
|
||||||
|
|
||||||
|
const commonFiltersValidators = [
|
||||||
|
query('blockedAccounts')
|
||||||
|
.optional()
|
||||||
|
.customSanitizer(toArray)
|
||||||
|
.custom(isStringArray).withMessage('Should have a valid blockedAccounts array'),
|
||||||
|
query('blockedHosts')
|
||||||
|
.optional()
|
||||||
|
.customSanitizer(toArray)
|
||||||
|
.custom(isStringArray).withMessage('Should have a valid hosts array'),
|
||||||
|
|
||||||
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
|
logger.debug({ parameters: req.query }, 'Checking commons filters query')
|
||||||
|
|
||||||
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
const commonVideosFiltersValidator = [
|
const commonVideosFiltersValidator = [
|
||||||
query('categoryOneOf')
|
query('categoryOneOf')
|
||||||
.optional()
|
.optional()
|
||||||
|
@ -31,7 +50,7 @@ const commonVideosFiltersValidator = [
|
||||||
.custom(isNSFWQueryValid).withMessage('Should have a valid NSFW attribute'),
|
.custom(isNSFWQueryValid).withMessage('Should have a valid NSFW attribute'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking commons video filters query', { parameters: req.query })
|
logger.debug({ parameters: req.query }, 'Checking commons video filters query')
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
@ -52,7 +71,7 @@ const videosSearchValidator = [
|
||||||
query('durationMax').optional().isInt().withMessage('Should have a valid max duration'),
|
query('durationMax').optional().isInt().withMessage('Should have a valid max duration'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking videos search query', { parameters: req.query })
|
logger.debug({ parameters: req.query }, 'Checking videos search query')
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
@ -64,7 +83,7 @@ const videoChannelsSearchValidator = [
|
||||||
query('search').not().isEmpty().withMessage('Should have a valid search'),
|
query('search').not().isEmpty().withMessage('Should have a valid search'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking video channels search query', { parameters: req.query })
|
logger.debug({ parameters: req.query }, 'Checking video channels search query')
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
@ -76,6 +95,7 @@ const videoChannelsSearchValidator = [
|
||||||
|
|
||||||
export {
|
export {
|
||||||
videoChannelsSearchValidator,
|
videoChannelsSearchValidator,
|
||||||
|
commonFiltersValidators,
|
||||||
commonVideosFiltersValidator,
|
commonVideosFiltersValidator,
|
||||||
videosSearchValidator
|
videosSearchValidator
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ const SORTABLE_VIDEOS_SEARCH_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VI
|
||||||
const SORTABLE_CHANNELS_SEARCH_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.CHANNELS_SEARCH)
|
const SORTABLE_CHANNELS_SEARCH_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.CHANNELS_SEARCH)
|
||||||
|
|
||||||
const videosSearchSortValidator = checkSort(SORTABLE_VIDEOS_SEARCH_COLUMNS)
|
const videosSearchSortValidator = checkSort(SORTABLE_VIDEOS_SEARCH_COLUMNS)
|
||||||
const channelsSearchSortValidator = checkSort(SORTABLE_VIDEOS_SEARCH_COLUMNS)
|
const channelsSearchSortValidator = checkSort(SORTABLE_CHANNELS_SEARCH_COLUMNS)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ function areValidationErrors (req: express.Request, res: express.Response) {
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req)
|
||||||
|
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors.mapped() })
|
logger.warn({ path: req.originalUrl, err: errors.mapped() }, 'Incorrect request parameters')
|
||||||
res.status(400).json({ errors: errors.mapped() })
|
res.status(400).json({ errors: errors.mapped() })
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -20,7 +20,7 @@ function checkSort (sortableColumns: string[]) {
|
||||||
query('sort').optional().isIn(sortableColumns).withMessage('Should have correct sortable column'),
|
query('sort').optional().isIn(sortableColumns).withMessage('Should have correct sortable column'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking sort parameters', { parameters: req.query })
|
logger.debug({ parameters: req.query }, 'Checking sort parameters')
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
VideoChannelsSearchQuery as PeerTubeChannelsSearchQuery
|
VideoChannelsSearchQuery as PeerTubeChannelsSearchQuery
|
||||||
} from '../../PeerTube/shared/models/search/video-channels-search-query.model'
|
} from '../../PeerTube/shared/models/search/video-channels-search-query.model'
|
||||||
|
import { CommonSearch } from './common-search.model'
|
||||||
|
|
||||||
export type ChannelsSearchQuery = PeerTubeChannelsSearchQuery & { fromHost?: string }
|
export type ChannelsSearchQuery = PeerTubeChannelsSearchQuery & CommonSearch
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { IndexableDoc } from './elastic-search.model'
|
import { IndexableDoc } from './elastic-search.model'
|
||||||
import { VideoChannel, VideoChannelSummary } from '@shared/models'
|
import { VideoChannel, VideoChannelSummary } from '@shared/models'
|
||||||
|
import { Account } from '@shared/models/actors/account.model'
|
||||||
|
|
||||||
export interface IndexableChannelSummary extends VideoChannelSummary, IndexableDoc {
|
export interface IndexableChannelSummary extends VideoChannelSummary, IndexableDoc {
|
||||||
}
|
}
|
||||||
|
@ -9,6 +10,9 @@ export interface IndexableChannel extends VideoChannel, IndexableDoc {
|
||||||
|
|
||||||
export interface DBChannel extends Omit<VideoChannel, 'isLocal'> {
|
export interface DBChannel extends Omit<VideoChannel, 'isLocal'> {
|
||||||
indexedAt: Date
|
indexedAt: Date
|
||||||
|
handle: string
|
||||||
|
|
||||||
|
ownerAccount?: Account & { handle: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DBChannelSummary extends VideoChannelSummary {
|
export interface DBChannelSummary extends VideoChannelSummary {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export type CommonSearch = {
|
||||||
|
blockedAccounts?: string[]
|
||||||
|
blockedHosts?: string[]
|
||||||
|
fromHost?: string
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
import { VideosSearchQuery as PeerTubeVideosSearchQuery} from '../../PeerTube/shared/models/search/videos-search-query.model'
|
import { VideosSearchQuery as PeerTubeVideosSearchQuery} from '../../PeerTube/shared/models/search/videos-search-query.model'
|
||||||
|
import { CommonSearch } from './common-search.model'
|
||||||
|
|
||||||
export type VideosSearchQuery = Omit<PeerTubeVideosSearchQuery, 'skipCount' | 'filter'>
|
export type VideosSearchQuery = Omit<PeerTubeVideosSearchQuery, 'skipCount' | 'filter'> & CommonSearch
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { VideoChannel, VideoChannelSummary } from '@shared/models/videos/channel/video-channel.model'
|
||||||
|
import { Account, AccountSummary } from '@shared/models/actors/account.model'
|
||||||
import { Video, VideoDetails } from '@shared/models/videos/video.model'
|
import { Video, VideoDetails } from '@shared/models/videos/video.model'
|
||||||
import { IndexableDoc } from './elastic-search.model'
|
import { IndexableDoc } from './elastic-search.model'
|
||||||
|
|
||||||
|
@ -10,9 +12,15 @@ export interface IndexableVideoDetails extends VideoDetails, IndexableDoc {
|
||||||
export interface DBVideoDetails extends Omit<VideoDetails, 'isLocal'> {
|
export interface DBVideoDetails extends Omit<VideoDetails, 'isLocal'> {
|
||||||
indexedAt: Date
|
indexedAt: Date
|
||||||
host: string
|
host: string
|
||||||
|
|
||||||
|
account: Account & { handle: string }
|
||||||
|
channel: VideoChannel & { handle: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DBVideo extends Omit<Video, 'isLocal'> {
|
export interface DBVideo extends Omit<Video, 'isLocal'> {
|
||||||
indexedAt: Date
|
indexedAt: Date
|
||||||
host: string
|
host: string
|
||||||
|
|
||||||
|
account: AccountSummary & { handle: string }
|
||||||
|
channel: VideoChannelSummary & { handle: string }
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,13 @@
|
||||||
"@types/qs" "*"
|
"@types/qs" "*"
|
||||||
"@types/serve-static" "*"
|
"@types/serve-static" "*"
|
||||||
|
|
||||||
|
"@types/fluent-ffmpeg@^2.1.14":
|
||||||
|
version "2.1.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.14.tgz#b21d60267fe269c2ea81fa3238a36a8349f8f2f3"
|
||||||
|
integrity sha512-nJrAX9ODNI7mUB0b7Y0Stx1a6dOpV3zXsOnWoBuEd9/woQhepBNCMeCyOL6SLJD3jn5sLw5ciDGH0RwJenCoag==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/json-schema@^7.0.3":
|
"@types/json-schema@^7.0.3":
|
||||||
version "7.0.4"
|
version "7.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
||||||
|
|
Loading…
Reference in New Issue