Skip to content
Merged
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
32 changes: 24 additions & 8 deletions config/sample.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
{
adminPass: "default",
adminSessionSecret: "default",
env: "dev",
port: 8080,
sandboxToken: "a8654152-74c0-41dd-a954-bcab50ff99d4",
sandboxServer: "https://pg-api.sensorup.com",
sandboxPath: "/st-playground/proxy/v1.0",
version: "1.0"
"adminPass": "default",
"adminSessionSecret": "default",
"env": "dev",
"port": 8080,
"sensorthings": {
"remote": {
"server": "https://pg-api.sensorup.com",
"path": "/st-playground/proxy/v1.0",
"credentials": {
"header": "St-P-Access-Token",
"value": "a8654152-74c0-41dd-a954-bcab50ff99d4"
}
},
"local": {
"db": {
"host": "localhost",
"port": "5432",
"name": "default",
"user": "default",
"password": "default"
}
}
},
"version": "1.0"
}
24 changes: 16 additions & 8 deletions config/test.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@

{
adminPass: "1.TestPassword.1",
adminSessionSecret: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
env: "test",
port: 8080,
sandboxToken: "a8654152-74c0-41dd-a954-bcab50ff99d4",
sandboxServer: "https://pg-api.sensorup.com",
sandboxPath: "/st-playground/proxy/v1.0",
version: "1.0"
"adminPass": "1.TestPassword.1",
"adminSessionSecret": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
"env": "test",
"port": 8080,
"sensorthings": {
"remote": {
"server": "https://pg-api.sensorup.com",
"path": "/st-playground/proxy/v1.0",
"credentials": {
"header": "St-P-Access-Token",
"value": "a8654152-74c0-41dd-a954-bcab50ff99d4"
}
}
},
"version": "1.0"
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"morgan-body": "^0.9.1",
"pg": "^6.1.0",
"on-headers": "^1.0.1",
"owasp-password-strength-test": "^1.3.0"
"owasp-password-strength-test": "^1.3.0",
"sensorthings": ""
},
"config": {
"blanket": {
Expand Down
104 changes: 81 additions & 23 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,71 @@ const avoidDefault = value => {
}
};

const conf = convict({
const password = value => {
const adminPass = owasp.test(value);
if (!adminPass.strong) {
adminPass.errors.forEach(error => console.error(error));
throw new Error('Admin pass is default or not strong enough.');
}
};

const remoteSTConfig = {
server: {
doc: 'SensorThings remote API server',
format: 'url',
default: 'https://pg-api.sensorup.com'
},
path: {
doc: 'SensorThings remote API path',
default: '/st-playground/proxy/v1.0'
},
credentials: {
header: {
doc: 'SensorThings auth header name',
format: avoidDefault,
default: defaultValue
},
value: {
doc: 'SensorThings auth header value',
format: avoidDefault,
default: defaultValue
}
}
};

const localSTConfig = {
db: {
host: {
doc: 'SensorThings DB host',
default: 'localhost'
},
port: {
doc: 'SensorThings DB port',
format: 'port',
default: 5432
},
name: {
doc: 'SensorThings DB name',
format: avoidDefault,
default: 'postgres'
},
user: {
doc: 'SensorThings DB user',
format: avoidDefault,
default: defaultValue
},
password: {
doc: 'SensorThings DB password',
format: password,
default: defaultValue
}
}
};

let commonConf = {
adminPass: {
doc: 'The password for the admin user. Follow OWASP guidelines for passwords',
format: value => {
const adminPass = owasp.test(value);
if (!adminPass.strong) {
adminPass.errors.forEach(error => console.error(error));
throw new Error('Admin pass is default or not strong enough.');
}
},
format: password,
default: 'invalid'
},
adminSessionSecret: {
Expand All @@ -41,20 +96,7 @@ const conf = convict({
default: 8080,
env: 'PORT'
},
sandboxPath: {
doc: 'SensorThings sandbox API path',
default: '/st-playground/proxy/v1.0'
},
sandboxServer: {
doc: 'SensorThings sandbox API server',
format: 'url',
default: 'https://pg-api.sensorup.com'
},
sandboxToken: {
doc: 'SensorThings sandbox API credentials',
format: avoidDefault,
default: defaultValue
},
sensorthings: {},
version: {
doc: 'API version. We follow SensorThing\'s versioning format as described at http://docs.opengeospatial.org/is/15-078r6/15-078r6.html#34',
format: value => {
Expand All @@ -66,7 +108,9 @@ const conf = convict({
},
default: '1.0'
}
});
};

let conf = convict(commonConf);

// Handle configuration files. You can specify a CSV list of configuration
// files to process, which will be overlayed in order, in the CONFIG_FILES
Expand All @@ -76,6 +120,20 @@ let files = (envConfig + ',' + process.env.CONFIG_FILES)
.split(',')
.filter(fs.existsSync);

conf.loadFile(files);

const currentSTConfig = conf.get('sensorthings');

if (currentSTConfig.local) {
commonConf.sensorthings.local = localSTConfig;
conf = convict(commonConf);
} else if (currentSTConfig.remote) {
commonConf.sensorthings.remote = remoteSTConfig;
conf = convict(commonConf);
} else {
throw new Error('SensorThings needs at least a local or remote configuration');
}

conf.loadFile(files);
conf.validate();

Expand Down
59 changes: 59 additions & 0 deletions src/routes/sensorthings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
*
* This module decides, based on configuration, if we mount our own
* Sensorthings API (through sensortings module) or proxy to an external
* implementation.
*
*/

import proxy from 'express-http-proxy';

import config from '../config';
import { resourceEndpoints } from '../routes/base';
import sensorthings from 'sensorthings'

const localAPI = config.has('sensorthings.local');
let sensorthingsAPI;

if (localAPI) {
//Init DB
sensorthingsAPI = sensorthings;
} else {
/**
*
* At the moment, we are using Sensorup as our remote implementation
* of the Sensorthings API, but we should be able to proxy to any
* other remote server.
*
* You will need to get an access token by creating an account at
* https://pg.sensorup.com/playground.html
*
* Add the access token to your 'sensorthings.remote.credentials.token'
* config file entry.
*/
sensorthingsAPI = proxy(config.get('sensorthings.remote.server'), {
filter: (req, res) => {
const matches = resourceEndpoints.filter(endpoint => {
const regexp = new RegExp('^((?!' + endpoint + ').)*$');
return req.path.match(regexp) == null;
});

// Only the paths listed in the resourcesEndpoints array are handled
// by the proxy.
if (matches.length) {
return true;
}
},
decorateRequest: (proxyReq, originalReq) => {
// Add auth header.
const header = config.get('sensorthings.remote.credentials.header');
proxyReq.headers[header] = config.get('sensorthings.remote.credentials.value');

proxyReq.path = config.get('sensorthings.remote.path') + proxyReq.path;

return proxyReq;
}
});
}

export default sensorthingsAPI
7 changes: 2 additions & 5 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import base from './routes/base';
import clients from './routes/clients';
import users from './routes/users';

import sensorup from './utils/sensorup';
import sensorthings from './routes/sensorthings';

let app = express();

Expand All @@ -29,10 +29,7 @@ app.use(cors());

const endpointPrefix = '/api/v' + config.get('version');

// SensorUp's sandbox.
// We use this sandbox until we have our own implementation of the
// SensorThings API in place.
app.use(endpointPrefix + '/', sensorup);
app.use(endpointPrefix + '/', sensorthings);

app.use(endpointPrefix + '/clients', auth(['admin']), clients);
app.use(endpointPrefix + '/users', users);
Expand Down
40 changes: 0 additions & 40 deletions src/utils/sensorup.js

This file was deleted.