aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-03-24 09:16:48 +0100
committerChocobozzz <me@florianbigard.com>2021-03-24 18:18:41 +0100
commit74a4d53110ebc073dafeb74a7ac815fe00f4706b (patch)
treec09797245d4ea1093b7bc7e61f925aef9e554b02
parenteebd9838f067369031af9770b899f75f30810549 (diff)
downloadPeerTube-74a4d53110ebc073dafeb74a7ac815fe00f4706b.tar.gz
PeerTube-74a4d53110ebc073dafeb74a7ac815fe00f4706b.tar.zst
PeerTube-74a4d53110ebc073dafeb74a7ac815fe00f4706b.zip
Add server hooks for search endpoint
-rw-r--r--server/controllers/api/search.ts37
-rw-r--r--server/tests/fixtures/peertube-plugin-test/main.js24
-rw-r--r--server/tests/plugins/filter-hooks.ts62
-rw-r--r--shared/models/plugins/server-hook.model.ts10
4 files changed, 121 insertions, 12 deletions
diff --git a/server/controllers/api/search.ts b/server/controllers/api/search.ts
index 57357b1e8..f0cdf3a89 100644
--- a/server/controllers/api/search.ts
+++ b/server/controllers/api/search.ts
@@ -3,6 +3,7 @@ import { sanitizeUrl } from '@server/helpers/core-utils'
3import { doJSONRequest } from '@server/helpers/requests' 3import { doJSONRequest } from '@server/helpers/requests'
4import { CONFIG } from '@server/initializers/config' 4import { CONFIG } from '@server/initializers/config'
5import { getOrCreateVideoAndAccountAndChannel } from '@server/lib/activitypub/videos' 5import { getOrCreateVideoAndAccountAndChannel } from '@server/lib/activitypub/videos'
6import { Hooks } from '@server/lib/plugins/hooks'
6import { AccountBlocklistModel } from '@server/models/account/account-blocklist' 7import { AccountBlocklistModel } from '@server/models/account/account-blocklist'
7import { getServerActor } from '@server/models/application/application' 8import { getServerActor } from '@server/models/application/application'
8import { ServerBlocklistModel } from '@server/models/server/server-blocklist' 9import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
@@ -22,8 +23,8 @@ import {
22 paginationValidator, 23 paginationValidator,
23 setDefaultPagination, 24 setDefaultPagination,
24 setDefaultSearchSort, 25 setDefaultSearchSort,
25 videoChannelsSearchSortValidator,
26 videoChannelsListSearchValidator, 26 videoChannelsListSearchValidator,
27 videoChannelsSearchSortValidator,
27 videosSearchSortValidator, 28 videosSearchSortValidator,
28 videosSearchValidator 29 videosSearchValidator
29} from '../../middlewares' 30} from '../../middlewares'
@@ -87,7 +88,7 @@ function searchVideoChannels (req: express.Request, res: express.Response) {
87async function searchVideoChannelsIndex (query: VideoChannelsSearchQuery, res: express.Response) { 88async function searchVideoChannelsIndex (query: VideoChannelsSearchQuery, res: express.Response) {
88 const result = await buildMutedForSearchIndex(res) 89 const result = await buildMutedForSearchIndex(res)
89 90
90 const body = Object.assign(query, result) 91 const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-channels.index.list.params')
91 92
92 const url = sanitizeUrl(CONFIG.SEARCH.SEARCH_INDEX.URL) + '/api/v1/search/video-channels' 93 const url = sanitizeUrl(CONFIG.SEARCH.SEARCH_INDEX.URL) + '/api/v1/search/video-channels'
93 94
@@ -95,8 +96,9 @@ async function searchVideoChannelsIndex (query: VideoChannelsSearchQuery, res: e
95 logger.debug('Doing video channels search index request on %s.', url, { body }) 96 logger.debug('Doing video channels search index request on %s.', url, { body })
96 97
97 const { body: searchIndexResult } = await doJSONRequest<ResultList<VideoChannel>>(url, { method: 'POST', json: body }) 98 const { body: searchIndexResult } = await doJSONRequest<ResultList<VideoChannel>>(url, { method: 'POST', json: body })
99 const jsonResult = await Hooks.wrapObject(searchIndexResult, 'filter:api.search.video-channels.index.list.result')
98 100
99 return res.json(searchIndexResult) 101 return res.json(jsonResult)
100 } catch (err) { 102 } catch (err) {
101 logger.warn('Cannot use search index to make video channels search.', { err }) 103 logger.warn('Cannot use search index to make video channels search.', { err })
102 104
@@ -107,14 +109,19 @@ async function searchVideoChannelsIndex (query: VideoChannelsSearchQuery, res: e
107async function searchVideoChannelsDB (query: VideoChannelsSearchQuery, res: express.Response) { 109async function searchVideoChannelsDB (query: VideoChannelsSearchQuery, res: express.Response) {
108 const serverActor = await getServerActor() 110 const serverActor = await getServerActor()
109 111
110 const options = { 112 const apiOptions = await Hooks.wrapObject({
111 actorId: serverActor.id, 113 actorId: serverActor.id,
112 search: query.search, 114 search: query.search,
113 start: query.start, 115 start: query.start,
114 count: query.count, 116 count: query.count,
115 sort: query.sort 117 sort: query.sort
116 } 118 }, 'filter:api.search.video-channels.local.list.params')
117 const resultList = await VideoChannelModel.searchForApi(options) 119
120 const resultList = await Hooks.wrapPromiseFun(
121 VideoChannelModel.searchForApi,
122 apiOptions,
123 'filter:api.search.video-channels.local.list.result'
124 )
118 125
119 return res.json(getFormattedObjects(resultList.data, resultList.total)) 126 return res.json(getFormattedObjects(resultList.data, resultList.total))
120} 127}
@@ -168,7 +175,7 @@ function searchVideos (req: express.Request, res: express.Response) {
168async function searchVideosIndex (query: VideosSearchQuery, res: express.Response) { 175async function searchVideosIndex (query: VideosSearchQuery, res: express.Response) {
169 const result = await buildMutedForSearchIndex(res) 176 const result = await buildMutedForSearchIndex(res)
170 177
171 const body: VideosSearchQuery = Object.assign(query, result) 178 let body: VideosSearchQuery = Object.assign(query, result)
172 179
173 // Use the default instance NSFW policy if not specified 180 // Use the default instance NSFW policy if not specified
174 if (!body.nsfw) { 181 if (!body.nsfw) {
@@ -181,14 +188,17 @@ async function searchVideosIndex (query: VideosSearchQuery, res: express.Respons
181 : 'both' 188 : 'both'
182 } 189 }
183 190
191 body = await Hooks.wrapObject(body, 'filter:api.search.videos.index.list.params')
192
184 const url = sanitizeUrl(CONFIG.SEARCH.SEARCH_INDEX.URL) + '/api/v1/search/videos' 193 const url = sanitizeUrl(CONFIG.SEARCH.SEARCH_INDEX.URL) + '/api/v1/search/videos'
185 194
186 try { 195 try {
187 logger.debug('Doing videos search index request on %s.', url, { body }) 196 logger.debug('Doing videos search index request on %s.', url, { body })
188 197
189 const { body: searchIndexResult } = await doJSONRequest<ResultList<Video>>(url, { method: 'POST', json: body }) 198 const { body: searchIndexResult } = await doJSONRequest<ResultList<Video>>(url, { method: 'POST', json: body })
199 const jsonResult = await Hooks.wrapObject(searchIndexResult, 'filter:api.search.videos.index.list.result')
190 200
191 return res.json(searchIndexResult) 201 return res.json(jsonResult)
192 } catch (err) { 202 } catch (err) {
193 logger.warn('Cannot use search index to make video search.', { err }) 203 logger.warn('Cannot use search index to make video search.', { err })
194 204
@@ -197,13 +207,18 @@ async function searchVideosIndex (query: VideosSearchQuery, res: express.Respons
197} 207}
198 208
199async function searchVideosDB (query: VideosSearchQuery, res: express.Response) { 209async function searchVideosDB (query: VideosSearchQuery, res: express.Response) {
200 const options = Object.assign(query, { 210 const apiOptions = await Hooks.wrapObject(Object.assign(query, {
201 includeLocalVideos: true, 211 includeLocalVideos: true,
202 nsfw: buildNSFWFilter(res, query.nsfw), 212 nsfw: buildNSFWFilter(res, query.nsfw),
203 filter: query.filter, 213 filter: query.filter,
204 user: res.locals.oauth ? res.locals.oauth.token.User : undefined 214 user: res.locals.oauth ? res.locals.oauth.token.User : undefined
205 }) 215 }), 'filter:api.search.videos.local.list.params')
206 const resultList = await VideoModel.searchAndPopulateAccountAndServer(options) 216
217 const resultList = await Hooks.wrapPromiseFun(
218 VideoModel.searchAndPopulateAccountAndServer,
219 apiOptions,
220 'filter:api.search.videos.local.list.result'
221 )
207 222
208 return res.json(getFormattedObjects(resultList.data, resultList.total)) 223 return res.json(getFormattedObjects(resultList.data, resultList.total))
209} 224}
diff --git a/server/tests/fixtures/peertube-plugin-test/main.js b/server/tests/fixtures/peertube-plugin-test/main.js
index dfcc874d4..ee0bc39f3 100644
--- a/server/tests/fixtures/peertube-plugin-test/main.js
+++ b/server/tests/fixtures/peertube-plugin-test/main.js
@@ -230,6 +230,30 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
230 } 230 }
231 } 231 }
232 }) 232 })
233
234 {
235 const searchHooks = [
236 'filter:api.search.videos.local.list.params',
237 'filter:api.search.videos.local.list.result',
238 'filter:api.search.videos.index.list.params',
239 'filter:api.search.videos.index.list.result',
240 'filter:api.search.video-channels.local.list.params',
241 'filter:api.search.video-channels.local.list.result',
242 'filter:api.search.video-channels.index.list.params',
243 'filter:api.search.video-channels.index.list.result',
244 ]
245
246 for (const h of searchHooks) {
247 registerHook({
248 target: h,
249 handler: (obj) => {
250 peertubeHelpers.logger.debug('Run hook %s.', h)
251
252 return obj
253 }
254 })
255 }
256 }
233} 257}
234 258
235async function unregister () { 259async function unregister () {
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index be47b20ba..6f7fec767 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -7,6 +7,7 @@ import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-code
7import { 7import {
8 addVideoCommentReply, 8 addVideoCommentReply,
9 addVideoCommentThread, 9 addVideoCommentThread,
10 advancedVideosSearch,
10 createLive, 11 createLive,
11 createVideoPlaylist, 12 createVideoPlaylist,
12 doubleFollow, 13 doubleFollow,
@@ -25,6 +26,7 @@ import {
25 installPlugin, 26 installPlugin,
26 makeRawRequest, 27 makeRawRequest,
27 registerUser, 28 registerUser,
29 searchVideo,
28 setAccessTokensToServers, 30 setAccessTokensToServers,
29 setDefaultVideoChannel, 31 setDefaultVideoChannel,
30 updateCustomSubConfig, 32 updateCustomSubConfig,
@@ -33,7 +35,7 @@ import {
33 uploadVideoAndGetId, 35 uploadVideoAndGetId,
34 waitJobs 36 waitJobs
35} from '../../../shared/extra-utils' 37} from '../../../shared/extra-utils'
36import { cleanupTests, flushAndRunMultipleServers, ServerInfo } from '../../../shared/extra-utils/server/servers' 38import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
37import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports' 39import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
38import { 40import {
39 VideoDetails, 41 VideoDetails,
@@ -44,6 +46,7 @@ import {
44 VideoPrivacy 46 VideoPrivacy
45} from '../../../shared/models/videos' 47} from '../../../shared/models/videos'
46import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' 48import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
49import { advancedVideoChannelSearch } from '@shared/extra-utils/search/video-channels'
47 50
48const expect = chai.expect 51const expect = chai.expect
49 52
@@ -468,6 +471,63 @@ describe('Test plugin filter hooks', function () {
468 }) 471 })
469 }) 472 })
470 473
474 describe('Search filters', function () {
475
476 before(async function () {
477 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
478 search: {
479 searchIndex: {
480 enabled: true,
481 isDefaultSearch: false,
482 disableLocalSearch: false
483 }
484 }
485 })
486 })
487
488 it('Should run filter:api.search.videos.local.list.{params,result}', async function () {
489 await advancedVideosSearch(servers[0].url, {
490 search: 'Sun Quan'
491 })
492
493 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
494 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
495 })
496
497 it('Should run filter:api.search.videos.index.list.{params,result}', async function () {
498 await advancedVideosSearch(servers[0].url, {
499 search: 'Sun Quan',
500 searchTarget: 'search-index'
501 })
502
503 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
504 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
505 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.params', 1)
506 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.result', 1)
507 })
508
509 it('Should run filter:api.search.video-channels.local.list.{params,result}', async function () {
510 await advancedVideoChannelSearch(servers[0].url, {
511 search: 'Sun Ce'
512 })
513
514 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
515 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
516 })
517
518 it('Should run filter:api.search.video-channels.index.list.{params,result}', async function () {
519 await advancedVideoChannelSearch(servers[0].url, {
520 search: 'Sun Ce',
521 searchTarget: 'search-index'
522 })
523
524 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
525 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
526 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.params', 1)
527 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.result', 1)
528 })
529 })
530
471 after(async function () { 531 after(async function () {
472 await cleanupTests(servers) 532 await cleanupTests(servers)
473 }) 533 })
diff --git a/shared/models/plugins/server-hook.model.ts b/shared/models/plugins/server-hook.model.ts
index d28f76dfe..88277af5a 100644
--- a/shared/models/plugins/server-hook.model.ts
+++ b/shared/models/plugins/server-hook.model.ts
@@ -18,6 +18,16 @@ export const serverFilterHookObject = {
18 'filter:api.user.me.videos.list.params': true, 18 'filter:api.user.me.videos.list.params': true,
19 'filter:api.user.me.videos.list.result': true, 19 'filter:api.user.me.videos.list.result': true,
20 20
21 // Filter params/results to search videos/channels in the DB or on the remote index
22 'filter:api.search.videos.local.list.params': true,
23 'filter:api.search.videos.local.list.result': true,
24 'filter:api.search.videos.index.list.params': true,
25 'filter:api.search.videos.index.list.result': true,
26 'filter:api.search.video-channels.local.list.params': true,
27 'filter:api.search.video-channels.local.list.result': true,
28 'filter:api.search.video-channels.index.list.params': true,
29 'filter:api.search.video-channels.index.list.result': true,
30
21 // Filter the result of the get function 31 // Filter the result of the get function
22 // Used to get detailed video information (video watch page for example) 32 // Used to get detailed video information (video watch page for example)
23 'filter:api.video.get.result': true, 33 'filter:api.video.get.result': true,