2022-12-23 01:08:14 +01:00
|
|
|
const { APUser, Instance, Resource } = require('../models/models')
|
2023-11-21 22:14:33 +01:00
|
|
|
const { getActor, unfollowActor, followActor } = require('../../federation/helpers')
|
2023-11-09 16:55:09 +01:00
|
|
|
const axios = require('axios')
|
|
|
|
const get = require('lodash/get')
|
2022-12-23 01:08:14 +01:00
|
|
|
|
2021-04-26 11:26:59 +02:00
|
|
|
const Sequelize = require('sequelize')
|
2023-11-09 16:55:09 +01:00
|
|
|
const log = require('../../log')
|
2023-12-22 09:28:20 +01:00
|
|
|
const { getNodeInfo } = require('../../federation/helpers')
|
2019-10-30 15:01:15 +01:00
|
|
|
|
|
|
|
const instancesController = {
|
2023-12-26 13:04:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* get all fediverse instances
|
|
|
|
* used in moderation panel
|
|
|
|
*/
|
2019-10-30 15:01:15 +01:00
|
|
|
async getAll (req, res) {
|
2021-04-26 11:26:59 +02:00
|
|
|
const instances = await Instance.findAll({
|
|
|
|
attributes: [
|
|
|
|
'domain', 'name', 'data', 'blocked',
|
|
|
|
[Sequelize.fn('COUNT', Sequelize.col('ap_users.ap_id')), 'users']
|
|
|
|
],
|
|
|
|
order: [[Sequelize.fn('COUNT', Sequelize.col('ap_users.ap_id')), 'DESC']],
|
|
|
|
group: ['instance.domain'],
|
|
|
|
include: [{ model: APUser, attributes: [] }]
|
|
|
|
})
|
2019-10-30 15:01:15 +01:00
|
|
|
return res.json(instances)
|
|
|
|
},
|
2019-11-13 10:56:01 +01:00
|
|
|
|
2020-03-02 15:37:42 +01:00
|
|
|
// async getUsedInstance (req, res) {
|
|
|
|
// // const ap_users = await APUser.findAll({
|
|
|
|
// // attributes: ['ap_id', 'blocked', 'instanceDomain'],
|
|
|
|
// // where: { [Op.or]: [{ follower: true }, { blocked: true }] },
|
|
|
|
// // include: [
|
|
|
|
// // { model: Resource, attributes: ['id', 'eventId'], include: [{ model: Event, attributes: ['title'] }] },
|
|
|
|
// // { model: Instance, attributes: ['blocked', 'name', 'domain'] }],
|
|
|
|
// // nest: true,
|
|
|
|
// // raw: true
|
|
|
|
// // })
|
|
|
|
// const instances = await Instance.findAll({
|
|
|
|
// include: [
|
|
|
|
// { model: APUser, where: { [Op.or]: [{ follower: true }, { blocked: true }] }, attributes: [] }
|
|
|
|
// ],
|
|
|
|
// attributes: ['domain', 'name', 'blocked'],
|
|
|
|
// raw: true
|
|
|
|
// })
|
|
|
|
// console.error(instances)
|
|
|
|
// res.json(instances)
|
|
|
|
// },
|
|
|
|
|
2019-11-13 10:56:01 +01:00
|
|
|
/**
|
2020-03-02 15:37:42 +01:00
|
|
|
* get instance's users
|
2019-11-13 10:56:01 +01:00
|
|
|
*/
|
|
|
|
async get (req, res) {
|
2019-12-06 00:49:44 +01:00
|
|
|
const ap_users = await APUser.findAll({ where: { instanceDomain: req.params.instance_domain }, include: [Resource] })
|
|
|
|
return res.json(ap_users)
|
2019-11-13 10:56:01 +01:00
|
|
|
},
|
|
|
|
|
2023-11-21 22:14:33 +01:00
|
|
|
// get friendly users
|
2023-11-09 16:55:09 +01:00
|
|
|
async getFriendly (req, res) {
|
2023-11-21 22:14:33 +01:00
|
|
|
const friendly_users = await APUser.findAll({ where: { friendly: true }, include: [Instance]})
|
|
|
|
return res.json(friendly_users)
|
2023-11-09 16:55:09 +01:00
|
|
|
},
|
|
|
|
|
2023-11-21 22:14:33 +01:00
|
|
|
// toggle instance block
|
2019-10-30 15:01:15 +01:00
|
|
|
async toggleBlock (req, res) {
|
2019-12-04 01:20:31 +01:00
|
|
|
const instance = await Instance.findByPk(req.body.instance)
|
2019-10-30 15:01:15 +01:00
|
|
|
if (!instance) { return res.status(404).send('Not found') }
|
|
|
|
await instance.update({ blocked: req.body.blocked })
|
|
|
|
return res.json(instance)
|
2023-11-09 16:55:09 +01:00
|
|
|
},
|
|
|
|
|
2023-11-20 23:15:28 +01:00
|
|
|
|
|
|
|
async removeFriendly (req, res) {
|
|
|
|
let ap_id = req.query.ap_id
|
|
|
|
log.info(`Remove friendly instance ${ap_id} ...`)
|
|
|
|
|
|
|
|
try {
|
|
|
|
const actor = await getActor(ap_id)
|
|
|
|
if (!actor || !actor.friendly) {
|
|
|
|
return res.sendStatus(404)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actor.following) {
|
|
|
|
// unfollow
|
|
|
|
await unfollowActor(actor)
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove friendlyness
|
|
|
|
await actor.update({ friendly: false })
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
log.warn(e)
|
|
|
|
return res.status(400).send(e)
|
|
|
|
}
|
|
|
|
|
|
|
|
return res.sendStatus(200)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
2023-11-09 16:55:09 +01:00
|
|
|
async addFriendly (req, res) {
|
|
|
|
|
2023-12-26 13:04:20 +01:00
|
|
|
/**
|
|
|
|
* url
|
|
|
|
* in case we have a @ we should use webfinger
|
|
|
|
* in case we have a full url could be an actor
|
|
|
|
* or a nodeinfo url to search for
|
|
|
|
*/
|
|
|
|
let url = req.body.url
|
|
|
|
|
|
|
|
if (url.includes('@')) {
|
|
|
|
const [ user, instance_url ] = url.replace(/^@/,'').split('@')
|
|
|
|
log.debug('[FEDI] Adds user: %s and instance: %s because url was: %s', user, instance_url, url)
|
|
|
|
try {
|
|
|
|
const webfinger = await axios.get(`https://${instance_url}/.well-known/webfinger?resource=acct:${user}@${instance_url}`).then(res => res.data)
|
|
|
|
if (webfinger?.links) {
|
|
|
|
const actor_url = webfinger.links.find(l => l.rel === 'self')
|
|
|
|
|
|
|
|
// if (!instance_url.startsWith('http')) {
|
|
|
|
// instance_url = `https://${instance_url}`
|
|
|
|
// }
|
|
|
|
log.info(`[FEDI] Adding trusted instance ${instance_url} and actor ${actor_url.href}...`)
|
|
|
|
const { applicationActor, nodeInfo } = await getNodeInfo('https://' + instance_url)
|
|
|
|
|
|
|
|
// create a new instance
|
|
|
|
const instance = {
|
|
|
|
url: 'https://' + instance_url,
|
|
|
|
name: get(nodeInfo, 'metadata.nodeName', ''),
|
|
|
|
label: get(nodeInfo, 'metadata.nodeLabel', ''),
|
|
|
|
timezone: get(nodeInfo, 'metadata.nodeTimezone', ''),
|
|
|
|
}
|
|
|
|
const actor = await getActor(actor_url.href)
|
|
|
|
log.debug('[FEDI] Actor %s', actor)
|
|
|
|
await actor.update({ friendly: true })
|
|
|
|
return res.json(actor)
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e)
|
|
|
|
log.error('[FEDI] Wrong webfinger response from %s: %s ', url, e?.response?.data ?? String(e))
|
|
|
|
return res.sendStatus(404)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-09 16:55:09 +01:00
|
|
|
try {
|
2023-12-26 13:04:20 +01:00
|
|
|
if (!url.startsWith('http')) {
|
|
|
|
url = `https://${url}`
|
2023-11-09 16:55:09 +01:00
|
|
|
}
|
2023-12-26 13:04:20 +01:00
|
|
|
url = url.replace(/\/$/, '')
|
2023-11-09 16:55:09 +01:00
|
|
|
|
2023-12-26 13:04:20 +01:00
|
|
|
log.info(`[FEDI] Adding trusted instance ${url} ...`)
|
|
|
|
const { applicationActor, nodeInfo } = await getNodeInfo(url)
|
2023-11-09 16:55:09 +01:00
|
|
|
|
|
|
|
// create a new instance
|
|
|
|
const instance = {
|
2023-12-26 13:04:20 +01:00
|
|
|
url: url,
|
2023-12-22 09:28:20 +01:00
|
|
|
name: get(nodeInfo, 'metadata.nodeName', ''),
|
|
|
|
label: get(nodeInfo, 'metadata.nodeLabel', ''),
|
|
|
|
timezone: get(nodeInfo, 'metadata.nodeTimezone', ''),
|
2023-11-09 16:55:09 +01:00
|
|
|
}
|
|
|
|
|
2023-12-22 09:28:20 +01:00
|
|
|
if (applicationActor) {
|
2023-12-22 20:58:38 +01:00
|
|
|
log.debug('[FEDI] This node supports FEP-2677')
|
2023-12-22 09:28:20 +01:00
|
|
|
const actor = await getActor(applicationActor)
|
2023-12-22 20:58:38 +01:00
|
|
|
log.debug('[FEDI] Actor %s', actor)
|
2023-12-22 09:28:20 +01:00
|
|
|
await actor.update({ friendly: true })
|
2023-12-26 13:04:20 +01:00
|
|
|
return res.json(actor)
|
2023-12-22 09:28:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (nodeInfo?.software?.name === 'Mobilizon') {
|
|
|
|
instance.actor = 'relay'
|
|
|
|
} else if (nodeInfo?.software?.name === 'gancio') {
|
|
|
|
instance.actor = get(nodeInfo, 'metadata.nodeActor', 'relay')
|
|
|
|
}
|
2023-11-09 16:55:09 +01:00
|
|
|
log.debug(`instance .well-known: ${instance.name} / ${instance.actor}`)
|
|
|
|
|
2023-11-20 23:15:28 +01:00
|
|
|
// if we have an actor, let's make friend
|
2023-11-09 16:55:09 +01:00
|
|
|
if (instance.actor) {
|
|
|
|
|
|
|
|
// send a well-known request
|
2023-12-26 13:04:20 +01:00
|
|
|
const instance_hostname = new URL(url).host
|
|
|
|
const { data: wellknown } = await axios.get(`${url}/.well-known/webfinger?resource=acct:${instance.actor}@${instance_hostname}`)
|
2023-11-09 16:55:09 +01:00
|
|
|
|
|
|
|
// search for actor url
|
|
|
|
const actorURL = wellknown?.links.find(l => l.rel === 'self').href
|
|
|
|
|
2023-11-20 23:15:28 +01:00
|
|
|
// retrieve the AP actor and flat it as friendly
|
2023-11-09 16:55:09 +01:00
|
|
|
const actor = await getActor(actorURL)
|
2023-11-20 23:15:28 +01:00
|
|
|
await actor.update({ friendly: true })
|
2023-11-09 16:55:09 +01:00
|
|
|
|
|
|
|
return res.json(actor)
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2023-12-26 13:04:20 +01:00
|
|
|
console.error(e)
|
2023-12-22 14:53:53 +01:00
|
|
|
log.error('[FEDI] Error adding friendly instance %s', e?.response?.data ?? String(e))
|
2023-11-09 16:55:09 +01:00
|
|
|
return res.status(400).send(e)
|
|
|
|
}
|
2019-10-30 15:01:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = instancesController
|