setup db utils in store directory, move getOrCreateActor and break out getActor for actions which require and existing actor (e.g. signature validation)

This commit is contained in:
Will Murphy 2019-09-21 16:53:55 -05:00
parent 8039b04799
commit a43419f9ff
9 changed files with 53 additions and 65 deletions

View file

@ -1,5 +0,0 @@
'use strict'
module.exports = {
}

View file

@ -17,7 +17,7 @@ const app = express();
// Connection URL // Connection URL
const url = 'mongodb://localhost:27017'; const url = 'mongodb://localhost:27017';
const dbSetup = require('./db/setup'); const dbSetup = require('./store/setup');
// Database Name // Database Name
const dbName = 'test'; const dbName = 'test';

View file

@ -3,6 +3,7 @@ const router = express.Router()
const utils = require('../utils') const utils = require('../utils')
const pub = require('../pub') const pub = require('../pub')
const net = require('../net') const net = require('../net')
const store = require('../store')
const request = require('request-promise-native') const request = require('request-promise-native')
const httpSignature = require('http-signature') const httpSignature = require('http-signature')
const {ObjectId} = require('mongodb') const {ObjectId} = require('mongodb')
@ -20,7 +21,7 @@ router.post('/', net.validators.activity, function (req, res) {
sigHead = httpSignature.parse(req, {clockSkew: 3000}) sigHead = httpSignature.parse(req, {clockSkew: 3000})
req.url = tempUrl req.url = tempUrl
// TODO - real key lookup with remote fetch // TODO - real key lookup with remote fetch
utils.getOrCreateActor(sigHead.keyId.replace(/.*\//, ''), db) store.actor.getActor(sigHead.keyId.replace(/.*\//, ''), db)
.then(user => { .then(user => {
const valid = httpSignature.verifySignature(sigHead, user.publicKey.publicKeyPem) const valid = httpSignature.verifySignature(sigHead, user.publicKey.publicKeyPem)
console.log('key validation', valid) console.log('key validation', valid)
@ -31,7 +32,7 @@ router.post('/', net.validators.activity, function (req, res) {
req.body._meta._target = req.body.object.id req.body._meta._target = req.body.object.id
// send acceptance reply // send acceptance reply
Promise.all([ Promise.all([
utils.getOrCreateActor(req.user, db, true), store.actor.getOrCreateActor(req.user, db, true),
request({ request({
url: pub.utils.actorFromActivity(req.body), url: pub.utils.actorFromActivity(req.body),
headers: {Accept: 'application/activity+json'}, headers: {Accept: 'application/activity+json'},

View file

@ -1,8 +1,9 @@
'use strict'; 'use strict'
const express = require('express'), const express = require('express')
router = express.Router(); const router = express.Router()
const utils = require('../utils') const utils = require('../utils')
const pub = require('../pub') const pub = require('../pub')
const store = require('../store')
router.get('/:name', async function (req, res) { router.get('/:name', async function (req, res) {
let name = req.params.name; let name = req.params.name;
@ -11,7 +12,7 @@ router.get('/:name', async function (req, res) {
} }
else { else {
let db = req.app.get('db') let db = req.app.get('db')
const user = await utils.getOrCreateActor(name, db) const user = await store.actor.getOrCreateActor(name, db)
if (user) { if (user) {
return res.json(pub.utils.toJSONLD(user)) return res.json(pub.utils.toJSONLD(user))
} }

View file

@ -1,7 +1,8 @@
'use strict'; 'use strict'
const express = require('express'), const express = require('express')
router = express.Router(); const router = express.Router()
const utils = require('../utils')
const store = require('../store')
const acctReg = /acct:[@~]?([^@]+)@?(.*)/ const acctReg = /acct:[@~]?([^@]+)@?(.*)/
router.get('/', function (req, res) { router.get('/', function (req, res) {
let resource = req.query.resource; let resource = req.query.resource;
@ -13,7 +14,7 @@ router.get('/', function (req, res) {
return res.status(400).send('Requested user is not from this domain') return res.status(400).send('Requested user is not from this domain')
} }
let db = req.app.get('db'); let db = req.app.get('db');
utils.getOrCreateActor(acct[1], db) store.actor.getOrCreateActor(acct[1], db)
.then(result => { .then(result => {
if (!result) { if (!result) {
return res.status(404).send(`${acct[1]}@${acct[2]} not found`) return res.status(404).send(`${acct[1]}@${acct[2]} not found`)

34
store/actor.js Normal file
View file

@ -0,0 +1,34 @@
'use strict'
const pub = require('../pub')
module.exports = {
getActor,
getOrCreateActor,
}
const actorProj = {_id: 0, _meta: 0}
const metaActorProj = {_id: 0}
function getActor (preferredUsername, db, includeMeta) {
return db.collection('objects')
.find({id: pub.utils.usernameToIRI(preferredUsername)})
.limit(1)
// strict comparison as we don't want to return private keys on accident
.project(includeMeta === true ? metaActorProj : actorProj)
.next()
}
async function getOrCreateActor(preferredUsername, db, includeMeta) {
let user = await getActor(preferredUsername, db, includeMeta)
if (user) {
return user
}
// auto create groups whenever an unknown actor is referenced
user = await pub.actor.createLocalActor(preferredUsername, 'Group')
await db.collection('objects').insertOne(user)
// only executed on success
delete user._id
if (includeMeta !== true) {
delete user._meta
}
return user
}

View file

@ -1,49 +1,5 @@
const crypto = require('crypto') 'use strict'
const {promisify} = require('util') // misc utilities
const utils = require('../utils') module.exports = {
const config = require('../config.json') consts: require('./consts')
const db = require('../db')
const pub = require('../pub')
module.exports.consts = require('./consts')
function isObject(value) {
return value && typeof value === 'object' && value.constructor === Object
} }
// outtermost closure starts the recursion counter
// const level = 0;
function traverseObject(obj, f) {
const traverse = o => {
// const level = level + 1
// if (level > 5) return o
traverseObject(o, f)
}
if (!isObject(obj)) return obj;
Object.keys(obj).forEach(traverse)
return f(obj);
}
const actorProj = {_id: 0, _meta: 0}
const metaActorProj = {_id: 0}
async function getOrCreateActor(preferredUsername, db, includeMeta) {
const id = pub.utils.usernameToIRI(preferredUsername)
let user = await db.collection('objects')
.find({id: id})
.limit(1)
// strict comparison as we don't want to return private keys on accident
.project(includeMeta === true ? metaActorProj : actorProj)
.next()
if (user) {
return user
}
// auto create groups whenever an unknown actor is referenced
user = await pub.actor.createLocalActor(preferredUsername, 'Group')
await db.collection('objects').insertOne(user)
// only executed on success
delete user._id
if (includeMeta !== true) {
delete user._meta
}
return user
}
module.exports.getOrCreateActor = getOrCreateActor