From fe98765624cdd6695739bda719fcb726b71c2b2a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 8 Jan 2020 14:15:16 +0100 Subject: [PATCH] Add ability to skip count query --- server/controllers/api/accounts.ts | 6 ++++-- server/controllers/api/overviews.ts | 5 +++-- server/controllers/api/users/my-subscriptions.ts | 7 +++++-- server/controllers/api/video-channel.ts | 6 ++++-- server/controllers/api/videos/index.ts | 7 +++++-- server/controllers/bots.ts | 7 ++++--- server/helpers/express-utils.ts | 7 ++++++- server/middlewares/validators/videos/videos.ts | 4 ++++ server/models/video/video.ts | 7 ++++--- server/tests/api/check-params/videos-filter.ts | 1 - server/tests/api/check-params/videos.ts | 6 +++++- server/tests/api/videos/single-server.ts | 9 +++++++++ shared/extra-utils/videos/videos.ts | 3 ++- 13 files changed, 55 insertions(+), 20 deletions(-) diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index c49da3c0a..00148ff55 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts @@ -22,7 +22,7 @@ import { import { AccountModel } from '../../models/account/account' import { AccountVideoRateModel } from '../../models/account/account-video-rate' import { VideoModel } from '../../models/video/video' -import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' +import { buildNSFWFilter, isUserAbleToSearchRemoteURI, getCountVideos } from '../../helpers/express-utils' import { VideoChannelModel } from '../../models/video/video-channel' import { JobQueue } from '../../lib/job-queue' import { logger } from '../../helpers/logger' @@ -155,6 +155,7 @@ async function listAccountPlaylists (req: express.Request, res: express.Response async function listAccountVideos (req: express.Request, res: express.Response) { const account = res.locals.account const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined + const countVideos = getCountVideos(req) const resultList = await VideoModel.listForApi({ followerActorId, @@ -171,7 +172,8 @@ async function listAccountVideos (req: express.Request, res: express.Response) { nsfw: buildNSFWFilter(res, req.query.nsfw), withFiles: false, accountId: account.id, - user: res.locals.oauth ? res.locals.oauth.token.User : undefined + user: res.locals.oauth ? res.locals.oauth.token.User : undefined, + countVideos }) return res.json(getFormattedObjects(resultList.data, resultList.total)) diff --git a/server/controllers/api/overviews.ts b/server/controllers/api/overviews.ts index 37ac152db..23706767a 100644 --- a/server/controllers/api/overviews.ts +++ b/server/controllers/api/overviews.ts @@ -98,10 +98,11 @@ async function getVideos ( sort: '-createdAt', includeLocalVideos: true, nsfw: buildNSFWFilter(res), - withFiles: false + withFiles: false, + countVideos: false }, where) - const { data } = await VideoModel.listForApi(query, false) + const { data } = await VideoModel.listForApi(query) return data.map(d => d.toFormattedJSON()) } diff --git a/server/controllers/api/users/my-subscriptions.ts b/server/controllers/api/users/my-subscriptions.ts index c52df3154..43c4c37d8 100644 --- a/server/controllers/api/users/my-subscriptions.ts +++ b/server/controllers/api/users/my-subscriptions.ts @@ -15,7 +15,7 @@ import { } from '../../../middlewares' import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators' import { VideoModel } from '../../../models/video/video' -import { buildNSFWFilter } from '../../../helpers/express-utils' +import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' import { VideoFilter } from '../../../../shared/models/videos/video-query.type' import { ActorFollowModel } from '../../../models/activitypub/actor-follow' import { JobQueue } from '../../../lib/job-queue' @@ -149,6 +149,8 @@ async function getUserSubscriptions (req: express.Request, res: express.Response async function getUserSubscriptionVideos (req: express.Request, res: express.Response) { const user = res.locals.oauth.token.User + const countVideos = getCountVideos(req) + const resultList = await VideoModel.listForApi({ start: req.query.start, count: req.query.count, @@ -163,7 +165,8 @@ async function getUserSubscriptionVideos (req: express.Request, res: express.Res filter: req.query.filter as VideoFilter, withFiles: false, followerActorId: user.Account.Actor.id, - user + user, + countVideos }) return res.json(getFormattedObjects(resultList.data, resultList.total)) diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index acc5b2987..e1f37a8fb 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts @@ -20,7 +20,7 @@ import { videoChannelsNameWithHostValidator, videosSortValidator } from '../../m import { sendUpdateActor } from '../../lib/activitypub/send' import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' import { createLocalVideoChannel, federateAllVideosOfChannel } from '../../lib/video-channel' -import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' +import { buildNSFWFilter, createReqFiles, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' import { setAsyncActorKeys } from '../../lib/activitypub' import { AccountModel } from '../../models/account/account' import { MIMETYPES } from '../../initializers/constants' @@ -256,6 +256,7 @@ async function listVideoChannelPlaylists (req: express.Request, res: express.Res async function listVideoChannelVideos (req: express.Request, res: express.Response) { const videoChannelInstance = res.locals.videoChannel const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined + const countVideos = getCountVideos(req) const resultList = await VideoModel.listForApi({ followerActorId, @@ -272,7 +273,8 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon nsfw: buildNSFWFilter(res, req.query.nsfw), withFiles: false, videoChannelId: videoChannelInstance.id, - user: res.locals.oauth ? res.locals.oauth.token.User : undefined + user: res.locals.oauth ? res.locals.oauth.token.User : undefined, + countVideos }) return res.json(getFormattedObjects(resultList.data, resultList.total)) diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 35f0b3152..8d4ff07eb 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -48,7 +48,7 @@ import { videoCommentRouter } from './comment' import { rateVideoRouter } from './rate' import { ownershipVideoRouter } from './ownership' import { VideoFilter } from '../../../../shared/models/videos/video-query.type' -import { buildNSFWFilter, createReqFiles } from '../../../helpers/express-utils' +import { buildNSFWFilter, createReqFiles, getCountVideos } from '../../../helpers/express-utils' import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' import { videoCaptionsRouter } from './captions' import { videoImportsRouter } from './import' @@ -495,6 +495,8 @@ async function getVideoDescription (req: express.Request, res: express.Response) } async function listVideos (req: express.Request, res: express.Response) { + const countVideos = getCountVideos(req) + const apiOptions = await Hooks.wrapObject({ start: req.query.start, count: req.query.count, @@ -508,7 +510,8 @@ async function listVideos (req: express.Request, res: express.Response) { nsfw: buildNSFWFilter(res, req.query.nsfw), filter: req.query.filter as VideoFilter, withFiles: false, - user: res.locals.oauth ? res.locals.oauth.token.User : undefined + user: res.locals.oauth ? res.locals.oauth.token.User : undefined, + countVideos }, 'filter:api.videos.list.params') const resultList = await Hooks.wrapPromiseFun( diff --git a/server/controllers/bots.ts b/server/controllers/bots.ts index ed1040176..f3e778b04 100644 --- a/server/controllers/bots.ts +++ b/server/controllers/bots.ts @@ -61,17 +61,18 @@ async function getSitemapAccountUrls () { } async function getSitemapLocalVideoUrls () { - const resultList = await VideoModel.listForApi({ + const { data } = await VideoModel.listForApi({ start: 0, count: undefined, sort: 'createdAt', includeLocalVideos: true, nsfw: buildNSFWFilter(), filter: 'local', - withFiles: false + withFiles: false, + countVideos: false }) - return resultList.data.map(v => ({ + return data.map(v => ({ url: WEBSERVER.URL + '/videos/watch/' + v.uuid, video: [ { diff --git a/server/helpers/express-utils.ts b/server/helpers/express-utils.ts index 00f3f198b..9bf6d85a8 100644 --- a/server/helpers/express-utils.ts +++ b/server/helpers/express-utils.ts @@ -117,6 +117,10 @@ function isUserAbleToSearchRemoteURI (res: express.Response) { (CONFIG.SEARCH.REMOTE_URI.USERS === true && user !== undefined) } +function getCountVideos (req: express.Request) { + return req.query.skipCount !== true +} + // --------------------------------------------------------------------------- export { @@ -125,5 +129,6 @@ export { isUserAbleToSearchRemoteURI, badRequest, createReqFiles, - cleanUpReqFiles + cleanUpReqFiles, + getCountVideos } diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index 5e0182cc3..6733d9dec 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts @@ -381,6 +381,10 @@ const commonVideosFiltersValidator = [ query('filter') .optional() .custom(isVideoFilterValid).withMessage('Should have a valid filter attribute'), + query('skipCount') + .optional() + .customSanitizer(toBooleanOrNull) + .custom(isBooleanValid).withMessage('Should have a valid skip count boolean'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking commons video filters query', { parameters: req.query }) diff --git a/server/models/video/video.ts b/server/models/video/video.ts index e85c5e38e..cd3245ee4 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -1284,8 +1284,9 @@ export class VideoModel extends Model { videoPlaylistId?: number, trendingDays?: number, user?: MUserAccountId, - historyOfUser?: MUserId - }, countVideos = true) { + historyOfUser?: MUserId, + countVideos?: boolean + }) { if (options.filter && options.filter === 'all-local' && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) { throw new Error('Try to filter all-local but no user has not the see all videos right') } @@ -1328,7 +1329,7 @@ export class VideoModel extends Model { trendingDays } - return VideoModel.getAvailableForApi(query, queryOptions, countVideos) + return VideoModel.getAvailableForApi(query, queryOptions, options.countVideos) } static async searchAndPopulateAccountAndServer (options: { diff --git a/server/tests/api/check-params/videos-filter.ts b/server/tests/api/check-params/videos-filter.ts index 5a5668665..811756745 100644 --- a/server/tests/api/check-params/videos-filter.ts +++ b/server/tests/api/check-params/videos-filter.ts @@ -40,7 +40,6 @@ describe('Test videos filters', function () { let server: ServerInfo let userAccessToken: string let moderatorAccessToken: string - let playlistUUID: string // --------------------------------------------------------------- diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index fa6d6f622..16ef1c505 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts @@ -75,8 +75,12 @@ describe('Test videos API validator', function () { await checkBadSortPagination(server.url, path) }) + it('Should fail with a bad skipVideos query', async function () { + await makeGetRequest({ url: server.url, path, statusCodeExpected: 200, query: { skipCount: 'toto' } }) + }) + it('Should success with the correct parameters', async function () { - await makeGetRequest({ url: server.url, path, statusCodeExpected: 200 }) + await makeGetRequest({ url: server.url, path, statusCodeExpected: 200, query: { skipCount: false } }) }) }) diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index d8f394ac7..362d6b78f 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts @@ -322,6 +322,15 @@ describe('Test a single server', function () { expect(videos[0].name).to.equal(videosListBase[5].name) }) + it('Should not have the total field', async function () { + const res = await getVideosListPagination(server.url, 5, 6, 'name', true) + + const videos = res.body.data + expect(res.body.total).to.not.exist + expect(videos.length).to.equal(1) + expect(videos[0].name).to.equal(videosListBase[5].name) + }) + it('Should list and sort by name in descending order', async function () { const res = await getVideosListSort(server.url, '-name') diff --git a/shared/extra-utils/videos/videos.ts b/shared/extra-utils/videos/videos.ts index c5de15552..9dec12703 100644 --- a/shared/extra-utils/videos/videos.ts +++ b/shared/extra-utils/videos/videos.ts @@ -248,7 +248,7 @@ function getPlaylistVideos ( }) } -function getVideosListPagination (url: string, start: number, count: number, sort?: string) { +function getVideosListPagination (url: string, start: number, count: number, sort?: string, skipCount?: boolean) { const path = '/api/v1/videos' const req = request(url) @@ -257,6 +257,7 @@ function getVideosListPagination (url: string, start: number, count: number, sor .query({ count: count }) if (sort) req.query({ sort }) + if (skipCount) req.query({ skipCount }) return req.set('Accept', 'application/json') .expect(200) -- 2.25.1