Skip to content

Commit 758518e

Browse files
authored
Merge pull request #1394 from assemblee-virtuelle/allow-transient-activities
Allow to post transient activities
2 parents 518c8c9 + a4d803d commit 758518e

4 files changed

Lines changed: 61 additions & 47 deletions

File tree

src/middleware/packages/activitypub/services/activitypub/subservices/activity-handlers/setRightsHandler.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { hasType } = require('@semapps/ldp');
1+
const { hasType, getId } = require('@semapps/ldp');
22
const { ACTIVITY_TYPES } = require('../../../../constants');
33

44
// const removeReadRights = async ({ ctx, recipientUris, resourceUri, skipObjectsWatcher, anon }) => {
@@ -53,7 +53,7 @@ const setRightsHandler = {
5353
match: '*',
5454
priority: 1,
5555
async onEmit(ctx, activity) {
56-
const activityUri = activity['@id'] || activity.id;
56+
const activityUri = getId(activity);
5757
const newRecipients = await ctx.call('activitypub.activity.getRecipients', { activity });
5858
const activityIsPublic = await ctx.call('activitypub.activity.isPublic', { activity });
5959
/** @type {string} */
@@ -65,14 +65,16 @@ const setRightsHandler = {
6565
if (!newRecipients.includes(activity.actor)) newRecipients.push(activity.actor);
6666
}
6767

68-
// Give read rights to the activity's recipients.
69-
await addReadRights({
70-
ctx,
71-
resourceUri: activityUri,
72-
recipientUris: newRecipients,
73-
skipObjectsWatcher: true,
74-
anon: activityIsPublic
75-
});
68+
// Give read rights to the recipients, unless the activity is transient
69+
if (!activityUri.includes('#')) {
70+
await addReadRights({
71+
ctx,
72+
resourceUri: activityUri,
73+
recipientUris: newRecipients,
74+
skipObjectsWatcher: true,
75+
anon: activityIsPublic
76+
});
77+
}
7678

7779
// If Create or Update activity, also give rights to the created object.
7880
if (hasType(activity, ACTIVITY_TYPES.CREATE) || hasType(activity, ACTIVITY_TYPES.UPDATE)) {

src/middleware/packages/activitypub/services/activitypub/subservices/object.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { getType } = require('@semapps/ldp');
12
const { MIME_TYPES } = require('@semapps/mime-types');
23
const { OBJECT_TYPES, ACTIVITY_TYPES } = require('../../../constants');
34

@@ -23,26 +24,29 @@ const ObjectService = {
2324
accept: MIME_TYPES.JSON
2425
});
2526
},
26-
async process(ctx) {
27-
let { activity, actorUri } = ctx.params;
28-
let activityType = activity.type || activity['@type'];
29-
let objectUri;
27+
// If an object is passed directly, wrap it in a Create activity
28+
async wrap(ctx) {
29+
const { activity } = ctx.params;
3030

31-
// If an object is passed directly, first wrap it in a Create activity
32-
if (Object.values(OBJECT_TYPES).includes(activityType)) {
31+
if (Object.values(OBJECT_TYPES).includes(getType(activity))) {
3332
const { to, cc, '@id': id, ...object } = activity;
34-
activityType = ACTIVITY_TYPES.CREATE;
35-
activity = {
33+
return {
3634
'@context': object['@context'],
37-
type: activityType,
35+
type: ACTIVITY_TYPES.CREATE,
3836
to,
3937
cc,
4038
actor: object.attributedTo,
4139
object
4240
};
41+
} else {
42+
return activity;
4343
}
44+
},
45+
async process(ctx) {
46+
let { activity, actorUri } = ctx.params;
47+
let objectUri;
4448

45-
switch (activityType) {
49+
switch (getType(activity)) {
4650
case ACTIVITY_TYPES.CREATE: {
4751
// If the object passed is an URI, this is an announcement and there is nothing to process
4852
if (typeof activity.object === 'string') break;

src/middleware/packages/activitypub/services/activitypub/subservices/outbox.js

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const fetch = require('node-fetch');
22
const { Errors: E } = require('moleculer-web');
33
const { MIME_TYPES } = require('@semapps/mime-types');
4+
const { getType, arrayOf } = require('@semapps/ldp');
45
const { collectionPermissionsWithAnonRead, getSlugFromUri, objectIdToCurrent } = require('../../../utils');
56
const { ACTOR_TYPES } = require('../../../constants');
67
const AwaitActivityMixin = require('../../../mixins/await-activity');
@@ -41,7 +42,8 @@ const OutboxService = {
4142
},
4243
actions: {
4344
async post(ctx) {
44-
let { collectionUri, username, ...activity } = ctx.params;
45+
let { collectionUri, username, transient, ...activity } = ctx.params;
46+
let activityUri;
4547

4648
const collectionExists = await ctx.call('activitypub.collection.exist', { resourceUri: collectionUri });
4749
if (!collectionExists) {
@@ -69,7 +71,10 @@ const OutboxService = {
6971
activity['@context'] = await ctx.call('jsonld.context.get');
7072
}
7173

72-
if (!ctx.meta.doNotProcessObject) {
74+
// Wrap object in Create activity, if necessary
75+
activity = await ctx.call('activitypub.object.wrap', { activity });
76+
77+
if (!ctx.meta.doNotProcessObject && transient !== true) {
7378
// Process object create, update or delete
7479
// and return an activity with the object ID
7580
activity = await ctx.call('activitypub.object.process', { activity, actorUri });
@@ -80,42 +85,44 @@ const OutboxService = {
8085
}
8186

8287
// Use the current time for the activity's publish date
83-
// TODO use it to order the ordered collections
8488
activity.published = new Date().toISOString();
8589

86-
const activitiesContainerUri = await ctx.call('activitypub.activity.getContainerUri', {
87-
webId: actorUri
88-
});
89-
90-
// There might be a capability attached which should not be persisted
91-
// because other's could otherwise read it from the (public) outbox.
92-
let { capability, ...activityToPersist } = activity;
90+
if (transient === true) {
91+
// Object or actor URI + hash with lower case activity
92+
activityUri = `${activity.object || activity.actor}#${arrayOf(getType(activity))[0].toLowerCase()}`;
93+
activity = { id: activityUri, ...activity };
94+
} else {
95+
const activitiesContainerUri = await ctx.call('activitypub.activity.getContainerUri', {
96+
webId: actorUri
97+
});
9398

94-
const activityUri = await ctx.call('activitypub.activity.post', {
95-
containerUri: activitiesContainerUri,
96-
resource: activityToPersist,
97-
contentType: MIME_TYPES.JSON,
98-
webId: 'system' // Post as system since there is no write permission to the activities container
99-
});
99+
activityUri = await ctx.call('activitypub.activity.post', {
100+
containerUri: activitiesContainerUri,
101+
resource: activity,
102+
contentType: MIME_TYPES.JSON,
103+
webId: 'system' // Post as system since there is no write permission to the activities container
104+
});
100105

101-
activityToPersist = await ctx.call('activitypub.activity.get', { resourceUri: activityUri, webId: 'system' });
102-
// Reattach capability for further processing (if available).
103-
activity = { ...activityToPersist, capability };
106+
activity = await ctx.call('activitypub.activity.get', { resourceUri: activityUri, webId: 'system' });
107+
}
104108

105109
try {
106-
// Notify listeners of activities.
107110
await ctx.call('activitypub.side-effects.processOutbox', { activity });
108111
} catch (e) {
109-
await ctx.call('activitypub.activity.delete', { resourceUri: activityUri, webId: 'system' });
112+
if (transient !== true) {
113+
await ctx.call('activitypub.activity.delete', { resourceUri: activityUri, webId: 'system' });
114+
}
110115
// TODO unprocess objects
111116
throw e;
112117
}
113118

114-
// Attach the newly-created activity to the outbox
115-
await ctx.call('activitypub.collection.add', {
116-
collectionUri,
117-
item: activityToPersist
118-
});
119+
if (transient !== true) {
120+
// Attach the newly-created activity to the outbox
121+
await ctx.call('activitypub.collection.add', {
122+
collectionUri,
123+
item: activity
124+
});
125+
}
119126

120127
const localRecipients = [];
121128
const remoteRecipients = [];

src/middleware/packages/sync/middlewares/objects-watcher.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const handledWacActions = [
1010
];
1111

1212
const ObjectsWatcherMiddleware = (config = {}) => {
13-
const { baseUrl, podProvider = false, postWithoutRecipients = false } = config;
13+
const { baseUrl, podProvider = false, postWithoutRecipients = false, transientActivities = false } = config;
1414
let relayActor;
1515
let excludedContainersPathRegex = [];
1616
let initialized = false;
@@ -75,6 +75,7 @@ const ObjectsWatcherMiddleware = (config = {}) => {
7575
'activitypub.outbox.post',
7676
{
7777
collectionUri: actor.outbox,
78+
transient: transientActivities,
7879
'@context': 'https://www.w3.org/ns/activitystreams',
7980
...activity,
8081
bto: recipients

0 commit comments

Comments
 (0)