]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame_incremental - 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
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import * as chai from 'chai'
5import { expectStartWith } from '@server/tests/shared'
6import { ActorFollow, FollowState } from '@shared/models'
7import {
8 cleanupTests,
9 createMultipleServers,
10 FollowsCommand,
11 PeerTubeServer,
12 setAccessTokensToServers,
13 waitJobs
14} from '@shared/server-commands'
15
16const expect = chai.expect
17
18async function checkServer1And2HasFollowers (servers: PeerTubeServer[], state = 'accepted') {
19 const fns = [
20 servers[0].follows.getFollowings.bind(servers[0].follows),
21 servers[1].follows.getFollowers.bind(servers[1].follows)
22 ]
23
24 for (const fn of fns) {
25 const body = await fn({ start: 0, count: 5, sort: 'createdAt' })
26 expect(body.total).to.equal(1)
27
28 const follow = body.data[0]
29 expect(follow.state).to.equal(state)
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: {
36 follower: PeerTubeServer
37 followerState: FollowState | 'deleted'
38
39 following: PeerTubeServer
40 followingState: FollowState | 'deleted'
41}) {
42 const { follower, followerState, followingState, following } = options
43
44 const followerUrl = follower.url + '/accounts/peertube'
45 const followingUrl = following.url + '/accounts/peertube'
46 const finder = (d: ActorFollow) => d.follower.url === followerUrl && d.following.url === followingUrl
47
48 {
49 const { data } = await follower.follows.getFollowings()
50 const follow = data.find(finder)
51
52 if (followerState === 'deleted') {
53 expect(follow).to.not.exist
54 } else {
55 expect(follow.state).to.equal(followerState)
56 expect(follow.follower.url).to.equal(followerUrl)
57 expect(follow.following.url).to.equal(followingUrl)
58 }
59 }
60
61 {
62 const { data } = await following.follows.getFollowers()
63 const follow = data.find(finder)
64
65 if (followingState === 'deleted') {
66 expect(follow).to.not.exist
67 } else {
68 expect(follow.state).to.equal(followingState)
69 expect(follow.follower.url).to.equal(followerUrl)
70 expect(follow.following.url).to.equal(followingUrl)
71 }
72 }
73}
74
75async function checkNoFollowers (servers: PeerTubeServer[]) {
76 const fns = [
77 servers[0].follows.getFollowings.bind(servers[0].follows),
78 servers[1].follows.getFollowers.bind(servers[1].follows)
79 ]
80
81 for (const fn of fns) {
82 const body = await fn({ start: 0, count: 5, sort: 'createdAt', state: 'accepted' })
83 expect(body.total).to.equal(0)
84 }
85}
86
87describe('Test follows moderation', function () {
88 let servers: PeerTubeServer[] = []
89 let commands: FollowsCommand[]
90
91 before(async function () {
92 this.timeout(30000)
93
94 servers = await createMultipleServers(3)
95
96 // Get the access tokens
97 await setAccessTokensToServers(servers)
98
99 commands = servers.map(s => s.follows)
100 })
101
102 it('Should have server 1 following server 2', async function () {
103 this.timeout(30000)
104
105 await commands[0].follow({ hosts: [ servers[1].url ] })
106
107 await waitJobs(servers)
108 })
109
110 it('Should have correct follows', async function () {
111 await checkServer1And2HasFollowers(servers)
112 })
113
114 it('Should remove follower on server 2', async function () {
115 this.timeout(10000)
116
117 await commands[1].removeFollower({ follower: servers[0] })
118
119 await waitJobs(servers)
120 })
121
122 it('Should not not have follows anymore', async function () {
123 await checkNoFollowers(servers)
124 })
125
126 it('Should disable followers on server 2', async function () {
127 this.timeout(10000)
128
129 const subConfig = {
130 followers: {
131 instance: {
132 enabled: false,
133 manualApproval: false
134 }
135 }
136 }
137
138 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
139
140 await commands[0].follow({ hosts: [ servers[1].url ] })
141 await waitJobs(servers)
142
143 await checkNoFollowers(servers)
144 })
145
146 it('Should re enable followers on server 2', async function () {
147 this.timeout(10000)
148
149 const subConfig = {
150 followers: {
151 instance: {
152 enabled: true,
153 manualApproval: false
154 }
155 }
156 }
157
158 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
159
160 await commands[0].follow({ hosts: [ servers[1].url ] })
161 await waitJobs(servers)
162
163 await checkServer1And2HasFollowers(servers)
164 })
165
166 it('Should manually approve followers', async function () {
167 this.timeout(20000)
168
169 await commands[0].unfollow({ target: servers[1] })
170 await waitJobs(servers)
171
172 const subConfig = {
173 followers: {
174 instance: {
175 enabled: true,
176 manualApproval: true
177 }
178 }
179 }
180
181 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
182 await servers[2].config.updateCustomSubConfig({ newConfig: subConfig })
183
184 await commands[0].follow({ hosts: [ servers[1].url ] })
185 await waitJobs(servers)
186
187 await checkServer1And2HasFollowers(servers, 'pending')
188 })
189
190 it('Should accept a follower', async function () {
191 this.timeout(10000)
192
193 await commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host })
194 await waitJobs(servers)
195
196 await checkServer1And2HasFollowers(servers)
197 })
198
199 it('Should reject another follower', async function () {
200 this.timeout(20000)
201
202 await commands[0].follow({ hosts: [ servers[2].url ] })
203 await waitJobs(servers)
204
205 {
206 const body = await commands[0].getFollowings()
207 expect(body.total).to.equal(2)
208 }
209
210 {
211 const body = await commands[1].getFollowers()
212 expect(body.total).to.equal(1)
213 }
214
215 {
216 const body = await commands[2].getFollowers()
217 expect(body.total).to.equal(1)
218 }
219
220 await commands[2].rejectFollower({ follower: 'peertube@' + servers[0].host })
221 await waitJobs(servers)
222
223 { // server 1
224 {
225 const { data } = await commands[0].getFollowings({ state: 'accepted' })
226 expect(data).to.have.lengthOf(1)
227 }
228
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 }
247 }
248 })
249
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({
256 follower: servers[0],
257 followerState: 'rejected',
258 following: servers[2],
259 followingState: 'rejected'
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({
275 follower: servers[0],
276 followerState: 'deleted',
277 following: servers[2],
278 followingState: 'rejected'
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({
290 follower: servers[0],
291 followerState: 'pending',
292 following: servers[2],
293 followingState: 'pending'
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({
302 follower: servers[0],
303 followerState: 'rejected',
304 following: servers[1],
305 followingState: 'rejected'
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({
314 follower: servers[0],
315 followerState: 'accepted',
316 following: servers[1],
317 followingState: 'accepted'
318 })
319 })
320
321 it('Should ignore follow requests of muted servers', async function () {
322 await servers[1].blocklist.addToServerBlocklist({ server: servers[0].host })
323
324 await commands[0].unfollow({ target: servers[1] })
325
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 })
344 })
345
346 after(async function () {
347 await cleanupTests(servers)
348 })
349})