Skip to content

Commit

Permalink
Merge webId and actors + fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
srosset81 committed Feb 13, 2020
1 parent 35bf4d7 commit 8d3bc87
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 115 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ docker-restart:
$(DOCKER_COMPOSE) up -d --force-recreate

log:
$(DOCKER_COMPOSE) logs -f middleware fuseki frontend mongo
$(DOCKER_COMPOSE) logs -f middleware frontend

log-prod:
$(DOCKER_COMPOSE_PROD) logs -f middleware fuseki frontend mongo
Expand Down
6 changes: 2 additions & 4 deletions src/middleware/boilerplates/runner/createServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const {
OutboxService,
InboxService,
FollowService,
CollectionService,
TripleStoreCollectionService,
ActorService,
ObjectService
} = require('@semapps/activitypub');
Expand Down Expand Up @@ -51,9 +51,7 @@ function createServices(broker) {
});

// ActivityPub
broker.createService(CollectionService, {
adapter: new MongoDbAdapter(CONFIG.MONGODB_URL)
});
broker.createService(TripleStoreCollectionService);
broker.createService(ActorService, {
adapter: new TripleStoreAdapter('ldp'),
settings: {
Expand Down
2 changes: 1 addition & 1 deletion src/middleware/packages/activitypub/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
ActorService: require('./services/actor'),
ActivityService: require('./services/activity'),
CollectionService: require('./services/collection-mongodb'),
TripleStoreCollectionService: require('./services/collection'),
FollowService: require('./services/follow'),
InboxService: require('./services/inbox'),
ObjectService: require('./services/object'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const JsonLdStorageMixin = {
before: {
create: [
function addId(ctx) {
if (!ctx.params['@id']) {
if (!ctx.params['id'] && !ctx.params['@id']) {
// If no ID has been set, generate one based on the container URI
if (ctx.params['slug']) {
ctx.params['@id'] = ctx.service.schema.settings.containerUri + ctx.params['slug'];
Expand Down
6 changes: 6 additions & 0 deletions src/middleware/packages/activitypub/services/actor.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ const ActorService = {
name: userData.name + ' ' + userData.familyName
});
},
async 'webid.updated'(userData) {
// TODO
},
async 'webid.removed'(userData) {
// TODO
},
'actor.created'() {
// Do nothing. We must define one event listener for EventsWatcher middleware to act correctly.
}
Expand Down
138 changes: 32 additions & 106 deletions src/middleware/packages/activitypub/services/collection.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'use strict';

const jsonld = require('jsonld');

const CollectionService = {
const TripleStoreCollectionService = {
name: 'activitypub.collection',
dependencies: ['triplestore'],
actions: {
Expand All @@ -15,7 +13,7 @@ const CollectionService = {
const collection = {
'@context': 'https://www.w3.org/ns/activitystreams',
id: ctx.params.collectionUri,
type: ['Collection', 'OrderedCollection'],
type: ctx.params.ordered ? ['Collection', 'OrderedCollection'] : 'Collection',
summary: ctx.params.summary
};

Expand Down Expand Up @@ -44,18 +42,18 @@ const CollectionService = {
/*
* Attach an object to a collection
* @param collectionUri The full URI of the collection
* @param objectUri The full URI of the object to add to the collection
* @param item The resource to add to the collection
*/
async attach(ctx) {
const collectionExist = ctx.call('activitypub.collection.exist', {
collectionUri: ctx.params.collectionUri
});
if (!collectionExist) throw new Error('Cannot attach to an unexisting collection !');
if (!collectionExist) throw new Error('Cannot attach to a non-existing collection !');

const collection = {
'@context': 'https://www.w3.org/ns/activitystreams',
id: ctx.params.collectionUri,
items: ctx.params.objectUri
items: typeof ctx.params.item === 'object' ? ctx.params.item['@id'] : ctx.params.item
};

return await ctx.call('triplestore.insert', {
Expand All @@ -64,126 +62,54 @@ const CollectionService = {
});
},
/*
* Returns a JSON-LD formatted OrderedCollection stored in the triple store
* @param collectionUri The full URI of the collection
* @param optionalTriplesToFetch RDF-formatted triples to fetch (use ?item for the base item)
* Returns a JSON-LD formatted collection stored in the triple store
* @param id The full URI of the collection
*/
async queryOrderedCollection(ctx) {
const result = await ctx.call('triplestore.query', {
async get(ctx) {
let collection = await ctx.call('triplestore.query', {
query: `
PREFIX as: <https://www.w3.org/ns/activitystreams#>
CONSTRUCT {
# We need to define the CONSTRUCT clause because it doesn't work
# when there is an OPTIONAL parameter in the WHERE clause
<${ctx.params.collectionUri}>
a as:OrderedCollection ;
<${ctx.params.id}>
a ?type ;
as:items ?item .
?item ?itemP ?itemO .
${ctx.params.optionalTriplesToFetch || ''}
}
WHERE {
<${ctx.params.collectionUri}> a as:OrderedCollection .
<${ctx.params.id}> a ?type .
OPTIONAL {
<${ctx.params.collectionUri}> as:items ?item .
?item ?itemP ?itemO .
${ctx.params.optionalTriplesToFetch || ''}
<${ctx.params.id}> as:items ?item .
}
}
ORDER BY ?published # Order by activities publication
`,
accept: 'json'
});

let framed = await jsonld.frame(result, {
'@context': 'https://www.w3.org/ns/activitystreams',
type: 'OrderedCollection'
});
framed = framed['@graph'][0];

if (!framed) {
// If no items was attached, the collection wasn't created
return null;
} else {
if (!framed.items) framed.items = [];
// If there is only one item, we receive it as an object so put it in an array
else if (!Array.isArray(framed.items)) framed.items = [framed.items];

return {
'@context': 'https://www.w3.org/ns/activitystreams',
id: framed.id,
type: framed.type,
summary: framed.summary,
totalItems: framed.items.length,
orderedItems: framed.items
};
}
},
/*
* Returns a JSON-LD formatted Collection stored in the triple store
* @param collectionUri The full URI of the collection
*/
async queryCollection(ctx) {
const result = await ctx.call('triplestore.query', {
query: `
PREFIX as: <https://www.w3.org/ns/activitystreams#>
CONSTRUCT {
<${ctx.params.collectionUri}>
a as:Collection ;
as:items ?item
}
WHERE {
<${ctx.params.collectionUri}> a as:Collection .
OPTIONAL { <${ctx.params.collectionUri}> as:items ?item . }
}
`,
accept: 'json'
collection = await jsonld.compact(collection, {
'@context': 'https://www.w3.org/ns/activitystreams'
});

let framed = await jsonld.frame(result, {
'@context': 'https://www.w3.org/ns/activitystreams',
type: 'Collection'
});
framed = framed['@graph'][0];
if (!collection.items) collection.items = [];
// If there is only one item, we receive it as an object so put it in an array
else if (!Array.isArray(collection.items)) collection.items = [collection.items];

if (!framed) {
// If no items was attached, the collection wasn't created
return null;
} else {
if (!framed.items) framed.items = [];
// If there is only one item, we receive it as an object so put it in an array
else if (!Array.isArray(framed.items)) framed.items = [framed.items];
collection.totalItems = collection.items.length ;

return {
'@context': 'https://www.w3.org/ns/activitystreams',
id: framed.id,
type: framed.type,
summary: framed.summary,
totalItems: framed.items ? framed.items.length : 0,
items: framed.items
};
if( this.isOrderedCollection(collection) ) {
collection.orderedItems = collection.items;
delete collection.items;
}
},
/*
* Returns a simple array of the resources URIs contained in the collection
* @param collectionUri The full URI of the collection
*/
async queryItems(ctx) {
const results = await ctx.call('triplestore.query', {
query: `
PREFIX as: <https://www.w3.org/ns/activitystreams#>
SELECT ?item
WHERE {
<${ctx.params.collectionUri}>
a as:Collection ;
as:items ?item
}
`,
accept: 'json'
});

return results ? results.map(item => item.item.value) : [];
return collection;
}
},
methods: {
isOrderedCollection(collection) {
return (
collection.type === 'OrderedCollection' ||
(Array.isArray(collection.type) && collection.type.includes('OrderedCollection'))
);
}
}
};

module.exports = CollectionService;
module.exports = TripleStoreCollectionService;
2 changes: 1 addition & 1 deletion src/middleware/packages/activitypub/services/inbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const InboxService = {
} else if (recipient === this.getFollowersUri(activity.actor)) {
// Followers list. Add the list of followers.
const collection = await this.broker.call('activitypub.collection.get', { id: recipient });
if (collection) output.push(...this.defaultToArray(collection.items));
if (collection && collection.items) output.push(...this.defaultToArray(collection.items));
} else {
// Simple actor URI
output.push(recipient);
Expand Down
1 change: 0 additions & 1 deletion src/middleware/packages/ldp/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ class TripleStoreAdapter {
* Remove an entity by ID
*/
removeById(_id) {
console.log('_id', _id);
return this.broker.call(this.ldpServiceName + '.delete', {
accept: 'application/ld+json',
'@context': this.service.schema.settings.context,
Expand Down

0 comments on commit 8d3bc87

Please sign in to comment.