diff --git a/PeerTube b/PeerTube index 68ca619..99139e7 160000 --- a/PeerTube +++ b/PeerTube @@ -1 +1 @@ -Subproject commit 68ca61941e3a7ca4c018566d2c496afd27dbd76d +Subproject commit 99139e7753e20ab0fba8eae5638d3dd3e792fe43 diff --git a/package.json b/package.json index 0b90050..63eba5f 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@types/body-parser": "^1.16.3", "@types/config": "^0.0.36", "@types/express": "^4.16.1", + "@types/fluent-ffmpeg": "^2.1.14", "@types/lodash": "^4.14.149", "@types/mkdirp": "^1.0.0", "@types/morgan": "^1.7.32", diff --git a/server.ts b/server.ts index 1d6ab78..34bd6b5 100644 --- a/server.ts +++ b/server.ts @@ -49,7 +49,7 @@ app.use(function (err, req, res, next) { 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() }) diff --git a/server/controllers/api/search-channels.ts b/server/controllers/api/search-channels.ts index afd6f9d..796da41 100644 --- a/server/controllers/api/search-channels.ts +++ b/server/controllers/api/search-channels.ts @@ -5,7 +5,7 @@ import { asyncMiddleware } from '../../middlewares/async' import { setDefaultPagination } from '../../middlewares/pagination' import { setDefaultSearchSort } from '../../middlewares/sort' 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' const searchChannelsRouter = express.Router() @@ -15,6 +15,7 @@ searchChannelsRouter.get('/search/video-channels', setDefaultPagination, channelsSearchSortValidator, setDefaultSearchSort, + commonFiltersValidators, videoChannelsSearchValidator, asyncMiddleware(searchChannels) ) diff --git a/server/controllers/api/search-videos.ts b/server/controllers/api/search-videos.ts index 3e9f22d..33c0bc2 100644 --- a/server/controllers/api/search-videos.ts +++ b/server/controllers/api/search-videos.ts @@ -4,8 +4,9 @@ import { setDefaultPagination } from '../../middlewares/pagination' import { asyncMiddleware } from '../../middlewares/async' import { formatVideoForAPI, queryVideos } from '../../lib/elastic-search-videos' 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 { VideosSearchQuery } from 'server/types/video-search.model' const searchVideosRouter = express.Router() @@ -14,6 +15,7 @@ searchVideosRouter.get('/search/videos', setDefaultPagination, videosSearchSortValidator, setDefaultSearchSort, + commonFiltersValidators, commonVideosFiltersValidator, videosSearchValidator, asyncMiddleware(searchVideos) @@ -26,10 +28,12 @@ export { searchVideosRouter } // --------------------------------------------------------------------------- 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({ total: resultList.total, - data: resultList.data.map(v => formatVideoForAPI(v, req.query.fromHost as string)) + data: resultList.data.map(v => formatVideoForAPI(v, query.fromHost)) }) } diff --git a/server/helpers/elastic-search.ts b/server/helpers/elastic-search.ts index b36d10b..2137b59 100644 --- a/server/helpers/elastic-search.ts +++ b/server/helpers/elastic-search.ts @@ -93,7 +93,7 @@ async function indexDocuments (options: { if (resultBody.errors === true) { const msg = 'Cannot insert data in elastic search.' - logger.error(msg, { err: resultBody }) + logger.error({ err: resultBody }, msg) throw new Error(msg) } diff --git a/server/lib/elastic-search-channels.ts b/server/lib/elastic-search-channels.ts index ea927cf..4b982b3 100644 --- a/server/lib/elastic-search-channels.ts +++ b/server/lib/elastic-search-channels.ts @@ -29,7 +29,7 @@ async function removeNotExistingChannels (host: string, existingChannels: Set cb()) .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() }) }, INDEXER_QUEUE_CONCURRENCY) @@ -38,7 +38,7 @@ export class VideosIndexer extends AbstractScheduler { this.indexSpecificChannel(task.host, task.name) .then(() => cb()) .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() }) }, INDEXER_QUEUE_CONCURRENCY) @@ -72,7 +72,7 @@ export class VideosIndexer extends AbstractScheduler { await this.indexHost(host) } catch (err) { 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 }) diff --git a/server/middlewares/validators/pagination.ts b/server/middlewares/validators/pagination.ts index 80ae57c..4bd20ad 100644 --- a/server/middlewares/validators/pagination.ts +++ b/server/middlewares/validators/pagination.ts @@ -8,7 +8,7 @@ const paginationValidator = [ query('count').optional().isInt({ min: 0 }).withMessage('Should have a number count'), (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 diff --git a/server/middlewares/validators/search.ts b/server/middlewares/validators/search.ts index 190106a..6bc6195 100644 --- a/server/middlewares/validators/search.ts +++ b/server/middlewares/validators/search.ts @@ -5,6 +5,25 @@ import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../helpers/cu import { logger } from '../../helpers/logger' 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 = [ query('categoryOneOf') .optional() @@ -31,7 +50,7 @@ const commonVideosFiltersValidator = [ .custom(isNSFWQueryValid).withMessage('Should have a valid NSFW attribute'), (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 @@ -52,7 +71,7 @@ const videosSearchValidator = [ query('durationMax').optional().isInt().withMessage('Should have a valid max duration'), (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 @@ -64,7 +83,7 @@ const videoChannelsSearchValidator = [ query('search').not().isEmpty().withMessage('Should have a valid search'), (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 @@ -76,6 +95,7 @@ const videoChannelsSearchValidator = [ export { videoChannelsSearchValidator, + commonFiltersValidators, commonVideosFiltersValidator, videosSearchValidator } diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts index c281a80..7ded0ba 100644 --- a/server/middlewares/validators/sort.ts +++ b/server/middlewares/validators/sort.ts @@ -5,7 +5,7 @@ const SORTABLE_VIDEOS_SEARCH_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VI const SORTABLE_CHANNELS_SEARCH_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.CHANNELS_SEARCH) const videosSearchSortValidator = checkSort(SORTABLE_VIDEOS_SEARCH_COLUMNS) -const channelsSearchSortValidator = checkSort(SORTABLE_VIDEOS_SEARCH_COLUMNS) +const channelsSearchSortValidator = checkSort(SORTABLE_CHANNELS_SEARCH_COLUMNS) // --------------------------------------------------------------------------- diff --git a/server/middlewares/validators/utils.ts b/server/middlewares/validators/utils.ts index 43e5652..618c417 100644 --- a/server/middlewares/validators/utils.ts +++ b/server/middlewares/validators/utils.ts @@ -6,7 +6,7 @@ function areValidationErrors (req: express.Request, res: express.Response) { const errors = validationResult(req) 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() }) return true @@ -20,7 +20,7 @@ function checkSort (sortableColumns: string[]) { query('sort').optional().isIn(sortableColumns).withMessage('Should have correct sortable column'), (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 diff --git a/server/types/channel-search.model.ts b/server/types/channel-search.model.ts index d29d078..7244043 100644 --- a/server/types/channel-search.model.ts +++ b/server/types/channel-search.model.ts @@ -1,5 +1,6 @@ import { VideoChannelsSearchQuery as PeerTubeChannelsSearchQuery } 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 diff --git a/server/types/channel.model.ts b/server/types/channel.model.ts index b2ac2f6..c89bd20 100644 --- a/server/types/channel.model.ts +++ b/server/types/channel.model.ts @@ -1,5 +1,6 @@ import { IndexableDoc } from './elastic-search.model' import { VideoChannel, VideoChannelSummary } from '@shared/models' +import { Account } from '@shared/models/actors/account.model' export interface IndexableChannelSummary extends VideoChannelSummary, IndexableDoc { } @@ -9,6 +10,9 @@ export interface IndexableChannel extends VideoChannel, IndexableDoc { export interface DBChannel extends Omit { indexedAt: Date + handle: string + + ownerAccount?: Account & { handle: string } } export interface DBChannelSummary extends VideoChannelSummary { diff --git a/server/types/common-search.model.ts b/server/types/common-search.model.ts new file mode 100644 index 0000000..f4b71ea --- /dev/null +++ b/server/types/common-search.model.ts @@ -0,0 +1,5 @@ +export type CommonSearch = { + blockedAccounts?: string[] + blockedHosts?: string[] + fromHost?: string +} diff --git a/server/types/video-search.model.ts b/server/types/video-search.model.ts index e8a4802..2bd0fd4 100644 --- a/server/types/video-search.model.ts +++ b/server/types/video-search.model.ts @@ -1,3 +1,4 @@ import { VideosSearchQuery as PeerTubeVideosSearchQuery} from '../../PeerTube/shared/models/search/videos-search-query.model' +import { CommonSearch } from './common-search.model' -export type VideosSearchQuery = Omit +export type VideosSearchQuery = Omit & CommonSearch diff --git a/server/types/video.model.ts b/server/types/video.model.ts index 8a501cf..5802a1f 100644 --- a/server/types/video.model.ts +++ b/server/types/video.model.ts @@ -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 { IndexableDoc } from './elastic-search.model' @@ -10,9 +12,15 @@ export interface IndexableVideoDetails extends VideoDetails, IndexableDoc { export interface DBVideoDetails extends Omit { indexedAt: Date host: string + + account: Account & { handle: string } + channel: VideoChannel & { handle: string } } export interface DBVideo extends Omit { indexedAt: Date host: string + + account: AccountSummary & { handle: string } + channel: VideoChannelSummary & { handle: string } } diff --git a/yarn.lock b/yarn.lock index 61b8691..8b67271 100644 --- a/yarn.lock +++ b/yarn.lock @@ -110,6 +110,13 @@ "@types/qs" "*" "@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": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"