]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/plugins/filter-hooks.ts
c235508e807b68ff9a3d8b651fa6b51e8d94f2a7
[github/Chocobozzz/PeerTube.git] / server / tests / plugins / filter-hooks.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import * as chai from 'chai'
5 import { HttpStatusCode } from '@shared/core-utils'
6 import {
7 cleanupTests,
8 doubleFollow,
9 flushAndRunMultipleServers,
10 getAccountVideos,
11 getMyVideos,
12 getVideo,
13 getVideoChannelVideos,
14 getVideosList,
15 getVideosListPagination,
16 getVideoWithToken,
17 ImportsCommand,
18 makeRawRequest,
19 PluginsCommand,
20 registerUser,
21 ServerInfo,
22 setAccessTokensToServers,
23 setDefaultVideoChannel,
24 updateVideo,
25 uploadVideo,
26 uploadVideoAndGetId,
27 waitJobs,
28 waitUntilLog
29 } from '@shared/extra-utils'
30 import { VideoDetails, VideoImportState, VideoPlaylist, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
31
32 const expect = chai.expect
33
34 describe('Test plugin filter hooks', function () {
35 let servers: ServerInfo[]
36 let videoUUID: string
37 let threadId: number
38
39 before(async function () {
40 this.timeout(60000)
41
42 servers = await flushAndRunMultipleServers(2)
43 await setAccessTokensToServers(servers)
44 await setDefaultVideoChannel(servers)
45 await doubleFollow(servers[0], servers[1])
46
47 await servers[0].pluginsCommand.install({ path: PluginsCommand.getPluginTestPath() })
48 await servers[0].pluginsCommand.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
49
50 for (let i = 0; i < 10; i++) {
51 await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'default video ' + i })
52 }
53
54 const res = await getVideosList(servers[0].url)
55 videoUUID = res.body.data[0].uuid
56
57 await servers[0].configCommand.updateCustomSubConfig({
58 newConfig: {
59 live: { enabled: true },
60 signup: { enabled: true },
61 import: {
62 videos: {
63 http: { enabled: true },
64 torrent: { enabled: true }
65 }
66 }
67 }
68 })
69 })
70
71 it('Should run filter:api.videos.list.params', async function () {
72 const res = await getVideosListPagination(servers[0].url, 0, 2)
73
74 // 2 plugins do +1 to the count parameter
75 expect(res.body.data).to.have.lengthOf(4)
76 })
77
78 it('Should run filter:api.videos.list.result', async function () {
79 const res = await getVideosListPagination(servers[0].url, 0, 0)
80
81 // Plugin do +1 to the total result
82 expect(res.body.total).to.equal(11)
83 })
84
85 it('Should run filter:api.accounts.videos.list.params', async function () {
86 const res = await getAccountVideos(servers[0].url, servers[0].accessToken, 'root', 0, 2)
87
88 // 1 plugin do +1 to the count parameter
89 expect(res.body.data).to.have.lengthOf(3)
90 })
91
92 it('Should run filter:api.accounts.videos.list.result', async function () {
93 const res = await getAccountVideos(servers[0].url, servers[0].accessToken, 'root', 0, 2)
94
95 // Plugin do +2 to the total result
96 expect(res.body.total).to.equal(12)
97 })
98
99 it('Should run filter:api.video-channels.videos.list.params', async function () {
100 const res = await getVideoChannelVideos(servers[0].url, servers[0].accessToken, 'root_channel', 0, 2)
101
102 // 1 plugin do +3 to the count parameter
103 expect(res.body.data).to.have.lengthOf(5)
104 })
105
106 it('Should run filter:api.video-channels.videos.list.result', async function () {
107 const res = await getVideoChannelVideos(servers[0].url, servers[0].accessToken, 'root_channel', 0, 2)
108
109 // Plugin do +3 to the total result
110 expect(res.body.total).to.equal(13)
111 })
112
113 it('Should run filter:api.user.me.videos.list.params', async function () {
114 const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 2)
115
116 // 1 plugin do +4 to the count parameter
117 expect(res.body.data).to.have.lengthOf(6)
118 })
119
120 it('Should run filter:api.user.me.videos.list.result', async function () {
121 const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 2)
122
123 // Plugin do +4 to the total result
124 expect(res.body.total).to.equal(14)
125 })
126
127 it('Should run filter:api.video.get.result', async function () {
128 const res = await getVideo(servers[0].url, videoUUID)
129
130 expect(res.body.name).to.contain('<3')
131 })
132
133 it('Should run filter:api.video.upload.accept.result', async function () {
134 await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, HttpStatusCode.FORBIDDEN_403)
135 })
136
137 it('Should run filter:api.live-video.create.accept.result', async function () {
138 const attributes = {
139 name: 'video with bad word',
140 privacy: VideoPrivacy.PUBLIC,
141 channelId: servers[0].videoChannel.id
142 }
143
144 await servers[0].liveCommand.create({ fields: attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
145 })
146
147 it('Should run filter:api.video.pre-import-url.accept.result', async function () {
148 const attributes = {
149 name: 'normal title',
150 privacy: VideoPrivacy.PUBLIC,
151 channelId: servers[0].videoChannel.id,
152 targetUrl: ImportsCommand.getGoodVideoUrl() + 'bad'
153 }
154 await servers[0].importsCommand.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
155 })
156
157 it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
158 const attributes = {
159 name: 'bad torrent',
160 privacy: VideoPrivacy.PUBLIC,
161 channelId: servers[0].videoChannel.id,
162 torrentfile: 'video-720p.torrent' as any
163 }
164 await servers[0].importsCommand.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
165 })
166
167 it('Should run filter:api.video.post-import-url.accept.result', async function () {
168 this.timeout(60000)
169
170 let videoImportId: number
171
172 {
173 const attributes = {
174 name: 'title with bad word',
175 privacy: VideoPrivacy.PUBLIC,
176 channelId: servers[0].videoChannel.id,
177 targetUrl: ImportsCommand.getGoodVideoUrl()
178 }
179 const body = await servers[0].importsCommand.importVideo({ attributes })
180 videoImportId = body.id
181 }
182
183 await waitJobs(servers)
184
185 {
186 const body = await servers[0].importsCommand.getMyVideoImports()
187 const videoImports = body.data
188
189 const videoImport = videoImports.find(i => i.id === videoImportId)
190
191 expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
192 expect(videoImport.state.label).to.equal('Rejected')
193 }
194 })
195
196 it('Should run filter:api.video.post-import-torrent.accept.result', async function () {
197 this.timeout(60000)
198
199 let videoImportId: number
200
201 {
202 const attributes = {
203 name: 'title with bad word',
204 privacy: VideoPrivacy.PUBLIC,
205 channelId: servers[0].videoChannel.id,
206 torrentfile: 'video-720p.torrent' as any
207 }
208 const body = await servers[0].importsCommand.importVideo({ attributes })
209 videoImportId = body.id
210 }
211
212 await waitJobs(servers)
213
214 {
215 const { data: videoImports } = await servers[0].importsCommand.getMyVideoImports()
216
217 const videoImport = videoImports.find(i => i.id === videoImportId)
218
219 expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
220 expect(videoImport.state.label).to.equal('Rejected')
221 }
222 })
223
224 it('Should run filter:api.video-thread.create.accept.result', async function () {
225 await servers[0].commentsCommand.createThread({
226 videoId: videoUUID,
227 text: 'comment with bad word',
228 expectedStatus: HttpStatusCode.FORBIDDEN_403
229 })
230 })
231
232 it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
233 const created = await servers[0].commentsCommand.createThread({ videoId: videoUUID, text: 'thread' })
234 threadId = created.id
235
236 await servers[0].commentsCommand.addReply({
237 videoId: videoUUID,
238 toCommentId: threadId,
239 text: 'comment with bad word',
240 expectedStatus: HttpStatusCode.FORBIDDEN_403
241 })
242 await servers[0].commentsCommand.addReply({
243 videoId: videoUUID,
244 toCommentId: threadId,
245 text: 'comment with good word',
246 expectedStatus: HttpStatusCode.OK_200
247 })
248 })
249
250 it('Should run filter:api.video-threads.list.params', async function () {
251 const { data } = await servers[0].commentsCommand.listThreads({ videoId: videoUUID, start: 0, count: 0 })
252
253 // our plugin do +1 to the count parameter
254 expect(data).to.have.lengthOf(1)
255 })
256
257 it('Should run filter:api.video-threads.list.result', async function () {
258 const { total } = await servers[0].commentsCommand.listThreads({ videoId: videoUUID, start: 0, count: 0 })
259
260 // Plugin do +1 to the total result
261 expect(total).to.equal(2)
262 })
263
264 it('Should run filter:api.video-thread-comments.list.params')
265
266 it('Should run filter:api.video-thread-comments.list.result', async function () {
267 const thread = await servers[0].commentsCommand.getThread({ videoId: videoUUID, threadId })
268
269 expect(thread.comment.text.endsWith(' <3')).to.be.true
270 })
271
272 describe('Should run filter:video.auto-blacklist.result', function () {
273
274 async function checkIsBlacklisted (id: number | string, value: boolean) {
275 const res = await getVideoWithToken(servers[0].url, servers[0].accessToken, id)
276 const video: VideoDetails = res.body
277 expect(video.blacklisted).to.equal(value)
278 }
279
280 it('Should blacklist on upload', async function () {
281 const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video please blacklist me' })
282 await checkIsBlacklisted(res.body.video.uuid, true)
283 })
284
285 it('Should blacklist on import', async function () {
286 this.timeout(15000)
287
288 const attributes = {
289 name: 'video please blacklist me',
290 targetUrl: ImportsCommand.getGoodVideoUrl(),
291 channelId: servers[0].videoChannel.id
292 }
293 const body = await servers[0].importsCommand.importVideo({ attributes })
294 await checkIsBlacklisted(body.video.uuid, true)
295 })
296
297 it('Should blacklist on update', async function () {
298 const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
299 const videoId = res.body.video.uuid
300 await checkIsBlacklisted(videoId, false)
301
302 await updateVideo(servers[0].url, servers[0].accessToken, videoId, { name: 'please blacklist me' })
303 await checkIsBlacklisted(videoId, true)
304 })
305
306 it('Should blacklist on remote upload', async function () {
307 this.timeout(120000)
308
309 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'remote please blacklist me' })
310 await waitJobs(servers)
311
312 await checkIsBlacklisted(res.body.video.uuid, true)
313 })
314
315 it('Should blacklist on remote update', async function () {
316 this.timeout(120000)
317
318 const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video' })
319 await waitJobs(servers)
320
321 const videoId = res.body.video.uuid
322 await checkIsBlacklisted(videoId, false)
323
324 await updateVideo(servers[1].url, servers[1].accessToken, videoId, { name: 'please blacklist me' })
325 await waitJobs(servers)
326
327 await checkIsBlacklisted(videoId, true)
328 })
329 })
330
331 describe('Should run filter:api.user.signup.allowed.result', function () {
332
333 it('Should run on config endpoint', async function () {
334 const body = await servers[0].configCommand.getConfig()
335 expect(body.signup.allowed).to.be.true
336 })
337
338 it('Should allow a signup', async function () {
339 await registerUser(servers[0].url, 'john', 'password')
340 })
341
342 it('Should not allow a signup', async function () {
343 const res = await registerUser(servers[0].url, 'jma', 'password', HttpStatusCode.FORBIDDEN_403)
344
345 expect(res.body.error).to.equal('No jma')
346 })
347 })
348
349 describe('Download hooks', function () {
350 const downloadVideos: VideoDetails[] = []
351
352 before(async function () {
353 this.timeout(120000)
354
355 await servers[0].configCommand.updateCustomSubConfig({
356 newConfig: {
357 transcoding: {
358 webtorrent: {
359 enabled: true
360 },
361 hls: {
362 enabled: true
363 }
364 }
365 }
366 })
367
368 const uuids: string[] = []
369
370 for (const name of [ 'bad torrent', 'bad file', 'bad playlist file' ]) {
371 const uuid = (await uploadVideoAndGetId({ server: servers[0], videoName: name })).uuid
372 uuids.push(uuid)
373 }
374
375 await waitJobs(servers)
376
377 for (const uuid of uuids) {
378 const res = await getVideo(servers[0].url, uuid)
379 downloadVideos.push(res.body)
380 }
381 })
382
383 it('Should run filter:api.download.torrent.allowed.result', async function () {
384 const res = await makeRawRequest(downloadVideos[0].files[0].torrentDownloadUrl, 403)
385 expect(res.body.error).to.equal('Liu Bei')
386
387 await makeRawRequest(downloadVideos[1].files[0].torrentDownloadUrl, 200)
388 await makeRawRequest(downloadVideos[2].files[0].torrentDownloadUrl, 200)
389 })
390
391 it('Should run filter:api.download.video.allowed.result', async function () {
392 {
393 const res = await makeRawRequest(downloadVideos[1].files[0].fileDownloadUrl, 403)
394 expect(res.body.error).to.equal('Cao Cao')
395
396 await makeRawRequest(downloadVideos[0].files[0].fileDownloadUrl, 200)
397 await makeRawRequest(downloadVideos[2].files[0].fileDownloadUrl, 200)
398 }
399
400 {
401 const res = await makeRawRequest(downloadVideos[2].streamingPlaylists[0].files[0].fileDownloadUrl, 403)
402 expect(res.body.error).to.equal('Sun Jian')
403
404 await makeRawRequest(downloadVideos[2].files[0].fileDownloadUrl, 200)
405
406 await makeRawRequest(downloadVideos[0].streamingPlaylists[0].files[0].fileDownloadUrl, 200)
407 await makeRawRequest(downloadVideos[1].streamingPlaylists[0].files[0].fileDownloadUrl, 200)
408 }
409 })
410 })
411
412 describe('Embed filters', function () {
413 const embedVideos: VideoDetails[] = []
414 const embedPlaylists: VideoPlaylist[] = []
415
416 before(async function () {
417 this.timeout(60000)
418
419 await servers[0].configCommand.updateCustomSubConfig({
420 newConfig: {
421 transcoding: {
422 enabled: false
423 }
424 }
425 })
426
427 for (const name of [ 'bad embed', 'good embed' ]) {
428 {
429 const uuid = (await uploadVideoAndGetId({ server: servers[0], videoName: name })).uuid
430 const res = await getVideo(servers[0].url, uuid)
431 embedVideos.push(res.body)
432 }
433
434 {
435 const attributes = { displayName: name, videoChannelId: servers[0].videoChannel.id, privacy: VideoPlaylistPrivacy.PUBLIC }
436 const { id } = await servers[0].playlistsCommand.create({ attributes })
437
438 const playlist = await servers[0].playlistsCommand.get({ playlistId: id })
439 embedPlaylists.push(playlist)
440 }
441 }
442 })
443
444 it('Should run filter:html.embed.video.allowed.result', async function () {
445 const res = await makeRawRequest(servers[0].url + embedVideos[0].embedPath, 200)
446 expect(res.text).to.equal('Lu Bu')
447 })
448
449 it('Should run filter:html.embed.video-playlist.allowed.result', async function () {
450 const res = await makeRawRequest(servers[0].url + embedPlaylists[0].embedPath, 200)
451 expect(res.text).to.equal('Diao Chan')
452 })
453 })
454
455 describe('Search filters', function () {
456
457 before(async function () {
458 await servers[0].configCommand.updateCustomSubConfig({
459 newConfig: {
460 search: {
461 searchIndex: {
462 enabled: true,
463 isDefaultSearch: false,
464 disableLocalSearch: false
465 }
466 }
467 }
468 })
469 })
470
471 it('Should run filter:api.search.videos.local.list.{params,result}', async function () {
472 await servers[0].searchCommand.advancedVideoSearch({
473 search: {
474 search: 'Sun Quan'
475 }
476 })
477
478 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
479 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
480 })
481
482 it('Should run filter:api.search.videos.index.list.{params,result}', async function () {
483 await servers[0].searchCommand.advancedVideoSearch({
484 search: {
485 search: 'Sun Quan',
486 searchTarget: 'search-index'
487 }
488 })
489
490 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
491 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
492 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.params', 1)
493 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.result', 1)
494 })
495
496 it('Should run filter:api.search.video-channels.local.list.{params,result}', async function () {
497 await servers[0].searchCommand.advancedChannelSearch({
498 search: {
499 search: 'Sun Ce'
500 }
501 })
502
503 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
504 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
505 })
506
507 it('Should run filter:api.search.video-channels.index.list.{params,result}', async function () {
508 await servers[0].searchCommand.advancedChannelSearch({
509 search: {
510 search: 'Sun Ce',
511 searchTarget: 'search-index'
512 }
513 })
514
515 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
516 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
517 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.params', 1)
518 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.result', 1)
519 })
520
521 it('Should run filter:api.search.video-playlists.local.list.{params,result}', async function () {
522 await servers[0].searchCommand.advancedPlaylistSearch({
523 search: {
524 search: 'Sun Jian'
525 }
526 })
527
528 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.params', 1)
529 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.result', 1)
530 })
531
532 it('Should run filter:api.search.video-playlists.index.list.{params,result}', async function () {
533 await servers[0].searchCommand.advancedPlaylistSearch({
534 search: {
535 search: 'Sun Jian',
536 searchTarget: 'search-index'
537 }
538 })
539
540 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.params', 1)
541 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.local.list.result', 1)
542 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.index.list.params', 1)
543 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-playlists.index.list.result', 1)
544 })
545 })
546
547 after(async function () {
548 await cleanupTests(servers)
549 })
550 })