Modify routes, refactor API structure
This commit is contained in:
parent
021578a2d8
commit
2c9b5ea3d8
@ -1,161 +1,18 @@
|
||||
import express from 'express';
|
||||
import bodyParser from 'body-parser';
|
||||
|
||||
|
||||
import { authUser, createUser, getUserById, authAPIUser, getNewUserAPIKey } from './services/user';
|
||||
import {
|
||||
queryBuildingsAtPoint,
|
||||
queryBuildingsByReference,
|
||||
getBuildingById,
|
||||
getBuildingLikeById,
|
||||
getBuildingUPRNsById,
|
||||
saveBuilding,
|
||||
likeBuilding,
|
||||
unlikeBuilding
|
||||
} from './services/building';
|
||||
import { authUser, createUser, getUserById, getNewUserAPIKey } from './services/user';
|
||||
import { queryLocation } from './services/search';
|
||||
|
||||
const server = express.Router();
|
||||
import buildingsRouter from './routes/buildingsRouter';
|
||||
|
||||
// GET buildings
|
||||
// not implemented - may be useful to GET all buildings, paginated
|
||||
|
||||
// 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' })
|
||||
})
|
||||
});
|
||||
const server = express();
|
||||
|
||||
// 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' })
|
||||
})
|
||||
});
|
||||
// parse POSTed json body
|
||||
server.use(bodyParser.json());
|
||||
|
||||
// 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) {
|
||||
res.send(result);
|
||||
}).catch(function (error) {
|
||||
console.error(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) {
|
||||
authAPIUser(req.query.api_key)
|
||||
.then(function (user) {
|
||||
updateBuilding(req, res, user.user_id)
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error(err);
|
||||
res.send({ error: 'Must be logged in' });
|
||||
});
|
||||
} else {
|
||||
res.send({ error: 'Must be logged in' });
|
||||
}
|
||||
})
|
||||
|
||||
function updateBuilding(req, res, userId) {
|
||||
const { building_id } = req.params;
|
||||
const building = req.body;
|
||||
saveBuilding(building_id, building, userId).then(building => {
|
||||
if (building.error) {
|
||||
res.send(building)
|
||||
return
|
||||
}
|
||||
if (typeof (building) === 'undefined') {
|
||||
res.send({ error: 'Database error' })
|
||||
return
|
||||
}
|
||||
res.send(building)
|
||||
}).catch(
|
||||
() => 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' })
|
||||
})
|
||||
})
|
||||
|
||||
// GET/POST like building
|
||||
server.route('/building/:building_id/like.json')
|
||||
.get(function (req, res) {
|
||||
if (!req.session.user_id) {
|
||||
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 => {
|
||||
// any value returned means like
|
||||
res.send({ like: like })
|
||||
}).catch(
|
||||
() => res.send({ error: 'Database error' })
|
||||
)
|
||||
})
|
||||
.post(function (req, res) {
|
||||
if (!req.session.user_id) {
|
||||
res.send({ error: 'Must be logged in' });
|
||||
return
|
||||
}
|
||||
const { building_id } = req.params;
|
||||
const { like } = req.body;
|
||||
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' })
|
||||
return
|
||||
}
|
||||
res.send(building)
|
||||
}).catch(
|
||||
() => res.send({ error: 'Database error' })
|
||||
)
|
||||
} else {
|
||||
unlikeBuilding(building_id, req.session.user_id).then(building => {
|
||||
if (building.error) {
|
||||
res.send(building)
|
||||
return
|
||||
}
|
||||
if (typeof (building) === 'undefined') {
|
||||
res.send({ error: 'Database error' })
|
||||
return
|
||||
}
|
||||
res.send(building)
|
||||
}).catch(
|
||||
() => res.send({ error: 'Database error' })
|
||||
)
|
||||
}
|
||||
})
|
||||
server.use('/buildings', buildingsRouter);
|
||||
|
||||
// POST new user
|
||||
server.post('/users', function (req, res) {
|
||||
|
154
app/src/api/controllers/buildingController.ts
Normal file
154
app/src/api/controllers/buildingController.ts
Normal file
@ -0,0 +1,154 @@
|
||||
import * as buildingService from '../services/building';
|
||||
import * as userService from '../services/user';
|
||||
|
||||
|
||||
// GET buildings
|
||||
// not implemented - may be useful to GET all buildings, paginated
|
||||
|
||||
// GET buildings at point
|
||||
function getBuildingsByLocation(req, res) {
|
||||
const { lng, lat } = req.query;
|
||||
buildingService.queryBuildingsAtPoint(lng, lat).then(function (result) {
|
||||
res.send(result);
|
||||
}).catch(function (error) {
|
||||
console.error(error);
|
||||
res.send({ error: 'Database error' })
|
||||
})
|
||||
}
|
||||
|
||||
// GET buildings by reference (UPRN/TOID or other identifier)
|
||||
function getBuildingsByReference(req, res) {
|
||||
const { key, id } = req.query;
|
||||
buildingService.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
|
||||
function getBuildingById(req, res) {
|
||||
const { building_id } = req.params;
|
||||
buildingService.getBuildingById(building_id).then(function (result) {
|
||||
res.send(result);
|
||||
}).catch(function (error) {
|
||||
console.error(error);
|
||||
res.send({ error: 'Database error' })
|
||||
})
|
||||
}
|
||||
|
||||
function updateBuildingById(req, res) {
|
||||
if (req.session.user_id) {
|
||||
updateBuilding(req, res, req.session.user_id);
|
||||
} else if (req.query.api_key) {
|
||||
userService.authAPIUser(req.query.api_key)
|
||||
.then(function (user) {
|
||||
updateBuilding(req, res, user.user_id)
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error(err);
|
||||
res.send({ error: 'Must be logged in' });
|
||||
});
|
||||
} else {
|
||||
res.send({ error: 'Must be logged in' });
|
||||
}
|
||||
}
|
||||
|
||||
function updateBuilding(req, res, userId) {
|
||||
const { building_id } = req.params;
|
||||
const building = req.body;
|
||||
buildingService.saveBuilding(building_id, building, userId).then(building => {
|
||||
if (building.error) {
|
||||
res.send(building)
|
||||
return
|
||||
}
|
||||
if (typeof (building) === 'undefined') {
|
||||
res.send({ error: 'Database error' })
|
||||
return
|
||||
}
|
||||
res.send(building)
|
||||
}).catch(
|
||||
() => res.send({ error: 'Database error' })
|
||||
)
|
||||
}
|
||||
|
||||
// GET building UPRNs
|
||||
function getBuildingUPRNsById(req, res) {
|
||||
const { building_id } = req.params;
|
||||
buildingService.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
|
||||
function getBuildingLikeById(req, res) {
|
||||
if (!req.session.user_id) {
|
||||
res.send({ like: false }); // not logged in, so cannot have liked
|
||||
return
|
||||
}
|
||||
const { building_id } = req.params;
|
||||
buildingService.getBuildingLikeById(building_id, req.session.user_id).then(like => {
|
||||
// any value returned means like
|
||||
res.send({ like: like })
|
||||
}).catch(
|
||||
() => res.send({ error: 'Database error' })
|
||||
)
|
||||
}
|
||||
|
||||
function updateBuildingLikeById(req, res) {
|
||||
if (!req.session.user_id) {
|
||||
res.send({ error: 'Must be logged in' });
|
||||
return
|
||||
}
|
||||
const { building_id } = req.params;
|
||||
const { like } = req.body;
|
||||
if (like) {
|
||||
buildingService.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' })
|
||||
return
|
||||
}
|
||||
res.send(building)
|
||||
}).catch(
|
||||
() => res.send({ error: 'Database error' })
|
||||
)
|
||||
} else {
|
||||
buildingService.unlikeBuilding(building_id, req.session.user_id).then(building => {
|
||||
if (building.error) {
|
||||
res.send(building)
|
||||
return
|
||||
}
|
||||
if (typeof (building) === 'undefined') {
|
||||
res.send({ error: 'Database error' })
|
||||
return
|
||||
}
|
||||
res.send(building)
|
||||
}).catch(
|
||||
() => res.send({ error: 'Database error' })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getBuildingsByLocation,
|
||||
getBuildingsByReference,
|
||||
getBuildingById,
|
||||
updateBuildingById,
|
||||
getBuildingUPRNsById,
|
||||
getBuildingLikeById,
|
||||
updateBuildingLikeById
|
||||
};
|
32
app/src/api/routes/buildingsRouter.ts
Normal file
32
app/src/api/routes/buildingsRouter.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import express from 'express';
|
||||
|
||||
import buildingController from '../controllers/buildingController';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
// GET buildings
|
||||
// not implemented - may be useful to GET all buildings, paginated
|
||||
|
||||
// GET buildings at point
|
||||
router.get('/locate', buildingController.getBuildingsByLocation);
|
||||
|
||||
// GET buildings by reference (UPRN/TOID or other identifier)
|
||||
router.get('/reference', buildingController.getBuildingsByReference);
|
||||
|
||||
router.route('/:building_id.json')
|
||||
// GET individual building
|
||||
.get(buildingController.getBuildingById)
|
||||
// POST building updates
|
||||
.post(buildingController.updateBuildingById);
|
||||
|
||||
|
||||
// GET building UPRNs
|
||||
router.get('/:building_id/uprns.json', buildingController.getBuildingUPRNsById);
|
||||
|
||||
// GET/POST like building
|
||||
router.route('/:building_id/like.json')
|
||||
.get(buildingController.getBuildingLikeById)
|
||||
.post(buildingController.updateBuildingLikeById);
|
||||
|
||||
export default router;
|
@ -85,7 +85,7 @@ class App extends React.Component<any, any> { // TODO: add proper types
|
||||
selectBuilding(building) {
|
||||
this.increaseRevision(building.revision_id);
|
||||
// get UPRNs and update
|
||||
fetch(`/building/${building.building_id}/uprns.json`, {
|
||||
fetch(`/api/buildings/${building.building_id}/uprns.json`, {
|
||||
method: 'GET',
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
@ -106,7 +106,7 @@ class App extends React.Component<any, any> { // TODO: add proper types
|
||||
});
|
||||
|
||||
// get if liked and update
|
||||
fetch(`/building/${building.building_id}/like.json`, {
|
||||
fetch(`/api/buildings/${building.building_id}/like.json`, {
|
||||
method: 'GET',
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
@ -147,7 +147,7 @@ class App extends React.Component<any, any> { // TODO: add proper types
|
||||
}
|
||||
|
||||
likeBuilding(buildingId) {
|
||||
fetch(`/building/${buildingId}/like.json`, {
|
||||
fetch(`/api/buildings/${buildingId}/like.json`, {
|
||||
method: 'POST',
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
@ -168,7 +168,7 @@ class App extends React.Component<any, any> { // TODO: add proper types
|
||||
}
|
||||
|
||||
updateBuilding(buildingId, data){
|
||||
fetch(`/building/${buildingId}.json`, {
|
||||
fetch(`/api/buildings/${buildingId}.json`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers:{
|
||||
|
@ -176,7 +176,7 @@ class EditForm extends Component<any, any> { // TODO: add proper types
|
||||
event.preventDefault();
|
||||
const like = event.target.checked;
|
||||
|
||||
fetch(`/building/${this.props.building_id}/like.json`, {
|
||||
fetch(`/api/buildings/${this.props.building_id}/like.json`, {
|
||||
method: 'POST',
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
@ -203,7 +203,7 @@ class EditForm extends Component<any, any> { // TODO: add proper types
|
||||
event.preventDefault();
|
||||
this.setState({error: undefined})
|
||||
|
||||
fetch(`/building/${this.props.building_id}.json`, {
|
||||
fetch(`/api/buildings/${this.props.building_id}.json`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.state),
|
||||
headers:{
|
||||
|
@ -39,7 +39,7 @@ class Login extends Component<any, any> { // TODO: add proper types
|
||||
event.preventDefault();
|
||||
this.setState({error: undefined})
|
||||
|
||||
fetch('/login', {
|
||||
fetch('/api/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.state),
|
||||
headers:{
|
||||
@ -52,7 +52,7 @@ class Login extends Component<any, any> { // TODO: add proper types
|
||||
if (res.error) {
|
||||
this.setState({error: res.error})
|
||||
} else {
|
||||
fetch('/users/me', {
|
||||
fetch('/api/users/me', {
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
(res) => res.json()
|
||||
|
@ -61,7 +61,7 @@ class ColouringMap extends Component<any, any> { // TODO: add proper types
|
||||
const newCat = parseCategoryURL(this.props.match.url);
|
||||
const mapCat = newCat || 'age';
|
||||
fetch(
|
||||
'/buildings/locate?lat='+lat+'&lng='+lng
|
||||
'/api/buildings/locate?lat='+lat+'&lng='+lng
|
||||
).then(
|
||||
(res) => res.json()
|
||||
).then(function(data){
|
||||
|
@ -30,7 +30,7 @@ class MyAccountPage extends Component<any, any> { // TODO: add proper types
|
||||
event.preventDefault();
|
||||
this.setState({error: undefined});
|
||||
|
||||
fetch('/logout', {
|
||||
fetch('/api/logout', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
@ -50,7 +50,7 @@ class MyAccountPage extends Component<any, any> { // TODO: add proper types
|
||||
event.preventDefault();
|
||||
this.setState({error: undefined});
|
||||
|
||||
fetch('/api/key', {
|
||||
fetch('/api/api/key', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
|
@ -78,7 +78,7 @@ class SearchBox extends Component<any, any> { // TODO: add proper types
|
||||
})
|
||||
|
||||
fetch(
|
||||
'/search?q='+this.state.q
|
||||
'/api/search?q='+this.state.q
|
||||
).then(
|
||||
(res) => res.json()
|
||||
).then((data) => {
|
||||
|
@ -42,7 +42,7 @@ class SignUp extends Component<any, any> { // TODO: add proper types
|
||||
event.preventDefault();
|
||||
this.setState({error: undefined})
|
||||
|
||||
fetch('/users', {
|
||||
fetch('/api/users', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.state),
|
||||
headers:{
|
||||
@ -55,7 +55,7 @@ class SignUp extends Component<any, any> { // TODO: add proper types
|
||||
if (res.error) {
|
||||
this.setState({error: res.error})
|
||||
} else {
|
||||
fetch('/users/me', {
|
||||
fetch('/api/users/me', {
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
(res) => res.json()
|
||||
|
@ -10,7 +10,6 @@ import express from 'express';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
import serialize from 'serialize-javascript';
|
||||
|
||||
import bodyParser from 'body-parser';
|
||||
import session from 'express-session';
|
||||
import pgConnect from 'connect-pg-simple';
|
||||
|
||||
@ -23,7 +22,7 @@ import {
|
||||
getBuildingUPRNsById
|
||||
} from './api/services/building';
|
||||
import tileserver from './tiles/tileserver';
|
||||
import apiRouter from './api/api';
|
||||
import apiServer from './api/api';
|
||||
import { parseBuildingURL } from './parse';
|
||||
|
||||
// create server
|
||||
@ -38,8 +37,6 @@ server.disable('x-powered-by');
|
||||
// serve static files
|
||||
server.use(express.static(process.env.RAZZLE_PUBLIC_DIR));
|
||||
|
||||
// parse POSTed json body
|
||||
server.use(bodyParser.json());
|
||||
|
||||
// handle user sessions
|
||||
const pgSession = pgConnect(session);
|
||||
@ -159,6 +156,6 @@ function renderHTML(context, data, req, res) {
|
||||
|
||||
server.use('/tiles', tileserver);
|
||||
|
||||
server.use('/api', apiRouter);
|
||||
server.use('/api', apiServer);
|
||||
|
||||
export default server;
|
||||
|
@ -59,7 +59,7 @@ def save_data(building_id, data, api_key, base_url):
|
||||
"""Save data to a building
|
||||
"""
|
||||
r = requests.post(
|
||||
"{}/building/{}.json?api_key={}".format(base_url, building_id, api_key),
|
||||
"{}/buildings/{}.json?api_key={}".format(base_url, building_id, api_key),
|
||||
json=data
|
||||
)
|
||||
|
||||
|
@ -89,7 +89,7 @@ def save_data(building_id, data, api_key, base_url):
|
||||
"""Save data to a building
|
||||
"""
|
||||
r = requests.post(
|
||||
"{}/building/{}.json?api_key={}".format(base_url, building_id, api_key),
|
||||
"{}/buildings/{}.json?api_key={}".format(base_url, building_id, api_key),
|
||||
json=data
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user