diff --git a/backend/package.json b/backend/package.json index 6bd5db20f..46c228485 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,7 +4,7 @@ "description": "GraphQL Backend for Human Connection", "main": "src/index.js", "config": { - "no_auth": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 PERMISSIONS=disabled" + "no_auth": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 DISABLED_MIDDLEWARES=permissions" }, "scripts": { "build": "babel src/ -d dist/ --copy-files", @@ -15,7 +15,7 @@ "test": "nyc --reporter=text-lcov yarn test:jest", "test:cypress": "run-p --race test:before:*", "test:before:server": "cross-env CLIENT_URI=http://localhost:4123 GRAPHQL_URI=http://localhost:4123 GRAPHQL_PORT=4123 babel-node src/ 2> /dev/null", - "test:before:seeder": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 PERMISSIONS=disabled babel-node src/ 2> /dev/null", + "test:before:seeder": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 DISABLED_MIDDLEWARES=permissions,activityPub babel-node src/ 2> /dev/null", "test:jest:cmd": "wait-on tcp:4001 tcp:4123 && jest --forceExit --detectOpenHandles --runInBand", "test:cucumber:cmd": "wait-on tcp:4001 tcp:4123 && cucumber-js --require-module @babel/register --exit test/", "test:jest:cmd:debug": "wait-on tcp:4001 tcp:4123 && node --inspect-brk ./node_modules/.bin/jest -i --forceExit --detectOpenHandles --runInBand", diff --git a/backend/src/activitypub/ActivityPub.js b/backend/src/activitypub/ActivityPub.js index 6c3fb4082..b89bc16da 100644 --- a/backend/src/activitypub/ActivityPub.js +++ b/backend/src/activitypub/ActivityPub.js @@ -22,21 +22,19 @@ let activityPub = null export { activityPub } export default class ActivityPub { - constructor (host, uri) { - this.host = host - this.dataSource = new NitroDataSource(uri) + constructor (activityPubEndpointUri, internalGraphQlUri) { + this.endpoint = activityPubEndpointUri + this.dataSource = new NitroDataSource(internalGraphQlUri) this.collections = new Collections(this.dataSource) } static init (server) { if (!activityPub) { dotenv.config() - const url = new URL(process.env.CLIENT_URI) - activityPub = new ActivityPub(url.host || 'localhost:4000', url.origin) + activityPub = new ActivityPub(process.env.CLIENT_URI || 'http://localhost:3000', process.env.GRAPHQL_URI || 'http://localhost:4000') // integrate into running graphql express server server.express.set('ap', activityPub) - server.express.set('port', url.port) server.express.use(router) console.log('-> ActivityPub middleware added to the graphql express server') } else { diff --git a/backend/src/activitypub/routes/webFinger.js b/backend/src/activitypub/routes/webFinger.js index ad1c806ad..8def32328 100644 --- a/backend/src/activitypub/routes/webFinger.js +++ b/backend/src/activitypub/routes/webFinger.js @@ -12,15 +12,20 @@ router.get('/', async function (req, res) { const nameAndDomain = resource.replace('acct:', '') const name = nameAndDomain.split('@')[0] - const result = await req.app.get('ap').dataSource.client.query({ - query: gql` + let result + try { + result = await req.app.get('ap').dataSource.client.query({ + query: gql` query { User(slug: "${name}") { slug } } ` - }) + }) + } catch (error) { + return res.status(500).json({ error }) + } if (result.data && result.data.User.length > 0) { const webFinger = createWebFinger(name) diff --git a/backend/src/activitypub/utils/activity.js b/backend/src/activitypub/utils/activity.js index a8c525302..57b6dfb83 100644 --- a/backend/src/activitypub/utils/activity.js +++ b/backend/src/activitypub/utils/activity.js @@ -11,14 +11,14 @@ export function createNoteObject (text, name, id, published) { return { '@context': 'https://www.w3.org/ns/activitystreams', - 'id': `https://${activityPub.host}/activitypub/users/${name}/status/${createUuid}`, + 'id': `${activityPub.endpoint}/activitypub/users/${name}/status/${createUuid}`, 'type': 'Create', - 'actor': `https://${activityPub.host}/activitypub/users/${name}`, + 'actor': `${activityPub.endpoint}/activitypub/users/${name}`, 'object': { - 'id': `https://${activityPub.host}/activitypub/users/${name}/status/${id}`, + 'id': `${activityPub.endpoint}/activitypub/users/${name}/status/${id}`, 'type': 'Note', 'published': published, - 'attributedTo': `https://${activityPub.host}/activitypub/users/${name}`, + 'attributedTo': `${activityPub.endpoint}/activitypub/users/${name}`, 'content': text, 'to': 'https://www.w3.org/ns/activitystreams#Public' } @@ -64,8 +64,8 @@ export async function getActorId (name) { export function sendAcceptActivity (theBody, name, targetDomain, url) { as.accept() - .id(`https://${activityPub.host}/activitypub/users/${name}/status/` + crypto.randomBytes(16).toString('hex')) - .actor(`https://${activityPub.host}/activitypub/users/${name}`) + .id(`${activityPub.endpoint}/activitypub/users/${name}/status/` + crypto.randomBytes(16).toString('hex')) + .actor(`${activityPub.endpoint}/activitypub/users/${name}`) .object(theBody) .prettyWrite((err, doc) => { if (!err) { @@ -79,8 +79,8 @@ export function sendAcceptActivity (theBody, name, targetDomain, url) { export function sendRejectActivity (theBody, name, targetDomain, url) { as.reject() - .id(`https://${activityPub.host}/activitypub/users/${name}/status/` + crypto.randomBytes(16).toString('hex')) - .actor(`https://${activityPub.host}/activitypub/users/${name}`) + .id(`${activityPub.endpoint}/activitypub/users/${name}/status/` + crypto.randomBytes(16).toString('hex')) + .actor(`${activityPub.endpoint}/activitypub/users/${name}`) .object(theBody) .prettyWrite((err, doc) => { if (!err) { diff --git a/backend/src/activitypub/utils/actor.js b/backend/src/activitypub/utils/actor.js index 0a3884023..27612517b 100644 --- a/backend/src/activitypub/utils/actor.js +++ b/backend/src/activitypub/utils/actor.js @@ -6,34 +6,35 @@ export function createActor (name, pubkey) { 'https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1' ], - 'id': `https://${activityPub.host}/activitypub/users/${name}`, + 'id': `${activityPub.endpoint}/activitypub/users/${name}`, 'type': 'Person', 'preferredUsername': `${name}`, 'name': `${name}`, - 'following': `https://${activityPub.host}/activitypub/users/${name}/following`, - 'followers': `https://${activityPub.host}/activitypub/users/${name}/followers`, - 'inbox': `https://${activityPub.host}/activitypub/users/${name}/inbox`, - 'outbox': `https://${activityPub.host}/activitypub/users/${name}/outbox`, - 'url': `https://${activityPub.host}/activitypub/@${name}`, + 'following': `${activityPub.endpoint}/activitypub/users/${name}/following`, + 'followers': `${activityPub.endpoint}/activitypub/users/${name}/followers`, + 'inbox': `${activityPub.endpoint}/activitypub/users/${name}/inbox`, + 'outbox': `${activityPub.endpoint}/activitypub/users/${name}/outbox`, + 'url': `${activityPub.endpoint}/activitypub/@${name}`, 'endpoints': { - 'sharedInbox': `https://${activityPub.host}/activitypub/inbox` + 'sharedInbox': `${activityPub.endpoint}/activitypub/inbox` }, 'publicKey': { - 'id': `https://${activityPub.host}/activitypub/users/${name}#main-key`, - 'owner': `https://${activityPub.host}/activitypub/users/${name}`, + 'id': `${activityPub.endpoint}/activitypub/users/${name}#main-key`, + 'owner': `${activityPub.endpoint}/activitypub/users/${name}`, 'publicKeyPem': pubkey } } } export function createWebFinger (name) { + const { host } = new URL(activityPub.endpoint) return { - 'subject': `acct:${name}@${activityPub.host}`, + 'subject': `acct:${name}@${host}`, 'links': [ { 'rel': 'self', 'type': 'application/activity+json', - 'href': `https://${activityPub.host}/activitypub/users/${name}` + 'href': `${activityPub.endpoint}/activitypub/users/${name}` } ] } diff --git a/backend/src/activitypub/utils/collection.js b/backend/src/activitypub/utils/collection.js index 61670bb47..e3a63c74d 100644 --- a/backend/src/activitypub/utils/collection.js +++ b/backend/src/activitypub/utils/collection.js @@ -5,10 +5,10 @@ const debug = require('debug')('ea:utils:collections') export function createOrderedCollection (name, collectionName) { return { '@context': 'https://www.w3.org/ns/activitystreams', - 'id': `https://${activityPub.host}/activitypub/users/${name}/${collectionName}`, + 'id': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`, 'summary': `${name}s ${collectionName} collection`, 'type': 'OrderedCollection', - 'first': `https://${activityPub.host}/activitypub/users/${name}/${collectionName}?page=true`, + 'first': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`, 'totalItems': 0 } } @@ -16,11 +16,11 @@ export function createOrderedCollection (name, collectionName) { export function createOrderedCollectionPage (name, collectionName) { return { '@context': 'https://www.w3.org/ns/activitystreams', - 'id': `https://${activityPub.host}/activitypub/users/${name}/${collectionName}?page=true`, + 'id': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}?page=true`, 'summary': `${name}s ${collectionName} collection`, 'type': 'OrderedCollectionPage', 'totalItems': 0, - 'partOf': `https://${activityPub.host}/activitypub/users/${name}/${collectionName}`, + 'partOf': `${activityPub.endpoint}/activitypub/users/${name}/${collectionName}`, 'orderedItems': [] } } diff --git a/backend/src/activitypub/utils/index.js b/backend/src/activitypub/utils/index.js index 4ae2b073f..e6853cecb 100644 --- a/backend/src/activitypub/utils/index.js +++ b/backend/src/activitypub/utils/index.js @@ -20,8 +20,8 @@ export function extractIdFromActivityId (uri) { return splitted[splitted.indexOf('status') + 1] } -export function constructIdFromName (name, fromDomain = activityPub.host) { - return `http://${fromDomain}/activitypub/users/${name}` +export function constructIdFromName (name, fromDomain = activityPub.endpoint) { + return `${fromDomain}/activitypub/users/${name}` } export function extractDomainFromUrl (url) { @@ -76,7 +76,7 @@ export function signAndSend (activity, fromName, targetDomain, url) { 'Host': targetDomain, 'Date': date, 'Signature': createSignature({ privateKey, - keyId: `http://${activityPub.host}/activitypub/users/${fromName}#main-key`, + keyId: `${activityPub.endpoint}/activitypub/users/${fromName}#main-key`, url, headers: { 'Host': targetDomain, diff --git a/backend/src/middleware/index.js b/backend/src/middleware/index.js index 57dd82025..8f86a88e6 100644 --- a/backend/src/middleware/index.js +++ b/backend/src/middleware/index.js @@ -27,9 +27,11 @@ export default schema => { // add permisions middleware at the first position (unless we're seeding) // NOTE: DO NOT SET THE PERMISSION FLAT YOUR SELF - if (process.env.PERMISSIONS !== 'disabled' && process.env.NODE_ENV !== 'production') { - middleware.unshift(activityPubMiddleware) - middleware.unshift(permissionsMiddleware.generate(schema)) + if (process.env.NODE_ENV !== 'production') { + const DISABLED_MIDDLEWARES = process.env.DISABLED_MIDDLEWARES || '' + const disabled = DISABLED_MIDDLEWARES.split(',') + if (!disabled.includes('activityPub')) middleware.unshift(activityPubMiddleware) + if (!disabled.includes('permissions')) middleware.unshift(permissionsMiddleware.generate(schema)) } return middleware } diff --git a/backend/test/features/activity-delete.feature b/backend/test/features/activity-delete.feature index f5e269cce..76c734952 100644 --- a/backend/test/features/activity-delete.feature +++ b/backend/test/features/activity-delete.feature @@ -29,7 +29,7 @@ Feature: Delete an object """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/karl-heinz/status/a4DJ2afdg323v32641vna42lkj685kasd2", + "id": "http://localhost:4123/activitypub/users/karl-heinz/status/a4DJ2afdg323v32641vna42lkj685kasd2", "type": "Delete", "object": { "id": "https://aronda.org/activitypub/users/bernd-das-brot/status/kljsdfg9843jknsdf234", diff --git a/backend/test/features/activity-follow.feature b/backend/test/features/activity-follow.feature index 6634a342b..3cfe73340 100644 --- a/backend/test/features/activity-follow.feature +++ b/backend/test/features/activity-follow.feature @@ -15,7 +15,7 @@ Feature: Follow a user """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83", + "id": "http://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83", "type": "Follow", "actor": "http://localhost:4123/activitypub/users/stuart-little", "object": "http://localhost:4123/activitypub/users/tero-vota" @@ -32,11 +32,11 @@ Feature: Follow a user """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/tero-vota/status/a4DJ2afdg323v32641vna42lkj685kasd2", + "id": "http://localhost:4123/activitypub/users/tero-vota/status/a4DJ2afdg323v32641vna42lkj685kasd2", "type": "Undo", "actor": "http://localhost:4123/activitypub/users/tero-vota", "object": { - "id": "https://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83", + "id": "http://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83", "type": "Follow", "actor": "http://localhost:4123/activitypub/users/stuart-little", "object": "http://localhost:4123/activitypub/users/tero-vota" diff --git a/backend/test/features/activity-like.feature b/backend/test/features/activity-like.feature index 35d32c842..ec8c99110 100644 --- a/backend/test/features/activity-like.feature +++ b/backend/test/features/activity-like.feature @@ -13,14 +13,14 @@ Feature: Like an object like an article or note """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/karl-heinz/status/faslkasa7dasfzkjn2398hsfd", + "id": "http://localhost:4123/activitypub/users/karl-heinz/status/faslkasa7dasfzkjn2398hsfd", "type": "Create", - "actor": "https://localhost:4123/activitypub/users/karl-heinz", + "actor": "http://localhost:4123/activitypub/users/karl-heinz", "object": { - "id": "https://localhost:4123/activitypub/users/karl-heinz/status/dkasfljsdfaafg9843jknsdf", + "id": "http://localhost:4123/activitypub/users/karl-heinz/status/dkasfljsdfaafg9843jknsdf", "type": "Article", "published": "2019-02-07T19:37:55.002Z", - "attributedTo": "https://localhost:4123/activitypub/users/karl-heinz", + "attributedTo": "http://localhost:4123/activitypub/users/karl-heinz", "content": "Hi Max, how are you?", "to": "https://www.w3.org/ns/activitystreams#Public" } @@ -32,7 +32,7 @@ Feature: Like an object like an article or note """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/peter-lustiger/status/83J23549sda1k72fsa4567na42312455kad83", + "id": "http://localhost:4123/activitypub/users/peter-lustiger/status/83J23549sda1k72fsa4567na42312455kad83", "type": "Like", "actor": "http://localhost:4123/activitypub/users/peter-lustiger", "object": "http://localhost:4123/activitypub/users/karl-heinz/status/dkasfljsdfaafg9843jknsdf" diff --git a/backend/test/features/collection.feature b/backend/test/features/collection.feature index 536d3aa2d..1bb4737e0 100644 --- a/backend/test/features/collection.feature +++ b/backend/test/features/collection.feature @@ -14,10 +14,10 @@ Feature: Receiving collections """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/renate-oberdorfer/outbox", + "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox", "summary": "renate-oberdorfers outbox collection", "type": "OrderedCollection", - "first": "https://localhost:4123/activitypub/users/renate-oberdorfer/outbox?page=true", + "first": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox?page=true", "totalItems": 0 } """ @@ -29,10 +29,10 @@ Feature: Receiving collections """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/renate-oberdorfer/following", + "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/following", "summary": "renate-oberdorfers following collection", "type": "OrderedCollection", - "first": "https://localhost:4123/activitypub/users/renate-oberdorfer/following?page=true", + "first": "http://localhost:4123/activitypub/users/renate-oberdorfer/following?page=true", "totalItems": 0 } """ @@ -44,10 +44,10 @@ Feature: Receiving collections """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/renate-oberdorfer/followers", + "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers", "summary": "renate-oberdorfers followers collection", "type": "OrderedCollection", - "first": "https://localhost:4123/activitypub/users/renate-oberdorfer/followers?page=true", + "first": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers?page=true", "totalItems": 0 } """ @@ -59,11 +59,11 @@ Feature: Receiving collections """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/renate-oberdorfer/outbox?page=true", + "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox?page=true", "summary": "renate-oberdorfers outbox collection", "type": "OrderedCollectionPage", "totalItems": 0, - "partOf": "https://localhost:4123/activitypub/users/renate-oberdorfer/outbox", + "partOf": "http://localhost:4123/activitypub/users/renate-oberdorfer/outbox", "orderedItems": [] } """ @@ -75,11 +75,11 @@ Feature: Receiving collections """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/renate-oberdorfer/following?page=true", + "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/following?page=true", "summary": "renate-oberdorfers following collection", "type": "OrderedCollectionPage", "totalItems": 0, - "partOf": "https://localhost:4123/activitypub/users/renate-oberdorfer/following", + "partOf": "http://localhost:4123/activitypub/users/renate-oberdorfer/following", "orderedItems": [] } """ @@ -91,11 +91,11 @@ Feature: Receiving collections """ { "@context": "https://www.w3.org/ns/activitystreams", - "id": "https://localhost:4123/activitypub/users/renate-oberdorfer/followers?page=true", + "id": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers?page=true", "summary": "renate-oberdorfers followers collection", "type": "OrderedCollectionPage", "totalItems": 0, - "partOf": "https://localhost:4123/activitypub/users/renate-oberdorfer/followers", + "partOf": "http://localhost:4123/activitypub/users/renate-oberdorfer/followers", "orderedItems": [] } """ diff --git a/backend/test/features/webfinger.feature b/backend/test/features/webfinger.feature index c9f9e587b..72062839a 100644 --- a/backend/test/features/webfinger.feature +++ b/backend/test/features/webfinger.feature @@ -4,7 +4,7 @@ Feature: Webfinger discovery In order to follow the actor Background: - Given our own server runs at "http://localhost:4100" + Given our own server runs at "http://localhost:4123" And we have the following users in our database: | Slug | | peter-lustiger | @@ -19,7 +19,7 @@ Feature: Webfinger discovery { "rel": "self", "type": "application/activity+json", - "href": "https://localhost:4123/activitypub/users/peter-lustiger" + "href": "http://localhost:4123/activitypub/users/peter-lustiger" } ] } @@ -44,21 +44,21 @@ Feature: Webfinger discovery "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1" ], - "id": "https://localhost:4123/activitypub/users/peter-lustiger", + "id": "http://localhost:4123/activitypub/users/peter-lustiger", "type": "Person", "preferredUsername": "peter-lustiger", "name": "peter-lustiger", - "following": "https://localhost:4123/activitypub/users/peter-lustiger/following", - "followers": "https://localhost:4123/activitypub/users/peter-lustiger/followers", - "inbox": "https://localhost:4123/activitypub/users/peter-lustiger/inbox", - "outbox": "https://localhost:4123/activitypub/users/peter-lustiger/outbox", - "url": "https://localhost:4123/activitypub/@peter-lustiger", + "following": "http://localhost:4123/activitypub/users/peter-lustiger/following", + "followers": "http://localhost:4123/activitypub/users/peter-lustiger/followers", + "inbox": "http://localhost:4123/activitypub/users/peter-lustiger/inbox", + "outbox": "http://localhost:4123/activitypub/users/peter-lustiger/outbox", + "url": "http://localhost:4123/activitypub/@peter-lustiger", "endpoints": { - "sharedInbox": "https://localhost:4123/activitypub/inbox" + "sharedInbox": "http://localhost:4123/activitypub/inbox" }, "publicKey": { - "id": "https://localhost:4123/activitypub/users/peter-lustiger#main-key", - "owner": "https://localhost:4123/activitypub/users/peter-lustiger", + "id": "http://localhost:4123/activitypub/users/peter-lustiger#main-key", + "owner": "http://localhost:4123/activitypub/users/peter-lustiger", "publicKeyPem": "adglkjlk89235kjn8obn2384f89z5bv9..." } } diff --git a/webapp/nuxt.config.js b/webapp/nuxt.config.js index 769b0fca0..6cac26ea1 100644 --- a/webapp/nuxt.config.js +++ b/webapp/nuxt.config.js @@ -133,7 +133,6 @@ module.exports = { '/activitypub': { // make this configurable (nuxt-dotenv) target: process.env.GRAPHQL_URI || 'http://localhost:4000', - pathRewrite: { '^/activitypub': '' }, toProxy: true, // cloudflare needs that headers: { Accept: 'application/json',