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