1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { expectStartWith } from '@server/tests/shared'
6 import { ActorFollow, FollowState } from '@shared/models'
12 setAccessTokensToServers,
14 } from '@shared/server-commands'
16 const expect = chai.expect
18 async function checkServer1And2HasFollowers (servers: PeerTubeServer[], state = 'accepted') {
20 servers[0].follows.getFollowings.bind(servers[0].follows),
21 servers[1].follows.getFollowers.bind(servers[1].follows)
24 for (const fn of fns) {
25 const body = await fn({ start: 0, count: 5, sort: 'createdAt' })
26 expect(body.total).to.equal(1)
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')
35 async function checkFollows (options: {
37 server: PeerTubeServer
38 state?: FollowState // if not provided, it means it does not exist
41 server: PeerTubeServer
42 state?: FollowState // if not provided, it means it does not exist
45 const { follower, following } = options
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
52 const { data } = await follower.server.follows.getFollowings()
53 const follow = data.find(finder)
55 if (!follower.state) {
56 expect(follow).to.not.exist
58 expect(follow.state).to.equal(follower.state)
59 expect(follow.follower.url).to.equal(followerUrl)
60 expect(follow.following.url).to.equal(followingUrl)
65 const { data } = await following.server.follows.getFollowers()
66 const follow = data.find(finder)
68 if (!following.state) {
69 expect(follow).to.not.exist
71 expect(follow.state).to.equal(following.state)
72 expect(follow.follower.url).to.equal(followerUrl)
73 expect(follow.following.url).to.equal(followingUrl)
78 async function checkNoFollowers (servers: PeerTubeServer[]) {
80 servers[0].follows.getFollowings.bind(servers[0].follows),
81 servers[1].follows.getFollowers.bind(servers[1].follows)
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)
90 describe('Test follows moderation', function () {
91 let servers: PeerTubeServer[] = []
92 let commands: FollowsCommand[]
94 before(async function () {
97 servers = await createMultipleServers(3)
99 // Get the access tokens
100 await setAccessTokensToServers(servers)
102 commands = servers.map(s => s.follows)
105 it('Should have server 1 following server 2', async function () {
108 await commands[0].follow({ hosts: [ servers[1].url ] })
110 await waitJobs(servers)
113 it('Should have correct follows', async function () {
114 await checkServer1And2HasFollowers(servers)
117 it('Should remove follower on server 2', async function () {
120 await commands[1].removeFollower({ follower: servers[0] })
122 await waitJobs(servers)
125 it('Should not not have follows anymore', async function () {
126 await checkNoFollowers(servers)
129 it('Should disable followers on server 2', async function () {
136 manualApproval: false
141 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
143 await commands[0].follow({ hosts: [ servers[1].url ] })
144 await waitJobs(servers)
146 await checkNoFollowers(servers)
149 it('Should re enable followers on server 2', async function () {
156 manualApproval: false
161 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
163 await commands[0].follow({ hosts: [ servers[1].url ] })
164 await waitJobs(servers)
166 await checkServer1And2HasFollowers(servers)
169 it('Should manually approve followers', async function () {
172 await commands[0].unfollow({ target: servers[1] })
173 await waitJobs(servers)
184 await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
185 await servers[2].config.updateCustomSubConfig({ newConfig: subConfig })
187 await commands[0].follow({ hosts: [ servers[1].url ] })
188 await waitJobs(servers)
190 await checkServer1And2HasFollowers(servers, 'pending')
193 it('Should accept a follower', async function () {
196 await commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host })
197 await waitJobs(servers)
199 await checkServer1And2HasFollowers(servers)
202 it('Should reject another follower', async function () {
205 await commands[0].follow({ hosts: [ servers[2].url ] })
206 await waitJobs(servers)
209 const body = await commands[0].getFollowings()
210 expect(body.total).to.equal(2)
214 const body = await commands[1].getFollowers()
215 expect(body.total).to.equal(1)
219 const body = await commands[2].getFollowers()
220 expect(body.total).to.equal(1)
223 await commands[2].rejectFollower({ follower: 'peertube@' + servers[0].host })
224 await waitJobs(servers)
228 const { data } = await commands[0].getFollowings({ state: 'accepted' })
229 expect(data).to.have.lengthOf(1)
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)
241 const { data } = await commands[2].getFollowers({ state: 'accepted' })
242 expect(data).to.have.lengthOf(0)
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)
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)
270 await servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: false } } } })
273 await servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: true } } } })
277 it('Should not change the rejected status on unfollow', async function () {
278 await commands[0].unfollow({ target: servers[2] })
279 await waitJobs(servers)
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)
296 await commands[0].follow({ hosts: [ servers[2].url ] })
297 await waitJobs(servers)
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)
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)
343 it('Should ignore follow requests of muted servers', async function () {
347 after(async function () {
348 await cleanupTests(servers)