allow limiting video-comments rss feeds to an account or video channel
[oweals/peertube.git] / server / tests / api / users / blocklist.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import * as chai from 'chai'
4 import 'mocha'
5 import { AccountBlock, ServerBlock, Video, UserNotification, UserNotificationType } from '../../../../shared/index'
6 import {
7   cleanupTests,
8   createUser,
9   deleteVideoComment,
10   doubleFollow,
11   flushAndRunMultipleServers,
12   ServerInfo,
13   uploadVideo,
14   userLogin,
15   follow,
16   unfollow
17 } from '../../../../shared/extra-utils/index'
18 import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
19 import { getVideosList, getVideosListWithToken } from '../../../../shared/extra-utils/videos/videos'
20 import {
21   addVideoCommentReply,
22   addVideoCommentThread,
23   getVideoCommentThreads,
24   getVideoThreadComments,
25   findCommentId
26 } from '../../../../shared/extra-utils/videos/video-comments'
27 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
28 import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model'
29 import {
30   addAccountToAccountBlocklist,
31   addAccountToServerBlocklist,
32   addServerToAccountBlocklist,
33   addServerToServerBlocklist,
34   getAccountBlocklistByAccount,
35   getAccountBlocklistByServer,
36   getServerBlocklistByAccount,
37   getServerBlocklistByServer,
38   removeAccountFromAccountBlocklist,
39   removeAccountFromServerBlocklist,
40   removeServerFromAccountBlocklist,
41   removeServerFromServerBlocklist
42 } from '../../../../shared/extra-utils/users/blocklist'
43 import { getUserNotifications } from '../../../../shared/extra-utils/users/user-notifications'
44
45 const expect = chai.expect
46
47 async function checkAllVideos (url: string, token: string) {
48   {
49     const res = await getVideosListWithToken(url, token)
50
51     expect(res.body.data).to.have.lengthOf(5)
52   }
53
54   {
55     const res = await getVideosList(url)
56
57     expect(res.body.data).to.have.lengthOf(5)
58   }
59 }
60
61 async function checkAllComments (url: string, token: string, videoUUID: string) {
62   const resThreads = await getVideoCommentThreads(url, videoUUID, 0, 25, '-createdAt', token)
63
64   const allThreads: VideoComment[] = resThreads.body.data
65   const threads = allThreads.filter(t => t.isDeleted === false)
66   expect(threads).to.have.lengthOf(2)
67
68   for (const thread of threads) {
69     const res = await getVideoThreadComments(url, videoUUID, thread.id, token)
70
71     const tree: VideoCommentThreadTree = res.body
72     expect(tree.children).to.have.lengthOf(1)
73   }
74 }
75
76 async function checkCommentNotification (
77   mainServer: ServerInfo,
78   comment: { server: ServerInfo, token: string, videoUUID: string, text: string },
79   check: 'presence' | 'absence'
80 ) {
81   const resComment = await addVideoCommentThread(comment.server.url, comment.token, comment.videoUUID, comment.text)
82   const created = resComment.body.comment as VideoComment
83   const threadId = created.id
84   const createdAt = created.createdAt
85
86   await waitJobs([ mainServer, comment.server ])
87
88   const res = await getUserNotifications(mainServer.url, mainServer.accessToken, 0, 30)
89   const commentNotifications = (res.body.data as UserNotification[])
90                                   .filter(n => n.comment && n.comment.video.uuid === comment.videoUUID && n.createdAt >= createdAt)
91
92   if (check === 'presence') expect(commentNotifications).to.have.lengthOf(1)
93   else expect(commentNotifications).to.have.lengthOf(0)
94
95   await deleteVideoComment(comment.server.url, comment.token, comment.videoUUID, threadId)
96
97   await waitJobs([ mainServer, comment.server ])
98 }
99
100 describe('Test blocklist', function () {
101   let servers: ServerInfo[]
102   let videoUUID1: string
103   let videoUUID2: string
104   let videoUUID3: string
105   let userToken1: string
106   let userModeratorToken: string
107   let userToken2: string
108
109   before(async function () {
110     this.timeout(60000)
111
112     servers = await flushAndRunMultipleServers(3)
113     await setAccessTokensToServers(servers)
114
115     {
116       const user = { username: 'user1', password: 'password' }
117       await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
118
119       userToken1 = await userLogin(servers[0], user)
120       await uploadVideo(servers[0].url, userToken1, { name: 'video user 1' })
121     }
122
123     {
124       const user = { username: 'moderator', password: 'password' }
125       await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
126
127       userModeratorToken = await userLogin(servers[0], user)
128     }
129
130     {
131       const user = { username: 'user2', password: 'password' }
132       await createUser({ url: servers[1].url, accessToken: servers[1].accessToken, username: user.username, password: user.password })
133
134       userToken2 = await userLogin(servers[1], user)
135       await uploadVideo(servers[1].url, userToken2, { name: 'video user 2' })
136     }
137
138     {
139       const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video server 1' })
140       videoUUID1 = res.body.video.uuid
141     }
142
143     {
144       const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video server 2' })
145       videoUUID2 = res.body.video.uuid
146     }
147
148     {
149       const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video 2 server 1' })
150       videoUUID3 = res.body.video.uuid
151     }
152
153     await doubleFollow(servers[0], servers[1])
154     await doubleFollow(servers[0], servers[2])
155
156     {
157       const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID1, 'comment root 1')
158       const resReply = await addVideoCommentReply(servers[0].url, userToken1, videoUUID1, resComment.body.comment.id, 'comment user 1')
159       await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID1, resReply.body.comment.id, 'comment root 1')
160     }
161
162     {
163       const resComment = await addVideoCommentThread(servers[0].url, userToken1, videoUUID1, 'comment user 1')
164       await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID1, resComment.body.comment.id, 'comment root 1')
165     }
166
167     await waitJobs(servers)
168   })
169
170   describe('User blocklist', function () {
171
172     describe('When managing account blocklist', function () {
173       it('Should list all videos', function () {
174         return checkAllVideos(servers[0].url, servers[0].accessToken)
175       })
176
177       it('Should list the comments', function () {
178         return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
179       })
180
181       it('Should block a remote account', async function () {
182         await addAccountToAccountBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
183       })
184
185       it('Should hide its videos', async function () {
186         const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
187
188         const videos: Video[] = res.body.data
189         expect(videos).to.have.lengthOf(4)
190
191         const v = videos.find(v => v.name === 'video user 2')
192         expect(v).to.be.undefined
193       })
194
195       it('Should block a local account', async function () {
196         await addAccountToAccountBlocklist(servers[0].url, servers[0].accessToken, 'user1')
197       })
198
199       it('Should hide its videos', async function () {
200         const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
201
202         const videos: Video[] = res.body.data
203         expect(videos).to.have.lengthOf(3)
204
205         const v = videos.find(v => v.name === 'video user 1')
206         expect(v).to.be.undefined
207       })
208
209       it('Should hide its comments', async function () {
210         const resThreads = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 25, '-createdAt', servers[0].accessToken)
211
212         const threads: VideoComment[] = resThreads.body.data
213         expect(threads).to.have.lengthOf(1)
214         expect(threads[0].totalReplies).to.equal(0)
215
216         const t = threads.find(t => t.text === 'comment user 1')
217         expect(t).to.be.undefined
218
219         for (const thread of threads) {
220           const res = await getVideoThreadComments(servers[0].url, videoUUID1, thread.id, servers[0].accessToken)
221
222           const tree: VideoCommentThreadTree = res.body
223           expect(tree.children).to.have.lengthOf(0)
224         }
225       })
226
227       it('Should not have notifications from blocked accounts', async function () {
228         this.timeout(20000)
229
230         {
231           const comment = { server: servers[0], token: userToken1, videoUUID: videoUUID1, text: 'hidden comment' }
232           await checkCommentNotification(servers[0], comment, 'absence')
233         }
234
235         {
236           const comment = {
237             server: servers[0],
238             token: userToken1,
239             videoUUID: videoUUID2,
240             text: 'hello @root@localhost:' + servers[0].port
241           }
242           await checkCommentNotification(servers[0], comment, 'absence')
243         }
244       })
245
246       it('Should list all the videos with another user', async function () {
247         return checkAllVideos(servers[0].url, userToken1)
248       })
249
250       it('Should list blocked accounts', async function () {
251         {
252           const res = await getAccountBlocklistByAccount(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
253           const blocks: AccountBlock[] = res.body.data
254
255           expect(res.body.total).to.equal(2)
256
257           const block = blocks[0]
258           expect(block.byAccount.displayName).to.equal('root')
259           expect(block.byAccount.name).to.equal('root')
260           expect(block.blockedAccount.displayName).to.equal('user2')
261           expect(block.blockedAccount.name).to.equal('user2')
262           expect(block.blockedAccount.host).to.equal('localhost:' + servers[1].port)
263         }
264
265         {
266           const res = await getAccountBlocklistByAccount(servers[0].url, servers[0].accessToken, 1, 2, 'createdAt')
267           const blocks: AccountBlock[] = res.body.data
268
269           expect(res.body.total).to.equal(2)
270
271           const block = blocks[0]
272           expect(block.byAccount.displayName).to.equal('root')
273           expect(block.byAccount.name).to.equal('root')
274           expect(block.blockedAccount.displayName).to.equal('user1')
275           expect(block.blockedAccount.name).to.equal('user1')
276           expect(block.blockedAccount.host).to.equal('localhost:' + servers[0].port)
277         }
278       })
279
280       it('Should not allow a remote blocked user to comment my videos', async function () {
281         this.timeout(60000)
282
283         {
284           await addVideoCommentThread(servers[1].url, userToken2, videoUUID3, 'comment user 2')
285           await waitJobs(servers)
286
287           await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID3, 'uploader')
288           await waitJobs(servers)
289
290           const commentId = await findCommentId(servers[1].url, videoUUID3, 'uploader')
291           const message = 'reply by user 2'
292           const resReply = await addVideoCommentReply(servers[1].url, userToken2, videoUUID3, commentId, message)
293           await addVideoCommentReply(servers[1].url, servers[1].accessToken, videoUUID3, resReply.body.comment.id, 'another reply')
294
295           await waitJobs(servers)
296         }
297
298         // Server 2 has all the comments
299         {
300           const resThreads = await getVideoCommentThreads(servers[1].url, videoUUID3, 0, 25, '-createdAt')
301           const threads: VideoComment[] = resThreads.body.data
302
303           expect(threads).to.have.lengthOf(2)
304           expect(threads[0].text).to.equal('uploader')
305           expect(threads[1].text).to.equal('comment user 2')
306
307           const resReplies = await getVideoThreadComments(servers[1].url, videoUUID3, threads[0].id)
308
309           const tree: VideoCommentThreadTree = resReplies.body
310           expect(tree.children).to.have.lengthOf(1)
311           expect(tree.children[0].comment.text).to.equal('reply by user 2')
312           expect(tree.children[0].children).to.have.lengthOf(1)
313           expect(tree.children[0].children[0].comment.text).to.equal('another reply')
314         }
315
316         // Server 1 and 3 should only have uploader comments
317         for (const server of [ servers[0], servers[2] ]) {
318           const resThreads = await getVideoCommentThreads(server.url, videoUUID3, 0, 25, '-createdAt')
319           const threads: VideoComment[] = resThreads.body.data
320
321           expect(threads).to.have.lengthOf(1)
322           expect(threads[0].text).to.equal('uploader')
323
324           const resReplies = await getVideoThreadComments(server.url, videoUUID3, threads[0].id)
325
326           const tree: VideoCommentThreadTree = resReplies.body
327           if (server.serverNumber === 1) {
328             expect(tree.children).to.have.lengthOf(0)
329           } else {
330             expect(tree.children).to.have.lengthOf(1)
331           }
332         }
333       })
334
335       it('Should unblock the remote account', async function () {
336         await removeAccountFromAccountBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
337       })
338
339       it('Should display its videos', async function () {
340         const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
341
342         const videos: Video[] = res.body.data
343         expect(videos).to.have.lengthOf(4)
344
345         const v = videos.find(v => v.name === 'video user 2')
346         expect(v).not.to.be.undefined
347       })
348
349       it('Should display its comments on my video', async function () {
350         for (const server of servers) {
351           const resThreads = await getVideoCommentThreads(server.url, videoUUID3, 0, 25, '-createdAt')
352           const threads: VideoComment[] = resThreads.body.data
353
354           // Server 3 should not have 2 comment threads, because server 1 did not forward the server 2 comment
355           if (server.serverNumber === 3) {
356             expect(threads).to.have.lengthOf(1)
357             continue
358           }
359
360           expect(threads).to.have.lengthOf(2)
361           expect(threads[0].text).to.equal('uploader')
362           expect(threads[1].text).to.equal('comment user 2')
363
364           const resReplies = await getVideoThreadComments(server.url, videoUUID3, threads[0].id)
365
366           const tree: VideoCommentThreadTree = resReplies.body
367           expect(tree.children).to.have.lengthOf(1)
368           expect(tree.children[0].comment.text).to.equal('reply by user 2')
369           expect(tree.children[0].children).to.have.lengthOf(1)
370           expect(tree.children[0].children[0].comment.text).to.equal('another reply')
371         }
372       })
373
374       it('Should unblock the local account', async function () {
375         await removeAccountFromAccountBlocklist(servers[0].url, servers[0].accessToken, 'user1')
376       })
377
378       it('Should display its comments', function () {
379         return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
380       })
381
382       it('Should have a notification from a non blocked account', async function () {
383         this.timeout(20000)
384
385         {
386           const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'displayed comment' }
387           await checkCommentNotification(servers[0], comment, 'presence')
388         }
389
390         {
391           const comment = {
392             server: servers[0],
393             token: userToken1,
394             videoUUID: videoUUID2,
395             text: 'hello @root@localhost:' + servers[0].port
396           }
397           await checkCommentNotification(servers[0], comment, 'presence')
398         }
399       })
400     })
401
402     describe('When managing server blocklist', function () {
403       it('Should list all videos', function () {
404         return checkAllVideos(servers[0].url, servers[0].accessToken)
405       })
406
407       it('Should list the comments', function () {
408         return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
409       })
410
411       it('Should block a remote server', async function () {
412         await addServerToAccountBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
413       })
414
415       it('Should hide its videos', async function () {
416         const res = await getVideosListWithToken(servers[0].url, servers[0].accessToken)
417
418         const videos: Video[] = res.body.data
419         expect(videos).to.have.lengthOf(3)
420
421         const v1 = videos.find(v => v.name === 'video user 2')
422         const v2 = videos.find(v => v.name === 'video server 2')
423
424         expect(v1).to.be.undefined
425         expect(v2).to.be.undefined
426       })
427
428       it('Should list all the videos with another user', async function () {
429         return checkAllVideos(servers[0].url, userToken1)
430       })
431
432       it('Should hide its comments', async function () {
433         this.timeout(10000)
434
435         const resThreads = await addVideoCommentThread(servers[1].url, userToken2, videoUUID1, 'hidden comment 2')
436         const threadId = resThreads.body.comment.id
437
438         await waitJobs(servers)
439
440         await checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
441
442         await deleteVideoComment(servers[1].url, userToken2, videoUUID1, threadId)
443       })
444
445       it('Should not have notifications from blocked server', async function () {
446         this.timeout(20000)
447
448         {
449           const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'hidden comment' }
450           await checkCommentNotification(servers[0], comment, 'absence')
451         }
452
453         {
454           const comment = {
455             server: servers[1],
456             token: userToken2,
457             videoUUID: videoUUID1,
458             text: 'hello @root@localhost:' + servers[0].port
459           }
460           await checkCommentNotification(servers[0], comment, 'absence')
461         }
462       })
463
464       it('Should list blocked servers', async function () {
465         const res = await getServerBlocklistByAccount(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
466         const blocks: ServerBlock[] = res.body.data
467
468         expect(res.body.total).to.equal(1)
469
470         const block = blocks[0]
471         expect(block.byAccount.displayName).to.equal('root')
472         expect(block.byAccount.name).to.equal('root')
473         expect(block.blockedServer.host).to.equal('localhost:' + servers[1].port)
474       })
475
476       it('Should unblock the remote server', async function () {
477         await removeServerFromAccountBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
478       })
479
480       it('Should display its videos', function () {
481         return checkAllVideos(servers[0].url, servers[0].accessToken)
482       })
483
484       it('Should display its comments', function () {
485         return checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
486       })
487
488       it('Should have notification from unblocked server', async function () {
489         this.timeout(20000)
490
491         {
492           const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'displayed comment' }
493           await checkCommentNotification(servers[0], comment, 'presence')
494         }
495
496         {
497           const comment = {
498             server: servers[1],
499             token: userToken2,
500             videoUUID: videoUUID1,
501             text: 'hello @root@localhost:' + servers[0].port
502           }
503           await checkCommentNotification(servers[0], comment, 'presence')
504         }
505       })
506     })
507   })
508
509   describe('Server blocklist', function () {
510
511     describe('When managing account blocklist', function () {
512       it('Should list all videos', async function () {
513         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
514           await checkAllVideos(servers[0].url, token)
515         }
516       })
517
518       it('Should list the comments', async function () {
519         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
520           await checkAllComments(servers[0].url, token, videoUUID1)
521         }
522       })
523
524       it('Should block a remote account', async function () {
525         await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
526       })
527
528       it('Should hide its videos', async function () {
529         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
530           const res = await getVideosListWithToken(servers[0].url, token)
531
532           const videos: Video[] = res.body.data
533           expect(videos).to.have.lengthOf(4)
534
535           const v = videos.find(v => v.name === 'video user 2')
536           expect(v).to.be.undefined
537         }
538       })
539
540       it('Should block a local account', async function () {
541         await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, 'user1')
542       })
543
544       it('Should hide its videos', async function () {
545         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
546           const res = await getVideosListWithToken(servers[0].url, token)
547
548           const videos: Video[] = res.body.data
549           expect(videos).to.have.lengthOf(3)
550
551           const v = videos.find(v => v.name === 'video user 1')
552           expect(v).to.be.undefined
553         }
554       })
555
556       it('Should hide its comments', async function () {
557         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
558           const resThreads = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 20, '-createdAt', token)
559
560           let threads: VideoComment[] = resThreads.body.data
561           threads = threads.filter(t => t.isDeleted === false)
562
563           expect(threads).to.have.lengthOf(1)
564           expect(threads[0].totalReplies).to.equal(0)
565
566           const t = threads.find(t => t.text === 'comment user 1')
567           expect(t).to.be.undefined
568
569           for (const thread of threads) {
570             const res = await getVideoThreadComments(servers[0].url, videoUUID1, thread.id, token)
571
572             const tree: VideoCommentThreadTree = res.body
573             expect(tree.children).to.have.lengthOf(0)
574           }
575         }
576       })
577
578       it('Should not have notification from blocked accounts by instance', async function () {
579         this.timeout(20000)
580
581         {
582           const comment = { server: servers[0], token: userToken1, videoUUID: videoUUID1, text: 'hidden comment' }
583           await checkCommentNotification(servers[0], comment, 'absence')
584         }
585
586         {
587           const comment = {
588             server: servers[1],
589             token: userToken2,
590             videoUUID: videoUUID1,
591             text: 'hello @root@localhost:' + servers[0].port
592           }
593           await checkCommentNotification(servers[0], comment, 'absence')
594         }
595       })
596
597       it('Should list blocked accounts', async function () {
598         {
599           const res = await getAccountBlocklistByServer(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
600           const blocks: AccountBlock[] = res.body.data
601
602           expect(res.body.total).to.equal(2)
603
604           const block = blocks[0]
605           expect(block.byAccount.displayName).to.equal('peertube')
606           expect(block.byAccount.name).to.equal('peertube')
607           expect(block.blockedAccount.displayName).to.equal('user2')
608           expect(block.blockedAccount.name).to.equal('user2')
609           expect(block.blockedAccount.host).to.equal('localhost:' + servers[1].port)
610         }
611
612         {
613           const res = await getAccountBlocklistByServer(servers[0].url, servers[0].accessToken, 1, 2, 'createdAt')
614           const blocks: AccountBlock[] = res.body.data
615
616           expect(res.body.total).to.equal(2)
617
618           const block = blocks[0]
619           expect(block.byAccount.displayName).to.equal('peertube')
620           expect(block.byAccount.name).to.equal('peertube')
621           expect(block.blockedAccount.displayName).to.equal('user1')
622           expect(block.blockedAccount.name).to.equal('user1')
623           expect(block.blockedAccount.host).to.equal('localhost:' + servers[0].port)
624         }
625       })
626
627       it('Should unblock the remote account', async function () {
628         await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, 'user2@localhost:' + servers[1].port)
629       })
630
631       it('Should display its videos', async function () {
632         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
633           const res = await getVideosListWithToken(servers[0].url, token)
634
635           const videos: Video[] = res.body.data
636           expect(videos).to.have.lengthOf(4)
637
638           const v = videos.find(v => v.name === 'video user 2')
639           expect(v).not.to.be.undefined
640         }
641       })
642
643       it('Should unblock the local account', async function () {
644         await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, 'user1')
645       })
646
647       it('Should display its comments', async function () {
648         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
649           await checkAllComments(servers[0].url, token, videoUUID1)
650         }
651       })
652
653       it('Should have notifications from unblocked accounts', async function () {
654         this.timeout(20000)
655
656         {
657           const comment = { server: servers[0], token: userToken1, videoUUID: videoUUID1, text: 'displayed comment' }
658           await checkCommentNotification(servers[0], comment, 'presence')
659         }
660
661         {
662           const comment = {
663             server: servers[1],
664             token: userToken2,
665             videoUUID: videoUUID1,
666             text: 'hello @root@localhost:' + servers[0].port
667           }
668           await checkCommentNotification(servers[0], comment, 'presence')
669         }
670       })
671     })
672
673     describe('When managing server blocklist', function () {
674       it('Should list all videos', async function () {
675         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
676           await checkAllVideos(servers[0].url, token)
677         }
678       })
679
680       it('Should list the comments', async function () {
681         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
682           await checkAllComments(servers[0].url, token, videoUUID1)
683         }
684       })
685
686       it('Should block a remote server', async function () {
687         await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
688       })
689
690       it('Should hide its videos', async function () {
691         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
692           const res1 = await getVideosList(servers[0].url)
693           const res2 = await getVideosListWithToken(servers[0].url, token)
694
695           for (const res of [ res1, res2 ]) {
696             const videos: Video[] = res.body.data
697             expect(videos).to.have.lengthOf(3)
698
699             const v1 = videos.find(v => v.name === 'video user 2')
700             const v2 = videos.find(v => v.name === 'video server 2')
701
702             expect(v1).to.be.undefined
703             expect(v2).to.be.undefined
704           }
705         }
706       })
707
708       it('Should hide its comments', async function () {
709         this.timeout(10000)
710
711         const resThreads = await addVideoCommentThread(servers[1].url, userToken2, videoUUID1, 'hidden comment 2')
712         const threadId = resThreads.body.comment.id
713
714         await waitJobs(servers)
715
716         await checkAllComments(servers[0].url, servers[0].accessToken, videoUUID1)
717
718         await deleteVideoComment(servers[1].url, userToken2, videoUUID1, threadId)
719       })
720
721       it('Should not have notification from blocked instances by instance', async function () {
722         this.timeout(50000)
723
724         {
725           const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'hidden comment' }
726           await checkCommentNotification(servers[0], comment, 'absence')
727         }
728
729         {
730           const comment = {
731             server: servers[1],
732             token: userToken2,
733             videoUUID: videoUUID1,
734             text: 'hello @root@localhost:' + servers[0].port
735           }
736           await checkCommentNotification(servers[0], comment, 'absence')
737         }
738
739         {
740           const now = new Date()
741           await unfollow(servers[1].url, servers[1].accessToken, servers[0])
742           await waitJobs(servers)
743           await follow(servers[1].url, [ servers[0].host ], servers[1].accessToken)
744
745           await waitJobs(servers)
746
747           const res = await getUserNotifications(servers[0].url, servers[0].accessToken, 0, 30)
748           const commentNotifications = (res.body.data as UserNotification[])
749                                           .filter(n => {
750                                             return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER &&
751                                             n.createdAt >= now.toISOString()
752                                           })
753
754           expect(commentNotifications).to.have.lengthOf(0)
755         }
756       })
757
758       it('Should list blocked servers', async function () {
759         const res = await getServerBlocklistByServer(servers[0].url, servers[0].accessToken, 0, 1, 'createdAt')
760         const blocks: ServerBlock[] = res.body.data
761
762         expect(res.body.total).to.equal(1)
763
764         const block = blocks[0]
765         expect(block.byAccount.displayName).to.equal('peertube')
766         expect(block.byAccount.name).to.equal('peertube')
767         expect(block.blockedServer.host).to.equal('localhost:' + servers[1].port)
768       })
769
770       it('Should unblock the remote server', async function () {
771         await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, 'localhost:' + servers[1].port)
772       })
773
774       it('Should list all videos', async function () {
775         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
776           await checkAllVideos(servers[0].url, token)
777         }
778       })
779
780       it('Should list the comments', async function () {
781         for (const token of [ userModeratorToken, servers[0].accessToken ]) {
782           await checkAllComments(servers[0].url, token, videoUUID1)
783         }
784       })
785
786       it('Should have notification from unblocked instances', async function () {
787         this.timeout(50000)
788
789         {
790           const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'displayed comment' }
791           await checkCommentNotification(servers[0], comment, 'presence')
792         }
793
794         {
795           const comment = {
796             server: servers[1],
797             token: userToken2,
798             videoUUID: videoUUID1,
799             text: 'hello @root@localhost:' + servers[0].port
800           }
801           await checkCommentNotification(servers[0], comment, 'presence')
802         }
803
804         {
805           const now = new Date()
806           await unfollow(servers[1].url, servers[1].accessToken, servers[0])
807           await waitJobs(servers)
808           await follow(servers[1].url, [ servers[0].host ], servers[1].accessToken)
809
810           await waitJobs(servers)
811
812           const res = await getUserNotifications(servers[0].url, servers[0].accessToken, 0, 30)
813           const commentNotifications = (res.body.data as UserNotification[])
814                                           .filter(n => {
815                                             return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER &&
816                                             n.createdAt >= now.toISOString()
817                                           })
818
819           expect(commentNotifications).to.have.lengthOf(1)
820         }
821       })
822     })
823   })
824
825   after(async function () {
826     await cleanupTests(servers)
827   })
828 })