diff options
author | Chocobozzz <me@florianbigard.com> | 2019-04-08 14:04:57 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2019-04-08 14:06:23 +0200 |
commit | 5b9c965d5aa747f29b081289f930ee215fdc23c8 (patch) | |
tree | 1c726117525230d74235e7fa986eb72e7376fb6c | |
parent | 594d0c6a7c64b045c11508bb4e4b19b75b3fc557 (diff) | |
download | PeerTube-5b9c965d5aa747f29b081289f930ee215fdc23c8.tar.gz PeerTube-5b9c965d5aa747f29b081289f930ee215fdc23c8.tar.zst PeerTube-5b9c965d5aa747f29b081289f930ee215fdc23c8.zip |
Add ability to forbid followers
-rw-r--r-- | config/default.yaml | 5 | ||||
-rw-r--r-- | config/production.yaml.example | 9 | ||||
-rw-r--r-- | server/controllers/api/config.ts | 5 | ||||
-rw-r--r-- | server/controllers/api/server/follows.ts | 2 | ||||
-rw-r--r-- | server/initializers/checker-before-init.ts | 3 | ||||
-rw-r--r-- | server/initializers/constants.ts | 5 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-follow.ts | 10 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-accept.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-follow.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-reject.ts | 18 | ||||
-rw-r--r-- | server/lib/activitypub/send/send-undo.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/url.ts | 12 | ||||
-rw-r--r-- | server/middlewares/validators/follows.ts | 15 | ||||
-rw-r--r-- | server/tests/api/check-params/config.ts | 5 | ||||
-rw-r--r-- | server/tests/api/check-params/follows.ts | 40 | ||||
-rw-r--r-- | server/tests/api/server/config.ts | 9 | ||||
-rw-r--r-- | server/tests/api/server/follows-moderation.ts | 96 | ||||
-rw-r--r-- | shared/models/server/custom-config.model.ts | 6 | ||||
-rw-r--r-- | shared/utils/server/config.ts | 5 |
19 files changed, 196 insertions, 55 deletions
diff --git a/config/default.yaml b/config/default.yaml index 615910478..51f3ad833 100644 --- a/config/default.yaml +++ b/config/default.yaml | |||
@@ -200,3 +200,8 @@ services: | |||
200 | # If false, we use an image link card that will redirect on your PeerTube instance | 200 | # If false, we use an image link card that will redirect on your PeerTube instance |
201 | # Change it to "true", and then test on https://cards-dev.twitter.com/validator to see if you are whitelisted | 201 | # Change it to "true", and then test on https://cards-dev.twitter.com/validator to see if you are whitelisted |
202 | whitelisted: false | 202 | whitelisted: false |
203 | |||
204 | followers: | ||
205 | instance: | ||
206 | # Allow or not other instances to follow yours | ||
207 | enabled: true | ||
diff --git a/config/production.yaml.example b/config/production.yaml.example index 5299484a5..a2811abd6 100644 --- a/config/production.yaml.example +++ b/config/production.yaml.example | |||
@@ -180,8 +180,8 @@ auto_blacklist: | |||
180 | # New videos automatically blacklisted so moderators can review before publishing | 180 | # New videos automatically blacklisted so moderators can review before publishing |
181 | videos: | 181 | videos: |
182 | of_users: | 182 | of_users: |
183 | enabled: false | 183 | enabled: false |
184 | 184 | ||
185 | # Instance settings | 185 | # Instance settings |
186 | instance: | 186 | instance: |
187 | name: 'PeerTube' | 187 | name: 'PeerTube' |
@@ -217,3 +217,8 @@ services: | |||
217 | # If false, we use an image link card that will redirect on your PeerTube instance | 217 | # If false, we use an image link card that will redirect on your PeerTube instance |
218 | # Test on https://cards-dev.twitter.com/validator to see if you are whitelisted | 218 | # Test on https://cards-dev.twitter.com/validator to see if you are whitelisted |
219 | whitelisted: false | 219 | whitelisted: false |
220 | |||
221 | followers: | ||
222 | instance: | ||
223 | # Allow or not other instances to follow yours | ||
224 | enabled: true | ||
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index bd0ba4f9d..f9bb0b947 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -279,6 +279,11 @@ function customConfig (): CustomConfig { | |||
279 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED | 279 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED |
280 | } | 280 | } |
281 | } | 281 | } |
282 | }, | ||
283 | followers: { | ||
284 | instance: { | ||
285 | enabled: CONFIG.FOLLOWERS.INSTANCE.ENABLED | ||
286 | } | ||
282 | } | 287 | } |
283 | } | 288 | } |
284 | } | 289 | } |
diff --git a/server/controllers/api/server/follows.ts b/server/controllers/api/server/follows.ts index c00069f93..87cf091cb 100644 --- a/server/controllers/api/server/follows.ts +++ b/server/controllers/api/server/follows.ts | |||
@@ -139,7 +139,7 @@ async function removeFollowing (req: express.Request, res: express.Response) { | |||
139 | async function removeFollower (req: express.Request, res: express.Response) { | 139 | async function removeFollower (req: express.Request, res: express.Response) { |
140 | const follow = res.locals.follow | 140 | const follow = res.locals.follow |
141 | 141 | ||
142 | await sendReject(follow) | 142 | await sendReject(follow.ActorFollower, follow.ActorFollowing) |
143 | 143 | ||
144 | await follow.destroy() | 144 | await follow.destroy() |
145 | 145 | ||
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts index e26f38564..a9896907d 100644 --- a/server/initializers/checker-before-init.ts +++ b/server/initializers/checker-before-init.ts | |||
@@ -24,7 +24,8 @@ function checkMissedConfig () { | |||
24 | 'trending.videos.interval_days', | 24 | 'trending.videos.interval_days', |
25 | 'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route', | 25 | 'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route', |
26 | 'instance.is_nsfw', 'instance.default_nsfw_policy', 'instance.robots', 'instance.securitytxt', | 26 | 'instance.is_nsfw', 'instance.default_nsfw_policy', 'instance.robots', 'instance.securitytxt', |
27 | 'services.twitter.username', 'services.twitter.whitelisted' | 27 | 'services.twitter.username', 'services.twitter.whitelisted', |
28 | 'followers.instance.enabled' | ||
28 | ] | 29 | ] |
29 | const requiredAlternatives = [ | 30 | const requiredAlternatives = [ |
30 | [ // set | 31 | [ // set |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index ac19231d0..43c5ec54c 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -324,6 +324,11 @@ const CONFIG = { | |||
324 | get USERNAME () { return config.get<string>('services.twitter.username') }, | 324 | get USERNAME () { return config.get<string>('services.twitter.username') }, |
325 | get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') } | 325 | get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') } |
326 | } | 326 | } |
327 | }, | ||
328 | FOLLOWERS: { | ||
329 | INSTANCE: { | ||
330 | get ENABLED () { return config.get<boolean>('followers.instance.enabled') } | ||
331 | } | ||
327 | } | 332 | } |
328 | } | 333 | } |
329 | 334 | ||
diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts index 0cd537187..cecf09b47 100644 --- a/server/lib/activitypub/process/process-follow.ts +++ b/server/lib/activitypub/process/process-follow.ts | |||
@@ -1,12 +1,13 @@ | |||
1 | import { ActivityFollow } from '../../../../shared/models/activitypub' | 1 | import { ActivityFollow } from '../../../../shared/models/activitypub' |
2 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 2 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
3 | import { logger } from '../../../helpers/logger' | 3 | import { logger } from '../../../helpers/logger' |
4 | import { sequelizeTypescript } from '../../../initializers' | 4 | import { sequelizeTypescript, CONFIG } from '../../../initializers' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | 5 | import { ActorModel } from '../../../models/activitypub/actor' |
6 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 6 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' |
7 | import { sendAccept } from '../send' | 7 | import { sendAccept, sendReject } from '../send' |
8 | import { Notifier } from '../../notifier' | 8 | import { Notifier } from '../../notifier' |
9 | import { getAPId } from '../../../helpers/activitypub' | 9 | import { getAPId } from '../../../helpers/activitypub' |
10 | import { getServerActor } from '../../../helpers/utils' | ||
10 | 11 | ||
11 | async function processFollowActivity (activity: ActivityFollow, byActor: ActorModel) { | 12 | async function processFollowActivity (activity: ActivityFollow, byActor: ActorModel) { |
12 | const activityObject = getAPId(activity.object) | 13 | const activityObject = getAPId(activity.object) |
@@ -29,6 +30,11 @@ async function processFollow (actor: ActorModel, targetActorURL: string) { | |||
29 | if (!targetActor) throw new Error('Unknown actor') | 30 | if (!targetActor) throw new Error('Unknown actor') |
30 | if (targetActor.isOwned() === false) throw new Error('This is not a local actor.') | 31 | if (targetActor.isOwned() === false) throw new Error('This is not a local actor.') |
31 | 32 | ||
33 | const serverActor = await getServerActor() | ||
34 | if (targetActor.id === serverActor.id && CONFIG.FOLLOWERS.INSTANCE.ENABLED === false) { | ||
35 | return sendReject(actor, targetActor) | ||
36 | } | ||
37 | |||
32 | const [ actorFollow, created ] = await ActorFollowModel.findOrCreate({ | 38 | const [ actorFollow, created ] = await ActorFollowModel.findOrCreate({ |
33 | where: { | 39 | where: { |
34 | actorId: actor.id, | 40 | actorId: actor.id, |
diff --git a/server/lib/activitypub/send/send-accept.ts b/server/lib/activitypub/send/send-accept.ts index b6abde13d..388a9ed23 100644 --- a/server/lib/activitypub/send/send-accept.ts +++ b/server/lib/activitypub/send/send-accept.ts | |||
@@ -17,7 +17,7 @@ async function sendAccept (actorFollow: ActorFollowModel) { | |||
17 | 17 | ||
18 | logger.info('Creating job to accept follower %s.', follower.url) | 18 | logger.info('Creating job to accept follower %s.', follower.url) |
19 | 19 | ||
20 | const followUrl = getActorFollowActivityPubUrl(actorFollow) | 20 | const followUrl = getActorFollowActivityPubUrl(follower, me) |
21 | const followData = buildFollowActivity(followUrl, follower, me) | 21 | const followData = buildFollowActivity(followUrl, follower, me) |
22 | 22 | ||
23 | const url = getActorFollowAcceptActivityPubUrl(actorFollow) | 23 | const url = getActorFollowAcceptActivityPubUrl(actorFollow) |
diff --git a/server/lib/activitypub/send/send-follow.ts b/server/lib/activitypub/send/send-follow.ts index 170b46b48..2c3d02014 100644 --- a/server/lib/activitypub/send/send-follow.ts +++ b/server/lib/activitypub/send/send-follow.ts | |||
@@ -14,7 +14,7 @@ function sendFollow (actorFollow: ActorFollowModel) { | |||
14 | 14 | ||
15 | logger.info('Creating job to send follow request to %s.', following.url) | 15 | logger.info('Creating job to send follow request to %s.', following.url) |
16 | 16 | ||
17 | const url = getActorFollowActivityPubUrl(actorFollow) | 17 | const url = getActorFollowActivityPubUrl(me, following) |
18 | const data = buildFollowActivity(url, me, following) | 18 | const data = buildFollowActivity(url, me, following) |
19 | 19 | ||
20 | return unicastTo(data, me, following.inboxUrl) | 20 | return unicastTo(data, me, following.inboxUrl) |
diff --git a/server/lib/activitypub/send/send-reject.ts b/server/lib/activitypub/send/send-reject.ts index db8c2d86d..bac7ff556 100644 --- a/server/lib/activitypub/send/send-reject.ts +++ b/server/lib/activitypub/send/send-reject.ts | |||
@@ -1,15 +1,11 @@ | |||
1 | import { ActivityFollow, ActivityReject } from '../../../../shared/models/activitypub' | 1 | import { ActivityFollow, ActivityReject } from '../../../../shared/models/activitypub' |
2 | import { ActorModel } from '../../../models/activitypub/actor' | 2 | import { ActorModel } from '../../../models/activitypub/actor' |
3 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 3 | import { getActorFollowActivityPubUrl, getActorFollowRejectActivityPubUrl } from '../url' |
4 | import { getActorFollowAcceptActivityPubUrl, getActorFollowActivityPubUrl } from '../url' | ||
5 | import { unicastTo } from './utils' | 4 | import { unicastTo } from './utils' |
6 | import { buildFollowActivity } from './send-follow' | 5 | import { buildFollowActivity } from './send-follow' |
7 | import { logger } from '../../../helpers/logger' | 6 | import { logger } from '../../../helpers/logger' |
8 | 7 | ||
9 | async function sendReject (actorFollow: ActorFollowModel) { | 8 | async function sendReject (follower: ActorModel, following: ActorModel) { |
10 | const follower = actorFollow.ActorFollower | ||
11 | const me = actorFollow.ActorFollowing | ||
12 | |||
13 | if (!follower.serverId) { // This should never happen | 9 | if (!follower.serverId) { // This should never happen |
14 | logger.warn('Do not sending reject to local follower.') | 10 | logger.warn('Do not sending reject to local follower.') |
15 | return | 11 | return |
@@ -17,13 +13,13 @@ async function sendReject (actorFollow: ActorFollowModel) { | |||
17 | 13 | ||
18 | logger.info('Creating job to reject follower %s.', follower.url) | 14 | logger.info('Creating job to reject follower %s.', follower.url) |
19 | 15 | ||
20 | const followUrl = getActorFollowActivityPubUrl(actorFollow) | 16 | const followUrl = getActorFollowActivityPubUrl(follower, following) |
21 | const followData = buildFollowActivity(followUrl, follower, me) | 17 | const followData = buildFollowActivity(followUrl, follower, following) |
22 | 18 | ||
23 | const url = getActorFollowAcceptActivityPubUrl(actorFollow) | 19 | const url = getActorFollowRejectActivityPubUrl(follower, following) |
24 | const data = buildRejectActivity(url, me, followData) | 20 | const data = buildRejectActivity(url, following, followData) |
25 | 21 | ||
26 | return unicastTo(data, me, follower.inboxUrl) | 22 | return unicastTo(data, following, follower.inboxUrl) |
27 | } | 23 | } |
28 | 24 | ||
29 | // --------------------------------------------------------------------------- | 25 | // --------------------------------------------------------------------------- |
diff --git a/server/lib/activitypub/send/send-undo.ts b/server/lib/activitypub/send/send-undo.ts index ecbf605d6..8727a121e 100644 --- a/server/lib/activitypub/send/send-undo.ts +++ b/server/lib/activitypub/send/send-undo.ts | |||
@@ -31,7 +31,7 @@ async function sendUndoFollow (actorFollow: ActorFollowModel, t: Transaction) { | |||
31 | 31 | ||
32 | logger.info('Creating job to send an unfollow request to %s.', following.url) | 32 | logger.info('Creating job to send an unfollow request to %s.', following.url) |
33 | 33 | ||
34 | const followUrl = getActorFollowActivityPubUrl(actorFollow) | 34 | const followUrl = getActorFollowActivityPubUrl(me, following) |
35 | const undoUrl = getUndoActivityPubUrl(followUrl) | 35 | const undoUrl = getUndoActivityPubUrl(followUrl) |
36 | 36 | ||
37 | const followActivity = buildFollowActivity(followUrl, me, following) | 37 | const followActivity = buildFollowActivity(followUrl, me, following) |
diff --git a/server/lib/activitypub/url.ts b/server/lib/activitypub/url.ts index 7c2ee5bc6..401b83fc2 100644 --- a/server/lib/activitypub/url.ts +++ b/server/lib/activitypub/url.ts | |||
@@ -74,11 +74,8 @@ function getVideoDislikesActivityPubUrl (video: VideoModel) { | |||
74 | return video.url + '/dislikes' | 74 | return video.url + '/dislikes' |
75 | } | 75 | } |
76 | 76 | ||
77 | function getActorFollowActivityPubUrl (actorFollow: ActorFollowModel) { | 77 | function getActorFollowActivityPubUrl (follower: ActorModel, following: ActorModel) { |
78 | const me = actorFollow.ActorFollower | 78 | return follower.url + '/follows/' + following.id |
79 | const following = actorFollow.ActorFollowing | ||
80 | |||
81 | return me.url + '/follows/' + following.id | ||
82 | } | 79 | } |
83 | 80 | ||
84 | function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModel) { | 81 | function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModel) { |
@@ -88,6 +85,10 @@ function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModel) { | |||
88 | return follower.url + '/accepts/follows/' + me.id | 85 | return follower.url + '/accepts/follows/' + me.id |
89 | } | 86 | } |
90 | 87 | ||
88 | function getActorFollowRejectActivityPubUrl (follower: ActorModel, following: ActorModel) { | ||
89 | return follower.url + '/rejects/follows/' + following.id | ||
90 | } | ||
91 | |||
91 | function getVideoAnnounceActivityPubUrl (byActor: ActorModel, video: VideoModel) { | 92 | function getVideoAnnounceActivityPubUrl (byActor: ActorModel, video: VideoModel) { |
92 | return video.url + '/announces/' + byActor.id | 93 | return video.url + '/announces/' + byActor.id |
93 | } | 94 | } |
@@ -120,6 +121,7 @@ export { | |||
120 | getVideoViewActivityPubUrl, | 121 | getVideoViewActivityPubUrl, |
121 | getVideoLikeActivityPubUrl, | 122 | getVideoLikeActivityPubUrl, |
122 | getVideoDislikeActivityPubUrl, | 123 | getVideoDislikeActivityPubUrl, |
124 | getActorFollowRejectActivityPubUrl, | ||
123 | getVideoCommentActivityPubUrl, | 125 | getVideoCommentActivityPubUrl, |
124 | getDeleteActivityPubUrl, | 126 | getDeleteActivityPubUrl, |
125 | getVideoSharesActivityPubUrl, | 127 | getVideoSharesActivityPubUrl, |
diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts index ef4151efe..38df39fda 100644 --- a/server/middlewares/validators/follows.ts +++ b/server/middlewares/validators/follows.ts | |||
@@ -9,7 +9,6 @@ import { ActorFollowModel } from '../../models/activitypub/actor-follow' | |||
9 | import { areValidationErrors } from './utils' | 9 | import { areValidationErrors } from './utils' |
10 | import { ActorModel } from '../../models/activitypub/actor' | 10 | import { ActorModel } from '../../models/activitypub/actor' |
11 | import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger' | 11 | import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger' |
12 | import { getOrCreateActorAndServerAndModel } from '../../lib/activitypub' | ||
13 | import { isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor' | 12 | import { isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor' |
14 | 13 | ||
15 | const followValidator = [ | 14 | const followValidator = [ |
@@ -66,12 +65,16 @@ const removeFollowerValidator = [ | |||
66 | 65 | ||
67 | if (areValidationErrors(req, res)) return | 66 | if (areValidationErrors(req, res)) return |
68 | 67 | ||
69 | const serverActor = await getServerActor() | 68 | let follow: ActorFollowModel |
70 | 69 | try { | |
71 | const actorUrl = await loadActorUrlOrGetFromWebfinger(req.params.nameWithHost) | 70 | const actorUrl = await loadActorUrlOrGetFromWebfinger(req.params.nameWithHost) |
72 | const actor = await ActorModel.loadByUrl(actorUrl) | 71 | const actor = await ActorModel.loadByUrl(actorUrl) |
73 | 72 | ||
74 | const follow = await ActorFollowModel.loadByActorAndTarget(actor.id, serverActor.id) | 73 | const serverActor = await getServerActor() |
74 | follow = await ActorFollowModel.loadByActorAndTarget(actor.id, serverActor.id) | ||
75 | } catch (err) { | ||
76 | logger.warn('Cannot get actor from handle.', { handle: req.params.nameWithHost, err }) | ||
77 | } | ||
75 | 78 | ||
76 | if (!follow) { | 79 | if (!follow) { |
77 | return res | 80 | return res |
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts index 0b333e2f4..d117f26e6 100644 --- a/server/tests/api/check-params/config.ts +++ b/server/tests/api/check-params/config.ts | |||
@@ -87,6 +87,11 @@ describe('Test config API validators', function () { | |||
87 | enabled: false | 87 | enabled: false |
88 | } | 88 | } |
89 | } | 89 | } |
90 | }, | ||
91 | followers: { | ||
92 | instance: { | ||
93 | enabled: false | ||
94 | } | ||
90 | } | 95 | } |
91 | } | 96 | } |
92 | 97 | ||
diff --git a/server/tests/api/check-params/follows.ts b/server/tests/api/check-params/follows.ts index 2ad1575a3..67fa43778 100644 --- a/server/tests/api/check-params/follows.ts +++ b/server/tests/api/check-params/follows.ts | |||
@@ -144,6 +144,46 @@ describe('Test server follows API validators', function () { | |||
144 | }) | 144 | }) |
145 | }) | 145 | }) |
146 | 146 | ||
147 | describe('When removing a follower', function () { | ||
148 | const path = '/api/v1/server/followers' | ||
149 | |||
150 | it('Should fail with an invalid token', async function () { | ||
151 | await makeDeleteRequest({ | ||
152 | url: server.url, | ||
153 | path: path + '/toto@localhost:9002', | ||
154 | token: 'fake_token', | ||
155 | statusCodeExpected: 401 | ||
156 | }) | ||
157 | }) | ||
158 | |||
159 | it('Should fail if the user is not an administrator', async function () { | ||
160 | await makeDeleteRequest({ | ||
161 | url: server.url, | ||
162 | path: path + '/toto@localhost:9002', | ||
163 | token: userAccessToken, | ||
164 | statusCodeExpected: 403 | ||
165 | }) | ||
166 | }) | ||
167 | |||
168 | it('Should fail with an invalid follower', async function () { | ||
169 | await makeDeleteRequest({ | ||
170 | url: server.url, | ||
171 | path: path + '/toto', | ||
172 | token: server.accessToken, | ||
173 | statusCodeExpected: 400 | ||
174 | }) | ||
175 | }) | ||
176 | |||
177 | it('Should fail with an unknown follower', async function () { | ||
178 | await makeDeleteRequest({ | ||
179 | url: server.url, | ||
180 | path: path + '/toto@localhost:9003', | ||
181 | token: server.accessToken, | ||
182 | statusCodeExpected: 404 | ||
183 | }) | ||
184 | }) | ||
185 | }) | ||
186 | |||
147 | describe('When removing following', function () { | 187 | describe('When removing following', function () { |
148 | const path = '/api/v1/server/following' | 188 | const path = '/api/v1/server/following' |
149 | 189 | ||
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index b9f05e952..cb2700f29 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts | |||
@@ -63,6 +63,8 @@ function checkInitialConfig (data: CustomConfig) { | |||
63 | expect(data.import.videos.http.enabled).to.be.true | 63 | expect(data.import.videos.http.enabled).to.be.true |
64 | expect(data.import.videos.torrent.enabled).to.be.true | 64 | expect(data.import.videos.torrent.enabled).to.be.true |
65 | expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.false | 65 | expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.false |
66 | |||
67 | expect(data.followers.instance.enabled).to.be.true | ||
66 | } | 68 | } |
67 | 69 | ||
68 | function checkUpdatedConfig (data: CustomConfig) { | 70 | function checkUpdatedConfig (data: CustomConfig) { |
@@ -105,6 +107,8 @@ function checkUpdatedConfig (data: CustomConfig) { | |||
105 | expect(data.import.videos.http.enabled).to.be.false | 107 | expect(data.import.videos.http.enabled).to.be.false |
106 | expect(data.import.videos.torrent.enabled).to.be.false | 108 | expect(data.import.videos.torrent.enabled).to.be.false |
107 | expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.true | 109 | expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.true |
110 | |||
111 | expect(data.followers.instance.enabled).to.be.false | ||
108 | } | 112 | } |
109 | 113 | ||
110 | describe('Test config', function () { | 114 | describe('Test config', function () { |
@@ -234,6 +238,11 @@ describe('Test config', function () { | |||
234 | enabled: true | 238 | enabled: true |
235 | } | 239 | } |
236 | } | 240 | } |
241 | }, | ||
242 | followers: { | ||
243 | instance: { | ||
244 | enabled: false | ||
245 | } | ||
237 | } | 246 | } |
238 | } | 247 | } |
239 | await updateCustomConfig(server.url, server.accessToken, newCustomConfig) | 248 | await updateCustomConfig(server.url, server.accessToken, newCustomConfig) |
diff --git a/server/tests/api/server/follows-moderation.ts b/server/tests/api/server/follows-moderation.ts index b1cbfb62c..a360706f2 100644 --- a/server/tests/api/server/follows-moderation.ts +++ b/server/tests/api/server/follows-moderation.ts | |||
@@ -2,7 +2,13 @@ | |||
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { flushAndRunMultipleServers, killallServers, ServerInfo, setAccessTokensToServers } from '../../../../shared/utils/index' | 5 | import { |
6 | flushAndRunMultipleServers, | ||
7 | killallServers, | ||
8 | ServerInfo, | ||
9 | setAccessTokensToServers, | ||
10 | updateCustomSubConfig | ||
11 | } from '../../../../shared/utils/index' | ||
6 | import { | 12 | import { |
7 | follow, | 13 | follow, |
8 | getFollowersListPaginationAndSort, | 14 | getFollowersListPaginationAndSort, |
@@ -14,6 +20,38 @@ import { ActorFollow } from '../../../../shared/models/actors' | |||
14 | 20 | ||
15 | const expect = chai.expect | 21 | const expect = chai.expect |
16 | 22 | ||
23 | async function checkHasFollowers (servers: ServerInfo[]) { | ||
24 | { | ||
25 | const res = await getFollowingListPaginationAndSort(servers[0].url, 0, 5, 'createdAt') | ||
26 | expect(res.body.total).to.equal(1) | ||
27 | |||
28 | const follow = res.body.data[0] as ActorFollow | ||
29 | expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube') | ||
30 | expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube') | ||
31 | } | ||
32 | |||
33 | { | ||
34 | const res = await getFollowersListPaginationAndSort(servers[1].url, 0, 5, 'createdAt') | ||
35 | expect(res.body.total).to.equal(1) | ||
36 | |||
37 | const follow = res.body.data[0] as ActorFollow | ||
38 | expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube') | ||
39 | expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube') | ||
40 | } | ||
41 | } | ||
42 | |||
43 | async function checkNoFollowers (servers: ServerInfo[]) { | ||
44 | { | ||
45 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, 'createdAt') | ||
46 | expect(res.body.total).to.equal(0) | ||
47 | } | ||
48 | |||
49 | { | ||
50 | const res = await getFollowersListPaginationAndSort(servers[ 1 ].url, 0, 5, 'createdAt') | ||
51 | expect(res.body.total).to.equal(0) | ||
52 | } | ||
53 | } | ||
54 | |||
17 | describe('Test follows moderation', function () { | 55 | describe('Test follows moderation', function () { |
18 | let servers: ServerInfo[] = [] | 56 | let servers: ServerInfo[] = [] |
19 | 57 | ||
@@ -35,23 +73,7 @@ describe('Test follows moderation', function () { | |||
35 | }) | 73 | }) |
36 | 74 | ||
37 | it('Should have correct follows', async function () { | 75 | it('Should have correct follows', async function () { |
38 | { | 76 | await checkHasFollowers(servers) |
39 | const res = await getFollowingListPaginationAndSort(servers[0].url, 0, 5, 'createdAt') | ||
40 | expect(res.body.total).to.equal(1) | ||
41 | |||
42 | const follow = res.body.data[0] as ActorFollow | ||
43 | expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube') | ||
44 | expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube') | ||
45 | } | ||
46 | |||
47 | { | ||
48 | const res = await getFollowersListPaginationAndSort(servers[1].url, 0, 5, 'createdAt') | ||
49 | expect(res.body.total).to.equal(1) | ||
50 | |||
51 | const follow = res.body.data[0] as ActorFollow | ||
52 | expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube') | ||
53 | expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube') | ||
54 | } | ||
55 | }) | 77 | }) |
56 | 78 | ||
57 | it('Should remove follower on server 2', async function () { | 79 | it('Should remove follower on server 2', async function () { |
@@ -61,15 +83,41 @@ describe('Test follows moderation', function () { | |||
61 | }) | 83 | }) |
62 | 84 | ||
63 | it('Should not not have follows anymore', async function () { | 85 | it('Should not not have follows anymore', async function () { |
64 | { | 86 | await checkNoFollowers(servers) |
65 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt') | 87 | }) |
66 | expect(res.body.total).to.equal(0) | 88 | |
89 | it('Should disable followers on server 2', async function () { | ||
90 | const subConfig = { | ||
91 | followers: { | ||
92 | instance: { | ||
93 | enabled: false | ||
94 | } | ||
95 | } | ||
67 | } | 96 | } |
68 | 97 | ||
69 | { | 98 | await updateCustomSubConfig(servers[1].url, servers[1].accessToken, subConfig) |
70 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt') | 99 | |
71 | expect(res.body.total).to.equal(0) | 100 | await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken) |
101 | await waitJobs(servers) | ||
102 | |||
103 | await checkNoFollowers(servers) | ||
104 | }) | ||
105 | |||
106 | it('Should re enable followers on server 2', async function () { | ||
107 | const subConfig = { | ||
108 | followers: { | ||
109 | instance: { | ||
110 | enabled: true | ||
111 | } | ||
112 | } | ||
72 | } | 113 | } |
114 | |||
115 | await updateCustomSubConfig(servers[1].url, servers[1].accessToken, subConfig) | ||
116 | |||
117 | await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken) | ||
118 | await waitJobs(servers) | ||
119 | |||
120 | await checkHasFollowers(servers) | ||
73 | }) | 121 | }) |
74 | 122 | ||
75 | after(async function () { | 123 | after(async function () { |
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts index 1607b40a8..642ffea39 100644 --- a/shared/models/server/custom-config.model.ts +++ b/shared/models/server/custom-config.model.ts | |||
@@ -86,4 +86,10 @@ export interface CustomConfig { | |||
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | followers: { | ||
90 | instance: { | ||
91 | enabled: boolean | ||
92 | } | ||
93 | } | ||
94 | |||
89 | } | 95 | } |
diff --git a/shared/utils/server/config.ts b/shared/utils/server/config.ts index eaa493a93..21c689714 100644 --- a/shared/utils/server/config.ts +++ b/shared/utils/server/config.ts | |||
@@ -119,6 +119,11 @@ function updateCustomSubConfig (url: string, token: string, newConfig: any) { | |||
119 | enabled: false | 119 | enabled: false |
120 | } | 120 | } |
121 | } | 121 | } |
122 | }, | ||
123 | followers: { | ||
124 | instance: { | ||
125 | enabled: true | ||
126 | } | ||
122 | } | 127 | } |
123 | } | 128 | } |
124 | 129 | ||