Add ability to forbid followers
This commit is contained in:
parent
594d0c6a7c
commit
5b9c965d5a
|
@ -200,3 +200,8 @@ services:
|
||||||
# If false, we use an image link card that will redirect on your PeerTube instance
|
# If false, we use an image link card that will redirect on your PeerTube instance
|
||||||
# Change it to "true", and then test on https://cards-dev.twitter.com/validator to see if you are whitelisted
|
# Change it to "true", and then test on https://cards-dev.twitter.com/validator to see if you are whitelisted
|
||||||
whitelisted: false
|
whitelisted: false
|
||||||
|
|
||||||
|
followers:
|
||||||
|
instance:
|
||||||
|
# Allow or not other instances to follow yours
|
||||||
|
enabled: true
|
||||||
|
|
|
@ -217,3 +217,8 @@ services:
|
||||||
# If false, we use an image link card that will redirect on your PeerTube instance
|
# If false, we use an image link card that will redirect on your PeerTube instance
|
||||||
# Test on https://cards-dev.twitter.com/validator to see if you are whitelisted
|
# Test on https://cards-dev.twitter.com/validator to see if you are whitelisted
|
||||||
whitelisted: false
|
whitelisted: false
|
||||||
|
|
||||||
|
followers:
|
||||||
|
instance:
|
||||||
|
# Allow or not other instances to follow yours
|
||||||
|
enabled: true
|
||||||
|
|
|
@ -279,6 +279,11 @@ function customConfig (): CustomConfig {
|
||||||
enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED
|
enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
followers: {
|
||||||
|
instance: {
|
||||||
|
enabled: CONFIG.FOLLOWERS.INSTANCE.ENABLED
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ async function removeFollowing (req: express.Request, res: express.Response) {
|
||||||
async function removeFollower (req: express.Request, res: express.Response) {
|
async function removeFollower (req: express.Request, res: express.Response) {
|
||||||
const follow = res.locals.follow
|
const follow = res.locals.follow
|
||||||
|
|
||||||
await sendReject(follow)
|
await sendReject(follow.ActorFollower, follow.ActorFollowing)
|
||||||
|
|
||||||
await follow.destroy()
|
await follow.destroy()
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@ function checkMissedConfig () {
|
||||||
'trending.videos.interval_days',
|
'trending.videos.interval_days',
|
||||||
'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route',
|
'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route',
|
||||||
'instance.is_nsfw', 'instance.default_nsfw_policy', 'instance.robots', 'instance.securitytxt',
|
'instance.is_nsfw', 'instance.default_nsfw_policy', 'instance.robots', 'instance.securitytxt',
|
||||||
'services.twitter.username', 'services.twitter.whitelisted'
|
'services.twitter.username', 'services.twitter.whitelisted',
|
||||||
|
'followers.instance.enabled'
|
||||||
]
|
]
|
||||||
const requiredAlternatives = [
|
const requiredAlternatives = [
|
||||||
[ // set
|
[ // set
|
||||||
|
|
|
@ -324,6 +324,11 @@ const CONFIG = {
|
||||||
get USERNAME () { return config.get<string>('services.twitter.username') },
|
get USERNAME () { return config.get<string>('services.twitter.username') },
|
||||||
get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') }
|
get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') }
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
FOLLOWERS: {
|
||||||
|
INSTANCE: {
|
||||||
|
get ENABLED () { return config.get<boolean>('followers.instance.enabled') }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { ActivityFollow } from '../../../../shared/models/activitypub'
|
import { ActivityFollow } from '../../../../shared/models/activitypub'
|
||||||
import { retryTransactionWrapper } from '../../../helpers/database-utils'
|
import { retryTransactionWrapper } from '../../../helpers/database-utils'
|
||||||
import { logger } from '../../../helpers/logger'
|
import { logger } from '../../../helpers/logger'
|
||||||
import { sequelizeTypescript } from '../../../initializers'
|
import { sequelizeTypescript, CONFIG } from '../../../initializers'
|
||||||
import { ActorModel } from '../../../models/activitypub/actor'
|
import { ActorModel } from '../../../models/activitypub/actor'
|
||||||
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
||||||
import { sendAccept } from '../send'
|
import { sendAccept, sendReject } from '../send'
|
||||||
import { Notifier } from '../../notifier'
|
import { Notifier } from '../../notifier'
|
||||||
import { getAPId } from '../../../helpers/activitypub'
|
import { getAPId } from '../../../helpers/activitypub'
|
||||||
|
import { getServerActor } from '../../../helpers/utils'
|
||||||
|
|
||||||
async function processFollowActivity (activity: ActivityFollow, byActor: ActorModel) {
|
async function processFollowActivity (activity: ActivityFollow, byActor: ActorModel) {
|
||||||
const activityObject = getAPId(activity.object)
|
const activityObject = getAPId(activity.object)
|
||||||
|
@ -29,6 +30,11 @@ async function processFollow (actor: ActorModel, targetActorURL: string) {
|
||||||
if (!targetActor) throw new Error('Unknown actor')
|
if (!targetActor) throw new Error('Unknown actor')
|
||||||
if (targetActor.isOwned() === false) throw new Error('This is not a local actor.')
|
if (targetActor.isOwned() === false) throw new Error('This is not a local actor.')
|
||||||
|
|
||||||
|
const serverActor = await getServerActor()
|
||||||
|
if (targetActor.id === serverActor.id && CONFIG.FOLLOWERS.INSTANCE.ENABLED === false) {
|
||||||
|
return sendReject(actor, targetActor)
|
||||||
|
}
|
||||||
|
|
||||||
const [ actorFollow, created ] = await ActorFollowModel.findOrCreate({
|
const [ actorFollow, created ] = await ActorFollowModel.findOrCreate({
|
||||||
where: {
|
where: {
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
|
|
|
@ -17,7 +17,7 @@ async function sendAccept (actorFollow: ActorFollowModel) {
|
||||||
|
|
||||||
logger.info('Creating job to accept follower %s.', follower.url)
|
logger.info('Creating job to accept follower %s.', follower.url)
|
||||||
|
|
||||||
const followUrl = getActorFollowActivityPubUrl(actorFollow)
|
const followUrl = getActorFollowActivityPubUrl(follower, me)
|
||||||
const followData = buildFollowActivity(followUrl, follower, me)
|
const followData = buildFollowActivity(followUrl, follower, me)
|
||||||
|
|
||||||
const url = getActorFollowAcceptActivityPubUrl(actorFollow)
|
const url = getActorFollowAcceptActivityPubUrl(actorFollow)
|
||||||
|
|
|
@ -14,7 +14,7 @@ function sendFollow (actorFollow: ActorFollowModel) {
|
||||||
|
|
||||||
logger.info('Creating job to send follow request to %s.', following.url)
|
logger.info('Creating job to send follow request to %s.', following.url)
|
||||||
|
|
||||||
const url = getActorFollowActivityPubUrl(actorFollow)
|
const url = getActorFollowActivityPubUrl(me, following)
|
||||||
const data = buildFollowActivity(url, me, following)
|
const data = buildFollowActivity(url, me, following)
|
||||||
|
|
||||||
return unicastTo(data, me, following.inboxUrl)
|
return unicastTo(data, me, following.inboxUrl)
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import { ActivityFollow, ActivityReject } from '../../../../shared/models/activitypub'
|
import { ActivityFollow, ActivityReject } from '../../../../shared/models/activitypub'
|
||||||
import { ActorModel } from '../../../models/activitypub/actor'
|
import { ActorModel } from '../../../models/activitypub/actor'
|
||||||
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
import { getActorFollowActivityPubUrl, getActorFollowRejectActivityPubUrl } from '../url'
|
||||||
import { getActorFollowAcceptActivityPubUrl, getActorFollowActivityPubUrl } from '../url'
|
|
||||||
import { unicastTo } from './utils'
|
import { unicastTo } from './utils'
|
||||||
import { buildFollowActivity } from './send-follow'
|
import { buildFollowActivity } from './send-follow'
|
||||||
import { logger } from '../../../helpers/logger'
|
import { logger } from '../../../helpers/logger'
|
||||||
|
|
||||||
async function sendReject (actorFollow: ActorFollowModel) {
|
async function sendReject (follower: ActorModel, following: ActorModel) {
|
||||||
const follower = actorFollow.ActorFollower
|
|
||||||
const me = actorFollow.ActorFollowing
|
|
||||||
|
|
||||||
if (!follower.serverId) { // This should never happen
|
if (!follower.serverId) { // This should never happen
|
||||||
logger.warn('Do not sending reject to local follower.')
|
logger.warn('Do not sending reject to local follower.')
|
||||||
return
|
return
|
||||||
|
@ -17,13 +13,13 @@ async function sendReject (actorFollow: ActorFollowModel) {
|
||||||
|
|
||||||
logger.info('Creating job to reject follower %s.', follower.url)
|
logger.info('Creating job to reject follower %s.', follower.url)
|
||||||
|
|
||||||
const followUrl = getActorFollowActivityPubUrl(actorFollow)
|
const followUrl = getActorFollowActivityPubUrl(follower, following)
|
||||||
const followData = buildFollowActivity(followUrl, follower, me)
|
const followData = buildFollowActivity(followUrl, follower, following)
|
||||||
|
|
||||||
const url = getActorFollowAcceptActivityPubUrl(actorFollow)
|
const url = getActorFollowRejectActivityPubUrl(follower, following)
|
||||||
const data = buildRejectActivity(url, me, followData)
|
const data = buildRejectActivity(url, following, followData)
|
||||||
|
|
||||||
return unicastTo(data, me, follower.inboxUrl)
|
return unicastTo(data, following, follower.inboxUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -31,7 +31,7 @@ async function sendUndoFollow (actorFollow: ActorFollowModel, t: Transaction) {
|
||||||
|
|
||||||
logger.info('Creating job to send an unfollow request to %s.', following.url)
|
logger.info('Creating job to send an unfollow request to %s.', following.url)
|
||||||
|
|
||||||
const followUrl = getActorFollowActivityPubUrl(actorFollow)
|
const followUrl = getActorFollowActivityPubUrl(me, following)
|
||||||
const undoUrl = getUndoActivityPubUrl(followUrl)
|
const undoUrl = getUndoActivityPubUrl(followUrl)
|
||||||
|
|
||||||
const followActivity = buildFollowActivity(followUrl, me, following)
|
const followActivity = buildFollowActivity(followUrl, me, following)
|
||||||
|
|
|
@ -74,11 +74,8 @@ function getVideoDislikesActivityPubUrl (video: VideoModel) {
|
||||||
return video.url + '/dislikes'
|
return video.url + '/dislikes'
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActorFollowActivityPubUrl (actorFollow: ActorFollowModel) {
|
function getActorFollowActivityPubUrl (follower: ActorModel, following: ActorModel) {
|
||||||
const me = actorFollow.ActorFollower
|
return follower.url + '/follows/' + following.id
|
||||||
const following = actorFollow.ActorFollowing
|
|
||||||
|
|
||||||
return me.url + '/follows/' + following.id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModel) {
|
function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModel) {
|
||||||
|
@ -88,6 +85,10 @@ function getActorFollowAcceptActivityPubUrl (actorFollow: ActorFollowModel) {
|
||||||
return follower.url + '/accepts/follows/' + me.id
|
return follower.url + '/accepts/follows/' + me.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getActorFollowRejectActivityPubUrl (follower: ActorModel, following: ActorModel) {
|
||||||
|
return follower.url + '/rejects/follows/' + following.id
|
||||||
|
}
|
||||||
|
|
||||||
function getVideoAnnounceActivityPubUrl (byActor: ActorModel, video: VideoModel) {
|
function getVideoAnnounceActivityPubUrl (byActor: ActorModel, video: VideoModel) {
|
||||||
return video.url + '/announces/' + byActor.id
|
return video.url + '/announces/' + byActor.id
|
||||||
}
|
}
|
||||||
|
@ -120,6 +121,7 @@ export {
|
||||||
getVideoViewActivityPubUrl,
|
getVideoViewActivityPubUrl,
|
||||||
getVideoLikeActivityPubUrl,
|
getVideoLikeActivityPubUrl,
|
||||||
getVideoDislikeActivityPubUrl,
|
getVideoDislikeActivityPubUrl,
|
||||||
|
getActorFollowRejectActivityPubUrl,
|
||||||
getVideoCommentActivityPubUrl,
|
getVideoCommentActivityPubUrl,
|
||||||
getDeleteActivityPubUrl,
|
getDeleteActivityPubUrl,
|
||||||
getVideoSharesActivityPubUrl,
|
getVideoSharesActivityPubUrl,
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { ActorFollowModel } from '../../models/activitypub/actor-follow'
|
||||||
import { areValidationErrors } from './utils'
|
import { areValidationErrors } from './utils'
|
||||||
import { ActorModel } from '../../models/activitypub/actor'
|
import { ActorModel } from '../../models/activitypub/actor'
|
||||||
import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger'
|
import { loadActorUrlOrGetFromWebfinger } from '../../helpers/webfinger'
|
||||||
import { getOrCreateActorAndServerAndModel } from '../../lib/activitypub'
|
|
||||||
import { isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
|
import { isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
|
||||||
|
|
||||||
const followValidator = [
|
const followValidator = [
|
||||||
|
@ -66,12 +65,16 @@ const removeFollowerValidator = [
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return
|
if (areValidationErrors(req, res)) return
|
||||||
|
|
||||||
const serverActor = await getServerActor()
|
let follow: ActorFollowModel
|
||||||
|
try {
|
||||||
const actorUrl = await loadActorUrlOrGetFromWebfinger(req.params.nameWithHost)
|
const actorUrl = await loadActorUrlOrGetFromWebfinger(req.params.nameWithHost)
|
||||||
const actor = await ActorModel.loadByUrl(actorUrl)
|
const actor = await ActorModel.loadByUrl(actorUrl)
|
||||||
|
|
||||||
const follow = await ActorFollowModel.loadByActorAndTarget(actor.id, serverActor.id)
|
const serverActor = await getServerActor()
|
||||||
|
follow = await ActorFollowModel.loadByActorAndTarget(actor.id, serverActor.id)
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn('Cannot get actor from handle.', { handle: req.params.nameWithHost, err })
|
||||||
|
}
|
||||||
|
|
||||||
if (!follow) {
|
if (!follow) {
|
||||||
return res
|
return res
|
||||||
|
|
|
@ -87,6 +87,11 @@ describe('Test config API validators', function () {
|
||||||
enabled: false
|
enabled: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
followers: {
|
||||||
|
instance: {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,46 @@ describe('Test server follows API validators', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('When removing a follower', function () {
|
||||||
|
const path = '/api/v1/server/followers'
|
||||||
|
|
||||||
|
it('Should fail with an invalid token', async function () {
|
||||||
|
await makeDeleteRequest({
|
||||||
|
url: server.url,
|
||||||
|
path: path + '/toto@localhost:9002',
|
||||||
|
token: 'fake_token',
|
||||||
|
statusCodeExpected: 401
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail if the user is not an administrator', async function () {
|
||||||
|
await makeDeleteRequest({
|
||||||
|
url: server.url,
|
||||||
|
path: path + '/toto@localhost:9002',
|
||||||
|
token: userAccessToken,
|
||||||
|
statusCodeExpected: 403
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an invalid follower', async function () {
|
||||||
|
await makeDeleteRequest({
|
||||||
|
url: server.url,
|
||||||
|
path: path + '/toto',
|
||||||
|
token: server.accessToken,
|
||||||
|
statusCodeExpected: 400
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an unknown follower', async function () {
|
||||||
|
await makeDeleteRequest({
|
||||||
|
url: server.url,
|
||||||
|
path: path + '/toto@localhost:9003',
|
||||||
|
token: server.accessToken,
|
||||||
|
statusCodeExpected: 404
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('When removing following', function () {
|
describe('When removing following', function () {
|
||||||
const path = '/api/v1/server/following'
|
const path = '/api/v1/server/following'
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,8 @@ function checkInitialConfig (data: CustomConfig) {
|
||||||
expect(data.import.videos.http.enabled).to.be.true
|
expect(data.import.videos.http.enabled).to.be.true
|
||||||
expect(data.import.videos.torrent.enabled).to.be.true
|
expect(data.import.videos.torrent.enabled).to.be.true
|
||||||
expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.false
|
expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.false
|
||||||
|
|
||||||
|
expect(data.followers.instance.enabled).to.be.true
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpdatedConfig (data: CustomConfig) {
|
function checkUpdatedConfig (data: CustomConfig) {
|
||||||
|
@ -105,6 +107,8 @@ function checkUpdatedConfig (data: CustomConfig) {
|
||||||
expect(data.import.videos.http.enabled).to.be.false
|
expect(data.import.videos.http.enabled).to.be.false
|
||||||
expect(data.import.videos.torrent.enabled).to.be.false
|
expect(data.import.videos.torrent.enabled).to.be.false
|
||||||
expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.true
|
expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.true
|
||||||
|
|
||||||
|
expect(data.followers.instance.enabled).to.be.false
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Test config', function () {
|
describe('Test config', function () {
|
||||||
|
@ -234,6 +238,11 @@ describe('Test config', function () {
|
||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
followers: {
|
||||||
|
instance: {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await updateCustomConfig(server.url, server.accessToken, newCustomConfig)
|
await updateCustomConfig(server.url, server.accessToken, newCustomConfig)
|
||||||
|
|
|
@ -2,7 +2,13 @@
|
||||||
|
|
||||||
import * as chai from 'chai'
|
import * as chai from 'chai'
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import { flushAndRunMultipleServers, killallServers, ServerInfo, setAccessTokensToServers } from '../../../../shared/utils/index'
|
import {
|
||||||
|
flushAndRunMultipleServers,
|
||||||
|
killallServers,
|
||||||
|
ServerInfo,
|
||||||
|
setAccessTokensToServers,
|
||||||
|
updateCustomSubConfig
|
||||||
|
} from '../../../../shared/utils/index'
|
||||||
import {
|
import {
|
||||||
follow,
|
follow,
|
||||||
getFollowersListPaginationAndSort,
|
getFollowersListPaginationAndSort,
|
||||||
|
@ -14,6 +20,38 @@ import { ActorFollow } from '../../../../shared/models/actors'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
async function checkHasFollowers (servers: ServerInfo[]) {
|
||||||
|
{
|
||||||
|
const res = await getFollowingListPaginationAndSort(servers[0].url, 0, 5, 'createdAt')
|
||||||
|
expect(res.body.total).to.equal(1)
|
||||||
|
|
||||||
|
const follow = res.body.data[0] as ActorFollow
|
||||||
|
expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube')
|
||||||
|
expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube')
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const res = await getFollowersListPaginationAndSort(servers[1].url, 0, 5, 'createdAt')
|
||||||
|
expect(res.body.total).to.equal(1)
|
||||||
|
|
||||||
|
const follow = res.body.data[0] as ActorFollow
|
||||||
|
expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube')
|
||||||
|
expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkNoFollowers (servers: ServerInfo[]) {
|
||||||
|
{
|
||||||
|
const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, 'createdAt')
|
||||||
|
expect(res.body.total).to.equal(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const res = await getFollowersListPaginationAndSort(servers[ 1 ].url, 0, 5, 'createdAt')
|
||||||
|
expect(res.body.total).to.equal(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('Test follows moderation', function () {
|
describe('Test follows moderation', function () {
|
||||||
let servers: ServerInfo[] = []
|
let servers: ServerInfo[] = []
|
||||||
|
|
||||||
|
@ -35,23 +73,7 @@ describe('Test follows moderation', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have correct follows', async function () {
|
it('Should have correct follows', async function () {
|
||||||
{
|
await checkHasFollowers(servers)
|
||||||
const res = await getFollowingListPaginationAndSort(servers[0].url, 0, 5, 'createdAt')
|
|
||||||
expect(res.body.total).to.equal(1)
|
|
||||||
|
|
||||||
const follow = res.body.data[0] as ActorFollow
|
|
||||||
expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube')
|
|
||||||
expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube')
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const res = await getFollowersListPaginationAndSort(servers[1].url, 0, 5, 'createdAt')
|
|
||||||
expect(res.body.total).to.equal(1)
|
|
||||||
|
|
||||||
const follow = res.body.data[0] as ActorFollow
|
|
||||||
expect(follow.follower.url).to.equal('http://localhost:9001/accounts/peertube')
|
|
||||||
expect(follow.following.url).to.equal('http://localhost:9002/accounts/peertube')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should remove follower on server 2', async function () {
|
it('Should remove follower on server 2', async function () {
|
||||||
|
@ -61,15 +83,41 @@ describe('Test follows moderation', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not not have follows anymore', async function () {
|
it('Should not not have follows anymore', async function () {
|
||||||
{
|
await checkNoFollowers(servers)
|
||||||
const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt')
|
})
|
||||||
expect(res.body.total).to.equal(0)
|
|
||||||
|
it('Should disable followers on server 2', async function () {
|
||||||
|
const subConfig = {
|
||||||
|
followers: {
|
||||||
|
instance: {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
await updateCustomSubConfig(servers[1].url, servers[1].accessToken, subConfig)
|
||||||
const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt')
|
|
||||||
expect(res.body.total).to.equal(0)
|
await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken)
|
||||||
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
await checkNoFollowers(servers)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should re enable followers on server 2', async function () {
|
||||||
|
const subConfig = {
|
||||||
|
followers: {
|
||||||
|
instance: {
|
||||||
|
enabled: true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateCustomSubConfig(servers[1].url, servers[1].accessToken, subConfig)
|
||||||
|
|
||||||
|
await follow(servers[0].url, [ servers[1].url ], servers[0].accessToken)
|
||||||
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
await checkHasFollowers(servers)
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -86,4 +86,10 @@ export interface CustomConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
followers: {
|
||||||
|
instance: {
|
||||||
|
enabled: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,11 @@ function updateCustomSubConfig (url: string, token: string, newConfig: any) {
|
||||||
enabled: false
|
enabled: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
followers: {
|
||||||
|
instance: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue