Fixed follow feature + clean database after tests run + wait for user to be created before proceed

This commit is contained in:
Armin 2019-03-13 00:25:32 +01:00
parent 00ba891cbf
commit 5ea3ef99e1
9 changed files with 63 additions and 44 deletions

View File

@ -20,7 +20,7 @@
"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",
"test:jest": "run-p --race test:before:* 'test:jest:cmd {@}' --",
"test:cucumber": "ACTIVITYPUB_PORT=4123 run-p --race test:before:* 'test:cucumber:cmd {@}' --",
"test:cucumber": "run-p --race test:before:* 'test:cucumber:cmd {@}' --",
"test:jest:debug": "run-p --race test:before:* 'test:jest:cmd:debug {@}' --",
"test:coverage": "nyc report --reporter=text-lcov > coverage.lcov",
"db:script:seed": "wait-on tcp:4001 && babel-node src/seed/seed-db.js",

View File

@ -35,12 +35,13 @@ export default class ActivityPub {
const url = new URL(process.env.GRAPHQL_URI)
activityPub = new ActivityPub(url.hostname || 'localhost', url.port || 4000, url.origin)
// integrated into "server's" express framework
// integrate into running graphql express server
server.express.set('ap', activityPub)
server.express.set('port', url.port)
server.express.use(router)
debug('ActivityPub middleware added to the express service')
console.log('-> ActivityPub middleware added to the graphql express server')
} else {
debug('ActivityPub middleware already added to the express service')
console.log('-> ActivityPub middleware already added to the graphql express server')
}
}
@ -60,6 +61,7 @@ export default class ActivityPub {
if (err) return reject(err)
debug(`name = ${toActorName}@${this.domain}`)
// save shared inbox
toActorObject = JSON.parse(toActorObject)
await this.dataSource.addSharedInboxEndpoint(toActorObject.endpoints.sharedInbox)
let followersCollectionPage = await this.dataSource.getFollowersCollectionPage(activity.object)
@ -159,7 +161,7 @@ export default class ActivityPub {
switch (activity.object.type) {
case 'Follow':
const followObject = activity.object
const followingCollectionPage = await this.getFollowingCollectionPage(followObject.actor)
const followingCollectionPage = await this.collections.getFollowingCollectionPage(followObject.actor)
followingCollectionPage.orderedItems.push(followObject.object)
await this.dataSource.saveFollowingCollectionPage(followingCollectionPage)
}

View File

@ -4,7 +4,7 @@ const debug = require('debug')('ea:verify')
export default async (req, res, next) => {
debug(`actorId = ${req.body.actor}`)
// TODO stop if signature validation fails
if (await verifySignature(`${req.protocol}://${req.hostname}:${req.port}${req.originalUrl}`, req.headers)) {
if (await verifySignature(`${req.protocol}://${req.hostname}:${req.app.get('port')}${req.originalUrl}`, req.headers)) {
debug('verify = true')
next()
} else {

View File

@ -60,7 +60,7 @@ describe('Signature creation and verification', () => {
httpSignature = createSignature(user.privateKey, 'http://localhost:4001/activitypub/users/test-user#main-key', 'https://democracy-app.de/activitypub/users/max/inbox', headers)
})
it('verifies a Signature by ', async () => {
it('verifies a Signature correct', async () => {
headers['Signature'] = httpSignature
const isVerified = await verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers)
expect(isVerified).to.equal(true)

View File

@ -37,7 +37,7 @@ Feature: Delete an object
"published": "2019-02-07T19:37:55.002Z",
"attributedTo": "https://aronda.org/activitypub/users/bernd-das-brot",
"content": "Hi Max, how are you?",
"to": "https://localhost:4123/activitypub/users/moritz"
"to": "https://www.w3.org/ns/activitystreams#Public"
}
}
"""
@ -50,6 +50,6 @@ Feature: Delete an object
"published": "2019-02-07T19:37:55.002Z",
"attributedTo": "https://aronda.org/activitypub/users/bernd-das-brot",
"content": "Hi Max, how are you?",
"to": "https://localhost:4123/activitypub/users/moritz"
"to": "https://www.w3.org/ns/activitystreams#Public"
}
"""

View File

@ -7,45 +7,44 @@ Feature: Follow a user
Given our own server runs at "http://localhost:4123"
And we have the following users in our database:
| Slug |
| peter-lustiger |
| bob-der-baumeister |
| karl-heinz |
| stuart-little |
| tero-vota |
Scenario: Send a follow to a user inbox and make sure it's added to the right followers collection
When I send a POST request with the following activity to "/activitypub/users/peter-lustiger/inbox":
When I send a POST request with the following activity to "/activitypub/users/tero-vota/inbox":
"""
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://localhost:4123/activitypub/users/bob-der-baumeister/status/83J23549sda1k72fsa4567na42312455kad83",
"id": "https://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83",
"type": "Follow",
"actor": "http://localhost:4123/activitypub/users/bob-der-baumeister",
"object": "http://localhost:4123/activitypub/users/peter-lustiger"
"actor": "http://localhost:4123/activitypub/users/stuart-little",
"object": "http://localhost:4123/activitypub/users/tero-vota"
}
"""
Then I expect the status code to be 200
And the follower is added to the followers collection of "peter-lustiger"
And the follower is added to the followers collection of "tero-vota"
"""
https://localhost:4123/activitypub/users/bob-der-baumeister
http://localhost:4123/activitypub/users/stuart-little
"""
Scenario: Send an undo activity to revert the previous follow activity
When I send a POST request with the following activity to "/activitypub/users/bob-der-baumeister/inbox":
When I send a POST request with the following activity to "/activitypub/users/stuart-little/inbox":
"""
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://localhost:4123/activitypub/users/peter-lustiger/status/a4DJ2afdg323v32641vna42lkj685kasd2",
"id": "https://localhost:4123/activitypub/users/tero-vota/status/a4DJ2afdg323v32641vna42lkj685kasd2",
"type": "Undo",
"actor": "http://localhost:4123/activitypub/users/peter-lustiger",
"actor": "http://localhost:4123/activitypub/users/tero-vota",
"object": {
"id": "https://localhost:4123/activitypub/users/bob-der-baumeister/status/83J23549sda1k72fsa4567na42312455kad83",
"id": "https://localhost:4123/activitypub/users/stuart-little/status/83J23549sda1k72fsa4567na42312455kad83",
"type": "Follow",
"actor": "http://localhost:4123/activitypub/users/bob-der-baumeister",
"object": "http://localhost:4123/activitypub/users/peter-lustiger"
"actor": "http://localhost:4123/activitypub/users/stuart-little",
"object": "http://localhost:4123/activitypub/users/tero-vota"
}
}
"""
Then I expect the status code to be 200
And the follower is removed from the followers collection of "peter-lustiger"
And the follower is removed from the followers collection of "tero-vota"
"""
https://localhost:4123/activitypub/users/bob-der-baumeister
http://localhost:4123/activitypub/users/stuart-little
"""

View File

@ -22,7 +22,7 @@ Feature: Send and receive Articles
"published": "2019-02-07T19:37:55.002Z",
"attributedTo": "https://aronda.org/users/marvin",
"content": "Hi Max, how are you?",
"to": "https://localhost:4123/activitypub/users/max"
"to": "as:Public"
}
}
"""

View File

@ -22,14 +22,15 @@ function createUser (slug) {
AfterAll('Clean up the test data', function () {
debug('All the tests are done! Deleting test data')
return factory.cleanDatabase()
})
Given('our own server runs at {string}', function (string) {
// just documenation
})
Given('we have the following users in our database:', async function (dataTable) {
await Promise.all(dataTable.hashes().map((user) => {
Given('we have the following users in our database:', function (dataTable) {
return Promise.all(dataTable.hashes().map((user) => {
return createUser(user.Slug)
}))
})
@ -45,6 +46,20 @@ When('I send a GET request to {string}', async function (pathname) {
When('I send a POST request with the following activity to {string}:', async function (inboxUrl, activity) {
debug(`inboxUrl = ${inboxUrl}`)
debug(`activity = ${activity}`)
const splitted = inboxUrl.split('/')
const slug = splitted[splitted.indexOf('users') + 1]
let result
do {
result = await client.request(`
query {
User(slug: "${slug}") {
id
slug
actorId
}
}
`)
} while (result.User.length === 0)
this.lastInboxUrl = inboxUrl
this.lastActivity = activity
const response = await this.post(inboxUrl, activity)
@ -100,22 +115,19 @@ Then('the follower is removed from the followers collection of {string}', async
expect(responseObject.orderedItems).to.not.include(follower)
})
Then('the activity is added to the users inbox collection', async function () {
})
Then('the post with id {string} to be created', async function (id) {
setTimeout(async () => {
const result = await client.request(`
let result
do {
result = await client.request(`
query {
Post(id: "${id}") {
title
}
}
`)
} while (result.Post.length === 0)
expect(result.data.Post).to.be.an('array').that.is.not.empty // eslint-disable-line
}, 2000)
expect(result.Post).to.be.an('array').that.is.not.empty // eslint-disable-line
})
Then('the object is removed from the outbox collection of {string}', async function (name, object) {
@ -128,9 +140,14 @@ Then('I send a GET request to {string} and expect a ordered collection', () => {
})
Then('the activity is added to the users inbox collection', async function () {
})
Then('the post with id {string} has been liked by {string}', async function (id, slug) {
setTimeout(async () => {
const result = await client.request(`
let result
do {
result = await client.request(`
query {
Post(id: "${id}") {
shoutedBy {
@ -139,7 +156,8 @@ Then('the post with id {string} has been liked by {string}', async function (id,
}
}
`)
expect(result.data.Post[0].shoutedBy).to.be.an('array').that.is.not.empty // eslint-disable-line
expect(result.data.Post[0].shoutedBy[0].slug).to.equal(slug)
}, 2000)
} while (result.Post.length === 0)
expect(result.Post[0].shoutedBy).to.be.an('array').that.is.not.empty // eslint-disable-line
expect(result.Post[0].shoutedBy[0].slug).to.equal(slug)
})

View File

@ -20,8 +20,8 @@ class CustomWorld {
'Accept': 'application/activity+json'
}}, function (error, response, body) {
if (!error) {
debug(`get response = ${response.headers['content-type']}`)
debug(`body = ${body}`)
debug(`get content-type = ${response.headers['content-type']}`)
debug(`get body = ${JSON.stringify(typeof body === 'string' ? JSON.parse(body) : body, null, 2)}`)
resolve({ lastResponse: body, lastContentType: response.headers['content-type'], statusCode: response.statusCode })
} else {
reject(error)