From 22e31f2b553cdc3a8b6fc87e2800eeab9a5ef282 Mon Sep 17 00:00:00 2001 From: Dmitri Zagidulin Date: Wed, 11 May 2016 16:48:07 -0400 Subject: [PATCH 1/5] Implement server capability discovery --- lib/capability-discovery.js | 64 ++++++++++++++++++++++++++++++++++++ lib/create-app.js | 3 ++ test/capability-discovery.js | 40 ++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 lib/capability-discovery.js create mode 100644 test/capability-discovery.js diff --git a/lib/capability-discovery.js b/lib/capability-discovery.js new file mode 100644 index 000000000..2912338b7 --- /dev/null +++ b/lib/capability-discovery.js @@ -0,0 +1,64 @@ +'use strict' +/** + * @module capability-discovery + */ +const express = require('express') +const addLink = require('./header').addLink +const util = require('./utils') + +const serviceConfig = { + 'api': { + 'account.changepassword': '/api/account/changepassword', + 'account.delete': '/api/account/delete', + 'account.new': '/api/account/new', + 'account.recover': '/api/account/recover', + 'account.signin': '/api/account/signin', + 'account.signout': '/api/account/signout' + } +} + +module.exports = capabilityDiscovery + +/** + * Returns a set of routes to deal with server capability discovery + * @method capabilityDiscovery + * @return {Router} Express router + */ +function capabilityDiscovery () { + var router = express.Router('/') + + // Advertise the server capability discover endpoint + router.options('*', serviceEndpointHeader) + router.get('/.well-known/solid', serviceCapabilityDocument(serviceConfig)) + return router +} + +/** + * Handles advertising the server capability endpoint (adds a Link Relation + * header of type `service`, points to the capability document). + * To be used with OPTIONS requests. + * @method serviceEndpointHeader + * @param req + * @param res + * @param next + */ +function serviceEndpointHeader (req, res, next) { + let serviceEndpoint = `${util.uriBase(req)}/.well-known/solid` + addLink(res, serviceEndpoint, 'service') + next() +} + +/** + * Serves the service capability document (containing server root URL, including + * any base path the user specified in config, server API endpoints, etc). + * @method serviceCapabilityDocument + * @param req + * @param res + * @param next + */ +function serviceCapabilityDocument (serviceConfig) { + return (req, res, next) => { + serviceConfig.root = util.uriBase(req) + res.json(serviceConfig) + } +} diff --git a/lib/create-app.js b/lib/create-app.js index 156bb3f4c..4bd46d89e 100644 --- a/lib/create-app.js +++ b/lib/create-app.js @@ -12,6 +12,7 @@ var vhost = require('vhost') var path = require('path') var EmailService = require('./email-service') const AccountRecovery = require('./account-recovery') +const capabilityDiscovery = require('./capability-discovery') var corsSettings = cors({ methods: [ @@ -76,6 +77,8 @@ function createApp (argv = {}) { next() }) + app.use('/', capabilityDiscovery()) + // Session app.use(session(sessionSettings)) diff --git a/test/capability-discovery.js b/test/capability-discovery.js new file mode 100644 index 000000000..30fd09a30 --- /dev/null +++ b/test/capability-discovery.js @@ -0,0 +1,40 @@ +var supertest = require('supertest') +var ldnode = require('../index') +var path = require('path') +var expect = require('chai').expect + +var ldpServer = ldnode.createServer({ + live: true, + root: path.join(__dirname, '/resources') +}) +var server = supertest(ldpServer) + +describe('Capability Discovery', function () { + describe('GET Service Capability document', function () { + it('should exist', function (done) { + server.get('/.well-known/solid') + .expect(200, done) + }) + it('should be a json file by default', function (done) { + server.get('/.well-known/solid') + .expect('content-type', /application\/json/) + .expect(200, done) + }) + it('includes a root element', function (done) { + server.get('/.well-known/solid') + .end(function (err, req) { + expect(req.body.root).to.exist + return done(err) + }) + }) + }) + + describe('OPTIONS API', function () { + it('should set the service Link header', + function (done) { + server.options('/') + .expect('Link', /<.*\.well-known\/solid>; rel="service"/) + .expect(204, done) + }) + }) +}) From 70aec89b0e9ec62dfa5ed488e893ca5b8badc378 Mon Sep 17 00:00:00 2001 From: Dmitri Zagidulin Date: Wed, 11 May 2016 16:55:42 -0400 Subject: [PATCH 2/5] Add CORS headers to capability discovery --- lib/capability-discovery.js | 5 +++-- lib/create-app.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/capability-discovery.js b/lib/capability-discovery.js index 2912338b7..d270a85f9 100644 --- a/lib/capability-discovery.js +++ b/lib/capability-discovery.js @@ -24,12 +24,13 @@ module.exports = capabilityDiscovery * @method capabilityDiscovery * @return {Router} Express router */ -function capabilityDiscovery () { +function capabilityDiscovery (corsSettings) { var router = express.Router('/') // Advertise the server capability discover endpoint router.options('*', serviceEndpointHeader) - router.get('/.well-known/solid', serviceCapabilityDocument(serviceConfig)) + router.get('/.well-known/solid', corsSettings, + serviceCapabilityDocument(serviceConfig)) return router } diff --git a/lib/create-app.js b/lib/create-app.js index 4bd46d89e..a0e3f8558 100644 --- a/lib/create-app.js +++ b/lib/create-app.js @@ -77,7 +77,7 @@ function createApp (argv = {}) { next() }) - app.use('/', capabilityDiscovery()) + app.use('/', capabilityDiscovery(corsSettings)) // Session app.use(session(sessionSettings)) From 00502b51750fe57bfac0f5cd10dab079d649442f Mon Sep 17 00:00:00 2001 From: Nicola Greco Date: Wed, 11 May 2016 17:04:25 -0400 Subject: [PATCH 3/5] updating default config --- lib/capability-discovery.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/capability-discovery.js b/lib/capability-discovery.js index d270a85f9..e9b33e977 100644 --- a/lib/capability-discovery.js +++ b/lib/capability-discovery.js @@ -8,12 +8,15 @@ const util = require('./utils') const serviceConfig = { 'api': { - 'account.changepassword': '/api/account/changepassword', - 'account.delete': '/api/account/delete', - 'account.new': '/api/account/new', - 'account.recover': '/api/account/recover', - 'account.signin': '/api/account/signin', - 'account.signout': '/api/account/signout' + 'accounts: { + // 'changePassword': '/api/account/changePassword', + // 'delete': '/api/accounts/delete', + 'new': '/api/accounts/new', + 'recover': '/api/accounts/recover', + 'signin': '/api/accounts/signin', + 'signout': '/api/accounts/signout', + 'validateToken': '/api/accounts/validateToken' + } } } @@ -59,7 +62,7 @@ function serviceEndpointHeader (req, res, next) { */ function serviceCapabilityDocument (serviceConfig) { return (req, res, next) => { - serviceConfig.root = util.uriBase(req) + serviceConfig.root = req.uriBase(req) // TODO make sure we align with the rest res.json(serviceConfig) } } From e6bd25ea78db5ec5e169f81342044273de96c3cc Mon Sep 17 00:00:00 2001 From: Nicola Greco Date: Wed, 11 May 2016 17:05:44 -0400 Subject: [PATCH 4/5] Update capability-discovery.js --- lib/capability-discovery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/capability-discovery.js b/lib/capability-discovery.js index e9b33e977..abb750dcd 100644 --- a/lib/capability-discovery.js +++ b/lib/capability-discovery.js @@ -8,7 +8,7 @@ const util = require('./utils') const serviceConfig = { 'api': { - 'accounts: { + 'accounts': { // 'changePassword': '/api/account/changePassword', // 'delete': '/api/accounts/delete', 'new': '/api/accounts/new', From 581b80a460eb8ac43abf96b699fa6a177031ec9e Mon Sep 17 00:00:00 2001 From: nicola Date: Wed, 11 May 2016 17:10:18 -0400 Subject: [PATCH 5/5] misnaming a function --- lib/capability-discovery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/capability-discovery.js b/lib/capability-discovery.js index abb750dcd..0a347d61b 100644 --- a/lib/capability-discovery.js +++ b/lib/capability-discovery.js @@ -62,7 +62,7 @@ function serviceEndpointHeader (req, res, next) { */ function serviceCapabilityDocument (serviceConfig) { return (req, res, next) => { - serviceConfig.root = req.uriBase(req) // TODO make sure we align with the rest + serviceConfig.root = util.uriBase(req) // TODO make sure we align with the rest res.json(serviceConfig) } }