diff --git a/app/src/api/building.js b/app/src/api/building.js index 9008dc69..ed47d6b5 100644 --- a/app/src/api/building.js +++ b/app/src/api/building.js @@ -31,14 +31,14 @@ function queryBuildingsAtPoint(lng, lat) { ) `, [lng, lat] - ).catch(function(error){ + ).catch(function (error) { console.error(error); return undefined; }); } function queryBuildingsByReference(key, id) { - if (key === 'toid'){ + if (key === 'toid') { return db.manyOrNone( `SELECT * @@ -48,7 +48,7 @@ function queryBuildingsByReference(key, id) { ref_toid = $1 `, [id] - ).catch(function(error){ + ).catch(function (error) { console.error(error); return undefined; }); @@ -65,19 +65,19 @@ function queryBuildingsByReference(key, id) { p.uprn = $1 `, [id] - ).catch(function(error){ + ).catch(function (error) { console.error(error); return undefined; }); } - return {error: 'Key must be UPRN or TOID'}; + return { error: 'Key must be UPRN or TOID' }; } function getBuildingById(id) { return db.one( "SELECT * FROM buildings WHERE building_id = $1", [id] - ).catch(function(error){ + ).catch(function (error) { console.error(error); return undefined; }); @@ -89,7 +89,7 @@ function getBuildingLikeById(building_id, user_id) { [building_id, user_id] ).then(res => { return res && res.like - }).catch(function(error){ + }).catch(function (error) { console.error(error); return undefined; }); @@ -99,7 +99,7 @@ function getBuildingUPRNsById(id) { return db.any( "SELECT uprn, parent_uprn FROM building_properties WHERE building_id = $1", [id] - ).catch(function(error){ + ).catch(function (error) { console.error(error); return undefined; }); @@ -160,10 +160,9 @@ function saveBuilding(building_id, building, user_id) { ) }); }); - }).catch(function(error){ - // TODO report transaction error as 'Need to re-fetch building before update' + }).catch(function (error) { console.error(error); - return {error: error}; + return { error: error }; }); } @@ -175,7 +174,7 @@ function likeBuilding(building_id, user_id) { // - insert changeset // - update building to latest state // commit or rollback (serializable - could be more compact?) - return db.tx({serializable}, t => { + return db.tx({ serializable }, t => { return t.none( "INSERT INTO building_user_likes ( building_id, user_id ) VALUES ($1, $2);", [building_id, user_id] @@ -191,7 +190,7 @@ function likeBuilding(building_id, user_id) { $1:json, $2, $3 ) RETURNING log_id `, - [{likes_total: building.likes}, building_id, user_id] + [{ likes_total: building.likes }, building_id, user_id] ).then(revision => { return t.one( `UPDATE buildings @@ -208,12 +207,11 @@ function likeBuilding(building_id, user_id) { }) }); }); - }).catch(function(error){ - // TODO report transaction error as 'Need to re-fetch building before update' + }).catch(function (error) { console.error(error); - if (error.detail && error.detail.includes("already exists")){ + if (error.detail && error.detail.includes("already exists")) { // 'already exists' is thrown if user already liked it - return {error: 'It looks like you already like that building!'}; + return { error: 'It looks like you already like that building!' }; } else { return undefined } @@ -228,7 +226,7 @@ function unlikeBuilding(building_id, user_id) { // - insert changeset // - update building to latest state // commit or rollback (serializable - could be more compact?) - return db.tx({serializable}, t => { + return db.tx({ serializable }, t => { return t.none( "DELETE FROM building_user_likes WHERE building_id = $1 AND user_id = $2;", [building_id, user_id] @@ -244,7 +242,7 @@ function unlikeBuilding(building_id, user_id) { $1:json, $2, $3 ) RETURNING log_id `, - [{likes_total: building.likes}, building_id, user_id] + [{ likes_total: building.likes }, building_id, user_id] ).then(revision => { return t.one( `UPDATE buildings @@ -261,12 +259,11 @@ function unlikeBuilding(building_id, user_id) { }) }); }); - }).catch(function(error){ - // TODO report transaction error as 'Need to re-fetch building before update' + }).catch(function (error) { console.error(error); - if (error.detail && error.detail.includes("already exists")){ + if (error.detail && error.detail.includes("already exists")) { // 'already exists' is thrown if user already liked it - return {error: 'It looks like you already like that building!'}; + return { error: 'It looks like you already like that building!' }; } else { return undefined } @@ -331,7 +328,7 @@ const BUILDING_FIELD_WHITELIST = new Set([ * @param {Set} whitelist * @returns {[object, object]} */ -function compare(old_obj, new_obj, whitelist){ +function compare(old_obj, new_obj, whitelist) { const reverse_patch = {} const forward_patch = {} for (const [key, value] of Object.entries(new_obj)) { diff --git a/app/src/api/search.js b/app/src/api/search.js index 83138248..1aed1835 100644 --- a/app/src/api/search.js +++ b/app/src/api/search.js @@ -8,7 +8,7 @@ */ import db from '../db'; -function queryLocation(term){ +function queryLocation(term) { const max_results = 5; return db.manyOrNone( `SELECT diff --git a/app/src/api/user.js b/app/src/api/user.js index 303da882..0e0995e0 100644 --- a/app/src/api/user.js +++ b/app/src/api/user.js @@ -7,10 +7,10 @@ import db from '../db'; function createUser(user) { if (!user.password || user.password.length < 8) { - return Promise.reject({error: 'Password must be at least 8 characters'}) + return Promise.reject({ error: 'Password must be at least 8 characters' }) } if (user.password.length > 70) { - return Promise.reject({error: 'Password must be at most 70 characters'}) + return Promise.reject({ error: 'Password must be at most 70 characters' }) } return db.one( `INSERT @@ -26,21 +26,21 @@ function createUser(user) { crypt($3, gen_salt('bf')) ) RETURNING user_id `, [ - user.username, - user.email, - user.password + user.username, + user.email, + user.password ] - ).catch(function(error){ + ).catch(function (error) { console.error('Error:', error) - if (error.detail.indexOf('already exists') !== -1){ - if (error.detail.indexOf('username') !== -1){ - return {error:'Username already registered'}; + if (error.detail.indexOf('already exists') !== -1) { + if (error.detail.indexOf('username') !== -1) { + return { error: 'Username already registered' }; } else if (error.detail.indexOf('email') !== -1) { - return {error: 'Email already registered'}; + return { error: 'Email already registered' }; } } - return {error: 'Database error'} + return { error: 'Database error' } }); } @@ -55,18 +55,18 @@ function authUser(username, password) { WHERE username = $1 `, [ - username, - password + username, + password ] - ).then(function(user){ + ).then(function (user) { if (user && user.auth_ok) { - return {user_id: user.user_id} + return { user_id: user.user_id } } else { - return {error: 'Username or password not recognised'} + return { error: 'Username or password not recognised' } } - }).catch(function(err){ + }).catch(function (err) { console.error(err); - return {error: 'Username or password not recognised'}; + return { error: 'Username or password not recognised' }; }) } @@ -81,7 +81,7 @@ function getUserById(user_id) { `, [ user_id ] - ).catch(function(error){ + ).catch(function (error) { console.error('Error:', error) return undefined; }); @@ -100,9 +100,9 @@ function getNewUserAPIKey(user_id) { `, [ user_id ] - ).catch(function(error){ + ).catch(function (error) { console.error('Error:', error) - return {error: 'Failed to generate new API key.'}; + return { error: 'Failed to generate new API key.' }; }); } @@ -117,7 +117,7 @@ function authAPIUser(api_key) { `, [ api_key ] - ).catch(function(error){ + ).catch(function (error) { console.error('Error:', error) return undefined; }); diff --git a/app/src/parse.js b/app/src/parse.js index 0b874fd6..4db75fc3 100644 --- a/app/src/parse.js +++ b/app/src/parse.js @@ -14,7 +14,7 @@ function strictParseInt(value) { } -function parseBuildingURL(url){ +function parseBuildingURL(url) { const re = /\/building\/([^/]+).html/; const matches = re.exec(url); @@ -30,7 +30,7 @@ function parseCategoryURL(url) { return default_cat } const matches = /^\/(view|edit)\/([^/.]+)/.exec(url); - const cat = (matches && matches.length >= 3)? matches[2] : default_cat; + const cat = (matches && matches.length >= 3) ? matches[2] : default_cat; return cat; } diff --git a/app/src/server.js b/app/src/server.js index a29aeea0..5bb44cdd 100644 --- a/app/src/server.js +++ b/app/src/server.js @@ -10,7 +10,7 @@ import express from 'express'; import { renderToString } from 'react-dom/server'; import serialize from 'serialize-javascript'; -import bodyParser from 'body-parser'; +import bodyParser from 'body-parser'; import session from 'express-session'; import pgConnect from 'connect-pg-simple'; @@ -52,7 +52,7 @@ const sess = { name: 'cl.session', store: new pgSession({ pgPromise: db, - tableName : 'user_sessions' + tableName: 'user_sessions' }), secret: process.env.APP_COOKIE_SECRET, saveUninitialized: false, @@ -78,22 +78,22 @@ function frontendRoute(req, res) { const user_id = req.session.user_id; const building_id = parseBuildingURL(req.url); - const is_building = (typeof(building_id) !== "undefined"); - if (is_building && isNaN(building_id)){ + const is_building = (typeof (building_id) !== "undefined"); + if (is_building && isNaN(building_id)) { context.status = 404; } Promise.all([ - user_id? getUserById(user_id) : undefined, - is_building? getBuildingById(building_id) : undefined, - is_building? getBuildingUPRNsById(building_id) : undefined, - (is_building && user_id)? getBuildingLikeById(building_id, user_id) : false - ]).then(function(values){ + user_id ? getUserById(user_id) : undefined, + is_building ? getBuildingById(building_id) : undefined, + is_building ? getBuildingUPRNsById(building_id) : undefined, + (is_building && user_id) ? getBuildingLikeById(building_id, user_id) : false + ]).then(function (values) { const user = values[0]; const building = values[1]; const uprns = values[2]; const building_like = values[3]; - if (is_building && typeof(building) === "undefined"){ + if (is_building && typeof (building) === "undefined") { context.status = 404 } data.user = user; @@ -113,7 +113,7 @@ function frontendRoute(req, res) { }); } -function renderHTML(context, data, req, res){ +function renderHTML(context, data, req, res) { const markup = renderToString( @@ -124,7 +124,7 @@ function renderHTML(context, data, req, res){ res.redirect(context.url); } else { res.status(context.status).send( -` + ` @@ -141,15 +141,15 @@ function renderHTML(context, data, req, res){ } ${ - assets.client.css - ? `` - : '' - } + assets.client.css + ? `` + : '' + } ${ - process.env.NODE_ENV === 'production' - ? `` - : `` - } + process.env.NODE_ENV === 'production' + ? `` + : `` + }
${markup}
@@ -169,24 +169,24 @@ server.use('/tiles', tileserver); // not implemented - may be useful to GET all buildings, paginated // GET buildings at point -server.get('/buildings/locate', function(req, res){ +server.get('/buildings/locate', function (req, res) { const { lng, lat } = req.query; - queryBuildingsAtPoint(lng, lat).then(function(result){ + queryBuildingsAtPoint(lng, lat).then(function (result) { res.send(result); - }).catch(function(error){ + }).catch(function (error) { console.error(error); - res.send({error:'Database error'}) + res.send({ error: 'Database error' }) }) }); // GET buildings by reference (UPRN/TOID or other identifier) -server.get('/buildings/reference', function(req, res){ +server.get('/buildings/reference', function (req, res) { const { key, id } = req.query; - queryBuildingsByReference(key, id).then(function(result){ + queryBuildingsByReference(key, id).then(function (result) { res.send(result); - }).catch(function(error){ + }).catch(function (error) { console.error(error); - res.send({error:'Database error'}) + res.send({ error: 'Database error' }) }) }); @@ -194,31 +194,31 @@ server.get('/buildings/reference', function(req, res){ server.route('/building/:building_id.json') .get(function (req, res) { const { building_id } = req.params; - getBuildingById(building_id).then(function(result){ + getBuildingById(building_id).then(function (result) { res.send(result); - }).catch(function(error){ + }).catch(function (error) { console.error(error); - res.send({error:'Database error'}) + res.send({ error: 'Database error' }) }) }) .post(function (req, res) { if (req.session.user_id) { updateBuilding(req, res, req.session.user_id); - } else if (req.query.api_key) { + } else if (req.query.api_key) { authAPIUser(req.query.api_key) - .then(function(user){ + .then(function (user) { updateBuilding(req, res, user.user_id) }) - .catch(function(err){ + .catch(function (err) { console.error(err); - res.send({error: 'Must be logged in'}); + res.send({ error: 'Must be logged in' }); }); } else { - res.send({error: 'Must be logged in'}); + res.send({ error: 'Must be logged in' }); } }) -function updateBuilding(req, res, user_id){ +function updateBuilding(req, res, user_id) { const { building_id } = req.params; const building = req.body; saveBuilding(building_id, building, user_id).then(building => { @@ -226,72 +226,72 @@ function updateBuilding(req, res, user_id){ res.send(building) return } - if (typeof(building) === "undefined") { - res.send({error:'Database error'}) + if (typeof (building) === "undefined") { + res.send({ error: 'Database error' }) return } res.send(building) }).catch( - () => res.send({error:'Database error'}) + () => res.send({ error: 'Database error' }) ) } // GET building UPRNs server.get('/building/:building_id/uprns.json', function (req, res) { - const { building_id } = req.params; - getBuildingUPRNsById(building_id).then(function(result){ - if (typeof(result) === "undefined") { - res.send({error:'Database error'}) - return - } - res.send({ - uprns: result - }); - }).catch(function(error){ - console.error(error); - res.send({error:'Database error'}) - }) + const { building_id } = req.params; + getBuildingUPRNsById(building_id).then(function (result) { + if (typeof (result) === "undefined") { + res.send({ error: 'Database error' }) + return + } + res.send({ + uprns: result + }); + }).catch(function (error) { + console.error(error); + res.send({ error: 'Database error' }) }) +}) // GET/POST like building server.route('/building/:building_id/like.json') - .get(function(req, res){ + .get(function (req, res) { if (!req.session.user_id) { - res.send({like: false}); // not logged in, so cannot have liked + res.send({ like: false }); // not logged in, so cannot have liked return } const { building_id } = req.params; getBuildingLikeById(building_id, req.session.user_id).then(like => { - if (typeof(like) === "undefined") { - res.send({like: false}) + if (typeof (like) === "undefined") { + res.send({ like: false }) return } // any value returned means like - res.send({like: true}) + res.send({ like: true }) }).catch( - () => res.send({error:'Database error'}) + () => res.send({ error: 'Database error' }) ) }) - .post(function(req, res){ + .post(function (req, res) { if (!req.session.user_id) { - res.send({error: 'Must be logged in'}); + res.send({ error: 'Must be logged in' }); return } const { building_id } = req.params; const { like } = req.body; - if (like){ + if (like) { likeBuilding(building_id, req.session.user_id).then(building => { if (building.error) { res.send(building) return } - if (typeof(building) === "undefined") { - res.send({error:'Database error'}) + if (typeof (building) === "undefined") { + res.send({ error: 'Database error' }) return } res.send(building) }).catch( - () => res.send({error:'Database error'}) + () => res.send({ error: 'Database error' }) ) } else { unlikeBuilding(building_id, req.session.user_id).then(building => { @@ -299,113 +299,113 @@ server.route('/building/:building_id/like.json') res.send(building) return } - if (typeof(building) === "undefined") { - res.send({error:'Database error'}) + if (typeof (building) === "undefined") { + res.send({ error: 'Database error' }) return } res.send(building) }).catch( - () => res.send({error:'Database error'}) + () => res.send({ error: 'Database error' }) ) } }) // POST new user -server.post('/users', function(req, res){ +server.post('/users', function (req, res) { const user = req.body; if (req.session.user_id) { - res.send({error: 'Already signed in'}); + res.send({ error: 'Already signed in' }); return } - if (user.email){ + if (user.email) { if (user.email != user.confirm_email) { - res.send({error: "Email did not match confirmation."}); + res.send({ error: "Email did not match confirmation." }); return } } else { user.email = null; } - createUser(user).then(function(result){ + createUser(user).then(function (result) { if (result.user_id) { req.session.user_id = result.user_id; - res.send({user_id: result.user_id}); + res.send({ user_id: result.user_id }); } else { req.session.user_id = undefined; - res.send({error: result.error}); + res.send({ error: result.error }); } - }).catch(function(err){ + }).catch(function (err) { console.error(err); res.send(err) }); }); // POST user auth -server.post('/login', function(req, res){ - authUser(req.body.username, req.body.password).then(function(user) { +server.post('/login', function (req, res) { + authUser(req.body.username, req.body.password).then(function (user) { if (user.user_id) { req.session.user_id = user.user_id; } else { req.session.user_id = undefined; } res.send(user); - }).catch(function(error){ + }).catch(function (error) { res.send(error); }) }); // POST user logout -server.post('/logout', function(req, res){ +server.post('/logout', function (req, res) { req.session.user_id = undefined; - req.session.destroy(function(err){ + req.session.destroy(function (err) { if (err) { console.error(err); - res.send({error: 'Failed to end session'}) + res.send({ error: 'Failed to end session' }) } - res.send({success: true}); + res.send({ success: true }); }); }); // GET own user info -server.get('/users/me', function(req, res){ +server.get('/users/me', function (req, res) { if (!req.session.user_id) { - res.send({error: 'Must be logged in'}); + res.send({ error: 'Must be logged in' }); return } - getUserById(req.session.user_id).then(function(user){ + getUserById(req.session.user_id).then(function (user) { res.send(user); - }).catch(function(error){ + }).catch(function (error) { res.send(error); }); }); // POST generate API key -server.post('/api/key', function(req, res){ +server.post('/api/key', function (req, res) { if (!req.session.user_id) { - res.send({error: 'Must be logged in'}); + res.send({ error: 'Must be logged in' }); return } - getNewUserAPIKey(req.session.user_id).then(function(api_key){ + getNewUserAPIKey(req.session.user_id).then(function (api_key) { res.send(api_key); - }).catch(function(error){ + }).catch(function (error) { res.send(error); }); }) // GET search -server.get('/search', function(req, res){ +server.get('/search', function (req, res) { const search_term = req.query.q; - if (!search_term){ + if (!search_term) { res.send({ error: 'Please provide a search term' }) return } queryLocation(search_term).then((results) => { - if (typeof(results) === "undefined") { + if (typeof (results) === "undefined") { res.send({ error: 'Database error' }) @@ -425,7 +425,7 @@ server.get('/search', function(req, res){ } }) }) - }).catch(function(error){ + }).catch(function (error) { res.send(error); }); }) diff --git a/app/src/tiles/cache.js b/app/src/tiles/cache.js index 5e4d0dea..4345e4c5 100644 --- a/app/src/tiles/cache.js +++ b/app/src/tiles/cache.js @@ -20,7 +20,7 @@ import fs from 'node-fs'; const CACHE_PATH = process.env.TILECACHE_PATH -function get(tileset, z, x, y, cb){ +function get(tileset, z, x, y, cb) { if (!should_try_cache(tileset, z)) { cb(`Skip cache get ${tileset}/${z}/${x}/${y}`, null) return @@ -30,7 +30,7 @@ function get(tileset, z, x, y, cb){ fs.readFile(fname, cb) } -function put(im, tileset, z, x, y, cb){ +function put(im, tileset, z, x, y, cb) { if (!should_try_cache(tileset, z)) { cb(`Skip cache put ${tileset}/${z}/${x}/${y}`) return @@ -40,7 +40,7 @@ function put(im, tileset, z, x, y, cb){ fs.writeFile(fname, im, 'binary', (err) => { if (err && err.code === 'ENOENT') { fs.mkdir(dir, 0o755, true, (err) => { - if (err){ + if (err) { cb(err); } else { fs.writeFile(fname, im, 'binary', cb); @@ -53,11 +53,11 @@ function put(im, tileset, z, x, y, cb){ } function should_try_cache(tileset, z) { - if (tileset === 'date_year'){ + if (tileset === 'date_year') { // cache high zoom because of front page hits return z <= 16 } - if (tileset === 'base_light' || tileset === 'base_night') { + if (tileset === 'base_light' || tileset === 'base_night') { // cache for higher zoom levels (unlikely to change) return z <= 17 } diff --git a/app/src/tiles/tile.js b/app/src/tiles/tile.js index ea41aa12..cca13a14 100644 --- a/app/src/tiles/tile.js +++ b/app/src/tiles/tile.js @@ -14,7 +14,7 @@ const DATASOURCE_CONFIG = { 'password': process.env.PGPASSWORD, 'port': process.env.PGPORT, 'geometry_field': 'geometry_geom', - 'extent' : '-20005048.4188,-9039211.13765,19907487.2779,17096598.5401', + 'extent': '-20005048.4188,-9039211.13765,19907487.2779,17096598.5401', 'srid': 3857, 'type': 'postgis' } @@ -129,26 +129,26 @@ const mercator = new SphericalMercator({ size: TILE_SIZE }); -function get_bbox(z, x, y){ +function get_bbox(z, x, y) { return mercator.bbox(x, y, z, false, '900913'); } -function get_xyz(bbox, z){ +function get_xyz(bbox, z) { return mercator.xyz(bbox, z, false, '900913') } -function render_tile(tileset, z, x, y, geometry_id, cb){ +function render_tile(tileset, z, x, y, geometry_id, cb) { const bbox = get_bbox(z, x, y) const map = new mapnik.Map(TILE_SIZE, TILE_SIZE, PROJ4_STRING); map.bufferSize = TILE_BUFFER_SIZE; const layer = new mapnik.Layer('tile', PROJ4_STRING); - const table_def = (tileset === 'highlight')? + const table_def = (tileset === 'highlight') ? get_highlight_table_def(geometry_id) : MAP_STYLE_TABLE_DEFINITIONS[tileset]; - const conf = Object.assign({table: table_def}, DATASOURCE_CONFIG) + const conf = Object.assign({ table: table_def }, DATASOURCE_CONFIG) var postgis; try { @@ -159,7 +159,7 @@ function render_tile(tileset, z, x, y, geometry_id, cb){ map.load( path.join(__dirname, '..', 'map_styles', 'polygon.xml'), { strict: true }, - function(err, map){ + function (err, map) { if (err) throw err map.add_layer(layer) @@ -171,7 +171,7 @@ function render_tile(tileset, z, x, y, geometry_id, cb){ }); } ) - } catch(err) { + } catch (err) { console.error(err); } } diff --git a/app/src/tiles/tileserver.js b/app/src/tiles/tileserver.js index fe7f2ac9..21c08e72 100644 --- a/app/src/tiles/tileserver.js +++ b/app/src/tiles/tileserver.js @@ -48,17 +48,17 @@ function handle_tile_request(tileset, req, res) { const int_x = strictParseInt(x); const int_y = strictParseInt(y); - if (isNaN(int_x) || isNaN(int_y) || isNaN(int_z)){ + if (isNaN(int_x) || isNaN(int_y) || isNaN(int_z)) { console.error("Missing x or y or z") - return {error:'Bad parameter'} + return { error: 'Bad parameter' } } load_tile(tileset, int_z, int_x, int_y).then((im) => { - res.writeHead(200, {'Content-Type': 'image/png'}) + res.writeHead(200, { 'Content-Type': 'image/png' }) res.end(im) }).catch((err) => { console.error(err) - res.status(500).send({error: err}) + res.status(500).send({ error: err }) }) } @@ -158,8 +158,8 @@ function stitch_tile(tileset, z, x, y) { ).png().toBuffer() }).then((buf) => { return sharp(buf - ).resize(256, 256, {fit: 'inside'} - ).png().toBuffer() + ).resize(256, 256, { fit: 'inside' } + ).png().toBuffer() }) }); } @@ -171,23 +171,23 @@ function handle_highlight_tile_request(req, res) { const int_x = strictParseInt(x); const int_y = strictParseInt(y); - if (isNaN(int_x) || isNaN(int_y) || isNaN(int_z)){ + if (isNaN(int_x) || isNaN(int_y) || isNaN(int_z)) { console.error("Missing x or y or z") - return {error:'Bad parameter'} + return { error: 'Bad parameter' } } // highlight layer uses geometry_id to outline a single building const { highlight } = req.query const geometry_id = strictParseInt(highlight); - if(isNaN(geometry_id)){ - res.status(400).send({error:'Bad parameter'}) + if (isNaN(geometry_id)) { + res.status(400).send({ error: 'Bad parameter' }) return } - render_tile('highlight', int_z, int_x, int_y, geometry_id, function(err, im) { + render_tile('highlight', int_z, int_x, int_y, geometry_id, function (err, im) { if (err) throw err - res.writeHead(200, {'Content-Type': 'image/png'}) + res.writeHead(200, { 'Content-Type': 'image/png' }) res.end(im) }) }