1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import { buildUUID } from '@server/helpers/uuid'
8 checkAutoInstanceFollowing,
11 checkNewAccountAbuseForModerators,
12 checkNewBlacklistOnMyVideo,
13 checkNewCommentAbuseForModerators,
14 checkNewInstanceFollower,
15 checkNewVideoAbuseForModerators,
16 checkNewVideoFromSubscription,
18 checkVideoAutoBlacklistForModerators,
19 checkVideoIsPublished,
22 generateUserAccessToken,
23 getVideoCommentThreads,
28 prepareNotificationsTest,
34 } from '@shared/extra-utils'
35 import { AbuseState, CustomConfig, UserNotification, VideoPrivacy } from '@shared/models'
37 describe('Test moderation notifications', function () {
38 let servers: ServerInfo[] = []
39 let userAccessToken: string
40 let userNotifications: UserNotification[] = []
41 let adminNotifications: UserNotification[] = []
42 let adminNotificationsServer2: UserNotification[] = []
43 let emails: object[] = []
45 before(async function () {
48 const res = await prepareNotificationsTest(3)
50 userAccessToken = res.userAccessToken
52 userNotifications = res.userNotifications
53 adminNotifications = res.adminNotifications
54 adminNotificationsServer2 = res.adminNotificationsServer2
57 describe('Abuse for moderators notification', function () {
58 let baseParams: CheckerBaseParams
64 socketNotifications: adminNotifications,
65 token: servers[0].accessToken
69 it('Should send a notification to moderators on local video abuse', async function () {
72 const name = 'video for abuse ' + buildUUID()
73 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
74 const video = resVideo.body.video
76 await servers[0].abusesCommand.report({ videoId: video.id, reason: 'super reason' })
78 await waitJobs(servers)
79 await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
82 it('Should send a notification to moderators on remote video abuse', async function () {
85 const name = 'video for abuse ' + buildUUID()
86 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
87 const video = resVideo.body.video
89 await waitJobs(servers)
91 const videoId = await getVideoIdFromUUID(servers[1].url, video.uuid)
92 await servers[1].abusesCommand.report({ videoId, reason: 'super reason' })
94 await waitJobs(servers)
95 await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
98 it('Should send a notification to moderators on local comment abuse', async function () {
101 const name = 'video for abuse ' + buildUUID()
102 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
103 const video = resVideo.body.video
104 const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, video.id, 'comment abuse ' + buildUUID())
105 const comment = resComment.body.comment
107 await waitJobs(servers)
109 await servers[0].abusesCommand.report({ commentId: comment.id, reason: 'super reason' })
111 await waitJobs(servers)
112 await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
115 it('Should send a notification to moderators on remote comment abuse', async function () {
118 const name = 'video for abuse ' + buildUUID()
119 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
120 const video = resVideo.body.video
121 await addVideoCommentThread(servers[0].url, userAccessToken, video.id, 'comment abuse ' + buildUUID())
123 await waitJobs(servers)
125 const resComments = await getVideoCommentThreads(servers[1].url, video.uuid, 0, 5)
126 const commentId = resComments.body.data[0].id
127 await servers[1].abusesCommand.report({ commentId, reason: 'super reason' })
129 await waitJobs(servers)
130 await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
133 it('Should send a notification to moderators on local account abuse', async function () {
136 const username = 'user' + new Date().getTime()
137 const resUser = await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username, password: 'donald' })
138 const accountId = resUser.body.user.account.id
140 await servers[0].abusesCommand.report({ accountId, reason: 'super reason' })
142 await waitJobs(servers)
143 await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
146 it('Should send a notification to moderators on remote account abuse', async function () {
149 const username = 'user' + new Date().getTime()
150 const tmpToken = await generateUserAccessToken(servers[0], username)
151 await uploadVideo(servers[0].url, tmpToken, { name: 'super video' })
153 await waitJobs(servers)
155 const account = await servers[1].accountsCommand.get({ accountName: username + '@' + servers[0].host })
156 await servers[1].abusesCommand.report({ accountId: account.id, reason: 'super reason' })
158 await waitJobs(servers)
159 await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
163 describe('Abuse state change notification', function () {
164 let baseParams: CheckerBaseParams
167 before(async function () {
171 socketNotifications: userNotifications,
172 token: userAccessToken
175 const name = 'abuse ' + buildUUID()
176 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
177 const video = resVideo.body.video
179 const body = await servers[0].abusesCommand.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
180 abuseId = body.abuse.id
183 it('Should send a notification to reporter if the abuse has been accepted', async function () {
186 await servers[0].abusesCommand.update({ abuseId, body: { state: AbuseState.ACCEPTED } })
187 await waitJobs(servers)
189 await checkAbuseStateChange(baseParams, abuseId, AbuseState.ACCEPTED, 'presence')
192 it('Should send a notification to reporter if the abuse has been rejected', async function () {
195 await servers[0].abusesCommand.update({ abuseId, body: { state: AbuseState.REJECTED } })
196 await waitJobs(servers)
198 await checkAbuseStateChange(baseParams, abuseId, AbuseState.REJECTED, 'presence')
202 describe('New abuse message notification', function () {
203 let baseParamsUser: CheckerBaseParams
204 let baseParamsAdmin: CheckerBaseParams
208 before(async function () {
212 socketNotifications: userNotifications,
213 token: userAccessToken
219 socketNotifications: adminNotifications,
220 token: servers[0].accessToken
223 const name = 'abuse ' + buildUUID()
224 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
225 const video = resVideo.body.video
228 const body = await servers[0].abusesCommand.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
229 abuseId = body.abuse.id
233 const body = await servers[0].abusesCommand.report({ token: userAccessToken, videoId: video.id, reason: 'super reason 2' })
234 abuseId2 = body.abuse.id
238 it('Should send a notification to reporter on new message', async function () {
241 const message = 'my super message to users'
242 await servers[0].abusesCommand.addMessage({ abuseId, message })
243 await waitJobs(servers)
245 await checkNewAbuseMessage(baseParamsUser, abuseId, message, 'user_1@example.com', 'presence')
248 it('Should not send a notification to the admin if sent by the admin', async function () {
251 const message = 'my super message that should not be sent to the admin'
252 await servers[0].abusesCommand.addMessage({ abuseId, message })
253 await waitJobs(servers)
255 await checkNewAbuseMessage(baseParamsAdmin, abuseId, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'absence')
258 it('Should send a notification to moderators', async function () {
261 const message = 'my super message to moderators'
262 await servers[0].abusesCommand.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
263 await waitJobs(servers)
265 await checkNewAbuseMessage(baseParamsAdmin, abuseId2, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'presence')
268 it('Should not send a notification to reporter if sent by the reporter', async function () {
271 const message = 'my super message that should not be sent to reporter'
272 await servers[0].abusesCommand.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
273 await waitJobs(servers)
275 await checkNewAbuseMessage(baseParamsUser, abuseId2, message, 'user_1@example.com', 'absence')
279 describe('Video blacklist on my video', function () {
280 let baseParams: CheckerBaseParams
286 socketNotifications: userNotifications,
287 token: userAccessToken
291 it('Should send a notification to video owner on blacklist', async function () {
294 const name = 'video for abuse ' + buildUUID()
295 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
296 const uuid = resVideo.body.video.uuid
298 await servers[0].blacklistCommand.add({ videoId: uuid })
300 await waitJobs(servers)
301 await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'blacklist')
304 it('Should send a notification to video owner on unblacklist', async function () {
307 const name = 'video for abuse ' + buildUUID()
308 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
309 const uuid = resVideo.body.video.uuid
311 await servers[0].blacklistCommand.add({ videoId: uuid })
313 await waitJobs(servers)
314 await servers[0].blacklistCommand.remove({ videoId: uuid })
315 await waitJobs(servers)
318 await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'unblacklist')
322 describe('New registration', function () {
323 let baseParams: CheckerBaseParams
329 socketNotifications: adminNotifications,
330 token: servers[0].accessToken
334 it('Should send a notification only to moderators when a user registers on the instance', async function () {
337 await registerUser(servers[0].url, 'user_45', 'password')
339 await waitJobs(servers)
341 await checkUserRegistered(baseParams, 'user_45', 'presence')
343 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
344 await checkUserRegistered(immutableAssign(baseParams, userOverride), 'user_45', 'absence')
348 describe('New instance follows', function () {
349 const instanceIndexServer = new MockInstancesIndex()
351 let baseParams: CheckerBaseParams
357 socketNotifications: adminNotifications,
358 token: servers[0].accessToken
361 const port = await instanceIndexServer.initialize()
362 instanceIndexServer.addInstance(servers[1].host)
368 indexUrl: `http://localhost:${port}/api/v1/instances/hosts`,
376 it('Should send a notification only to admin when there is a new instance follower', async function () {
379 await servers[2].followsCommand.follow({ targets: [ servers[0].url ] })
381 await waitJobs(servers)
383 await checkNewInstanceFollower(baseParams, 'localhost:' + servers[2].port, 'presence')
385 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
386 await checkNewInstanceFollower(immutableAssign(baseParams, userOverride), 'localhost:' + servers[2].port, 'absence')
389 it('Should send a notification on auto follow back', async function () {
392 await servers[2].followsCommand.unfollow({ target: servers[0] })
393 await waitJobs(servers)
398 autoFollowBack: { enabled: true }
402 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
404 await servers[2].followsCommand.follow({ targets: [ servers[0].url ] })
406 await waitJobs(servers)
408 const followerHost = servers[0].host
409 const followingHost = servers[2].host
410 await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
412 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
413 await checkAutoInstanceFollowing(immutableAssign(baseParams, userOverride), followerHost, followingHost, 'absence')
415 config.followings.instance.autoFollowBack.enabled = false
416 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
417 await servers[0].followsCommand.unfollow({ target: servers[2] })
418 await servers[2].followsCommand.unfollow({ target: servers[0] })
421 it('Should send a notification on auto instances index follow', async function () {
423 await servers[0].followsCommand.unfollow({ target: servers[1] })
425 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
428 await waitJobs(servers)
430 const followerHost = servers[0].host
431 const followingHost = servers[1].host
432 await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
434 config.followings.instance.autoFollowIndex.enabled = false
435 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
436 await servers[0].followsCommand.unfollow({ target: servers[1] })
440 describe('Video-related notifications when video auto-blacklist is enabled', function () {
441 let userBaseParams: CheckerBaseParams
442 let adminBaseParamsServer1: CheckerBaseParams
443 let adminBaseParamsServer2: CheckerBaseParams
444 let videoUUID: string
445 let videoName: string
446 let currentCustomConfig: CustomConfig
450 adminBaseParamsServer1 = {
453 socketNotifications: adminNotifications,
454 token: servers[0].accessToken
457 adminBaseParamsServer2 = {
460 socketNotifications: adminNotificationsServer2,
461 token: servers[1].accessToken
467 socketNotifications: userNotifications,
468 token: userAccessToken
471 currentCustomConfig = await servers[0].configCommand.getCustomConfig()
473 const autoBlacklistTestsCustomConfig = immutableAssign(currentCustomConfig, {
483 // enable transcoding otherwise own publish notification after transcoding not expected
484 autoBlacklistTestsCustomConfig.transcoding.enabled = true
485 await servers[0].configCommand.updateCustomConfig({ newCustomConfig: autoBlacklistTestsCustomConfig })
487 await servers[0].subscriptionsCommand.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
488 await servers[1].subscriptionsCommand.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
492 it('Should send notification to moderators on new video with auto-blacklist', async function () {
495 videoName = 'video with auto-blacklist ' + buildUUID()
496 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
497 videoUUID = resVideo.body.video.uuid
499 await waitJobs(servers)
500 await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, videoUUID, videoName, 'presence')
503 it('Should not send video publish notification if auto-blacklisted', async function () {
504 await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'absence')
507 it('Should not send a local user subscription notification if auto-blacklisted', async function () {
508 await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'absence')
511 it('Should not send a remote user subscription notification if auto-blacklisted', async function () {
512 await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'absence')
515 it('Should send video published and unblacklist after video unblacklisted', async function () {
518 await servers[0].blacklistCommand.remove({ videoId: videoUUID })
520 await waitJobs(servers)
522 // FIXME: Can't test as two notifications sent to same user and util only checks last one
523 // One notification might be better anyways
524 // await checkNewBlacklistOnMyVideo(userBaseParams, videoUUID, videoName, 'unblacklist')
525 // await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'presence')
528 it('Should send a local user subscription notification after removed from blacklist', async function () {
529 await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'presence')
532 it('Should send a remote user subscription notification after removed from blacklist', async function () {
533 await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'presence')
536 it('Should send unblacklist but not published/subscription notes after unblacklisted if scheduled update pending', async function () {
539 const updateAt = new Date(new Date().getTime() + 1000000)
541 const name = 'video with auto-blacklist and future schedule ' + buildUUID()
545 privacy: VideoPrivacy.PRIVATE,
547 updateAt: updateAt.toISOString(),
548 privacy: VideoPrivacy.PUBLIC
552 const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
553 const uuid = resVideo.body.video.uuid
555 await servers[0].blacklistCommand.remove({ videoId: uuid })
557 await waitJobs(servers)
558 await checkNewBlacklistOnMyVideo(userBaseParams, uuid, name, 'unblacklist')
560 // FIXME: Can't test absence as two notifications sent to same user and util only checks last one
561 // One notification might be better anyways
562 // await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
564 await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
565 await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
568 it('Should not send publish/subscription notifications after scheduled update if video still auto-blacklisted', async function () {
572 const updateAt = new Date(new Date().getTime() + 2000)
574 const name = 'video with schedule done and still auto-blacklisted ' + buildUUID()
578 privacy: VideoPrivacy.PRIVATE,
580 updateAt: updateAt.toISOString(),
581 privacy: VideoPrivacy.PUBLIC
585 const resVideo = await uploadVideo(servers[0].url, userAccessToken, data)
586 const uuid = resVideo.body.video.uuid
589 await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
590 await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
591 await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
594 it('Should not send a notification to moderators on new video without auto-blacklist', async function () {
597 const name = 'video without auto-blacklist ' + buildUUID()
599 // admin with blacklist right will not be auto-blacklisted
600 const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name })
601 const uuid = resVideo.body.video.uuid
603 await waitJobs(servers)
604 await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, uuid, name, 'absence')
608 await servers[0].configCommand.updateCustomConfig({ newCustomConfig: currentCustomConfig })
610 await servers[0].subscriptionsCommand.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
611 await servers[1].subscriptionsCommand.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
615 after(async function () {
616 MockSmtpServer.Instance.kill()
618 await cleanupTests(servers)