diff --git a/index.js b/index.js
index ca368de..adc2af9 100644
--- a/index.js
+++ b/index.js
@@ -8,21 +8,11 @@ const https = require('https')
const routes = require('./routes')
const pub = require('./pub')
-const config = require('./config.json')
-const { DOMAIN, KEY_PATH, CERT_PATH, PORT, PORT_HTTPS } = config
+const store = require('./store')
+const { DOMAIN, KEY_PATH, CERT_PATH, PORT, PORT_HTTPS, DB_URL, DB_NAME } = require('./config.json')
const app = express()
-// Connection URL
-const url = 'mongodb://localhost:27017'
-
-const store = require('./store')
-// Database Name
-const dbName = 'test'
-
-// Create a new MongoClient
-const client = new MongoClient(url, { useUnifiedTopology: true })
-
-let db
+const client = new MongoClient(DB_URL, { useUnifiedTopology: true, useNewUrlParser: true })
const sslOptions = {
key: fs.readFileSync(path.join(__dirname, KEY_PATH)),
@@ -50,18 +40,22 @@ app.get('/', (req, res) => res.send('Hello World!'))
// admin page
app.use('/.well-known/webfinger', cors(), routes.webfinger)
app.use('/u', cors(), routes.user)
-app.use('/m', cors(), routes.message)
+app.use('/o', cors(), routes.object)
+
+// admin page
+app.use('/.well-known/webfinger', cors(), routes.webfinger)
+app.use('/u', cors(), routes.user)
+app.use('/o', cors(), routes.object)
+app.use('/s', cors(), routes.stream)
app.use('/u/:name/inbox', routes.inbox)
app.use('/u/:name/outbox', routes.outbox)
app.use('/admin', express.static('public/admin'))
app.use('/f', express.static('public/files'))
-// app.use('/hubs', express.static('../hubs/dist'));
-// Use connect method to connect to the Server
client.connect({ useNewUrlParser: true })
.then(() => {
- console.log('Connected successfully to server')
- db = client.db(dbName)
+ console.log('Connected successfully to db')
+ const db = client.db(DB_NAME)
app.set('db', db)
store.connection.setDb(db)
return pub.actor.createLocalActor('dummy', 'Person')
diff --git a/net/security.js b/net/security.js
index a20b109..7f79093 100644
--- a/net/security.js
+++ b/net/security.js
@@ -3,13 +3,25 @@ const httpSignature = require('http-signature')
const pub = require('../pub')
// http communication middleware
module.exports = {
+ auth,
verifySignature
}
+function auth (req, res, next) {
+ // no client-to-server support at this time
+ if (req.app.get('env') !== 'development') {
+ return res.status(405).send()
+ }
+ next()
+}
+
async function verifySignature (req, res, next) {
if (!req.get('authorization')) {
// support for apps not using signature extension to ActivityPub
- // TODO check if actor has a publicKey and require signature
+ const actor = await pub.object.resolveObject(pub.utils.actorFromActivity(req.body))
+ if (actor.publicKey && req.app.get('env') !== 'development') {
+ return res.status(400).send('Missing http signature')
+ }
return next()
}
// workaround for node-http-signature#87
diff --git a/pub/activity.js b/pub/activity.js
index b1dda40..88434c1 100644
--- a/pub/activity.js
+++ b/pub/activity.js
@@ -14,7 +14,7 @@ function build (type, actorId, object, to, cc, etc) {
const oid = new ObjectId()
const act = Object.assign({
// _id: oid,
- id: pubUtils.objectIdToIRI(oid),
+ id: pubUtils.actvityIdToIRI(oid),
type,
actor: actorId,
object,
diff --git a/pub/utils.js b/pub/utils.js
index cddcb83..4545f2f 100644
--- a/pub/utils.js
+++ b/pub/utils.js
@@ -3,6 +3,7 @@ const config = require('../config.json')
const pubConsts = require('./consts')
module.exports = {
+ actvityIdToIRI,
usernameToIRI,
toJSONLD,
arrayToCollection,
@@ -47,6 +48,13 @@ function objectIdToIRI (oid) {
return `https://${config.DOMAIN}/o/${oid}`
}
+function actvityIdToIRI (oid) {
+ if (oid.toHexString) {
+ oid = oid.toHexString()
+ }
+ return `https://${config.DOMAIN}/s/${oid}`
+}
+
function validateObject (object) {
if (object && object.id) {
// object['@context'] = object['@context'] || pubConsts.ASContext
diff --git a/public/admin/index.html b/public/admin/index.html
deleted file mode 100644
index ea66339..0000000
--- a/public/admin/index.html
+++ /dev/null
@@ -1,108 +0,0 @@
-
-
-
-
- Admin Page
-
-
-
-Admin Page
-Create Account
-Create a new ActivityPub Actor (account). Requires the admin user/pass on submit.
-
-
-
-
-
-Send Message To Followers
-Enter an account name, its API key, and a message. This message will send to all its followers.
-
-
-
-
-
a long hex key you got when you created your account
-
-
-
-
-
-
-
-
-
-
diff --git a/routes/index.js b/routes/index.js
index 58e5eb9..b29d088 100644
--- a/routes/index.js
+++ b/routes/index.js
@@ -1,9 +1,10 @@
'use strict'
module.exports = {
- user: require('./user'),
- message: require('./message'),
inbox: require('./inbox'),
+ object: require('./object'),
outbox: require('./outbox'),
+ stream: require('./stream'),
+ user: require('./user'),
webfinger: require('./webfinger')
}
diff --git a/routes/message.js b/routes/message.js
deleted file mode 100644
index d21fb5d..0000000
--- a/routes/message.js
+++ /dev/null
@@ -1,20 +0,0 @@
-'use strict'
-const express = require('express')
-const router = express.Router()
-
-router.get('/:guid', function (req, res) {
- const guid = req.params.guid
- if (!guid) {
- return res.status(400).send('Bad request.')
- } else {
- const db = req.app.get('db')
- const result = db.prepare('select message from messages where guid = ?').get(guid)
- if (result === undefined) {
- return res.status(404).send(`No record found for ${guid}.`)
- } else {
- res.json(JSON.parse(result.message))
- }
- }
-})
-
-module.exports = router
diff --git a/routes/object.js b/routes/object.js
new file mode 100644
index 0000000..8b86657
--- /dev/null
+++ b/routes/object.js
@@ -0,0 +1,26 @@
+'use strict'
+const express = require('express')
+const router = express.Router()
+const store = require('../store')
+const pub = require('../pub')
+
+router.get('/:name', function (req, res) {
+ const name = req.params.name
+ if (!name) {
+ return res.status(400).send('Bad request.')
+ } else {
+ store.object.get(pub.utils.objectIdToIRI(name))
+ .then(obj => {
+ if (obj) {
+ return res.json(pub.utils.toJSONLD(obj))
+ }
+ return res.status(404).send('Object not found')
+ })
+ .catch(err => {
+ console.log(err)
+ res.status(500).send()
+ })
+ }
+})
+
+module.exports = router
diff --git a/routes/outbox.js b/routes/outbox.js
index 909e875..04298dc 100644
--- a/routes/outbox.js
+++ b/routes/outbox.js
@@ -4,7 +4,7 @@ const net = require('../net')
const pub = require('../pub')
const store = require('../store')
-router.post('/', net.validators.outboxActivity, function (req, res) {
+router.post('/', net.security.auth, net.validators.outboxActivity, function (req, res) {
store.actor.get(pub.utils.usernameToIRI(req.user), true)
.then(actor => {
return pub.activity.addToOutbox(actor, req.body)
diff --git a/routes/stream.js b/routes/stream.js
new file mode 100644
index 0000000..a7cb6e2
--- /dev/null
+++ b/routes/stream.js
@@ -0,0 +1,26 @@
+'use strict'
+const express = require('express')
+const router = express.Router()
+const store = require('../store')
+const pub = require('../pub')
+
+router.get('/:name', function (req, res) {
+ const name = req.params.name
+ if (!name) {
+ return res.status(400).send('Bad request.')
+ } else {
+ store.stream.get(pub.utils.actvityIdToIRI(name))
+ .then(obj => {
+ if (obj) {
+ return res.json(pub.utils.toJSONLD(obj))
+ }
+ return res.status(404).send('Activity not found')
+ })
+ .catch(err => {
+ console.log(err)
+ res.status(500).send()
+ })
+ }
+})
+
+module.exports = router
diff --git a/routes/user.js b/routes/user.js
index de37014..71299c1 100644
--- a/routes/user.js
+++ b/routes/user.js
@@ -8,8 +8,7 @@ router.get('/:name', async function (req, res) {
if (!name) {
return res.status(400).send('Bad request.')
} else {
- const db = req.app.get('db')
- const user = await pub.actor.getOrCreateActor(name, db)
+ const user = await pub.actor.getOrCreateActor(name)
if (user) {
return res.json(pub.utils.toJSONLD(user))
}
diff --git a/store/stream.js b/store/stream.js
index f7175fd..c603544 100644
--- a/store/stream.js
+++ b/store/stream.js
@@ -1,21 +1,23 @@
'use strict'
const connection = require('./connection')
module.exports = {
- // get,
+ get,
save
}
-// function get (id, type, db) {
-// return db.collection('objects')
-// .find({ id: id })
-// .limit(1)
-// .project({ _id: 0, _meta: 0 })
-// .next()
-// }
+function get (id) {
+ const db = connection.getDb()
+ return db.collection('streams')
+ .find({ id: id })
+ .limit(1)
+ .project({ _id: 0, _meta: 0 })
+ .next()
+}
async function save (activity) {
const db = connection.getDb()
const q = { id: activity.id }
+ // activities may be duplicated for multiple local targets
if (activity._meta && activity._meta._target) {
q['_meta._target'] = activity._meta._target
}