Skip to content

Commit

Permalink
Merge pull request #1242 from assemblee-virtuelle/refactor-collections
Browse files Browse the repository at this point in the history
Refactor ActivityStreams collections
  • Loading branch information
srosset81 authored Apr 19, 2024
2 parents 9520203 + b93f5d8 commit f292da8
Show file tree
Hide file tree
Showing 68 changed files with 1,934 additions and 934 deletions.
6 changes: 3 additions & 3 deletions src/middleware/packages/activitypub/containers.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const { ACTOR_TYPES, OBJECT_TYPES } = require('./constants');
const { FULL_ACTOR_TYPES, FULL_OBJECT_TYPES } = require('./constants');

module.exports = [
{
path: '/as/actor',
acceptedTypes: Object.values(ACTOR_TYPES)
acceptedTypes: Object.values(FULL_ACTOR_TYPES)
},
{
path: '/as/object',
acceptedTypes: Object.values(OBJECT_TYPES)
acceptedTypes: Object.values(FULL_OBJECT_TYPES)
}
];
2 changes: 1 addition & 1 deletion src/middleware/packages/activitypub/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ const constants = require('./constants');

module.exports = {
ActivityPubService: require('./services/activitypub'),
ActivityPubMigrationService: require('./services/migration'),
ActivityMappingService: require('./services/activity-mapping'),
RelayService: require('./services/relay'),
// Mixins
BotMixin: require('./mixins/bot'),
ControlledCollectionMixin: require('./mixins/controlled-collection'),
ActivitiesHandlerMixin: require('./mixins/activities-handler'),
// Misc.
matchActivity: require('./utils/matchActivity'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const ActivitiesHandlerMixin = {
return;
}

ctx.meta.webId = actorUri;

if (boxType === 'inbox' && activityHandler.onReceive) {
await activityHandler.onReceive.bind(this)(ctx, dereferencedActivity, actorUri);
} else if (boxType === 'outbox' && activityHandler.onEmit) {
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions src/middleware/packages/activitypub/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"moleculer-db": "^0.8.16",
"moleculer-web": "^0.10.0-beta1",
"node-fetch": "^2.6.6",
"sparqljs": "^3.5.2",
"url-join": "^4.0.1"
},
"publishConfig": {
Expand Down
35 changes: 18 additions & 17 deletions src/middleware/packages/activitypub/services/activitypub/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,36 @@ const { as, sec } = require('@semapps/ontologies');
const ActorService = require('./subservices/actor');
const ActivitiesWatcherService = require('./subservices/activities-watcher');
const ActivityService = require('./subservices/activity');
const ApiService = require('./subservices/api');
const CollectionService = require('./subservices/collection');
const FollowService = require('./subservices/follow');
const InboxService = require('./subservices/inbox');
const LikeService = require('./subservices/like');
const ObjectService = require('./subservices/object');
const OutboxService = require('./subservices/outbox');
const RegistryService = require('./subservices/registry');
const CollectionsRegistryService = require('./subservices/collections-registry');
const ReplyService = require('./subservices/reply');
const { OBJECT_TYPES, ACTOR_TYPES } = require('../../constants');
const { ACTOR_TYPES } = require('../../constants');

const ActivityPubService = {
name: 'activitypub',
settings: {
baseUri: null,
podProvider: false,
activitiesPath: '/as/activity',
activateTombstones: true,
selectActorData: null,
queueServiceUrl: null,
like: {
attachToObjectTypes: null,
attachToActorTypes: null
},
follow: {
attachToActorTypes: null
},
reply: {
attachToObjectTypes: null
}
},
dependencies: ['api', 'ontologies'],
created() {
const { baseUri, podProvider, activitiesPath, selectActorData, queueServiceUrl, reply, like, follow } =
const { baseUri, podProvider, activitiesPath, selectActorData, queueServiceUrl, activateTombstones, like, follow } =
this.settings;

this.broker.createService(ActivitiesWatcherService);
Expand All @@ -45,7 +43,7 @@ const ActivityPubService = {
}
});

this.broker.createService(RegistryService, {
this.broker.createService(CollectionsRegistryService, {
settings: {
baseUri,
podProvider
Expand All @@ -60,13 +58,21 @@ const ActivityPubService = {
}
});

this.broker.createService(ObjectService, {
this.broker.createService(ApiService, {
settings: {
baseUri,
podProvider
}
});

this.broker.createService(ObjectService, {
settings: {
baseUri,
podProvider,
activateTombstones
}
});

this.broker.createService(ActivityService, {
settings: {
baseUri,
Expand All @@ -76,30 +82,25 @@ const ActivityPubService = {

this.broker.createService(FollowService, {
settings: {
baseUri,
attachToActorTypes: follow.attachToActorTypes || Object.values(ACTOR_TYPES)
baseUri
}
});

this.broker.createService(InboxService, {
settings: {
baseUri,
podProvider
}
});

this.broker.createService(LikeService, {
settings: {
baseUri,
attachToObjectTypes: like.attachToObjectTypes || Object.values(OBJECT_TYPES),
attachToActorTypes: like.attachToActorTypes || Object.values(ACTOR_TYPES)
baseUri
}
});

this.broker.createService(ReplyService, {
settings: {
baseUri,
attachToObjectTypes: reply.attachToObjectTypes || Object.values(OBJECT_TYPES)
baseUri
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ const { ControlledContainerMixin } = require('@semapps/ldp');
const { MIME_TYPES } = require('@semapps/mime-types');
const { Errors: E } = require('moleculer-web');
const { objectCurrentToId, objectIdToCurrent, arrayOf } = require('../../../utils');
const { PUBLIC_URI, ACTIVITY_TYPES } = require('../../../constants');
const { PUBLIC_URI, FULL_ACTIVITY_TYPES } = require('../../../constants');

const ActivityService = {
name: 'activitypub.activity',
mixins: [ControlledContainerMixin],
settings: {
baseUri: null,
path: '/as/activity',
acceptedTypes: Object.values(ACTIVITY_TYPES),
acceptedTypes: Object.values(FULL_ACTIVITY_TYPES),
accept: MIME_TYPES.JSON,
permissions: {},
newResourcesPermissions: {},
readOnly: true,
excludeFromMirror: true,
activateTombstones: false,
controlledActions: {
// Activities shouldn't be handled manually
patch: 'activitypub.activity.forbidden',
Expand Down Expand Up @@ -50,7 +51,7 @@ const ActivityService = {
// TODO Fetch remote followers list ?
if (recipient.startsWith(this.settings.baseUri)) {
const collection = await ctx.call('activitypub.collection.get', {
collectionUri: recipient,
resourceUri: recipient,
webId: activity.actor
});
if (collection && collection.items) output.push(...arrayOf(collection.items));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
const urlJoin = require('url-join');
const { arrayOf } = require('@semapps/ldp');
const {
parseUrl,
parseHeader,
parseSparql,
negotiateContentType,
negotiateAccept,
parseJson,
parseTurtle,
parseFile,
saveDatasetMeta
} = require('@semapps/middlewares');
const { FULL_ACTOR_TYPES } = require('../../../constants');

const ApiService = {
name: 'activitypub.api',
settings: {
baseUri: null,
podProvider: false
},
dependencies: ['api', 'ldp', 'ldp.registry'],
async started() {
const resourcesWithContainerPath = await this.broker.call('ldp.getSetting', { key: 'resourcesWithContainerPath' });
if (this.settings.podProvider) {
await this.broker.call('api.addRoute', { route: this.getBoxesRoute('/:username([^/.][^/]+)') });
} else if (!resourcesWithContainerPath) {
await this.broker.call('api.addRoute', { route: this.getBoxesRoute(`/:actorSlug`) });
} else {
// If some actor containers are already registered, add the corresponding API routes
const registeredContainers = await this.broker.call('ldp.registry.list');
for (const container of Object.values(registeredContainers)) {
if (arrayOf(container.acceptedTypes).some(type => Object.values(FULL_ACTOR_TYPES).includes(type))) {
await this.broker.call('api.addRoute', { route: this.getBoxesRoute(`${container.fullPath}/:actorSlug`) });
}
}
}
},
actions: {
async inbox(ctx) {
const { actorSlug, ...activity } = ctx.params;
const { requestUrl } = ctx.meta;

await ctx.call('activitypub.inbox.post', {
collectionUri: urlJoin(this.settings.baseUri, requestUrl),
...activity
});

ctx.meta.$statusCode = 202;
},
async outbox(ctx) {
let { actorSlug, ...activity } = ctx.params;
const { requestUrl } = ctx.meta;

activity = await ctx.call('activitypub.outbox.post', {
collectionUri: urlJoin(this.settings.baseUri, requestUrl),
...activity
});

ctx.meta.$responseHeaders = {
Location: activity.id || activity['@id'],
'Content-Length': 0
};
ctx.meta.$statusCode = 201;
}
},
events: {
async 'ldp.registry.registered'(ctx) {
const { container } = ctx.params;
const resourcesWithContainerPath = await this.broker.call('ldp.getSetting', {
key: 'resourcesWithContainerPath'
});
if (
!this.settings.podProvider &&
resourcesWithContainerPath &&
arrayOf(container.acceptedTypes).some(type => Object.values(FULL_ACTOR_TYPES).includes(type))
) {
await ctx.call('api.addRoute', { route: this.getBoxesRoute(`${container.fullPath}/:actorSlug`) });
}
}
},
methods: {
getBoxesRoute(actorsPath) {
const middlewares = [
parseUrl,
parseHeader,
negotiateContentType,
negotiateAccept,
parseSparql,
parseJson,
parseTurtle,
parseFile,
saveDatasetMeta
];

return {
name: this.settings.podProvider ? 'boxes' : `boxes${actorsPath}`,
path: actorsPath,
// Disable the body parsers so that we can parse the body ourselves
// (Moleculer-web doesn't handle non-JSON bodies, so we must do it)
bodyParsers: false,
authorization: false,
authentication: true,
aliases: {
'POST /inbox': [...middlewares, 'activitypub.api.inbox'],
'POST /outbox': [...middlewares, 'activitypub.api.outbox']
}
};
}
}
};

module.exports = ApiService;
Loading

0 comments on commit f292da8

Please sign in to comment.