This commit is contained in:
lesion
2019-08-02 13:43:28 +02:00
parent 5b013829fe
commit 40f7ffa99e
16 changed files with 183 additions and 51 deletions

View File

@@ -2,7 +2,7 @@ const crypto = require('crypto')
const moment = require('moment')
const { Op } = require('sequelize')
const lodash = require('lodash')
const { event: Event, comment: Comment, tag: Tag, place: Place, notification: Notification } = require('../models')
const { event: Event, comment: Comment, tag: Tag, place: Place, user: User, notification: Notification } = require('../models')
const Sequelize = require('sequelize')
const notifier = require('../../notifier')
@@ -94,6 +94,7 @@ const eventController = {
},
include: [
{ model: Tag, attributes: ['tag', 'weigth'], through: { attributes: [] } },
{ model: User, attributes: ['username'] },
{ model: Place, attributes: ['name', 'address'] },
Comment
],

View File

@@ -122,7 +122,9 @@ const userController = {
// send response to client
res.json(event)
federation.sendEvent(event, req.user)
if (req.user)
federation.sendEvent(event, req.user)
res.json(200)
// send notification (mastodon/email/confirmation)

View File

@@ -101,8 +101,15 @@ api.get('/export/:type', exportController.export)
api.get('/event/:month/:year', eventController.getAll)
// api.get('/event/:month/:year', eventController.getAfter)
// mastodon oauth auth
//api.post('/settings/getauthurl', jwt, isAuth, isAdmin, settingsController.getAuthURL)
//api.get('/settings/oauth', jwt, isAuth, isAdmin, settingsController.code)
// Handle 404
api.use(function(req, res) {
res.send('404: Page not Found', 404)
})
// Handle 500
api.use(function(error, req, res, next) {
res.send('500: Internal Server Error', 500)
})
module.exports = api

17
server/federation/ego.js Normal file
View File

@@ -0,0 +1,17 @@
const { event: Event } = require('../api/models')
const config = require('config')
module.exports = {
async boost (req, res) {
const event_id = req.body.object.match(`${config.baseurl}/federation/m/(.*)`)[1]
const event = await Event.findByPk(event_id)
await event.update({ boost: [...event.boost, req.body.actor]})
res.sendStatus(201)
},
async like (req, res) {
const event_id = req.body.object.match(`${config.baseurl}/federation/m/(.*)`)[1]
const event = await Event.findByPk(event_id)
await event.update({ likes: [...event.likes, req.body.actor]})
res.sendStatus(201)
}
}

View File

@@ -8,13 +8,12 @@ module.exports = {
async follow (req, res, body, targetOrigin, domain) {
if (typeof body.object !== 'string') return
const username = body.object.replace(`${config.baseurl}/federation/u/`, '')
console.error('someone wants to follow ' + username)
const user = await User.findOne({ where: { username }})
if (!user) {
console.error('No user found!')
res.sendStatus(404)
return
}
console.error('FOLLOWERS ', user.followers)
// check for duplicate
if (user.followers.indexOf(body.actor) === -1) {
console.error('ok this is a new follower: ', body.actor)
await user.update({ followers: [...user.followers, body.actor] })
@@ -27,8 +26,8 @@ module.exports = {
'actor': `${config.baseurl}/federation/u/${user.username}`,
'object': body,
}
return Helpers.signAndSend(message, user, body.actor)
Helpers.signAndSend(message, user, body.actor)
res.sendStatus(200)
},
// unfollow request from fediverse
unfollow () {

View File

@@ -55,6 +55,26 @@ const Helpers = {
body['@context'] = 'https://www.w3.org/ns/activitystreams'
Helpers.signAndSend(body, user, follower)
}
},
// TODO: cache
// user: les@mastodon.cisti.org
async getFederatedUser(address) {
address = address.trim()
let [ user, host ] = address.split('@')
const url = `https://${host}/.well-known/webfinger?resource=acct:${user}@${host}`
console.error('get federated user at => ', address, url)
const user = await fetch(url, { headers: {'Accept': 'application/jrd+json, application/json'} })
return user
},
async verifySignature(req, res) {
console.error(req.headers['signature'])
// https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/
const signature_header = req.headers['signature'].split(',')
.map(pair => pair.split('='))
console.error(signature_header)
return true
}
}

View File

@@ -6,6 +6,8 @@ const Follows = require('./follows')
const Users = require('./users')
const { event: Event, user: User } = require('../api/models')
const Comments = require('./comments')
const Helpers = require('./helpers')
const Ego = require('./ego')
/**
* Federation is calling!
@@ -28,6 +30,11 @@ router.get('/m/:event_id', async (req, res) => {
// get any message coming from federation
// Federation is calling!
router.post('/u/:name/inbox', async (req, res) => {
if (!Helpers.verifySignature(req, res)) {
res.send('Request signature could not be verified', 401)
}
const b = req.body
console.error('> INBOX ', b.type, b)
const targetOrigin = new URL(b.actor).origin
@@ -49,20 +56,18 @@ router.post('/u/:name/inbox', async (req, res) => {
break
case 'Announce':
console.error('This is a boost ?')
Ego.boost(req, res)
break
case 'Note':
console.error('This is a note ! I probably should not receive this')
break
case 'Like':
console.error('This is a like!')
Ego.like(req, res)
break
case 'Delete':
console.error('Delete a comment ?!?!')
break
case 'Announce':
console.error('Boost!')
break
case 'Create':
// this is a reply
if (b.object.type === 'Note' && b.object.inReplyTo) {

View File

@@ -1,10 +1,12 @@
const express = require('express')
const router = express.Router()
const { user: User } = require('../api/models')
const cors = require('cors')
const settingsController = require('../api/controller/settings')
const config = require('config')
const version = require('../../package.json').version
router.use(cors())
router.get('/', async (req, res) => {
const ret = {
version: '1.0',

View File

@@ -1,10 +1,14 @@
const express = require('express')
const router = express.Router()
const { user: User } = require('../api/models')
const cors = require('cors')
const settingsController = require('../api/controller/settings')
const config = require('config')
const version = require('../../package.json').version
router.get('/', async (req, res) => {
console.error('ma sono dentro webfinger ?!?!')
router.use(cors())
router.get('/webfinger', async (req, res) => {
const resource = req.query.resource
if (!resource || !resource.includes('acct:')) {
return res.status(400).send('Bad request. Please make sure "acct:USER@DOMAIN" is what you are sending as the "resource" query parameter.')
@@ -26,4 +30,78 @@ router.get('/', async (req, res) => {
res.set('Content-Type', 'application/jrd+json; charset=utf-8')
res.json(ret)
})
router.get('/nodeinfo/:nodeinfo_version', async (req, res) => {
const ret = {
metadata: {
nodeDescription: 'Gancio instance',
nodeName: config.title
},
openRegistrations : settingsController.settings.allow_registration,
protocols :['activitypub'],
services: { inbound: [], outbound :["atom1.0"]},
software: {
name: 'gancio',
version
},
usage: {
localComments: 0,
localPosts:0,
users: {
total:3
}
},
version: req.params.nodeinfo_version
}
if(req.params.nodeinfo_version === '2.1') {
ret.software.repository = 'https://git.lattuga.net/cisti/gancio'
}
res.json(ret)
})
router.get('/x-nodeinfo2', async (req, res) => {
const ret = {
version: '1.0',
server: {
baseUrl: config.baseurl,
name: config.title,
software: 'Gancio',
version
},
protocols: ['activitypub'],
openRegistrations: settingsController.settings.allow_registration,
usage:{
users: {
total: 10
}
},
localPost: 3,
localComments: 0
}
res.json(ret)
})
router.get('/nodeinfo', async (req, res) => {
const ret = {
links: [
{ href: `${config.baseurl}/.well-known/nodeinfo/2.0`, rel: `http://nodeinfo.diaspora.software/ns/schema/2.0` },
{ href: `${config.baseurl}/.well-known/nodeinfo/2.1`, rel: `http://nodeinfo.diaspora.software/ns/schema/2.1` },
]
}
res.json(ret)
})
// Handle 404
router.use(function(req, res) {
res.send('404: Page not Found', 404)
})
// Handle 500
router.use(function(error, req, res, next) {
res.send('500: Internal Server Error', 500)
})
module.exports = router

View File

@@ -3,9 +3,12 @@ const path = require('path')
const express = require('express')
const consola = require('consola')
const morgan = require('morgan')
const cors = require('cors')
const { Nuxt, Builder } = require('nuxt')
const api = require('./api')
const federation = require('./federation')
const webfinger = require('./federation/webfinger')
// Import and Set Nuxt.js options
const nuxt_config = require('../nuxt.config.js')
const config = require('config')
@@ -31,12 +34,11 @@ async function start() {
app.use('/media/', express.static(config.upload_path))
// gancio standard api
app.use('/api', require('./api/index'))
app.use('/api', api)
// federation api / activitypub / webfinger / nodeinfo
app.use('/.well-known/webfinger', cors(), require('./federation/webfinger'))
app.use('/.well-known/x-nodeinfo2', cors(), require('./federation/nodeinfo'))
app.use('/federation', require('./federation'))
app.use('/.well-known', webfinger)
app.use('/federation', federation)
// Give nuxt middleware to express
app.use(nuxt.render)