1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { AbusePredefinedReasonsString, AbuseState, AdminAbuse } from '@shared/models'
10 flushAndRunMultipleServers,
16 setAccessTokensToServers,
20 } from '../../../../shared/extra-utils/index'
21 import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
22 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
24 addAccountToServerBlocklist,
25 addServerToServerBlocklist,
26 removeAccountFromServerBlocklist,
27 removeServerFromServerBlocklist
28 } from '../../../../shared/extra-utils/users/blocklist'
30 const expect = chai.expect
32 // FIXME: deprecated in 2.3. Remove this controller
34 describe('Test video abuses', function () {
35 let servers: ServerInfo[] = []
36 let abuseServer2: AdminAbuse
38 before(async function () {
42 servers = await flushAndRunMultipleServers(2)
44 // Get the access tokens
45 await setAccessTokensToServers(servers)
47 // Server 1 and server 2 follow each other
48 await doubleFollow(servers[0], servers[1])
50 // Upload some videos on each servers
51 const video1Attributes = {
52 name: 'my super name for server 1',
53 description: 'my super description for server 1'
55 await uploadVideo(servers[0].url, servers[0].accessToken, video1Attributes)
57 const video2Attributes = {
58 name: 'my super name for server 2',
59 description: 'my super description for server 2'
61 await uploadVideo(servers[1].url, servers[1].accessToken, video2Attributes)
63 // Wait videos propagation, server 2 has transcoding enabled
64 await waitJobs(servers)
66 const res = await getVideosList(servers[0].url)
67 const videos = res.body.data
69 expect(videos.length).to.equal(2)
71 servers[0].video = videos.find(video => video.name === 'my super name for server 1')
72 servers[1].video = videos.find(video => video.name === 'my super name for server 2')
75 it('Should not have video abuses', async function () {
76 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
78 expect(res.body.total).to.equal(0)
79 expect(res.body.data).to.be.an('array')
80 expect(res.body.data.length).to.equal(0)
83 it('Should report abuse on a local video', async function () {
86 const reason = 'my super bad reason'
87 await reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[0].video.id, reason)
89 // We wait requests propagation, even if the server 1 is not supposed to make a request to server 2
90 await waitJobs(servers)
93 it('Should have 1 video abuses on server 1 and 0 on server 2', async function () {
94 const res1 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
96 expect(res1.body.total).to.equal(1)
97 expect(res1.body.data).to.be.an('array')
98 expect(res1.body.data.length).to.equal(1)
100 const abuse: AdminAbuse = res1.body.data[0]
101 expect(abuse.reason).to.equal('my super bad reason')
102 expect(abuse.reporterAccount.name).to.equal('root')
103 expect(abuse.reporterAccount.host).to.equal('localhost:' + servers[0].port)
104 expect(abuse.video.id).to.equal(servers[0].video.id)
105 expect(abuse.video.channel).to.exist
106 expect(abuse.video.countReports).to.equal(1)
107 expect(abuse.video.nthReport).to.equal(1)
108 expect(abuse.countReportsForReporter).to.equal(1)
109 expect(abuse.countReportsForReportee).to.equal(1)
111 const res2 = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
112 expect(res2.body.total).to.equal(0)
113 expect(res2.body.data).to.be.an('array')
114 expect(res2.body.data.length).to.equal(0)
117 it('Should report abuse on a remote video', async function () {
120 const reason = 'my super bad reason 2'
121 await reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[1].video.id, reason)
123 // We wait requests propagation
124 await waitJobs(servers)
127 it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
128 const res1 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
129 expect(res1.body.total).to.equal(2)
130 expect(res1.body.data).to.be.an('array')
131 expect(res1.body.data.length).to.equal(2)
133 const abuse1: AdminAbuse = res1.body.data[0]
134 expect(abuse1.reason).to.equal('my super bad reason')
135 expect(abuse1.reporterAccount.name).to.equal('root')
136 expect(abuse1.reporterAccount.host).to.equal('localhost:' + servers[0].port)
137 expect(abuse1.video.id).to.equal(servers[0].video.id)
138 expect(abuse1.state.id).to.equal(AbuseState.PENDING)
139 expect(abuse1.state.label).to.equal('Pending')
140 expect(abuse1.moderationComment).to.be.null
141 expect(abuse1.video.countReports).to.equal(1)
142 expect(abuse1.video.nthReport).to.equal(1)
144 const abuse2: AdminAbuse = res1.body.data[1]
145 expect(abuse2.reason).to.equal('my super bad reason 2')
146 expect(abuse2.reporterAccount.name).to.equal('root')
147 expect(abuse2.reporterAccount.host).to.equal('localhost:' + servers[0].port)
148 expect(abuse2.video.id).to.equal(servers[1].video.id)
149 expect(abuse2.state.id).to.equal(AbuseState.PENDING)
150 expect(abuse2.state.label).to.equal('Pending')
151 expect(abuse2.moderationComment).to.be.null
153 const res2 = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
154 expect(res2.body.total).to.equal(1)
155 expect(res2.body.data).to.be.an('array')
156 expect(res2.body.data.length).to.equal(1)
158 abuseServer2 = res2.body.data[0]
159 expect(abuseServer2.reason).to.equal('my super bad reason 2')
160 expect(abuseServer2.reporterAccount.name).to.equal('root')
161 expect(abuseServer2.reporterAccount.host).to.equal('localhost:' + servers[0].port)
162 expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
163 expect(abuseServer2.state.label).to.equal('Pending')
164 expect(abuseServer2.moderationComment).to.be.null
167 it('Should update the state of a video abuse', async function () {
168 const body = { state: AbuseState.REJECTED }
169 await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body)
171 const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
172 expect(res.body.data[0].state.id).to.equal(AbuseState.REJECTED)
175 it('Should add a moderation comment', async function () {
176 const body = { state: AbuseState.ACCEPTED, moderationComment: 'It is valid' }
177 await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body)
179 const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
180 expect(res.body.data[0].state.id).to.equal(AbuseState.ACCEPTED)
181 expect(res.body.data[0].moderationComment).to.equal('It is valid')
184 it('Should hide video abuses from blocked accounts', async function () {
188 await reportVideoAbuse(servers[1].url, servers[1].accessToken, servers[0].video.uuid, 'will mute this')
189 await waitJobs(servers)
191 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
192 expect(res.body.total).to.equal(3)
195 const accountToBlock = 'root@localhost:' + servers[1].port
198 await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
200 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
201 expect(res.body.total).to.equal(2)
203 const abuse = res.body.data.find(a => a.reason === 'will mute this')
204 expect(abuse).to.be.undefined
208 await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
210 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
211 expect(res.body.total).to.equal(3)
215 it('Should hide video abuses from blocked servers', async function () {
216 const serverToBlock = servers[1].host
219 await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, servers[1].host)
221 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
222 expect(res.body.total).to.equal(2)
224 const abuse = res.body.data.find(a => a.reason === 'will mute this')
225 expect(abuse).to.be.undefined
229 await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock)
231 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
232 expect(res.body.total).to.equal(3)
236 it('Should keep the video abuse when deleting the video', async function () {
239 await removeVideo(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid)
241 await waitJobs(servers)
243 const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
244 expect(res.body.total).to.equal(2, "wrong number of videos returned")
245 expect(res.body.data.length).to.equal(2, "wrong number of videos returned")
246 expect(res.body.data[0].id).to.equal(abuseServer2.id, "wrong origin server id for first video")
248 const abuse: AdminAbuse = res.body.data[0]
249 expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id")
250 expect(abuse.video.channel).to.exist
251 expect(abuse.video.deleted).to.be.true
254 it('Should include counts of reports from reporter and reportee', async function () {
257 // register a second user to have two reporters/reportees
258 const user = { username: 'user2', password: 'password' }
259 await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, ...user })
260 const userAccessToken = await userLogin(servers[0], user)
262 // upload a third video via this user
263 const video3Attributes = {
264 name: 'my second super name for server 1',
265 description: 'my second super description for server 1'
267 await uploadVideo(servers[0].url, userAccessToken, video3Attributes)
269 const res1 = await getVideosList(servers[0].url)
270 const videos = res1.body.data
271 const video3 = videos.find(video => video.name === 'my second super name for server 1')
273 // resume with the test
274 const reason3 = 'my super bad reason 3'
275 await reportVideoAbuse(servers[0].url, servers[0].accessToken, video3.id, reason3)
276 const reason4 = 'my super bad reason 4'
277 await reportVideoAbuse(servers[0].url, userAccessToken, servers[0].video.id, reason4)
279 const res2 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
282 for (const abuse of res2.body.data as AdminAbuse[]) {
283 if (abuse.video.id === video3.id) {
284 expect(abuse.video.countReports).to.equal(1, "wrong reports count for video 3")
285 expect(abuse.video.nthReport).to.equal(1, "wrong report position in report list for video 3")
286 expect(abuse.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse")
287 expect(abuse.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse")
289 if (abuse.video.id === servers[0].video.id) {
290 expect(abuse.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 abuse")
296 it('Should list predefined reasons as well as timestamps for the reported video', async function () {
299 const reason5 = 'my super bad reason 5'
300 const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ]
301 const createdAbuse = (await reportVideoAbuse(
303 servers[0].accessToken,
311 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
314 const abuse = (res.body.data as AdminAbuse[]).find(a => a.id === createdAbuse.id)
315 expect(abuse.reason).to.equals(reason5)
316 expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, "predefined reasons do not match the one reported")
317 expect(abuse.video.startAt).to.equal(1, "starting timestamp doesn't match the one reported")
318 expect(abuse.video.endAt).to.equal(5, "ending timestamp doesn't match the one reported")
322 it('Should delete the video abuse', async function () {
325 await deleteVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id)
327 await waitJobs(servers)
330 const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
331 expect(res.body.total).to.equal(1)
332 expect(res.body.data.length).to.equal(1)
333 expect(res.body.data[0].id).to.not.equal(abuseServer2.id)
337 const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
338 expect(res.body.total).to.equal(6)
342 it('Should list and filter video abuses', async function () {
343 async function list (query: Omit<Parameters<typeof getVideoAbusesList>[0], 'url' | 'token'>) {
346 token: servers[0].accessToken
349 Object.assign(options, query)
351 const res = await getVideoAbusesList(options)
353 return res.body.data as AdminAbuse[]
356 expect(await list({ id: 56 })).to.have.lengthOf(0)
357 expect(await list({ id: 1 })).to.have.lengthOf(1)
359 expect(await list({ search: 'my super name for server 1' })).to.have.lengthOf(4)
360 expect(await list({ search: 'aaaaaaaaaaaaaaaaaaaaaaaaaa' })).to.have.lengthOf(0)
362 expect(await list({ searchVideo: 'my second super name for server 1' })).to.have.lengthOf(1)
364 expect(await list({ searchVideoChannel: 'root' })).to.have.lengthOf(4)
365 expect(await list({ searchVideoChannel: 'aaaa' })).to.have.lengthOf(0)
367 expect(await list({ searchReporter: 'user2' })).to.have.lengthOf(1)
368 expect(await list({ searchReporter: 'root' })).to.have.lengthOf(5)
370 expect(await list({ searchReportee: 'root' })).to.have.lengthOf(5)
371 expect(await list({ searchReportee: 'aaaa' })).to.have.lengthOf(0)
373 expect(await list({ videoIs: 'deleted' })).to.have.lengthOf(1)
374 expect(await list({ videoIs: 'blacklisted' })).to.have.lengthOf(0)
376 expect(await list({ state: AbuseState.ACCEPTED })).to.have.lengthOf(0)
377 expect(await list({ state: AbuseState.PENDING })).to.have.lengthOf(6)
379 expect(await list({ predefinedReason: 'violentOrRepulsive' })).to.have.lengthOf(1)
380 expect(await list({ predefinedReason: 'serverRules' })).to.have.lengthOf(0)
383 after(async function () {
384 await cleanupTests(servers)