diff --git a/app.js b/app.js index 97c710a..75b8553 100644 --- a/app.js +++ b/app.js @@ -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) { @@ -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)}?`); @@ -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. , "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" ) { diff --git a/config/rules.js b/config/rules.js index 643ef99..41d5848 100644 --- a/config/rules.js +++ b/config/rules.js @@ -7,5 +7,25 @@ export default [ callback: { uri: "http://maildelivery/send", method: "PATCH" } + }, + { + match: { + subject: { + ask: "?org ?identifier. ?identifier {{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 + } } ];