From 3e4beb5423d22ca95a3e16e056447917a0fca443 Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Sat, 29 Sep 2018 19:09:48 +0100 Subject: [PATCH] Query buildings by location or reference --- app/src/building.js | 86 ++++++++++++++++++++++++++++--------------- app/src/server.js | 90 +++++++++++++++++++++++++-------------------- 2 files changed, 107 insertions(+), 69 deletions(-) diff --git a/app/src/building.js b/app/src/building.js index e67c7657..b34e522e 100644 --- a/app/src/building.js +++ b/app/src/building.js @@ -1,6 +1,6 @@ import { query } from './db'; -function queryBuildingAtPoint(lng, lat) { +function queryBuildingsAtPoint(lng, lat) { return query( `SELECT b.building_id as id, @@ -17,26 +17,52 @@ function queryBuildingAtPoint(lng, lat) { ), g.geometry_geom ) - LIMIT 1 `, [lng, lat] - ).then(function(data){ - const rows = data.rows - if (rows.length){ - const id = rows[0].id - const doc = rows[0].doc - const geometry_id = rows[0].geometry_id - - doc.id = id - doc.geometry_id = geometry_id - return doc - } - return undefined; - }).catch(function(error){ + ).then(buildingRowsToDocs).catch(function(error){ console.error(error); return undefined; }); } +function queryBuildingsByReference(key, id) { + if (key === 'toid'){ + return query( + `SELECT + b.building_id as id, + b.building_doc as doc, + g.geometry_id as geometry_id + FROM buildings as b, geometries as g + WHERE + b.geometry_id = g.geometry_id + AND + b.ref_toid = $1 + `, + [id] + ).then(buildingRowsToDocs).catch(function(error){ + console.error(error); + return undefined; + }); + } + if (key === 'uprn') { + return query( + `SELECT + b.building_id as id, + b.building_doc as doc, + g.geometry_id as geometry_id + FROM buildings as b, geometries as g + WHERE + b.geometry_id = g.geometry_id + AND + b.ref_uprn = $1 + `, + [id] + ).then(buildingRowsToDocs).catch(function(error){ + console.error(error); + return undefined; + }); + } + return {error: 'Key must be UPRN or TOID'}; +} function getBuildingById(id) { return query( @@ -50,24 +76,26 @@ function getBuildingById(id) { building_id = $1 `, [ id ] - ).then(function(data){ - const rows = data.rows - if (rows.length){ - const id = rows[0].id - const doc = rows[0].doc - const geometry_id = rows[0].geometry_id - - doc.id = id - doc.geometry_id = geometry_id - return doc - } - return undefined; - }).catch(function(error){ + ).then(buildingRowsToDocs).catch(function(error){ console.error(error); return undefined; }); } +function buildingRowsToDocs(data){ + const rows = data.rows + const data = rows.map(function(row){ + const id = row.id + const doc = row.doc + const geometry_id = row.geometry_id + + doc.id = id + doc.geometry_id = geometry_id + return doc + }); + return data; +} + function saveBuilding(id, building_doc) { // don't save id or geometry_id into doc delete building_doc.id; @@ -88,4 +116,4 @@ function saveBuilding(id, building_doc) { }); } -export { queryBuildingAtPoint, getBuildingById, saveBuilding }; +export { queryBuildingsAtPoint, queryBuildingsByReference, getBuildingById, saveBuilding }; diff --git a/app/src/server.js b/app/src/server.js index 95f8735c..0820b66a 100644 --- a/app/src/server.js +++ b/app/src/server.js @@ -11,7 +11,8 @@ import pgConnect from 'connect-pg-simple'; import App from './frontend/app'; import { pool } from './db'; import { authUser, createUser, getUserById } from './user'; -import { queryBuildingAtPoint, getBuildingById, saveBuilding } from './building'; +import { queryBuildingsAtPoint, queryBuildingsByReference, getBuildingById, + saveBuilding } from './building'; import tileserver from './tileserver'; import { parseBuildingURL } from './parse'; @@ -33,21 +34,21 @@ server.use(bodyParser.json()); // handle user sessions const pgSession = pgConnect(session); const sess = { - name: 'cl.session', - store: new pgSession({ - pool: pool, - tableName : 'user_sessions' - }), - secret: process.env.APP_COOKIE_SECRET, - saveUninitialized: false, - resave: false, - cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 } // 30 days + name: 'cl.session', + store: new pgSession({ + pool: pool, + tableName : 'user_sessions' + }), + secret: process.env.APP_COOKIE_SECRET, + saveUninitialized: false, + resave: false, + cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 } // 30 days }; if (server.get('env') === 'production') { - // trust first proxy - server.set('trust proxy', 1) - // serve secure cookies - sess.cookie.secure = true + // trust first proxy + server.set('trust proxy', 1) + // serve secure cookies + sess.cookie.secure = true } server.use(session(sess)); @@ -84,16 +85,16 @@ function frontendRoute(req, res) { function renderHTML(context, data, req, res){ const markup = renderToString( - - - + + + ); if (context.url) { - res.redirect(context.url); + res.redirect(context.url); } else { - res.status(context.status).send( - ` + res.status(context.status).send( +` @@ -127,34 +128,44 @@ function renderHTML(context, data, req, res){ ` - ); + ); } } // GET tiles server.use('/tiles', tileserver); +// GET buildings +// not implemented - may be useful to GET all buildings, paginated -// GET building at point -server.get('/buildings.json', function(req, res){ - const { lng, lat } = req.query - queryBuildingAtPoint(lng, lat).then(function(result){ - if (result) { - res.send(result) - } else { - res.status(404).send({error:'Not Found'}) - } - }).catch(function(error){ - res.send({error:'Database error'}) - }) -}) +// GET buildings at point +server.get('/buildings/locate', function(req, res){ + const { lng, lat } = req.query; + queryBuildingsAtPoint(lng, lat).then(function(result){ + res.send(result); + }).catch(function(error){ + console.error(error); + res.send({error:'Database error'}) + }) +}); -// Building routes +// GET buildings by reference (UPRN/TOID or other identifier) +server.get('/buildings/reference', function(req, res){ + const { key, id } = req.query; + queryBuildingsByReference(key, id).then(function(result){ + res.send(result); + }).catch(function(error){ + console.error(error); + res.send({error:'Database error'}) + }) +}); + +// GET individual building, POST building updates server.route('/building/:building_id.json') .get(function (req, res) { const { building_id } = req.params; getBuildingById(building_id).then(function(result){ - if (result) { + if (result && result.length) { res.send(result) } else { res.status(404).send({error:'Not Found'}) @@ -173,7 +184,6 @@ server.route('/building/:building_id.json') ) }) - // POST new user server.post('/users', function(req, res){ const user = req.body; @@ -184,8 +194,8 @@ server.post('/users', function(req, res){ if (user.email){ if (user.email != user.confirm_email) { - res.send({error: "Email did not match confirmation."}); - return + res.send({error: "Email did not match confirmation."}); + return } } else { user.email = null; @@ -221,6 +231,7 @@ server.post('/login', function(req, res){ // POST user logout server.post('/logout', function(req, res){ + req.session.user_id = undefined; req.session.destroy(function(err){ if (err) { console.error(err); @@ -244,5 +255,4 @@ server.get('/users/me', function(req, res){ }); }); - export default server;