diff --git a/package.json b/package.json index 8aa36d7e..994a0483 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "author": "lesion", "scripts": { "dev:nuxt": "cross-env NODE_ENV=development nuxt dev", - "dev": "cross-env DEBUG=fediverse:* NODE_ENV=development nuxt", + "dev": "cross-env DEBUG=*,-follow-redirects,-send,-body-parser:*,-express:*,-connect:*,-sequelize:* NODE_ENV=development node server/index.js", "build": "nuxt build", - "start": "cross-env sequelize db:migrate && NODE_ENV=production node server/cli.js", + "start": "cross-env NODE_ENV=production node server/cli.js", "lint": "eslint --ext .js,.vue --ignore-path .gitignore .", "doc": "cd docs && bundle exec jekyll b", "doc:dev": "cd docs && bundle exec jekyll s --drafts", diff --git a/server/api/models/event.js b/server/api/models/event.js index 8581f7b6..8ca92853 100644 --- a/server/api/models/event.js +++ b/server/api/models/event.js @@ -57,11 +57,11 @@ module.exports = (sequelize, DataTypes) => { } return { - id: `${config.baseurl}/federation/m/c_${this.id}`, - type: 'Create', - actor: `${config.baseurl}/federation/u/${username}`, - url: `${config.baseurl}/federation/m/${this.id}`, - object: { + // id: `${config.baseurl}/federation/m/c_${this.id}`, + // type: 'Create', + // actor: `${config.baseurl}/federation/u/${username}`, + // url: `${config.baseurl}/federation/m/${this.id}`, + // object: { attachment, tag: this.tags.map(tag => ({ type: 'Hashtag', diff --git a/server/federation/comments.js b/server/federation/comments.js index 15ef55d0..e7b7816e 100644 --- a/server/federation/comments.js +++ b/server/federation/comments.js @@ -7,14 +7,19 @@ module.exports = { const body = req.body //search for related event const inReplyTo = body.object.inReplyTo - const match = inReplyTo.match(`${config.baseurl}/federation/m/(.*)`) - if (!match || match.length<2) return res.status(404).send('Event not found!') + const match = inReplyTo.match('.*\/federation\/m\/(.*)') + console.error('inReplyTo', inReplyTo) + console.error('match', match) + if (!match || match.length<2) { + debug("Comment not found %s", inReplyTo) + return res.status(404).send('Event not found!') + } let event = await Event.findByPk(Number(match[1])) debug('comment coming for %s', inReplyTo) if (!event) { // in reply to another comment... - const comment = await Comment.findByPk(inReplyTo, { include: [Event] }) + const comment = await Comment.findOne({ where: { activitypub_id: inReplyTo }, include: [Event] }) if (!comment) return res.status(404).send('Not found') event = comment.event } @@ -27,6 +32,16 @@ module.exports = { }) res.sendStatus(201) + }, + async remove (req, res) { + const comment = await Comment.findOne({where: { activitypub_id: req.body.object.id }}) + if (!comment) { + debug('Comment %s not found', req.body.object.id) + return res.status(404).send('Not found') + } + await comment.destroy() + debug('Comment %s removed!', req.body.object.id) + return res.sendStatus(201) } } diff --git a/server/federation/follows.js b/server/federation/follows.js index 5a7c5294..7f626bbe 100644 --- a/server/federation/follows.js +++ b/server/federation/follows.js @@ -2,7 +2,7 @@ const config = require('config') const Helpers = require('./helpers') const { user: User } = require('../api/models') const crypto = require('crypto') -const debug = require('debug')('follows') +const debug = require('debug')('fedivers:follows') module.exports = { // follow request from fediverse @@ -15,8 +15,8 @@ module.exports = { // check for duplicate if (user.followers.indexOf(body.actor) === -1) { - debug('%s followed by %s (%d)', username, body.actor, user.followers.length) await user.update({ followers: [...user.followers, body.actor] }) + debug('%s followed by %s (%d)', username, body.actor, user.followers.length) } else { debug('duplicate %s followed by %s', username, body.actor) } @@ -34,16 +34,18 @@ module.exports = { // unfollow request from fediverse async unfollow (req, res) { - debug("Unfollow UNFOLLOW!") const body = req.body const username = body.object.object.replace(`${config.baseurl}/federation/u/`, '') const user = await User.findOne({ where: { username }}) if (!user) return res.status(404).send('User not found') - if (body.actor !== body.object.actor) return res.status(400).send('Bad things') - user.followers = user.followers.filter(follower => follower !== username) + if (body.actor !== body.object.actor) { + debug('Unfollow an user created by a different actor !?!?') + return res.status(400).send('Bad things') + } + const followers = user.followers.filter(follower => follower !== body.actor) + await user.update({ followers }) debug('%s unfollowed by %s (%d)', username, body.actor, user.followers.length) - await user.save() res.sendStatus(200) } } diff --git a/server/federation/helpers.js b/server/federation/helpers.js index a4f9c693..a322edce 100644 --- a/server/federation/helpers.js +++ b/server/federation/helpers.js @@ -43,20 +43,40 @@ const Helpers = { // TODO: has to use sharedInbox! // event is sent by user that published it and by the admin instance const instanceAdmin = await User.findOne({where: { email: config.admin }}) - if(!instanceAdmin) return + if(!instanceAdmin || !instanceAdmin.username) { + debug('Instance admin not found (there is no user with email => %s)', config.admin) + return + } for(let follower of instanceAdmin.followers) { debug('Notify %s with event %s', follower, event.title) - const body = event.toAP(instanceAdmin.username, follower) + const body = { + id: `${config.baseurl}/federation/m/c_${event.id}`, + type: 'Create', + actor: `${config.baseurl}/federation/u/${instanceAdmin.username}`, + url: `${config.baseurl}/federation/m/${event.id}`, + object: event.toAP(instanceAdmin.username, follower) + } body['@context'] = 'https://www.w3.org/ns/activitystreams' Helpers.signAndSend(body, user, follower) } // in case the event is published by the Admin itself do not republish - if (instanceAdmin.id === user.id) return + if (instanceAdmin.id === user.id) { + debug('') + return + } + + if (!user.settings.enable_federation || !user.username) return for(let follower of user.followers) { debug('Notify %s with event %s', follower, event.title) - const body = event.toAP(user.username, follower) + const body = { + id: `${config.baseurl}/federation/m/c_${event.id}`, + type: 'Create', + actor: `${config.baseurl}/federation/u/${user.username}`, + url: `${config.baseurl}/federation/m/${event.id}`, + object: event.toAP(user.username, follower) + } body['@context'] = 'https://www.w3.org/ns/activitystreams' Helpers.signAndSend(body, user, follower) } @@ -87,7 +107,6 @@ const Helpers = { // ref: https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/ async verifySignature(req, res, next) { - debug('Inside verify signature', req.body.actor) let user = await Helpers.getActor(req.body.actor) if (!user) return res.status(401).send('Actor not found') diff --git a/server/federation/index.js b/server/federation/index.js index 00768c7c..309ead2a 100644 --- a/server/federation/index.js +++ b/server/federation/index.js @@ -29,7 +29,7 @@ router.get('/m/:event_id', async (req, res) => { // get any message coming from federation // Federation is calling! router.post('/u/:name/inbox', Helpers.verifySignature, async (req, res) => { - + const b = req.body switch(b.type) { @@ -56,7 +56,7 @@ router.post('/u/:name/inbox', Helpers.verifySignature, async (req, res) => { Ego.bookmark(req, res) break case 'Delete': - console.error('Delete ?!?!') + await Comments.remove(req, res) break case 'Create': // this is a reply diff --git a/server/federation/users.js b/server/federation/users.js index 1f7124f7..80db30b9 100644 --- a/server/federation/users.js +++ b/server/federation/users.js @@ -1,6 +1,7 @@ -const { user: User, event: Event } = require('../api/models') +const { user: User, event: Event, place: Place, tag: Tag } = require('../api/models') const config = require('config') const get = require('lodash/get') +const debug = require('debug')('fediverse:user') module.exports = { async get (req, res) { @@ -55,13 +56,12 @@ module.exports = { if (!name) return res.status(400).send('Bad request.') const user = await User.findOne({ - include: [ Event ], + include: [ { model: Event, include: [ Place, Tag ] } ], where: { username: name } }) if (!user) return res.status(404).send(`No record found for ${name}`) - - console.error('Inside outbox, should return all events from this user') + debug('Inside outbox, should return all events from this user') // https://www.w3.org/TR/activitypub/#outbox if (!page) { const ret = {