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