activity pub

This commit is contained in:
Ulf Gebhardt 2023-06-12 14:06:55 +02:00
parent fcf92ea6e6
commit b59cc1f6c4
Signed by: ulfgebhardt
GPG Key ID: DA6B843E748679C9
8 changed files with 31 additions and 23 deletions

View File

@ -11,11 +11,15 @@ import { v4 as uuid } from 'uuid'
import CONFIG from '../config' import CONFIG from '../config'
const debug = require('debug')('ea') const debug = require('debug')('ea')
let activityPub = null let activityPub: any = null
export { activityPub } export { activityPub }
export default class ActivityPub { export default class ActivityPub {
endpoint: any
dataSource: any
collections: any
host: any
constructor(activityPubEndpointUri, internalGraphQlUri) { constructor(activityPubEndpointUri, internalGraphQlUri) {
this.endpoint = activityPubEndpointUri this.endpoint = activityPubEndpointUri
this.dataSource = new NitroDataSource(internalGraphQlUri) this.dataSource = new NitroDataSource(internalGraphQlUri)
@ -211,16 +215,16 @@ export default class ActivityPub {
// serve the rest // serve the rest
activity.to.map(async (recipient) => { activity.to.map(async (recipient) => {
debug('serve rest') debug('serve rest')
const actorObject = await this.getActorObject(recipient) const actorObject: any = await this.getActorObject(recipient)
return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox) return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox)
}) })
} else if (typeof activity.to === 'string') { } else if (typeof activity.to === 'string') {
debug('is string') debug('is string')
const actorObject = await this.getActorObject(activity.to) const actorObject: any = await this.getActorObject(activity.to)
return this.trySend(activity, fromName, new URL(activity.to).host, actorObject.inbox) return this.trySend(activity, fromName, new URL(activity.to).host, actorObject.inbox)
} else if (Array.isArray(activity.to)) { } else if (Array.isArray(activity.to)) {
activity.to.map(async (recipient) => { activity.to.map(async (recipient) => {
const actorObject = await this.getActorObject(recipient) const actorObject: any = await this.getActorObject(recipient)
return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox) return this.trySend(activity, fromName, new URL(recipient).host, actorObject.inbox)
}) })
} }
@ -231,7 +235,7 @@ export default class ActivityPub {
return await signAndSend(activity, fromName, host, url) return await signAndSend(activity, fromName, host, url)
} catch (e) { } catch (e) {
if (tries > 0) { if (tries > 0) {
setTimeout(function () { setTimeout(() => {
return this.trySend(activity, fromName, host, url, --tries) return this.trySend(activity, fromName, host, url, --tries)
}, 20000) }, 20000)
} }

View File

@ -1,4 +1,5 @@
export default class Collections { export default class Collections {
dataSource: any
constructor(dataSource) { constructor(dataSource) {
this.dataSource = dataSource this.dataSource = dataSource
} }

View File

@ -17,15 +17,17 @@ import trunc from 'trunc-html'
const debug = require('debug')('ea:datasource') const debug = require('debug')('ea:datasource')
export default class NitroDataSource { export default class NitroDataSource {
uri: any
client: any
constructor(uri) { constructor(uri) {
this.uri = uri this.uri = uri
const defaultOptions = { const defaultOptions: any = {
query: { query: {
fetchPolicy: 'network-only', fetchPolicy: 'network-only',
errorPolicy: 'all', errorPolicy: 'all',
}, },
} }
const link = createHttpLink({ uri: this.uri, fetch: fetch }) // eslint-disable-line const link = createHttpLink({ uri: this.uri, fetch: fetch } as any) // eslint-disable-line
const cache = new InMemoryCache() const cache = new InMemoryCache()
const authLink = setContext((_, { headers }) => { const authLink = setContext((_, { headers }) => {
// generate the authentication token (maybe from env? Which user?) // generate the authentication token (maybe from env? Which user?)
@ -95,7 +97,7 @@ export default class NitroDataSource {
const followers = actor.followedBy const followers = actor.followedBy
const followersCount = actor.followedByCount const followersCount = actor.followedByCount
const followersCollection = createOrderedCollectionPage(slug, 'followers') const followersCollection: any = createOrderedCollectionPage(slug, 'followers')
followersCollection.totalItems = followersCount followersCollection.totalItems = followersCount
debug(`followers = ${JSON.stringify(followers, null, 2)}`) debug(`followers = ${JSON.stringify(followers, null, 2)}`)
await Promise.all( await Promise.all(
@ -157,7 +159,7 @@ export default class NitroDataSource {
const following = actor.following const following = actor.following
const followingCount = actor.followingCount const followingCount = actor.followingCount
const followingCollection = createOrderedCollectionPage(slug, 'following') const followingCollection: any = createOrderedCollectionPage(slug, 'following')
followingCollection.totalItems = followingCount followingCollection.totalItems = followingCount
await Promise.all( await Promise.all(
@ -235,7 +237,7 @@ export default class NitroDataSource {
const actor = result.data.User[0] const actor = result.data.User[0]
const posts = actor.contributions const posts = actor.contributions
const outboxCollection = createOrderedCollectionPage(slug, 'outbox') const outboxCollection: any = createOrderedCollectionPage(slug, 'outbox')
outboxCollection.totalItems = posts.length outboxCollection.totalItems = posts.length
await Promise.all( await Promise.all(
posts.map(async (post) => { posts.map(async (post) => {

View File

@ -11,8 +11,8 @@ export default function () {
cors(), cors(),
express.json({ express.json({
type: ['application/activity+json', 'application/ld+json', 'application/json'], type: ['application/activity+json', 'application/ld+json', 'application/json'],
}), }) as any,
express.urlencoded({ extended: true }), express.urlencoded({ extended: true }) as any,
user, user,
) )
router.use( router.use(
@ -20,8 +20,8 @@ export default function () {
cors(), cors(),
express.json({ express.json({
type: ['application/activity+json', 'application/ld+json', 'application/json'], type: ['application/activity+json', 'application/ld+json', 'application/json'],
}), }) as any,
express.urlencoded({ extended: true }), express.urlencoded({ extended: true }) as any,
verify, verify,
inbox, inbox,
) )

View File

@ -54,6 +54,6 @@ export async function handler(req, res) {
export default function () { export default function () {
const router = express.Router() const router = express.Router()
router.use('/webfinger', cors(), express.urlencoded({ extended: true }), handler) router.use('/webfinger', cors(), express.urlencoded({ extended: true }) as any, handler)
return router return router
} }

View File

@ -8,7 +8,7 @@ const debug = require('debug')('ea:security')
// TODO Does this reference a local config? Why? // TODO Does this reference a local config? Why?
// dotenv.config({ path: resolve('src', 'activitypub', '.env') }) // dotenv.config({ path: resolve('src', 'activitypub', '.env') })
export function generateRsaKeyPair(options = {}) { export function generateRsaKeyPair(options: any = {}) {
const { passphrase = CONFIG.PRIVATE_KEY_PASSPHRASE } = options const { passphrase = CONFIG.PRIVATE_KEY_PASSPHRASE } = options
return crypto.generateKeyPairSync('rsa', { return crypto.generateKeyPairSync('rsa', {
modulusLength: 4096, modulusLength: 4096,

View File

@ -100,18 +100,19 @@ export async function getActorId(name) {
// } // }
export function isPublicAddressed(postObject) { export function isPublicAddressed(postObject) {
const result: { to: any[]} = { to: []}
if (typeof postObject.to === 'string') { if (typeof postObject.to === 'string') {
postObject.to = [postObject.to] result.to = [postObject.to]
} }
if (typeof postObject === 'string') { if (typeof postObject === 'string') {
postObject.to = [postObject] result.to = [postObject]
} }
if (Array.isArray(postObject)) { if (Array.isArray(postObject)) {
postObject.to = postObject result.to = postObject
} }
return ( return (
postObject.to.includes('Public') || result.to.includes('Public') ||
postObject.to.includes('as:Public') || result.to.includes('as:Public') ||
postObject.to.includes('https://www.w3.org/ns/activitystreams#Public') result.to.includes('https://www.w3.org/ns/activitystreams#Public')
) )
} }

View File

@ -101,7 +101,7 @@ export function signAndSend(activity, fromName, targetDomain, url) {
} else { } else {
debug('Response Headers:', JSON.stringify(response.headers, null, 2)) debug('Response Headers:', JSON.stringify(response.headers, null, 2))
debug('Response Body:', JSON.stringify(response.body, null, 2)) debug('Response Body:', JSON.stringify(response.body, null, 2))
resolve() resolve(response)
} }
}, },
) )