mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Some refactoring + add timeout functions to some step definitions + add objectId to Post and schema
This commit is contained in:
parent
5aeb2845db
commit
00ba891cbf
@ -14,6 +14,7 @@ import NitroDataSource from './NitroDataSource'
|
||||
import router from './routes'
|
||||
import dotenv from 'dotenv'
|
||||
import Collections from './Collections'
|
||||
import uuid from 'uuid/v4'
|
||||
const debug = require('debug')('ea')
|
||||
|
||||
let activityPub = null
|
||||
@ -27,6 +28,7 @@ export default class ActivityPub {
|
||||
this.dataSource = new NitroDataSource(uri)
|
||||
this.collections = new Collections(this.dataSource)
|
||||
}
|
||||
|
||||
static init (server) {
|
||||
if (!activityPub) {
|
||||
dotenv.config()
|
||||
@ -179,30 +181,37 @@ export default class ActivityPub {
|
||||
})
|
||||
}
|
||||
|
||||
generateStatusId (slug) {
|
||||
return `http://${this.domain}/activitypub/users/${slug}/status/${uuid()}`
|
||||
}
|
||||
|
||||
async sendActivity (activity) {
|
||||
delete activity.send
|
||||
const fromName = extractNameFromId(activity.actor)
|
||||
if (Array.isArray(activity.to) && isPublicAddressed(activity)) {
|
||||
debug('is public addressed')
|
||||
const sharedInboxEndpoints = await this.dataSource.getSharedInboxEndpoints()
|
||||
// serve shared inbox endpoints
|
||||
sharedInboxEndpoints.map((el) => {
|
||||
return this.trySend(activity, fromName, new URL(el).host, el)
|
||||
sharedInboxEndpoints.map((sharedInbox) => {
|
||||
return this.trySend(activity, fromName, new URL(sharedInbox).host, sharedInbox)
|
||||
})
|
||||
activity.to = activity.to.filter((el) => {
|
||||
return !(isPublicAddressed({ to: el }))
|
||||
activity.to = activity.to.filter((recipient) => {
|
||||
return !(isPublicAddressed({ to: recipient }))
|
||||
})
|
||||
// serve the rest
|
||||
activity.to.map(async (el) => {
|
||||
const actorObject = await this.getActorObject(el)
|
||||
return this.trySend(activity, fromName, new URL(el).host, actorObject.inbox)
|
||||
activity.to.map(async (recipient) => {
|
||||
debug('serve rest')
|
||||
const actorObject = await this.getActorObject(recipient)
|
||||
return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox)
|
||||
})
|
||||
} else if (typeof activity.to === 'string') {
|
||||
debug('is string')
|
||||
const actorObject = await this.getActorObject(activity.to)
|
||||
return this.trySend(activity, fromName, new URL(activity.to).host, actorObject.inbox)
|
||||
} else if (Array.isArray(activity.to)) {
|
||||
activity.to.map(async (el) => {
|
||||
const actorObject = await this.getActorObject(el)
|
||||
return this.trySend(activity, fromName, new URL(el).host, actorObject.inbox)
|
||||
activity.to.map(async (recipient) => {
|
||||
const actorObject = await this.getActorObject(recipient)
|
||||
return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,8 +19,6 @@ import { setContext } from 'apollo-link-context'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import fetch from 'node-fetch'
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import uuid from 'uuid'
|
||||
import encode from '../jwt/encode'
|
||||
import trunc from 'trunc-html'
|
||||
const debug = require('debug')('ea:nitro-datasource')
|
||||
|
||||
@ -37,12 +35,12 @@ export default class NitroDataSource {
|
||||
const cache = new InMemoryCache()
|
||||
const authLink = setContext((_, { headers }) => {
|
||||
// generate the authentication token (maybe from env? Which user?)
|
||||
const token = encode({ name: 'ActivityPub', id: uuid() })
|
||||
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJuYW1lIjoiUGV0ZXIgTHVzdGlnIiwiYXZhdGFyIjoiaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VpZmFjZXMvZmFjZXMvdHdpdHRlci9qb2huY2FmYXp6YS8xMjguanBnIiwiaWQiOiJ1MSIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJzbHVnIjoicGV0ZXItbHVzdGlnIiwiaWF0IjoxNTUyNDIwMTExLCJleHAiOjE2Mzg4MjAxMTEsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMCIsInN1YiI6InUxIn0.G7An1yeQUViJs-0Qj-Tc-zm0WrLCMB3M02pfPnm6xzw'
|
||||
// return the headers to the context so httpLink can read them
|
||||
return {
|
||||
headers: {
|
||||
...headers,
|
||||
authorization: token ? `Bearer ${token}` : ''
|
||||
Authorization: token ? `Bearer ${token}` : ''
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -213,6 +211,7 @@ export default class NitroDataSource {
|
||||
|
||||
async getOutboxCollectionPage (actorId) {
|
||||
const slug = extractNameFromId(actorId)
|
||||
debug(`inside getting outbox collection page => ${slug}`)
|
||||
const result = await this.client.query({
|
||||
query: gql`
|
||||
query {
|
||||
@ -220,11 +219,16 @@ export default class NitroDataSource {
|
||||
actorId
|
||||
contributions {
|
||||
id
|
||||
activityId
|
||||
objectId
|
||||
title
|
||||
slug
|
||||
content
|
||||
contentExcerpt
|
||||
createdAt
|
||||
author {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,7 +244,7 @@ export default class NitroDataSource {
|
||||
outboxCollection.totalItems = posts.length
|
||||
await Promise.all(
|
||||
posts.map(async (post) => {
|
||||
outboxCollection.orderedItems.push(await createArticleObject(post.activityId, post.objectId, post.content, extractNameFromId(post.id), post.id, post.createdAt))
|
||||
outboxCollection.orderedItems.push(await createArticleObject(post.activityId, post.objectId, post.content, post.author.name, post.id, post.createdAt))
|
||||
})
|
||||
)
|
||||
|
||||
@ -332,6 +336,7 @@ export default class NitroDataSource {
|
||||
}
|
||||
const title = postObject.summary ? postObject.summary : postObject.content.split(' ').slice(0, 5).join(' ')
|
||||
const postId = extractIdFromActivityId(postObject.id)
|
||||
debug('inside create post')
|
||||
let result = await this.client.mutate({
|
||||
mutation: gql`
|
||||
mutation {
|
||||
@ -346,10 +351,16 @@ export default class NitroDataSource {
|
||||
|
||||
// ensure user and add author to post
|
||||
const userId = await this.ensureUser(postObject.attributedTo)
|
||||
debug(`userId = ${userId}`)
|
||||
debug(`postId = ${postId}`)
|
||||
result = await this.client.mutate({
|
||||
mutation: gql`
|
||||
mutation {
|
||||
AddPostAuthor(from: {id: "${userId}"}, to: {id: "${postId}"})
|
||||
AddPostAuthor(from: {id: "${userId}"}, to: {id: "${postId}"}) {
|
||||
from {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
@ -523,10 +534,11 @@ export default class NitroDataSource {
|
||||
debug('ensureUser: user not exists.. createUser')
|
||||
// user does not exist.. create it
|
||||
const pw = crypto.randomBytes(16).toString('hex')
|
||||
const slug = name.toLowerCase().split(' ').join('-')
|
||||
const result = await this.client.mutate({
|
||||
mutation: gql`
|
||||
mutation {
|
||||
CreateUser(password: "${pw}", slug:"${name}", actorId: "${actorId}", name: "${name}") {
|
||||
CreateUser(password: "${pw}", slug:"${slug}", actorId: "${actorId}", name: "${name}", email: "${slug}@test.org") {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,36 +13,36 @@ router.post('/', async function (req, res, next) {
|
||||
debug(`Request headers = ${JSON.stringify(req.headers, null, 2)}`)
|
||||
switch (req.body.type) {
|
||||
case 'Create':
|
||||
if (req.body.send) {
|
||||
await activityPub.sendActivity(req.body).catch(next)
|
||||
break
|
||||
}
|
||||
await activityPub.handleCreateActivity(req.body).catch(next)
|
||||
break
|
||||
case 'Undo':
|
||||
await activityPub.handleUndoActivity(req.body).catch(next)
|
||||
break
|
||||
case 'Follow':
|
||||
debug('handleFollow')
|
||||
await activityPub.handleFollowActivity(req.body)
|
||||
debug('handledFollow')
|
||||
await activityPub.handleFollowActivity(req.body).catch(next)
|
||||
break
|
||||
case 'Delete':
|
||||
await activityPub.handleDeleteActivity(req.body).catch(next)
|
||||
break
|
||||
/* eslint-disable */
|
||||
/* eslint-disable */
|
||||
case 'Update':
|
||||
|
||||
await activityPub.handleUpdateActivity(req.body).catch(next)
|
||||
break
|
||||
case 'Accept':
|
||||
await activityPub.handleAcceptActivity(req.body).catch(next)
|
||||
case 'Reject':
|
||||
|
||||
// Do nothing
|
||||
break
|
||||
case 'Add':
|
||||
|
||||
break
|
||||
case 'Remove':
|
||||
|
||||
break
|
||||
case 'Like':
|
||||
|
||||
await activityPub.handleLikeActivity(req.body).catch(next)
|
||||
break
|
||||
case 'Dislike':
|
||||
await activityPub.handleDislikeActivity(req.body).catch(next)
|
||||
break
|
||||
case 'Announce':
|
||||
debug('else!!')
|
||||
debug(JSON.stringify(req.body, null, 2))
|
||||
|
||||
@ -96,6 +96,12 @@ export function isPublicAddressed (postObject) {
|
||||
if (typeof postObject.to === 'string') {
|
||||
postObject.to = [postObject.to]
|
||||
}
|
||||
if (typeof postObject === 'string') {
|
||||
postObject.to = [postObject]
|
||||
}
|
||||
if (Array.isArray(postObject)) {
|
||||
postObject.to = postObject
|
||||
}
|
||||
return postObject.to.includes('Public') ||
|
||||
postObject.to.includes('as:Public') ||
|
||||
postObject.to.includes('https://www.w3.org/ns/activitystreams#Public')
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
import createOrUpdateLocations from './nodes/locations'
|
||||
import { generateRsaKeyPair } from '../activitypub/security'
|
||||
import dotenv from 'dotenv'
|
||||
import { resolve } from 'path'
|
||||
|
||||
dotenv.config({ path: resolve('src', 'activitypub', '.env') })
|
||||
dotenv.config()
|
||||
|
||||
export default {
|
||||
Mutation: {
|
||||
CreateUser: async (resolve, root, args, context, info) => {
|
||||
const keys = generateRsaKeyPair()
|
||||
Object.assign(args, keys)
|
||||
args.actorId = `${process.env.ACTIVITYPUB_URI}/activitypub/users/${args.slug}`
|
||||
args.actorId = `${process.env.GRAPHQL_URI}/activitypub/users/${args.slug}`
|
||||
const result = await resolve(root, args, context, info)
|
||||
await createOrUpdateLocations(args.id, args.locationName, context.driver)
|
||||
return result
|
||||
|
||||
@ -1,22 +1,23 @@
|
||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
import { activityPub } from '../activitypub/ActivityPub'
|
||||
import uuid from 'uuid/v4'
|
||||
import as from 'activitystrea.ms'
|
||||
import dotenv from 'dotenv'
|
||||
/*
|
||||
import as from 'activitystrea.ms'
|
||||
import request from 'request'
|
||||
*/
|
||||
|
||||
const debug = require('debug')('backend:schema')
|
||||
dotenv.config()
|
||||
|
||||
export default {
|
||||
Mutation: {
|
||||
CreatePost: async (object, params, context, resolveInfo) => {
|
||||
params.activityId = uuid()
|
||||
params.activityId = activityPub.generateStatusId(context.user.slug)
|
||||
params.objectId = activityPub.generateStatusId(context.user.slug)
|
||||
const result = await neo4jgraphql(object, params, context, resolveInfo, false)
|
||||
|
||||
const session = context.driver.session()
|
||||
|
||||
const author = await session.run(
|
||||
'MATCH (author:User {id: $userId}), (post:Post {id: $postId}) ' +
|
||||
'MERGE (post)<-[:WROTE]-(author) ' +
|
||||
@ -25,6 +26,7 @@ export default {
|
||||
postId: result.id
|
||||
}
|
||||
)
|
||||
session.close()
|
||||
|
||||
debug(`actorId = ${author.records[0]._fields[0].properties.actorId}`)
|
||||
if (Array.isArray(author.records) && author.records.length > 0) {
|
||||
@ -54,10 +56,9 @@ export default {
|
||||
try {
|
||||
await activityPub.sendActivity(createActivity)
|
||||
} catch (e) {
|
||||
debug(`error sending post activity = ${JSON.stringify(e, null, 2)}`)
|
||||
debug(`error sending post activity\n${e}`)
|
||||
}
|
||||
}
|
||||
session.close()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -158,6 +158,7 @@ type User {
|
||||
type Post {
|
||||
id: ID!
|
||||
activityId: String
|
||||
objectId: String
|
||||
author: User @relation(name: "WROTE", direction: "IN")
|
||||
title: String!
|
||||
slug: String
|
||||
|
||||
@ -14,7 +14,7 @@ Feature: Delete an object
|
||||
"type": "Create",
|
||||
"actor": "https://aronda.org/users/bernd-das-brot",
|
||||
"object": {
|
||||
"id": "https://aronda.org/users/bernd-das-brot/status/kljsdfg9843jknsdf",
|
||||
"id": "https://aronda.org/users/bernd-das-brot/status/kljsdfg9843jknsdf234",
|
||||
"type": "Article",
|
||||
"published": "2019-02-07T19:37:55.002Z",
|
||||
"attributedTo": "https://aronda.org/users/bernd-das-brot",
|
||||
@ -29,13 +29,13 @@ Feature: Delete an object
|
||||
"""
|
||||
{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"id": "https://localhost:4123/users/karl-heinz/status/a4DJ2afdg323v32641vna42lkj685kasd2",
|
||||
"id": "https://localhost:4123/activitypub/users/karl-heinz/status/a4DJ2afdg323v32641vna42lkj685kasd2",
|
||||
"type": "Delete",
|
||||
"object": {
|
||||
"id": "https://aronda.org/users/bernd-das-brot/status/kljsdfg9843jknsdf",
|
||||
"id": "https://aronda.org/activitypub/users/bernd-das-brot/status/kljsdfg9843jknsdf234",
|
||||
"type": "Article",
|
||||
"published": "2019-02-07T19:37:55.002Z",
|
||||
"attributedTo": "https://aronda.org/users/bernd-das-brot",
|
||||
"attributedTo": "https://aronda.org/activitypub/users/bernd-das-brot",
|
||||
"content": "Hi Max, how are you?",
|
||||
"to": "https://localhost:4123/activitypub/users/moritz"
|
||||
}
|
||||
@ -45,10 +45,10 @@ Feature: Delete an object
|
||||
And the object is removed from the outbox collection of "bernd-das-brot"
|
||||
"""
|
||||
{
|
||||
"id": "https://aronda.org/users/bernd-das-brot/status/kljsdfg9843jknsdf",
|
||||
"id": "https://aronda.org/activitypub/users/bernd-das-brot/status/kljsdfg9843jknsdf234",
|
||||
"type": "Article",
|
||||
"published": "2019-02-07T19:37:55.002Z",
|
||||
"attributedTo": "https://aronda.org/users/bernd-das-brot",
|
||||
"attributedTo": "https://aronda.org/activitypub/users/bernd-das-brot",
|
||||
"content": "Hi Max, how are you?",
|
||||
"to": "https://localhost:4123/activitypub/users/moritz"
|
||||
}
|
||||
|
||||
@ -105,14 +105,17 @@ Then('the activity is added to the users inbox collection', async function () {
|
||||
})
|
||||
|
||||
Then('the post with id {string} to be created', async function (id) {
|
||||
const result = await client.request(`
|
||||
setTimeout(async () => {
|
||||
const result = await client.request(`
|
||||
query {
|
||||
Post(id: "${id}") {
|
||||
title
|
||||
}
|
||||
}
|
||||
`)
|
||||
expect(result.data.Post).to.be.an('array').that.is.not.empty // eslint-disable-line
|
||||
|
||||
expect(result.data.Post).to.be.an('array').that.is.not.empty // eslint-disable-line
|
||||
}, 2000)
|
||||
})
|
||||
|
||||
Then('the object is removed from the outbox collection of {string}', async function (name, object) {
|
||||
@ -126,7 +129,8 @@ Then('I send a GET request to {string} and expect a ordered collection', () => {
|
||||
})
|
||||
|
||||
Then('the post with id {string} has been liked by {string}', async function (id, slug) {
|
||||
const result = await client.request(`
|
||||
setTimeout(async () => {
|
||||
const result = await client.request(`
|
||||
query {
|
||||
Post(id: "${id}") {
|
||||
shoutedBy {
|
||||
@ -135,6 +139,7 @@ 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)
|
||||
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)
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user