Split notification tests
[oweals/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 { v4 as uuidv4 } from 'uuid'
5 import {
6   addVideoToBlacklist,
7   cleanupTests,
8   follow,
9   getCustomConfig,
10   immutableAssign,
11   MockInstancesIndex,
12   registerUser,
13   removeVideoFromBlacklist,
14   reportVideoAbuse,
15   unfollow,
16   updateCustomConfig,
17   updateCustomSubConfig,
18   wait
19 } from '../../../../shared/extra-utils'
20 import { ServerInfo, uploadVideo } from '../../../../shared/extra-utils/index'
21 import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
22 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
23 import {
24   checkAutoInstanceFollowing,
25   CheckerBaseParams,
26   checkNewBlacklistOnMyVideo,
27   checkNewInstanceFollower,
28   checkNewVideoAbuseForModerators,
29   checkNewVideoFromSubscription,
30   checkUserRegistered,
31   checkVideoAutoBlacklistForModerators,
32   checkVideoIsPublished,
33   prepareNotificationsTest
34 } from '../../../../shared/extra-utils/users/user-notifications'
35 import { addUserSubscription, removeUserSubscription } from '../../../../shared/extra-utils/users/user-subscriptions'
36 import { CustomConfig } from '../../../../shared/models/server'
37 import { UserNotification } from '../../../../shared/models/users'
38 import { VideoPrivacy } from '../../../../shared/models/videos'
39
40 describe('Test moderation notifications', function () {
41   let servers: ServerInfo[] = []
42   let userAccessToken: string
43   let userNotifications: UserNotification[] = []
44   let adminNotifications: UserNotification[] = []
45   let adminNotificationsServer2: UserNotification[] = []
46   let emails: object[] = []
47
48   before(async function () {
49     this.timeout(120000)
50
51     const res = await prepareNotificationsTest(3)
52     emails = res.emails
53     userAccessToken = res.userAccessToken
54     servers = res.servers
55     userNotifications = res.userNotifications
56     adminNotifications = res.adminNotifications
57     adminNotificationsServer2 = res.adminNotificationsServer2
58   })
59
60   describe('Video abuse for moderators notification', function () {
61     let baseParams: CheckerBaseParams
62
63     before(() => {
64       baseParams = {
65         server: servers[0],
66         emails,
67         socketNotifications: adminNotifications,
68         token: servers[0].accessToken
69       }
70     })
71
72     it('Should send a notification to moderators on local video abuse', async function () {
73       this.timeout(10000)
74
75       const name = 'video for abuse ' + uuidv4()
76       const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
77       const uuid = resVideo.body.video.uuid
78
79       await reportVideoAbuse(servers[0].url, servers[0].accessToken, uuid, 'super reason')
80
81       await waitJobs(servers)
82       await checkNewVideoAbuseForModerators(baseParams, uuid, name, 'presence')
83     })
84
85     it('Should send a notification to moderators on remote video abuse', async function () {
86       this.timeout(10000)
87
88       const name = 'video for abuse ' + uuidv4()
89       const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
90       const uuid = resVideo.body.video.uuid
91
92       await waitJobs(servers)
93
94       await reportVideoAbuse(servers[1].url, servers[1].accessToken, uuid, 'super reason')
95
96       await waitJobs(servers)
97       await checkNewVideoAbuseForModerators(baseParams, uuid, name, 'presence')
98     })
99   })
100
101   describe('Video blacklist on my video', function () {
102     let baseParams: CheckerBaseParams
103
104     before(() => {
105       baseParams = {
106         server: servers[0],
107         emails,
108         socketNotifications: userNotifications,
109         token: userAccessToken
110       }
111     })
112
113     it('Should send a notification to video owner on blacklist', async function () {
114       this.timeout(10000)
115
116       const name = 'video for abuse ' + uuidv4()
117       const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
118       const uuid = resVideo.body.video.uuid
119
120       await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid)
121
122       await waitJobs(servers)
123       await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'blacklist')
124     })
125
126     it('Should send a notification to video owner on unblacklist', async function () {
127       this.timeout(10000)
128
129       const name = 'video for abuse ' + uuidv4()
130       const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
131       const uuid = resVideo.body.video.uuid
132
133       await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid)
134
135       await waitJobs(servers)
136       await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, uuid)
137       await waitJobs(servers)
138
139       await wait(500)
140       await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'unblacklist')
141     })
142   })
143
144   describe('New registration', function () {
145     let baseParams: CheckerBaseParams
146
147     before(() => {
148       baseParams = {
149         server: servers[0],
150         emails,
151         socketNotifications: adminNotifications,
152         token: servers[0].accessToken
153       }
154     })
155
156     it('Should send a notification only to moderators when a user registers on the instance', async function () {
157       this.timeout(10000)
158
159       await registerUser(servers[0].url, 'user_45', 'password')
160
161       await waitJobs(servers)
162
163       await checkUserRegistered(baseParams, 'user_45', 'presence')
164
165       const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
166       await checkUserRegistered(immutableAssign(baseParams, userOverride), 'user_45', 'absence')
167     })
168   })
169
170   describe('New instance follows', function () {
171     const instanceIndexServer = new MockInstancesIndex()
172     const config = {
173       followings: {
174         instance: {
175           autoFollowIndex: {
176             indexUrl: 'http://localhost:42101/api/v1/instances/hosts',
177             enabled: true
178           }
179         }
180       }
181     }
182     let baseParams: CheckerBaseParams
183
184     before(async () => {
185       baseParams = {
186         server: servers[0],
187         emails,
188         socketNotifications: adminNotifications,
189         token: servers[0].accessToken
190       }
191
192       await instanceIndexServer.initialize()
193       instanceIndexServer.addInstance(servers[1].host)
194     })
195
196     it('Should send a notification only to admin when there is a new instance follower', async function () {
197       this.timeout(20000)
198
199       await follow(servers[2].url, [ servers[0].url ], servers[2].accessToken)
200
201       await waitJobs(servers)
202
203       await checkNewInstanceFollower(baseParams, 'localhost:' + servers[2].port, 'presence')
204
205       const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
206       await checkNewInstanceFollower(immutableAssign(baseParams, userOverride), 'localhost:' + servers[2].port, 'absence')
207     })
208
209     it('Should send a notification on auto follow back', async function () {
210       this.timeout(40000)
211
212       await unfollow(servers[2].url, servers[2].accessToken, servers[0])
213       await waitJobs(servers)
214
215       const config = {
216         followings: {
217           instance: {
218             autoFollowBack: { enabled: true }
219           }
220         }
221       }
222       await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
223
224       await follow(servers[2].url, [ servers[0].url ], servers[2].accessToken)
225
226       await waitJobs(servers)
227
228       const followerHost = servers[0].host
229       const followingHost = servers[2].host
230       await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
231
232       const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
233       await checkAutoInstanceFollowing(immutableAssign(baseParams, userOverride), followerHost, followingHost, 'absence')
234
235       config.followings.instance.autoFollowBack.enabled = false
236       await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
237       await unfollow(servers[0].url, servers[0].accessToken, servers[2])
238       await unfollow(servers[2].url, servers[2].accessToken, servers[0])
239     })
240
241     it('Should send a notification on auto instances index follow', async function () {
242       this.timeout(30000)
243       await unfollow(servers[0].url, servers[0].accessToken, servers[1])
244
245       await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
246
247       await wait(5000)
248       await waitJobs(servers)
249
250       const followerHost = servers[0].host
251       const followingHost = servers[1].host
252       await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
253
254       config.followings.instance.autoFollowIndex.enabled = false
255       await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
256       await unfollow(servers[0].url, servers[0].accessToken, servers[1])
257     })
258   })
259
260   describe('Video-related notifications when video auto-blacklist is enabled', function () {
261     let userBaseParams: CheckerBaseParams
262     let adminBaseParamsServer1: CheckerBaseParams
263     let adminBaseParamsServer2: CheckerBaseParams
264     let videoUUID: string
265     let videoName: string
266     let currentCustomConfig: CustomConfig
267
268     before(async () => {
269
270       adminBaseParamsServer1 = {
271         server: servers[0],
272         emails,
273         socketNotifications: adminNotifications,
274         token: servers[0].accessToken
275       }
276
277       adminBaseParamsServer2 = {
278         server: servers[1],
279         emails,
280         socketNotifications: adminNotificationsServer2,
281         token: servers[1].accessToken
282       }
283
284       userBaseParams = {
285         server: servers[0],
286         emails,
287         socketNotifications: userNotifications,
288         token: userAccessToken
289       }
290
291       const resCustomConfig = await getCustomConfig(servers[0].url, servers[0].accessToken)
292       currentCustomConfig = resCustomConfig.body
293       const autoBlacklistTestsCustomConfig = immutableAssign(currentCustomConfig, {
294         autoBlacklist: {
295           videos: {
296             ofUsers: {
297               enabled: true
298             }
299           }
300         }
301       })
302       // enable transcoding otherwise own publish notification after transcoding not expected
303       autoBlacklistTestsCustomConfig.transcoding.enabled = true
304       await updateCustomConfig(servers[0].url, servers[0].accessToken, autoBlacklistTestsCustomConfig)
305
306       await addUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:' + servers[0].port)
307       await addUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:' + servers[0].port)
308
309     })
310
311     it('Should send notification to moderators on new video with auto-blacklist', async function () {
312       this.timeout(20000)
313
314       videoName = 'video with auto-blacklist ' + uuidv4()
315       const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
316       videoUUID = resVideo.body.video.uuid
317
318       await waitJobs(servers)
319       await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, videoUUID, videoName, 'presence')
320     })
321
322     it('Should not send video publish notification if auto-blacklisted', async function () {
323       await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'absence')
324     })
325
326     it('Should not send a local user subscription notification if auto-blacklisted', async function () {
327       await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'absence')
328     })
329
330     it('Should not send a remote user subscription notification if auto-blacklisted', async function () {
331       await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'absence')
332     })
333
334     it('Should send video published and unblacklist after video unblacklisted', async function () {
335       this.timeout(20000)
336
337       await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, videoUUID)
338
339       await waitJobs(servers)
340
341       // FIXME: Can't test as two notifications sent to same user and util only checks last one
342       // One notification might be better anyways
343       // await checkNewBlacklistOnMyVideo(userBaseParams, videoUUID, videoName, 'unblacklist')
344       // await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'presence')
345     })
346
347     it('Should send a local user subscription notification after removed from blacklist', async function () {
348       await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'presence')
349     })
350
351     it('Should send a remote user subscription notification after removed from blacklist', async function () {
352       await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'presence')
353     })
354
355     it('Should send unblacklist but not published/subscription notes after unblacklisted if scheduled update pending', async function () {
356       this.timeout(20000)
357
358       const updateAt = new Date(new Date().getTime() + 1000000)
359
360       const name = 'video with auto-blacklist and future schedule ' + uuidv4()
361
362       const data = {
363         name,
364         privacy: VideoPrivacy.PRIVATE,
365         scheduleUpdate: {
366           updateAt: updateAt.toISOString(),
367           privacy: VideoPrivacy.PUBLIC
368         }
369       }
370
371       const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
372       const uuid = resVideo.body.video.uuid
373
374       await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, uuid)
375
376       await waitJobs(servers)
377       await checkNewBlacklistOnMyVideo(userBaseParams, uuid, name, 'unblacklist')
378
379       // FIXME: Can't test absence as two notifications sent to same user and util only checks last one
380       // One notification might be better anyways
381       // await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
382
383       await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
384       await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
385     })
386
387     it('Should not send publish/subscription notifications after scheduled update if video still auto-blacklisted', async function () {
388       this.timeout(20000)
389
390       // In 2 seconds
391       const updateAt = new Date(new Date().getTime() + 2000)
392
393       const name = 'video with schedule done and still auto-blacklisted ' + uuidv4()
394
395       const data = {
396         name,
397         privacy: VideoPrivacy.PRIVATE,
398         scheduleUpdate: {
399           updateAt: updateAt.toISOString(),
400           privacy: VideoPrivacy.PUBLIC
401         }
402       }
403
404       const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
405       const uuid = resVideo.body.video.uuid
406
407       await wait(6000)
408       await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
409       await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
410       await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
411     })
412
413     it('Should not send a notification to moderators on new video without auto-blacklist', async function () {
414       this.timeout(20000)
415
416       const name = 'video without auto-blacklist ' + uuidv4()
417
418       // admin with blacklist right will not be auto-blacklisted
419       const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name })
420       const uuid = resVideo.body.video.uuid
421
422       await waitJobs(servers)
423       await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, uuid, name, 'absence')
424     })
425
426     after(async () => {
427       await updateCustomConfig(servers[0].url, servers[0].accessToken, currentCustomConfig)
428
429       await removeUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:' + servers[0].port)
430       await removeUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:' + servers[0].port)
431     })
432   })
433
434   after(async function () {
435     MockSmtpServer.Instance.kill()
436
437     await cleanupTests(servers)
438   })
439 })