]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/notifications/moderation-notifications.ts
Adapt CLI to new commands
[github/Chocobozzz/PeerTube.git] / server / tests / api / notifications / moderation-notifications.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import { buildUUID } from '@server/helpers/uuid'
5 import {
6 checkAbuseStateChange,
7 checkAutoInstanceFollowing,
8 CheckerBaseParams,
9 checkNewAbuseMessage,
10 checkNewAccountAbuseForModerators,
11 checkNewBlacklistOnMyVideo,
12 checkNewCommentAbuseForModerators,
13 checkNewInstanceFollower,
14 checkNewVideoAbuseForModerators,
15 checkNewVideoFromSubscription,
16 checkUserRegistered,
17 checkVideoAutoBlacklistForModerators,
18 checkVideoIsPublished,
19 cleanupTests,
20 createUser,
21 generateUserAccessToken,
22 getVideoIdFromUUID,
23 MockInstancesIndex,
24 MockSmtpServer,
25 prepareNotificationsTest,
26 registerUser,
27 ServerInfo,
28 uploadVideo,
29 wait,
30 waitJobs
31 } from '@shared/extra-utils'
32 import { AbuseState, CustomConfig, UserNotification, VideoPrivacy } from '@shared/models'
33
34 describe('Test moderation notifications', function () {
35 let servers: ServerInfo[] = []
36 let userAccessToken: string
37 let userNotifications: UserNotification[] = []
38 let adminNotifications: UserNotification[] = []
39 let adminNotificationsServer2: UserNotification[] = []
40 let emails: object[] = []
41
42 before(async function () {
43 this.timeout(120000)
44
45 const res = await prepareNotificationsTest(3)
46 emails = res.emails
47 userAccessToken = res.userAccessToken
48 servers = res.servers
49 userNotifications = res.userNotifications
50 adminNotifications = res.adminNotifications
51 adminNotificationsServer2 = res.adminNotificationsServer2
52 })
53
54 describe('Abuse for moderators notification', function () {
55 let baseParams: CheckerBaseParams
56
57 before(() => {
58 baseParams = {
59 server: servers[0],
60 emails,
61 socketNotifications: adminNotifications,
62 token: servers[0].accessToken
63 }
64 })
65
66 it('Should send a notification to moderators on local video abuse', async function () {
67 this.timeout(20000)
68
69 const name = 'video for abuse ' + buildUUID()
70 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
71 const video = resVideo.body.video
72
73 await servers[0].abusesCommand.report({ videoId: video.id, reason: 'super reason' })
74
75 await waitJobs(servers)
76 await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
77 })
78
79 it('Should send a notification to moderators on remote video abuse', async function () {
80 this.timeout(20000)
81
82 const name = 'video for abuse ' + buildUUID()
83 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
84 const video = resVideo.body.video
85
86 await waitJobs(servers)
87
88 const videoId = await getVideoIdFromUUID(servers[1].url, video.uuid)
89 await servers[1].abusesCommand.report({ videoId, reason: 'super reason' })
90
91 await waitJobs(servers)
92 await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
93 })
94
95 it('Should send a notification to moderators on local comment abuse', async function () {
96 this.timeout(20000)
97
98 const name = 'video for abuse ' + buildUUID()
99 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
100 const video = resVideo.body.video
101 const comment = await servers[0].commentsCommand.createThread({
102 token: userAccessToken,
103 videoId: video.id,
104 text: 'comment abuse ' + buildUUID()
105 })
106
107 await waitJobs(servers)
108
109 await servers[0].abusesCommand.report({ commentId: comment.id, reason: 'super reason' })
110
111 await waitJobs(servers)
112 await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
113 })
114
115 it('Should send a notification to moderators on remote comment abuse', async function () {
116 this.timeout(20000)
117
118 const name = 'video for abuse ' + buildUUID()
119 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
120 const video = resVideo.body.video
121
122 await servers[0].commentsCommand.createThread({
123 token: userAccessToken,
124 videoId: video.id,
125 text: 'comment abuse ' + buildUUID()
126 })
127
128 await waitJobs(servers)
129
130 const { data } = await servers[1].commentsCommand.listThreads({ videoId: video.uuid })
131 const commentId = data[0].id
132 await servers[1].abusesCommand.report({ commentId, reason: 'super reason' })
133
134 await waitJobs(servers)
135 await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
136 })
137
138 it('Should send a notification to moderators on local account abuse', async function () {
139 this.timeout(20000)
140
141 const username = 'user' + new Date().getTime()
142 const resUser = await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username, password: 'donald' })
143 const accountId = resUser.body.user.account.id
144
145 await servers[0].abusesCommand.report({ accountId, reason: 'super reason' })
146
147 await waitJobs(servers)
148 await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
149 })
150
151 it('Should send a notification to moderators on remote account abuse', async function () {
152 this.timeout(20000)
153
154 const username = 'user' + new Date().getTime()
155 const tmpToken = await generateUserAccessToken(servers[0], username)
156 await uploadVideo(servers[0].url, tmpToken, { name: 'super video' })
157
158 await waitJobs(servers)
159
160 const account = await servers[1].accountsCommand.get({ accountName: username + '@' + servers[0].host })
161 await servers[1].abusesCommand.report({ accountId: account.id, reason: 'super reason' })
162
163 await waitJobs(servers)
164 await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
165 })
166 })
167
168 describe('Abuse state change notification', function () {
169 let baseParams: CheckerBaseParams
170 let abuseId: number
171
172 before(async function () {
173 baseParams = {
174 server: servers[0],
175 emails,
176 socketNotifications: userNotifications,
177 token: userAccessToken
178 }
179
180 const name = 'abuse ' + buildUUID()
181 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
182 const video = resVideo.body.video
183
184 const body = await servers[0].abusesCommand.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
185 abuseId = body.abuse.id
186 })
187
188 it('Should send a notification to reporter if the abuse has been accepted', async function () {
189 this.timeout(10000)
190
191 await servers[0].abusesCommand.update({ abuseId, body: { state: AbuseState.ACCEPTED } })
192 await waitJobs(servers)
193
194 await checkAbuseStateChange(baseParams, abuseId, AbuseState.ACCEPTED, 'presence')
195 })
196
197 it('Should send a notification to reporter if the abuse has been rejected', async function () {
198 this.timeout(10000)
199
200 await servers[0].abusesCommand.update({ abuseId, body: { state: AbuseState.REJECTED } })
201 await waitJobs(servers)
202
203 await checkAbuseStateChange(baseParams, abuseId, AbuseState.REJECTED, 'presence')
204 })
205 })
206
207 describe('New abuse message notification', function () {
208 let baseParamsUser: CheckerBaseParams
209 let baseParamsAdmin: CheckerBaseParams
210 let abuseId: number
211 let abuseId2: number
212
213 before(async function () {
214 baseParamsUser = {
215 server: servers[0],
216 emails,
217 socketNotifications: userNotifications,
218 token: userAccessToken
219 }
220
221 baseParamsAdmin = {
222 server: servers[0],
223 emails,
224 socketNotifications: adminNotifications,
225 token: servers[0].accessToken
226 }
227
228 const name = 'abuse ' + buildUUID()
229 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
230 const video = resVideo.body.video
231
232 {
233 const body = await servers[0].abusesCommand.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
234 abuseId = body.abuse.id
235 }
236
237 {
238 const body = await servers[0].abusesCommand.report({ token: userAccessToken, videoId: video.id, reason: 'super reason 2' })
239 abuseId2 = body.abuse.id
240 }
241 })
242
243 it('Should send a notification to reporter on new message', async function () {
244 this.timeout(10000)
245
246 const message = 'my super message to users'
247 await servers[0].abusesCommand.addMessage({ abuseId, message })
248 await waitJobs(servers)
249
250 await checkNewAbuseMessage(baseParamsUser, abuseId, message, 'user_1@example.com', 'presence')
251 })
252
253 it('Should not send a notification to the admin if sent by the admin', async function () {
254 this.timeout(10000)
255
256 const message = 'my super message that should not be sent to the admin'
257 await servers[0].abusesCommand.addMessage({ abuseId, message })
258 await waitJobs(servers)
259
260 await checkNewAbuseMessage(baseParamsAdmin, abuseId, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'absence')
261 })
262
263 it('Should send a notification to moderators', async function () {
264 this.timeout(10000)
265
266 const message = 'my super message to moderators'
267 await servers[0].abusesCommand.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
268 await waitJobs(servers)
269
270 await checkNewAbuseMessage(baseParamsAdmin, abuseId2, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'presence')
271 })
272
273 it('Should not send a notification to reporter if sent by the reporter', async function () {
274 this.timeout(10000)
275
276 const message = 'my super message that should not be sent to reporter'
277 await servers[0].abusesCommand.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
278 await waitJobs(servers)
279
280 await checkNewAbuseMessage(baseParamsUser, abuseId2, message, 'user_1@example.com', 'absence')
281 })
282 })
283
284 describe('Video blacklist on my video', function () {
285 let baseParams: CheckerBaseParams
286
287 before(() => {
288 baseParams = {
289 server: servers[0],
290 emails,
291 socketNotifications: userNotifications,
292 token: userAccessToken
293 }
294 })
295
296 it('Should send a notification to video owner on blacklist', async function () {
297 this.timeout(10000)
298
299 const name = 'video for abuse ' + buildUUID()
300 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
301 const uuid = resVideo.body.video.uuid
302
303 await servers[0].blacklistCommand.add({ videoId: uuid })
304
305 await waitJobs(servers)
306 await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'blacklist')
307 })
308
309 it('Should send a notification to video owner on unblacklist', async function () {
310 this.timeout(10000)
311
312 const name = 'video for abuse ' + buildUUID()
313 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
314 const uuid = resVideo.body.video.uuid
315
316 await servers[0].blacklistCommand.add({ videoId: uuid })
317
318 await waitJobs(servers)
319 await servers[0].blacklistCommand.remove({ videoId: uuid })
320 await waitJobs(servers)
321
322 await wait(500)
323 await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'unblacklist')
324 })
325 })
326
327 describe('New registration', function () {
328 let baseParams: CheckerBaseParams
329
330 before(() => {
331 baseParams = {
332 server: servers[0],
333 emails,
334 socketNotifications: adminNotifications,
335 token: servers[0].accessToken
336 }
337 })
338
339 it('Should send a notification only to moderators when a user registers on the instance', async function () {
340 this.timeout(10000)
341
342 await registerUser(servers[0].url, 'user_45', 'password')
343
344 await waitJobs(servers)
345
346 await checkUserRegistered(baseParams, 'user_45', 'presence')
347
348 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
349 await checkUserRegistered({ ...baseParams, ...userOverride }, 'user_45', 'absence')
350 })
351 })
352
353 describe('New instance follows', function () {
354 const instanceIndexServer = new MockInstancesIndex()
355 let config: any
356 let baseParams: CheckerBaseParams
357
358 before(async () => {
359 baseParams = {
360 server: servers[0],
361 emails,
362 socketNotifications: adminNotifications,
363 token: servers[0].accessToken
364 }
365
366 const port = await instanceIndexServer.initialize()
367 instanceIndexServer.addInstance(servers[1].host)
368
369 config = {
370 followings: {
371 instance: {
372 autoFollowIndex: {
373 indexUrl: `http://localhost:${port}/api/v1/instances/hosts`,
374 enabled: true
375 }
376 }
377 }
378 }
379 })
380
381 it('Should send a notification only to admin when there is a new instance follower', async function () {
382 this.timeout(20000)
383
384 await servers[2].followsCommand.follow({ targets: [ servers[0].url ] })
385
386 await waitJobs(servers)
387
388 await checkNewInstanceFollower(baseParams, 'localhost:' + servers[2].port, 'presence')
389
390 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
391 await checkNewInstanceFollower({ ...baseParams, ...userOverride }, 'localhost:' + servers[2].port, 'absence')
392 })
393
394 it('Should send a notification on auto follow back', async function () {
395 this.timeout(40000)
396
397 await servers[2].followsCommand.unfollow({ target: servers[0] })
398 await waitJobs(servers)
399
400 const config = {
401 followings: {
402 instance: {
403 autoFollowBack: { enabled: true }
404 }
405 }
406 }
407 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
408
409 await servers[2].followsCommand.follow({ targets: [ servers[0].url ] })
410
411 await waitJobs(servers)
412
413 const followerHost = servers[0].host
414 const followingHost = servers[2].host
415 await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
416
417 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
418 await checkAutoInstanceFollowing({ ...baseParams, ...userOverride }, followerHost, followingHost, 'absence')
419
420 config.followings.instance.autoFollowBack.enabled = false
421 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
422 await servers[0].followsCommand.unfollow({ target: servers[2] })
423 await servers[2].followsCommand.unfollow({ target: servers[0] })
424 })
425
426 it('Should send a notification on auto instances index follow', async function () {
427 this.timeout(30000)
428 await servers[0].followsCommand.unfollow({ target: servers[1] })
429
430 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
431
432 await wait(5000)
433 await waitJobs(servers)
434
435 const followerHost = servers[0].host
436 const followingHost = servers[1].host
437 await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
438
439 config.followings.instance.autoFollowIndex.enabled = false
440 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
441 await servers[0].followsCommand.unfollow({ target: servers[1] })
442 })
443 })
444
445 describe('Video-related notifications when video auto-blacklist is enabled', function () {
446 let userBaseParams: CheckerBaseParams
447 let adminBaseParamsServer1: CheckerBaseParams
448 let adminBaseParamsServer2: CheckerBaseParams
449 let videoUUID: string
450 let videoName: string
451 let currentCustomConfig: CustomConfig
452
453 before(async () => {
454
455 adminBaseParamsServer1 = {
456 server: servers[0],
457 emails,
458 socketNotifications: adminNotifications,
459 token: servers[0].accessToken
460 }
461
462 adminBaseParamsServer2 = {
463 server: servers[1],
464 emails,
465 socketNotifications: adminNotificationsServer2,
466 token: servers[1].accessToken
467 }
468
469 userBaseParams = {
470 server: servers[0],
471 emails,
472 socketNotifications: userNotifications,
473 token: userAccessToken
474 }
475
476 currentCustomConfig = await servers[0].configCommand.getCustomConfig()
477
478 const autoBlacklistTestsCustomConfig = {
479 ...currentCustomConfig,
480
481 autoBlacklist: {
482 videos: {
483 ofUsers: {
484 enabled: true
485 }
486 }
487 }
488 }
489
490 // enable transcoding otherwise own publish notification after transcoding not expected
491 autoBlacklistTestsCustomConfig.transcoding.enabled = true
492 await servers[0].configCommand.updateCustomConfig({ newCustomConfig: autoBlacklistTestsCustomConfig })
493
494 await servers[0].subscriptionsCommand.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
495 await servers[1].subscriptionsCommand.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
496
497 })
498
499 it('Should send notification to moderators on new video with auto-blacklist', async function () {
500 this.timeout(40000)
501
502 videoName = 'video with auto-blacklist ' + buildUUID()
503 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
504 videoUUID = resVideo.body.video.uuid
505
506 await waitJobs(servers)
507 await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, videoUUID, videoName, 'presence')
508 })
509
510 it('Should not send video publish notification if auto-blacklisted', async function () {
511 await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'absence')
512 })
513
514 it('Should not send a local user subscription notification if auto-blacklisted', async function () {
515 await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'absence')
516 })
517
518 it('Should not send a remote user subscription notification if auto-blacklisted', async function () {
519 await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'absence')
520 })
521
522 it('Should send video published and unblacklist after video unblacklisted', async function () {
523 this.timeout(40000)
524
525 await servers[0].blacklistCommand.remove({ videoId: videoUUID })
526
527 await waitJobs(servers)
528
529 // FIXME: Can't test as two notifications sent to same user and util only checks last one
530 // One notification might be better anyways
531 // await checkNewBlacklistOnMyVideo(userBaseParams, videoUUID, videoName, 'unblacklist')
532 // await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'presence')
533 })
534
535 it('Should send a local user subscription notification after removed from blacklist', async function () {
536 await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'presence')
537 })
538
539 it('Should send a remote user subscription notification after removed from blacklist', async function () {
540 await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'presence')
541 })
542
543 it('Should send unblacklist but not published/subscription notes after unblacklisted if scheduled update pending', async function () {
544 this.timeout(40000)
545
546 const updateAt = new Date(new Date().getTime() + 1000000)
547
548 const name = 'video with auto-blacklist and future schedule ' + buildUUID()
549
550 const data = {
551 name,
552 privacy: VideoPrivacy.PRIVATE,
553 scheduleUpdate: {
554 updateAt: updateAt.toISOString(),
555 privacy: VideoPrivacy.PUBLIC
556 }
557 }
558
559 const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
560 const uuid = resVideo.body.video.uuid
561
562 await servers[0].blacklistCommand.remove({ videoId: uuid })
563
564 await waitJobs(servers)
565 await checkNewBlacklistOnMyVideo(userBaseParams, uuid, name, 'unblacklist')
566
567 // FIXME: Can't test absence as two notifications sent to same user and util only checks last one
568 // One notification might be better anyways
569 // await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
570
571 await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
572 await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
573 })
574
575 it('Should not send publish/subscription notifications after scheduled update if video still auto-blacklisted', async function () {
576 this.timeout(40000)
577
578 // In 2 seconds
579 const updateAt = new Date(new Date().getTime() + 2000)
580
581 const name = 'video with schedule done and still auto-blacklisted ' + buildUUID()
582
583 const data = {
584 name,
585 privacy: VideoPrivacy.PRIVATE,
586 scheduleUpdate: {
587 updateAt: updateAt.toISOString(),
588 privacy: VideoPrivacy.PUBLIC
589 }
590 }
591
592 const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
593 const uuid = resVideo.body.video.uuid
594
595 await wait(6000)
596 await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
597 await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
598 await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
599 })
600
601 it('Should not send a notification to moderators on new video without auto-blacklist', async function () {
602 this.timeout(60000)
603
604 const name = 'video without auto-blacklist ' + buildUUID()
605
606 // admin with blacklist right will not be auto-blacklisted
607 const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name })
608 const uuid = resVideo.body.video.uuid
609
610 await waitJobs(servers)
611 await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, uuid, name, 'absence')
612 })
613
614 after(async () => {
615 await servers[0].configCommand.updateCustomConfig({ newCustomConfig: currentCustomConfig })
616
617 await servers[0].subscriptionsCommand.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
618 await servers[1].subscriptionsCommand.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
619 })
620 })
621
622 after(async function () {
623 MockSmtpServer.Instance.kill()
624
625 await cleanupTests(servers)
626 })
627 })