]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/server/follows-moderation.ts
We don't need to import mocha
[github/Chocobozzz/PeerTube.git] / server / tests / api / server / follows-moderation.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
0e9c48c2 2
c3d29f69 3import * as chai from 'chai'
927fa4b1
C
4import { expectStartWith } from '@server/tests/shared'
5import { ActorFollow, FollowState } from '@shared/models'
5b9c965d 6import {
7243f84d 7 cleanupTests,
254d3579 8 createMultipleServers,
c3d29f69 9 FollowsCommand,
254d3579 10 PeerTubeServer,
5b9c965d 11 setAccessTokensToServers,
c3d29f69 12 waitJobs
bf54587a 13} from '@shared/server-commands'
0e9c48c2
C
14
15const expect = chai.expect
16
254d3579 17async function checkServer1And2HasFollowers (servers: PeerTubeServer[], state = 'accepted') {
c3d29f69 18 const fns = [
89d241a7
C
19 servers[0].follows.getFollowings.bind(servers[0].follows),
20 servers[1].follows.getFollowers.bind(servers[1].follows)
c3d29f69 21 ]
5b9c965d 22
c3d29f69
C
23 for (const fn of fns) {
24 const body = await fn({ start: 0, count: 5, sort: 'createdAt' })
25 expect(body.total).to.equal(1)
5b9c965d 26
c3d29f69 27 const follow = body.data[0]
14893eb7 28 expect(follow.state).to.equal(state)
927fa4b1
C
29 expect(follow.follower.url).to.equal(servers[0].url + '/accounts/peertube')
30 expect(follow.following.url).to.equal(servers[1].url + '/accounts/peertube')
31 }
32}
33
34async function checkFollows (options: {
073deef8
C
35 follower: PeerTubeServer
36 followerState: FollowState | 'deleted'
37
38 following: PeerTubeServer
39 followingState: FollowState | 'deleted'
927fa4b1 40}) {
073deef8 41 const { follower, followerState, followingState, following } = options
927fa4b1 42
073deef8
C
43 const followerUrl = follower.url + '/accounts/peertube'
44 const followingUrl = following.url + '/accounts/peertube'
927fa4b1
C
45 const finder = (d: ActorFollow) => d.follower.url === followerUrl && d.following.url === followingUrl
46
47 {
073deef8 48 const { data } = await follower.follows.getFollowings()
927fa4b1
C
49 const follow = data.find(finder)
50
073deef8 51 if (followerState === 'deleted') {
927fa4b1
C
52 expect(follow).to.not.exist
53 } else {
073deef8 54 expect(follow.state).to.equal(followerState)
927fa4b1
C
55 expect(follow.follower.url).to.equal(followerUrl)
56 expect(follow.following.url).to.equal(followingUrl)
57 }
58 }
59
60 {
073deef8 61 const { data } = await following.follows.getFollowers()
927fa4b1
C
62 const follow = data.find(finder)
63
073deef8 64 if (followingState === 'deleted') {
927fa4b1
C
65 expect(follow).to.not.exist
66 } else {
073deef8 67 expect(follow.state).to.equal(followingState)
927fa4b1
C
68 expect(follow.follower.url).to.equal(followerUrl)
69 expect(follow.following.url).to.equal(followingUrl)
70 }
5b9c965d
C
71 }
72}
73
254d3579 74async function checkNoFollowers (servers: PeerTubeServer[]) {
c3d29f69 75 const fns = [
89d241a7
C
76 servers[0].follows.getFollowings.bind(servers[0].follows),
77 servers[1].follows.getFollowers.bind(servers[1].follows)
c3d29f69
C
78 ]
79
80 for (const fn of fns) {
927fa4b1 81 const body = await fn({ start: 0, count: 5, sort: 'createdAt', state: 'accepted' })
c3d29f69 82 expect(body.total).to.equal(0)
5b9c965d
C
83 }
84}
85
0e9c48c2 86describe('Test follows moderation', function () {
254d3579 87 let servers: PeerTubeServer[] = []
c3d29f69 88 let commands: FollowsCommand[]
0e9c48c2
C
89
90 before(async function () {
3b2006bb 91 this.timeout(240000)
0e9c48c2 92
254d3579 93 servers = await createMultipleServers(3)
0e9c48c2
C
94
95 // Get the access tokens
96 await setAccessTokensToServers(servers)
c3d29f69 97
89d241a7 98 commands = servers.map(s => s.follows)
0e9c48c2
C
99 })
100
101 it('Should have server 1 following server 2', async function () {
102 this.timeout(30000)
103
4d029ef8 104 await commands[0].follow({ hosts: [ servers[1].url ] })
0e9c48c2
C
105
106 await waitJobs(servers)
107 })
108
109 it('Should have correct follows', async function () {
14893eb7 110 await checkServer1And2HasFollowers(servers)
0e9c48c2
C
111 })
112
113 it('Should remove follower on server 2', async function () {
de94ac86
C
114 this.timeout(10000)
115
c3d29f69 116 await commands[1].removeFollower({ follower: servers[0] })
0e9c48c2
C
117
118 await waitJobs(servers)
119 })
120
121 it('Should not not have follows anymore', async function () {
5b9c965d
C
122 await checkNoFollowers(servers)
123 })
124
125 it('Should disable followers on server 2', async function () {
de94ac86
C
126 this.timeout(10000)
127
5b9c965d
C
128 const subConfig = {
129 followers: {
130 instance: {
14893eb7
C
131 enabled: false,
132 manualApproval: false
5b9c965d
C
133 }
134 }
0e9c48c2
C
135 }
136
89d241a7 137 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
5b9c965d 138
4d029ef8 139 await commands[0].follow({ hosts: [ servers[1].url ] })
5b9c965d
C
140 await waitJobs(servers)
141
142 await checkNoFollowers(servers)
143 })
144
145 it('Should re enable followers on server 2', async function () {
de94ac86
C
146 this.timeout(10000)
147
5b9c965d
C
148 const subConfig = {
149 followers: {
150 instance: {
14893eb7
C
151 enabled: true,
152 manualApproval: false
5b9c965d
C
153 }
154 }
0e9c48c2 155 }
5b9c965d 156
89d241a7 157 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
5b9c965d 158
4d029ef8 159 await commands[0].follow({ hosts: [ servers[1].url ] })
5b9c965d
C
160 await waitJobs(servers)
161
14893eb7
C
162 await checkServer1And2HasFollowers(servers)
163 })
164
165 it('Should manually approve followers', async function () {
166 this.timeout(20000)
167
927fa4b1 168 await commands[0].unfollow({ target: servers[1] })
14893eb7
C
169 await waitJobs(servers)
170
171 const subConfig = {
172 followers: {
173 instance: {
174 enabled: true,
175 manualApproval: true
176 }
177 }
178 }
179
89d241a7
C
180 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
181 await servers[2].config.updateCustomSubConfig({ newConfig: subConfig })
14893eb7 182
4d029ef8 183 await commands[0].follow({ hosts: [ servers[1].url ] })
14893eb7
C
184 await waitJobs(servers)
185
186 await checkServer1And2HasFollowers(servers, 'pending')
187 })
188
189 it('Should accept a follower', async function () {
de94ac86
C
190 this.timeout(10000)
191
927fa4b1 192 await commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host })
14893eb7
C
193 await waitJobs(servers)
194
195 await checkServer1And2HasFollowers(servers)
196 })
197
198 it('Should reject another follower', async function () {
199 this.timeout(20000)
200
4d029ef8 201 await commands[0].follow({ hosts: [ servers[2].url ] })
14893eb7
C
202 await waitJobs(servers)
203
204 {
927fa4b1 205 const body = await commands[0].getFollowings()
c3d29f69 206 expect(body.total).to.equal(2)
14893eb7
C
207 }
208
209 {
927fa4b1 210 const body = await commands[1].getFollowers()
c3d29f69 211 expect(body.total).to.equal(1)
14893eb7
C
212 }
213
214 {
927fa4b1 215 const body = await commands[2].getFollowers()
c3d29f69 216 expect(body.total).to.equal(1)
14893eb7
C
217 }
218
927fa4b1 219 await commands[2].rejectFollower({ follower: 'peertube@' + servers[0].host })
14893eb7
C
220 await waitJobs(servers)
221
927fa4b1
C
222 { // server 1
223 {
224 const { data } = await commands[0].getFollowings({ state: 'accepted' })
225 expect(data).to.have.lengthOf(1)
226 }
14893eb7 227
927fa4b1
C
228 {
229 const { data } = await commands[0].getFollowings({ state: 'rejected' })
230 expect(data).to.have.lengthOf(1)
231 expectStartWith(data[0].following.url, servers[2].url)
232 }
233 }
234
235 { // server 3
236 {
237 const { data } = await commands[2].getFollowers({ state: 'accepted' })
238 expect(data).to.have.lengthOf(0)
239 }
240
241 {
242 const { data } = await commands[2].getFollowers({ state: 'rejected' })
243 expect(data).to.have.lengthOf(1)
244 expectStartWith(data[0].follower.url, servers[0].url)
245 }
14893eb7 246 }
0e9c48c2
C
247 })
248
927fa4b1
C
249 it('Should not change the follow on refollow with and without auto accept', async function () {
250 const run = async () => {
251 await commands[0].follow({ hosts: [ servers[2].url ] })
252 await waitJobs(servers)
253
254 await checkFollows({
073deef8
C
255 follower: servers[0],
256 followerState: 'rejected',
257 following: servers[2],
258 followingState: 'rejected'
927fa4b1
C
259 })
260 }
261
262 await servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: false } } } })
263 await run()
264
265 await servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: true } } } })
266 await run()
267 })
268
269 it('Should not change the rejected status on unfollow', async function () {
270 await commands[0].unfollow({ target: servers[2] })
271 await waitJobs(servers)
272
273 await checkFollows({
073deef8
C
274 follower: servers[0],
275 followerState: 'deleted',
276 following: servers[2],
277 followingState: 'rejected'
927fa4b1
C
278 })
279 })
280
281 it('Should delete the follower and add again the follower', async function () {
282 await commands[2].removeFollower({ follower: servers[0] })
283 await waitJobs(servers)
284
285 await commands[0].follow({ hosts: [ servers[2].url ] })
286 await waitJobs(servers)
287
288 await checkFollows({
073deef8
C
289 follower: servers[0],
290 followerState: 'pending',
291 following: servers[2],
292 followingState: 'pending'
927fa4b1
C
293 })
294 })
295
296 it('Should be able to reject a previously accepted follower', async function () {
297 await commands[1].rejectFollower({ follower: 'peertube@' + servers[0].host })
298 await waitJobs(servers)
299
300 await checkFollows({
073deef8
C
301 follower: servers[0],
302 followerState: 'rejected',
303 following: servers[1],
304 followingState: 'rejected'
927fa4b1
C
305 })
306 })
307
308 it('Should be able to re accept a previously rejected follower', async function () {
309 await commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host })
310 await waitJobs(servers)
311
312 await checkFollows({
073deef8
C
313 follower: servers[0],
314 followerState: 'accepted',
315 following: servers[1],
316 followingState: 'accepted'
927fa4b1
C
317 })
318 })
319
320 it('Should ignore follow requests of muted servers', async function () {
073deef8
C
321 await servers[1].blocklist.addToServerBlocklist({ server: servers[0].host })
322
323 await commands[0].unfollow({ target: servers[1] })
927fa4b1 324
073deef8
C
325 await waitJobs(servers)
326
327 await checkFollows({
328 follower: servers[0],
329 followerState: 'deleted',
330 following: servers[1],
331 followingState: 'deleted'
332 })
333
334 await commands[0].follow({ hosts: [ servers[1].host ] })
335 await waitJobs(servers)
336
337 await checkFollows({
338 follower: servers[0],
339 followerState: 'rejected',
340 following: servers[1],
341 followingState: 'deleted'
342 })
927fa4b1
C
343 })
344
7c3b7976
C
345 after(async function () {
346 await cleanupTests(servers)
0e9c48c2
C
347 })
348})