1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import { buildUUID } from '@server/helpers/uuid'
7 checkAutoInstanceFollowing,
10 checkNewAccountAbuseForModerators,
11 checkNewBlacklistOnMyVideo,
12 checkNewCommentAbuseForModerators,
13 checkNewInstanceFollower,
14 checkNewVideoAbuseForModerators,
15 checkNewVideoFromSubscription,
17 checkVideoAutoBlacklistForModerators,
18 checkVideoIsPublished,
23 prepareNotificationsTest,
26 } from '@shared/extra-utils'
27 import { AbuseState, CustomConfig, UserNotification, VideoPrivacy } from '@shared/models'
29 describe('Test moderation notifications', function () {
30 let servers: PeerTubeServer[] = []
31 let userAccessToken: string
32 let userNotifications: UserNotification[] = []
33 let adminNotifications: UserNotification[] = []
34 let adminNotificationsServer2: UserNotification[] = []
35 let emails: object[] = []
37 before(async function () {
40 const res = await prepareNotificationsTest(3)
42 userAccessToken = res.userAccessToken
44 userNotifications = res.userNotifications
45 adminNotifications = res.adminNotifications
46 adminNotificationsServer2 = res.adminNotificationsServer2
49 describe('Abuse for moderators notification', function () {
50 let baseParams: CheckerBaseParams
56 socketNotifications: adminNotifications,
57 token: servers[0].accessToken
61 it('Should send a notification to moderators on local video abuse', async function () {
64 const name = 'video for abuse ' + buildUUID()
65 const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
67 await servers[0].abuses.report({ videoId: video.id, reason: 'super reason' })
69 await waitJobs(servers)
70 await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
73 it('Should send a notification to moderators on remote video abuse', async function () {
76 const name = 'video for abuse ' + buildUUID()
77 const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
79 await waitJobs(servers)
81 const videoId = await servers[1].videos.getId({ uuid: video.uuid })
82 await servers[1].abuses.report({ videoId, reason: 'super reason' })
84 await waitJobs(servers)
85 await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
88 it('Should send a notification to moderators on local comment abuse', async function () {
91 const name = 'video for abuse ' + buildUUID()
92 const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
93 const comment = await servers[0].comments.createThread({
94 token: userAccessToken,
96 text: 'comment abuse ' + buildUUID()
99 await waitJobs(servers)
101 await servers[0].abuses.report({ commentId: comment.id, reason: 'super reason' })
103 await waitJobs(servers)
104 await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
107 it('Should send a notification to moderators on remote comment abuse', async function () {
110 const name = 'video for abuse ' + buildUUID()
111 const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
113 await servers[0].comments.createThread({
114 token: userAccessToken,
116 text: 'comment abuse ' + buildUUID()
119 await waitJobs(servers)
121 const { data } = await servers[1].comments.listThreads({ videoId: video.uuid })
122 const commentId = data[0].id
123 await servers[1].abuses.report({ commentId, reason: 'super reason' })
125 await waitJobs(servers)
126 await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
129 it('Should send a notification to moderators on local account abuse', async function () {
132 const username = 'user' + new Date().getTime()
133 const { account } = await servers[0].users.create({ username, password: 'donald' })
134 const accountId = account.id
136 await servers[0].abuses.report({ accountId, reason: 'super reason' })
138 await waitJobs(servers)
139 await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
142 it('Should send a notification to moderators on remote account abuse', async function () {
145 const username = 'user' + new Date().getTime()
146 const tmpToken = await servers[0].users.generateUserAndToken(username)
147 await servers[0].videos.upload({ token: tmpToken, attributes: { name: 'super video' } })
149 await waitJobs(servers)
151 const account = await servers[1].accounts.get({ accountName: username + '@' + servers[0].host })
152 await servers[1].abuses.report({ accountId: account.id, reason: 'super reason' })
154 await waitJobs(servers)
155 await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
159 describe('Abuse state change notification', function () {
160 let baseParams: CheckerBaseParams
163 before(async function () {
167 socketNotifications: userNotifications,
168 token: userAccessToken
171 const name = 'abuse ' + buildUUID()
172 const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
174 const body = await servers[0].abuses.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
175 abuseId = body.abuse.id
178 it('Should send a notification to reporter if the abuse has been accepted', async function () {
181 await servers[0].abuses.update({ abuseId, body: { state: AbuseState.ACCEPTED } })
182 await waitJobs(servers)
184 await checkAbuseStateChange(baseParams, abuseId, AbuseState.ACCEPTED, 'presence')
187 it('Should send a notification to reporter if the abuse has been rejected', async function () {
190 await servers[0].abuses.update({ abuseId, body: { state: AbuseState.REJECTED } })
191 await waitJobs(servers)
193 await checkAbuseStateChange(baseParams, abuseId, AbuseState.REJECTED, 'presence')
197 describe('New abuse message notification', function () {
198 let baseParamsUser: CheckerBaseParams
199 let baseParamsAdmin: CheckerBaseParams
203 before(async function () {
207 socketNotifications: userNotifications,
208 token: userAccessToken
214 socketNotifications: adminNotifications,
215 token: servers[0].accessToken
218 const name = 'abuse ' + buildUUID()
219 const video = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
222 const body = await servers[0].abuses.report({ token: userAccessToken, videoId: video.id, reason: 'super reason' })
223 abuseId = body.abuse.id
227 const body = await servers[0].abuses.report({ token: userAccessToken, videoId: video.id, reason: 'super reason 2' })
228 abuseId2 = body.abuse.id
232 it('Should send a notification to reporter on new message', async function () {
235 const message = 'my super message to users'
236 await servers[0].abuses.addMessage({ abuseId, message })
237 await waitJobs(servers)
239 await checkNewAbuseMessage(baseParamsUser, abuseId, message, 'user_1@example.com', 'presence')
242 it('Should not send a notification to the admin if sent by the admin', async function () {
245 const message = 'my super message that should not be sent to the admin'
246 await servers[0].abuses.addMessage({ abuseId, message })
247 await waitJobs(servers)
249 await checkNewAbuseMessage(baseParamsAdmin, abuseId, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'absence')
252 it('Should send a notification to moderators', async function () {
255 const message = 'my super message to moderators'
256 await servers[0].abuses.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
257 await waitJobs(servers)
259 await checkNewAbuseMessage(baseParamsAdmin, abuseId2, message, 'admin' + servers[0].internalServerNumber + '@example.com', 'presence')
262 it('Should not send a notification to reporter if sent by the reporter', async function () {
265 const message = 'my super message that should not be sent to reporter'
266 await servers[0].abuses.addMessage({ token: userAccessToken, abuseId: abuseId2, message })
267 await waitJobs(servers)
269 await checkNewAbuseMessage(baseParamsUser, abuseId2, message, 'user_1@example.com', 'absence')
273 describe('Video blacklist on my video', function () {
274 let baseParams: CheckerBaseParams
280 socketNotifications: userNotifications,
281 token: userAccessToken
285 it('Should send a notification to video owner on blacklist', async function () {
288 const name = 'video for abuse ' + buildUUID()
289 const { uuid } = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
291 await servers[0].blacklist.add({ videoId: uuid })
293 await waitJobs(servers)
294 await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'blacklist')
297 it('Should send a notification to video owner on unblacklist', async function () {
300 const name = 'video for abuse ' + buildUUID()
301 const { uuid } = await servers[0].videos.upload({ token: userAccessToken, attributes: { name } })
303 await servers[0].blacklist.add({ videoId: uuid })
305 await waitJobs(servers)
306 await servers[0].blacklist.remove({ videoId: uuid })
307 await waitJobs(servers)
310 await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'unblacklist')
314 describe('New registration', function () {
315 let baseParams: CheckerBaseParams
321 socketNotifications: adminNotifications,
322 token: servers[0].accessToken
326 it('Should send a notification only to moderators when a user registers on the instance', async function () {
329 await servers[0].users.register({ username: 'user_45' })
331 await waitJobs(servers)
333 await checkUserRegistered(baseParams, 'user_45', 'presence')
335 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
336 await checkUserRegistered({ ...baseParams, ...userOverride }, 'user_45', 'absence')
340 describe('New instance follows', function () {
341 const instanceIndexServer = new MockInstancesIndex()
343 let baseParams: CheckerBaseParams
349 socketNotifications: adminNotifications,
350 token: servers[0].accessToken
353 const port = await instanceIndexServer.initialize()
354 instanceIndexServer.addInstance(servers[1].host)
360 indexUrl: `http://localhost:${port}/api/v1/instances/hosts`,
368 it('Should send a notification only to admin when there is a new instance follower', async function () {
371 await servers[2].follows.follow({ hosts: [ servers[0].url ] })
373 await waitJobs(servers)
375 await checkNewInstanceFollower(baseParams, 'localhost:' + servers[2].port, 'presence')
377 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
378 await checkNewInstanceFollower({ ...baseParams, ...userOverride }, 'localhost:' + servers[2].port, 'absence')
381 it('Should send a notification on auto follow back', async function () {
384 await servers[2].follows.unfollow({ target: servers[0] })
385 await waitJobs(servers)
390 autoFollowBack: { enabled: true }
394 await servers[0].config.updateCustomSubConfig({ newConfig: config })
396 await servers[2].follows.follow({ hosts: [ servers[0].url ] })
398 await waitJobs(servers)
400 const followerHost = servers[0].host
401 const followingHost = servers[2].host
402 await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
404 const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } }
405 await checkAutoInstanceFollowing({ ...baseParams, ...userOverride }, followerHost, followingHost, 'absence')
407 config.followings.instance.autoFollowBack.enabled = false
408 await servers[0].config.updateCustomSubConfig({ newConfig: config })
409 await servers[0].follows.unfollow({ target: servers[2] })
410 await servers[2].follows.unfollow({ target: servers[0] })
413 it('Should send a notification on auto instances index follow', async function () {
415 await servers[0].follows.unfollow({ target: servers[1] })
417 await servers[0].config.updateCustomSubConfig({ newConfig: config })
420 await waitJobs(servers)
422 const followerHost = servers[0].host
423 const followingHost = servers[1].host
424 await checkAutoInstanceFollowing(baseParams, followerHost, followingHost, 'presence')
426 config.followings.instance.autoFollowIndex.enabled = false
427 await servers[0].config.updateCustomSubConfig({ newConfig: config })
428 await servers[0].follows.unfollow({ target: servers[1] })
432 describe('Video-related notifications when video auto-blacklist is enabled', function () {
433 let userBaseParams: CheckerBaseParams
434 let adminBaseParamsServer1: CheckerBaseParams
435 let adminBaseParamsServer2: CheckerBaseParams
436 let videoUUID: string
437 let videoName: string
438 let currentCustomConfig: CustomConfig
442 adminBaseParamsServer1 = {
445 socketNotifications: adminNotifications,
446 token: servers[0].accessToken
449 adminBaseParamsServer2 = {
452 socketNotifications: adminNotificationsServer2,
453 token: servers[1].accessToken
459 socketNotifications: userNotifications,
460 token: userAccessToken
463 currentCustomConfig = await servers[0].config.getCustomConfig()
465 const autoBlacklistTestsCustomConfig = {
466 ...currentCustomConfig,
477 // enable transcoding otherwise own publish notification after transcoding not expected
478 autoBlacklistTestsCustomConfig.transcoding.enabled = true
479 await servers[0].config.updateCustomConfig({ newCustomConfig: autoBlacklistTestsCustomConfig })
481 await servers[0].subscriptions.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
482 await servers[1].subscriptions.add({ targetUri: 'user_1_channel@localhost:' + servers[0].port })
486 it('Should send notification to moderators on new video with auto-blacklist', async function () {
489 videoName = 'video with auto-blacklist ' + buildUUID()
490 const { uuid } = await servers[0].videos.upload({ token: userAccessToken, attributes: { name: videoName } })
493 await waitJobs(servers)
494 await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, videoUUID, videoName, 'presence')
497 it('Should not send video publish notification if auto-blacklisted', async function () {
498 await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'absence')
501 it('Should not send a local user subscription notification if auto-blacklisted', async function () {
502 await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'absence')
505 it('Should not send a remote user subscription notification if auto-blacklisted', async function () {
506 await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'absence')
509 it('Should send video published and unblacklist after video unblacklisted', async function () {
512 await servers[0].blacklist.remove({ videoId: videoUUID })
514 await waitJobs(servers)
516 // FIXME: Can't test as two notifications sent to same user and util only checks last one
517 // One notification might be better anyways
518 // await checkNewBlacklistOnMyVideo(userBaseParams, videoUUID, videoName, 'unblacklist')
519 // await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'presence')
522 it('Should send a local user subscription notification after removed from blacklist', async function () {
523 await checkNewVideoFromSubscription(adminBaseParamsServer1, videoName, videoUUID, 'presence')
526 it('Should send a remote user subscription notification after removed from blacklist', async function () {
527 await checkNewVideoFromSubscription(adminBaseParamsServer2, videoName, videoUUID, 'presence')
530 it('Should send unblacklist but not published/subscription notes after unblacklisted if scheduled update pending', async function () {
533 const updateAt = new Date(new Date().getTime() + 1000000)
535 const name = 'video with auto-blacklist and future schedule ' + buildUUID()
539 privacy: VideoPrivacy.PRIVATE,
541 updateAt: updateAt.toISOString(),
542 privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
546 const { uuid } = await servers[0].videos.upload({ token: userAccessToken, attributes })
548 await servers[0].blacklist.remove({ videoId: uuid })
550 await waitJobs(servers)
551 await checkNewBlacklistOnMyVideo(userBaseParams, uuid, name, 'unblacklist')
553 // FIXME: Can't test absence as two notifications sent to same user and util only checks last one
554 // One notification might be better anyways
555 // await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
557 await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
558 await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
561 it('Should not send publish/subscription notifications after scheduled update if video still auto-blacklisted', async function () {
565 const updateAt = new Date(new Date().getTime() + 2000)
567 const name = 'video with schedule done and still auto-blacklisted ' + buildUUID()
571 privacy: VideoPrivacy.PRIVATE,
573 updateAt: updateAt.toISOString(),
574 privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
578 const { uuid } = await servers[0].videos.upload({ token: userAccessToken, attributes })
581 await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
582 await checkNewVideoFromSubscription(adminBaseParamsServer1, name, uuid, 'absence')
583 await checkNewVideoFromSubscription(adminBaseParamsServer2, name, uuid, 'absence')
586 it('Should not send a notification to moderators on new video without auto-blacklist', async function () {
589 const name = 'video without auto-blacklist ' + buildUUID()
591 // admin with blacklist right will not be auto-blacklisted
592 const { uuid } = await servers[0].videos.upload({ attributes: { name } })
594 await waitJobs(servers)
595 await checkVideoAutoBlacklistForModerators(adminBaseParamsServer1, uuid, name, 'absence')
599 await servers[0].config.updateCustomConfig({ newCustomConfig: currentCustomConfig })
601 await servers[0].subscriptions.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
602 await servers[1].subscriptions.remove({ uri: 'user_1_channel@localhost:' + servers[0].port })
606 after(async function () {
607 MockSmtpServer.Instance.kill()
609 await cleanupTests(servers)