From ea8cbb43c3879bcc2ea0ea95c53b33117b08b5bd Mon Sep 17 00:00:00 2001 From: DanielMowitz Date: Tue, 24 Sep 2019 15:08:03 +0200 Subject: [PATCH] Webfinger detection now works and incoming Activities are saved to the ssb log. --- config.json | 6 ++-- index.js | 13 ++++++- package.json | 3 +- save_to_ssb.js | 38 ++++++++++---------- server.js | 96 ++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 117 insertions(+), 39 deletions(-) diff --git a/config.json b/config.json index dd32768..e480b76 100644 --- a/config.json +++ b/config.json @@ -1,4 +1,4 @@ { - "DOMAIN" : "", - "PORT" : 3000 -} + "DOMAIN": "", + "PORT": 3000 +} \ No newline at end of file diff --git a/index.js b/index.js index 6bb4498..5386512 100644 --- a/index.js +++ b/index.js @@ -2,8 +2,16 @@ const config = require('./config'); const server = require('./server'); const express = require('express'); const app = express(); +const bodyParser = require('body-parser'); const http = require('http'); +var options = { //todo: maybe be more specific here + type: "application/*" +}; + +app.use(bodyParser.raw(options)); +app.use(bodyParser.urlencoded({extended: true})); + app.set('domain', config.DOMAIN); app.set('port', process.env.PORT || config.PORT || 3000); app.set('port-https', process.env.PORT_HTTPS || 8443); @@ -12,7 +20,10 @@ app.get('/', (req, res) => res.send('Hello World!')); app.get('/u/:name', server.get_user); app.get('/.well-known/webfinger', server.get_webfinger); app.get('/inbox', (req, res) => res.send('Here lies the inbox')); +app.get('/users', server.get_users); -http.createServer(app).listen(app.get('port'), function(){ +app.post('/inbox', server.post_inbox); + +http.createServer(app).listen(app.get('port'), function () { console.log('Express server listening on port ' + app.get('port')); }); diff --git a/package.json b/package.json index 177504a..601e755 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,12 @@ "version": "1.0.0", "dependencies": { "express": "latest", + "http": "latest", "node-fetch": "latest", "pull-stream": "latest", "ssb-client": "latest", "ssb-friends": "latest", "stream-to-pull-stream": "latest", - "http": "latest" + "body-parser": "latest" } } diff --git a/save_to_ssb.js b/save_to_ssb.js index 271da1a..724df32 100644 --- a/save_to_ssb.js +++ b/save_to_ssb.js @@ -3,16 +3,16 @@ const pull = require('pull-stream'); const allowed_message_types = [ //valid activitypub message types 'create', - 'update', - 'delete', - 'follow', - 'update', - 'reject', - 'add', - 'remove', - 'like', - 'announce', - 'undo' + 'update', + 'delete', + 'follow', + 'update', + 'reject', + 'add', + 'remove', + 'like', + 'announce', + 'undo' ]; async function createBlobObject(type, objectId, otherData) { @@ -99,16 +99,16 @@ async function get_last_by_activity_id(id) { if (err) reject(err); for (let i in array) { if (array[i].value.content.type.length > 3 && - array[i].value.content.type.substr(0,3) === 'ap-' && + array[i].value.content.type.substr(0, 3) === 'ap-' && allowed_message_types.indexOf(array[i].value.content.type.substr(3)) >= 0) { if (array[i].value.content.id === id) { last = array[i]; } } } - if (last){ + if (last) { resolve(last); - }else { + } else { reject('no activity found'); } @@ -199,7 +199,7 @@ function add_ssb_message(type, id, actor, summary, object, origin = null, target } -async function get_json_from_blob(blob_id){ +async function get_json_from_blob(blob_id) { /* * Gets the Object with the specified id from the @@ -225,7 +225,7 @@ async function get_json_from_blob(blob_id){ return await out; } -async function restore_ssb_message(id){ +async function restore_ssb_message(id) { /* * Gets the Message with the specified id from the @@ -246,12 +246,12 @@ async function restore_ssb_message(id){ msg.type = msg.type.substr(3); delete msg.actor.otherData; - for (let key in actor_data){ + for (let key in actor_data) { msg.actor[key] = actor_data[key]; } delete msg.object.otherData; - for (let key in object_data){ + for (let key in object_data) { msg.object[key] = object_data[key]; } @@ -267,8 +267,8 @@ async function restore_ssb_message(id){ } module.exports = { - save : (message) => { - if (message["@context"] === "https://www.w3.org/ns/activitystreams") { //todo: should be @context + save: (message) => { + if (message["@context"] === "https://www.w3.org/ns/activitystreams") { add_ssb_message( message.type, diff --git a/server.js b/server.js index 183cd7e..763aea3 100644 --- a/server.js +++ b/server.js @@ -1,11 +1,29 @@ const config = require('./config'); const ssbClient = require('ssb-client'); const pull = require('pull-stream'); +const ssb_bridge = require('./save_to_ssb'); DOMAIN = config.DOMAIN; -async function check_if_in_friends(name){ +let chars_to_encode = "_!*'();:@&=+$,/?#[]"; // basically anything covered by %-encoding plus underscore + +function encode_webfinger_name(name) { + for (let i in chars_to_encode) { + name = name.replace(chars_to_encode[i], "_" + chars_to_encode[i].charCodeAt(0).toString(16) + "_"); + } + return name; +} + +function decode_webfinger_name(name) { + for (let i in chars_to_encode) { + name = name.replace("_" + chars_to_encode[i].charCodeAt(0).toString(16) + "_", chars_to_encode[i]); + } + return name +} + +async function check_if_in_friends(name) { let result = false; + name = decode_webfinger_name(name); let out = new Promise((resolve, reject) => { ssbClient((err, sbot) => { if (err) reject(err); @@ -28,14 +46,31 @@ async function check_if_in_friends(name){ return await out; } +async function get_friends() { + let out = new Promise((resolve, reject) => { + ssbClient((err, sbot) => { + if (err) reject(err); + + pull( + sbot.friends.createFriendStream(), + pull.collect((err, array) => { + sbot.close(); + resolve(array); + }) + ); + }); + }); + return await out; +} + function get_webfinger(req, res) { let 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.'); - } - else { - let name = resource.replace('acct:',''); - name = name.substr(0,name.indexOf('@')); + } else { + let name = resource.replace('acct:', ''); + name = name.substr(0, name.indexOf('@')); + let encoded_name = encodeURIComponent(name); let p = check_if_in_friends(name + "=.ed25519"); @@ -43,18 +78,18 @@ function get_webfinger(req, res) { if (result) { res.json( { - 'subject': `acct:${name}@${DOMAIN}`, + 'subject': `acct:${encoded_name}@${DOMAIN}`, links: [ { rel: 'self', type: 'application/activity+json', - href: `https://${DOMAIN}/u/${name}` + href: `https://${DOMAIN}/u/${encoded_name}` } ], } ); } else { - return res.status(404).send(`No record found for ${name}.`); + return res.status(404).send(`No record found for ${encoded_name}.`); } }).catch((err) => { return res.status(500).send(`An error occured: ${err}.`); @@ -62,12 +97,11 @@ function get_webfinger(req, res) { } } -function get_user(req, res){ +function get_user(req, res) { let name = req.params.name; if (!name) { return res.status(400).send('Bad request.'); - } - else { + } else { let p = check_if_in_friends(name + "=.ed25519"); @@ -83,8 +117,9 @@ function get_user(req, res){ id: `https://${DOMAIN}/u/${name}`, type: 'Person', - preferredUsername: 'TESTPERSON PLS CHANGE', //todo: read from latest about message - inbox: `https://${DOMAIN}/u/${name}/inbox`, + preferredUsername: 'TESTPERSON', //todo: read from latest about message + // inbox: `https://${DOMAIN}/u/${name}/inbox`, + inbox: `https://${DOMAIN}/inbox`, publicKey: { id: `https://${DOMAIN}/u/${name}#main-key`, @@ -101,7 +136,7 @@ function get_user(req, res){ } } ); - }else { + } else { return res.status(404).send(`No record found for ${name}.`); } }).catch((err) => { @@ -110,7 +145,38 @@ function get_user(req, res){ } } +function get_users(req, res) { + let p = get_friends(); + + p.then((result) => { + if (result) { + let out = {}; + for (let i in result) { + out[i] = encode_webfinger_name(result[i].substr(1).replace("=.ed25519", "")); + } + res.json(out); + } else { + return res.status(404).send(`No record found for ${name}.`); + } + }).catch((err) => { + return res.status(500).send(`An error occured: ${err}.`); + }) +} + +function post_inbox(req, res) { + console.log("Saved activity to ssb log."); + try { + let in_activity = JSON.parse(req.body.toString()); + ssb_bridge.save(in_activity); + } catch (e) { + + } + return res.status(200).send('ayy\n'); +} + module.exports = { get_user, - get_webfinger + get_webfinger, + get_users, + post_inbox, }; \ No newline at end of file