Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

basic ask functionality #10

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { app, uuid } from 'mu';
import { app, uuid, sparql, query } from 'mu';
import request from 'request';
import services from '/config/rules.js';
import bodyParser from 'body-parser';
import dns from 'dns';

const expensiveChecks = ['ask', 'class'];

// Also parse application/json as json
app.use( bodyParser.json( {
type: function(req) {
Expand Down Expand Up @@ -90,7 +92,7 @@ async function informWatchers( changeSets, res, muCallIdTrail ){
} );
}

function tripleMatchesSpec( triple, matchSpec ) {
async function tripleMatchesSpec( triple, matchSpec ) {
// form of triple is {s, p, o}, same as matchSpec
if( process.env["DEBUG_TRIPLE_MATCHES_SPEC"] )
console.log(`Does ${JSON.stringify(triple)} match ${JSON.stringify(matchSpec)}?`);
Expand All @@ -102,15 +104,42 @@ function tripleMatchesSpec( triple, matchSpec ) {

if( subMatchSpec && !subMatchValue )
return false;

for( let subKey in subMatchSpec )
// we're now matching something like {type: "url", value: "http..."}
if( subMatchSpec[subKey] !== subMatchValue[subKey] )
// first iteration performs the cheap checks locally.
if( !isExpensiveCheck(subKey) && subMatchSpec[subKey] !== subMatchValue[subKey] )
return false;
}

for( let key in matchSpec ){
// key is one of s, p, o
const subMatchSpec = matchSpec[key];
const subMatchValue = triple[key];

for( let subKey in subMatchSpec )
// second iteration performs more expensive checks.
if( subKey == "ask" ) {
const matchesSpec = await askMatchSpec(subMatchValue['value'], subMatchSpec['ask']);
if( !matchesSpec )
return false;
}
}
return true; // no false matches found, let's send a response
}

function isExpensiveCheck( key ) {
return expensiveChecks.includes( key );
}

// TODO: make more intelligent: type handling. i.e. <uriValue>, "literalValue", ...
async function askMatchSpec( resource, queryTemplate) {
const q = `ASK {
${queryTemplate.replace(/{{this}}/g, `<${resource}>`)}
}`;
var result = await query(q);
return result.boolean;
}

function formatChangesetBody( changeSets, options ) {
if( options.resourceFormat == "v0.0.1" ) {
Expand Down
20 changes: 20 additions & 0 deletions config/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,25 @@ export default [
callback: {
uri: "http://maildelivery/send", method: "PATCH"
}
},
{
match: {
subject: {
ask: "?org <http://www.w3.org/ns/adms#identifier> ?identifier. ?identifier <https://data.vlaanderen.be/ns/generiek#gestructureerdeIdentificator> {{this}}"
},
predicate: {
type: 'uri',
value: 'https://data.vlaanderen.be/ns/generiek#lokaleIdentificator'
}
},
callback: {
url: "http://kalliope-api/delta",
method: "POST"
},
options: {
resourceFormat: "v0.0.1",
gracePeriod: 1000,
ignoreFromSelf: true
}
}
];