Added countries & cities REST services

This commit is contained in:
fkereki
2018-06-07 00:38:16 -04:00
parent abaeb6c089
commit 4101f57b25
7 changed files with 743 additions and 43 deletions
+171
View File
@@ -0,0 +1,171 @@
/* @flow */
"use strict";
// eslint-disable
const getCity = async (res: any, dbConn: any, city: string) => {
try {
res.set("Connection", "close");
let sqlQuery = "";
sqlQuery = `
SELECT *
FROM cities
WHERE cityId=?
`;
const cities = await dbConn.query(sqlQuery, [city]);
if (cities.length === 0) {
res.status(404).send("City not found");
} else {
res
.status(200)
.set("Content-Type", "application/json")
.send(JSON.stringify(cities));
}
} catch (e) {
res.status(500).send("Server error");
}
};
const deleteCity = async (res: any, dbConn: any, city: string) => {
try {
res.set("Connection", "close");
const deleteCity = `
DELETE FROM cities
WHERE cityId=?
`;
const result = await dbConn.query(deleteCity, [city]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(404).send("City not found");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const postCity = async (
res: any,
dbConn: any,
name: string,
latitude: number,
longitude: number,
population: number,
country: string,
region: string
) => {
res.set("Connection", "close");
if (!name) {
res.status(400).send("Missing name");
return;
}
try {
const sqlRegion = `
SELECT 1
FROM regions
WHERE countryCode=? AND regionCode=?
`;
const regions = await dbConn.query(sqlRegion, [country, region]);
if (regions.length === 0) {
res.status(403).send("Region must exist");
return;
}
const sqlGetId = `
SELECT MAX(CAST(cityId AS INTEGER)) AS maxr
FROM cities
`;
const cities = await dbConn.query(sqlGetId);
const newId = cities.length === 0 ? 1 : 1 + Number(cities[0].maxr);
const sqlAddCity = `
INSERT INTO cities SET
cityId=?
cityName=?,
latitude=?,
longitude=?,
population=?,
countryCode=?,
regionCode=?
`;
const result = await dbConn.query(sqlAddCity, [
newId,
name,
latitude,
longitude,
population,
country,
region
]);
if (result.info.affectedRows > 0) {
res
.status(201)
.header("Location", `/cities/${newId}`)
.send("City created");
} else {
res.status(409).send("City not created");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const putCity = async (
res: any,
dbConn: any,
city: string,
name: string,
latitude: number,
longitude: number,
population: number,
country: string,
region: string
) => {
res.set("Connection", "close");
if (!name) {
res.status(400).send("Missing name");
return;
}
try {
const sqlUpdateCity = `
UPDATE cities
SET
cityName=?,
latitude=?,
longitude=?,
population=?,
countryCode=?,
regionCode=?
WHERE cityId=?
`;
const result = await dbConn.query(sqlUpdateCity, [
name,
latitude,
longitude,
population,
country,
region,
city
]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(409).send("City not updated");
}
} catch (e) {
res.status(500).send("Server error");
}
};
module.exports = { getCity, deleteCity, postCity, putCity };
+107
View File
@@ -0,0 +1,107 @@
/* @flow */
"use strict";
const getCountry = async (res: any, dbConn: any, country: ?string) => {
try {
res.set("Connection", "close");
let sqlQuery = "";
let countries;
if (country == null) {
sqlQuery = `
SELECT cc.*
FROM countries cc
ORDER BY cc.countryCode
`;
countries = await dbConn.query(sqlQuery);
} else {
sqlQuery = `
SELECT cc.*
FROM countries cc
WHERE cc.countryCode=?
`;
countries = await dbConn.query(sqlQuery, [country]);
}
if (countries.length > 0) {
res
.status(200)
.set("Content-Type", "application/json")
.send(JSON.stringify(countries));
} else {
res.status(404).send("Not found");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const deleteCountry = async (res: any, dbConn: any, country: string) => {
try {
res.set("Connection", "close");
const sqlRegions = `
SELECT 1 FROM regions
WHERE countryCode=?
LIMIT 1
`;
const regions = await dbConn.query(sqlRegions, [country]);
if (regions.length > 0) {
res.status(405).send("Cannot delete a country with regions");
return;
}
const deleteCountry = `
DELETE FROM countries
WHERE countryCode=?
`;
const result = await dbConn.query(deleteCountry, [country]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(404).send("Country not found");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const putCountry = async (
res: any,
dbConn: any,
country: string,
name: string
) => {
res.set("Connection", "close");
if (!name) {
res.status(400).send("Missing name");
return;
}
try {
const sqlInsertOrUpdateCountry = `
INSERT INTO countries (countryCode, countryName)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE
countryName = ?
`;
const result = await dbConn.query(sqlInsertOrUpdateCountry, [
country,
name,
name
]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(409).send("Country not updated");
}
} catch (e) {
res.status(500).send("Server error");
}
};
module.exports = { getCountry, deleteCountry, putCountry };
+53 -37
View File
@@ -8,7 +8,10 @@ const getRegion = async (
region: ?string region: ?string
) => { ) => {
try { try {
res.set("Connection", "close");
let sqlQuery = ""; let sqlQuery = "";
let regions;
if (country == null) { if (country == null) {
sqlQuery = ` sqlQuery = `
SELECT rr.* SELECT rr.*
@@ -16,17 +19,19 @@ const getRegion = async (
JOIN countries cc JOIN countries cc
ON cc.countryCode=rr.countryCode ON cc.countryCode=rr.countryCode
ORDER BY cc.countryCode, rr.regionCode ORDER BY cc.countryCode, rr.regionCode
`; `;
regions = await dbConn.query(sqlQuery);
} else if (region == null) { } else if (region == null) {
sqlQuery = ` sqlQuery = `
SELECT 1 SELECT 1
FROM countries FROM countries
WHERE countryCode="${country}" WHERE countryCode=?
`; `;
const countries = await dbConn.query(sqlQuery); const countries = await dbConn.query(sqlQuery, [country]);
if (countries.length === 0) { if (countries.length === 0) {
return res.status(404).send("Country not found"); res.status(404).send("Country not found");
return;
} }
sqlQuery = ` sqlQuery = `
@@ -34,23 +39,22 @@ const getRegion = async (
FROM regions rr FROM regions rr
JOIN countries cc JOIN countries cc
ON cc.countryCode=rr.countryCode ON cc.countryCode=rr.countryCode
WHERE rr.countryCode="${country}" WHERE rr.countryCode=?
ORDER BY rr.regionCode ORDER BY rr.regionCode
`; `;
regions = await dbConn.query(sqlQuery, [country]);
} else { } else {
sqlQuery = ` sqlQuery = `
SELECT rr.* SELECT rr.*
FROM regions rr FROM regions rr
JOIN countries cc JOIN countries cc
ON cc.countryCode=rr.countryCode ON cc.countryCode=rr.countryCode
WHERE rr.countryCode="${country}" WHERE rr.countryCode=?
AND rr.regionCode="${region}" AND rr.regionCode=?
`; `;
regions = await dbConn.query(sqlQuery, [country, region]);
} }
res.set("Connection", "close");
const regions = await dbConn.query(sqlQuery);
if (regions.length > 0 || region === null) { if (regions.length > 0 || region === null) {
res res
.status(200) .status(200)
@@ -75,26 +79,27 @@ const deleteRegion = async (
const sqlCities = ` const sqlCities = `
SELECT 1 FROM cities SELECT 1 FROM cities
WHERE countryCode="${country}" WHERE countryCode=?
AND regionCode="${region}" AND regionCode=?
LIMIT 1 LIMIT 1
`; `;
const cities = await dbConn.query(sqlCities); const cities = await dbConn.query(sqlCities, [country, region]);
if (cities.length > 0) { if (cities.length > 0) {
res.status(405).send("Cannot delete a region with cities"); res.status(405).send("Cannot delete a region with cities");
} else { return;
const deleteRegion = ` }
const deleteRegion = `
DELETE FROM regions DELETE FROM regions
WHERE countryCode="${country}" WHERE countryCode=?
AND regionCode="${region}" AND regionCode=?
`; `;
const result = await dbConn.query(deleteRegion); const result = await dbConn.query(deleteRegion, [country, region]);
if (result.info.affectedRows > 0) { if (result.info.affectedRows > 0) {
res.status(204).send(); res.status(204).send();
} else { } else {
res.status(404).send("Region not found"); res.status(404).send("Region not found");
}
} }
} catch (e) { } catch (e) {
res.status(500).send("Server error"); res.status(500).send("Server error");
@@ -110,37 +115,43 @@ const postRegion = async (
res.set("Connection", "close"); res.set("Connection", "close");
if (!name) { if (!name) {
return res.status(400).send("Missing name"); res.status(400).send("Missing name");
return;
} }
try { try {
const sqlCountry = ` const sqlCountry = `
SELECT 1 SELECT 1
FROM countries FROM countries
WHERE countryCode="${country}" WHERE countryCode=?
`; `;
const countries = await dbConn.query(sqlCountry); const countries = await dbConn.query(sqlCountry, [country]);
if (countries.length === 0) { if (countries.length === 0) {
res.status(403).send("Country must exist"); res.status(403).send("Country must exist");
return;
} }
const sqlGetId = ` const sqlGetId = `
SELECT MAX(CAST(regionCode AS INTEGER)) AS maxr SELECT MAX(CAST(regionCode AS INTEGER)) AS maxr
FROM regions FROM regions
WHERE countryCode="${country}" WHERE countryCode=?
`; `;
const regions = await dbConn.query(sqlGetId); const regions = await dbConn.query(sqlGetId, [country]);
const newId = const newId =
regions.length === 0 ? 1 : 1 + Number(regions[0].maxr); regions.length === 0 ? 1 : 1 + Number(regions[0].maxr);
const sqlAddRegion = ` const sqlAddRegion = `
INSERT INTO regions SET INSERT INTO regions SET
countryCode="${country}", countryCode=?,
regionCode="${newId}", regionCode=?,
regionName="${name}" regionName=?
`; `;
const result = await dbConn.query(sqlAddRegion); const result = await dbConn.query(sqlAddRegion, [
country,
newId,
name
]);
if (result.info.affectedRows > 0) { if (result.info.affectedRows > 0) {
res res
.status(201) .status(201)
@@ -164,18 +175,23 @@ const putRegion = async (
res.set("Connection", "close"); res.set("Connection", "close");
if (!name) { if (!name) {
return res.status(400).send("Missing name"); res.status(400).send("Missing name");
return;
} }
try { try {
const sqlUpdateRegion = ` const sqlUpdateRegion = `
UPDATE regions UPDATE regions
SET regionName="${name}" SET regionName=?
WHERE countryCode="${country}" WHERE countryCode=?
AND regionCode="${region}" AND regionCode=?
`; `;
const result = await dbConn.query(sqlUpdateRegion); const result = await dbConn.query(sqlUpdateRegion, [
name,
country,
region
]);
if (result.info.affectedRows > 0) { if (result.info.affectedRows > 0) {
res.status(204).send(); res.status(204).send();
+67 -3
View File
@@ -23,6 +23,26 @@ app.use(bodyParser.urlencoded({ extended: false }));
and the logic for validating a JWT, as shown earlier and the logic for validating a JWT, as shown earlier
*/ */
const {
getCountry,
deleteCountry,
putCountry
} = require("./restful_countries.js");
app.get("/countries", (req, res) => getCountry(res, dbConn));
app.get("/countries/:country", (req, res) =>
getCountry(res, dbConn, req.params.country)
);
app.delete("/countries/:country", (req, res) =>
deleteCountry(res, dbConn, req.params.country)
);
app.put("/countries/:country", (req, res) =>
putCountry(res, dbConn, req.params.country, req.body.name)
);
const { const {
getRegion, getRegion,
deleteRegion, deleteRegion,
@@ -30,13 +50,13 @@ const {
putRegion putRegion
} = require("./restful_regions.js"); } = require("./restful_regions.js");
app.get("/regions/", (req, res) => getRegion(res, dbConn)); app.get("/regions", (req, res) => getRegion(res, dbConn));
app.get("/regions/:country/", (req, res) => app.get("/regions/:country", (req, res) =>
getRegion(res, dbConn, req.params.country) getRegion(res, dbConn, req.params.country)
); );
app.get("/regions/:country/:region/", (req, res) => app.get("/regions/:country/:region", (req, res) =>
getRegion(res, dbConn, req.params.country, req.params.region) getRegion(res, dbConn, req.params.country, req.params.region)
); );
@@ -58,6 +78,50 @@ app.put("/regions/:country/:region", (req, res) =>
) )
); );
const {
getCity,
deleteCity,
postCity,
putCity
} = require("./restful_cities.js");
// We do not allow calling /cities to get every city in the world
app.get("/cities/:city", (req, res) =>
getCity(res, dbConn, req.params.city)
);
app.delete("/cities/:city", (req, res) =>
deleteCity(res, dbConn, req.params.city)
);
app.post("/cities/:city", (req, res) =>
postCity(
res,
dbConn,
req.body.name,
req.body.latitude,
req.body.longitude,
req.body.population,
req.body.country,
req.body.region
)
);
app.put("/cities/:city", (req, res) =>
putCity(
res,
dbConn,
req.params.city,
req.body.name,
req.body.latitude,
req.body.longitude,
req.body.population,
req.body.country,
req.body.region
)
);
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => { app.use((err, req, res, next) => {
console.error("Error....", err.message); console.error("Error....", err.message);
+171
View File
@@ -0,0 +1,171 @@
/* @flow */
"use strict";
// eslint-disable
const getCity = async (res: any, dbConn: any, city: string) => {
try {
res.set("Connection", "close");
let sqlQuery = "";
sqlQuery = `
SELECT *
FROM cities
WHERE cityId=?
`;
const cities = await dbConn.query(sqlQuery, [city]);
if (cities.length === 0) {
res.status(404).send("City not found");
} else {
res
.status(200)
.set("Content-Type", "application/json")
.send(JSON.stringify(cities));
}
} catch (e) {
res.status(500).send("Server error");
}
};
const deleteCity = async (res: any, dbConn: any, city: string) => {
try {
res.set("Connection", "close");
const deleteCity = `
DELETE FROM cities
WHERE cityId=?
`;
const result = await dbConn.query(deleteCity, [city]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(404).send("City not found");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const postCity = async (
res: any,
dbConn: any,
name: string,
latitude: number,
longitude: number,
population: number,
country: string,
region: string
) => {
res.set("Connection", "close");
if (!name) {
res.status(400).send("Missing name");
return;
}
try {
const sqlRegion = `
SELECT 1
FROM regions
WHERE countryCode=? AND regionCode=?
`;
const regions = await dbConn.query(sqlRegion, [country, region]);
if (regions.length === 0) {
res.status(403).send("Region must exist");
return;
}
const sqlGetId = `
SELECT MAX(CAST(cityId AS INTEGER)) AS maxr
FROM cities
`;
const cities = await dbConn.query(sqlGetId);
const newId = cities.length === 0 ? 1 : 1 + Number(cities[0].maxr);
const sqlAddCity = `
INSERT INTO cities SET
cityId=?
cityName=?,
latitude=?,
longitude=?,
population=?,
countryCode=?,
regionCode=?
`;
const result = await dbConn.query(sqlAddCity, [
newId,
name,
latitude,
longitude,
population,
country,
region
]);
if (result.info.affectedRows > 0) {
res
.status(201)
.header("Location", `/cities/${newId}`)
.send("City created");
} else {
res.status(409).send("City not created");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const putCity = async (
res: any,
dbConn: any,
city: string,
name: string,
latitude: number,
longitude: number,
population: number,
country: string,
region: string
) => {
res.set("Connection", "close");
if (!name) {
res.status(400).send("Missing name");
return;
}
try {
const sqlUpdateCity = `
UPDATE cities
SET
cityName=?,
latitude=?,
longitude=?,
population=?,
countryCode=?,
regionCode=?
WHERE cityId=?
`;
const result = await dbConn.query(sqlUpdateCity, [
name,
latitude,
longitude,
population,
country,
region,
city
]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(409).send("City not updated");
}
} catch (e) {
res.status(500).send("Server error");
}
};
module.exports = { getCity, deleteCity, postCity, putCity };
+107
View File
@@ -0,0 +1,107 @@
/* @flow */
"use strict";
const getCountry = async (res: any, dbConn: any, country: ?string) => {
try {
res.set("Connection", "close");
let sqlQuery = "";
let countries;
if (country == null) {
sqlQuery = `
SELECT cc.*
FROM countries cc
ORDER BY cc.countryCode
`;
countries = await dbConn.query(sqlQuery);
} else {
sqlQuery = `
SELECT cc.*
FROM countries cc
WHERE cc.countryCode=?
`;
countries = await dbConn.query(sqlQuery, [country]);
}
if (countries.length > 0) {
res
.status(200)
.set("Content-Type", "application/json")
.send(JSON.stringify(countries));
} else {
res.status(404).send("Not found");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const deleteCountry = async (res: any, dbConn: any, country: string) => {
try {
res.set("Connection", "close");
const sqlRegions = `
SELECT 1 FROM regions
WHERE countryCode=?
LIMIT 1
`;
const regions = await dbConn.query(sqlRegions, [country]);
if (regions.length > 0) {
res.status(405).send("Cannot delete a country with regions");
return;
}
const deleteCountry = `
DELETE FROM countries
WHERE countryCode=?
`;
const result = await dbConn.query(deleteCountry, [country]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(404).send("Country not found");
}
} catch (e) {
res.status(500).send("Server error");
}
};
const putCountry = async (
res: any,
dbConn: any,
country: string,
name: string
) => {
res.set("Connection", "close");
if (!name) {
res.status(400).send("Missing name");
return;
}
try {
const sqlInsertOrUpdateCountry = `
INSERT INTO countries (countryCode, countryName)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE
countryName = ?
`;
const result = await dbConn.query(sqlInsertOrUpdateCountry, [
country,
name,
name
]);
if (result.info.affectedRows > 0) {
res.status(204).send();
} else {
res.status(409).send("Country not updated");
}
} catch (e) {
res.status(500).send("Server error");
}
};
module.exports = { getCountry, deleteCountry, putCountry };
+67 -3
View File
@@ -79,6 +79,26 @@ app.use((req, res, next) => {
}); });
}); });
const {
getCountry,
deleteCountry,
putCountry
} = require("./restful_countries.js");
app.get("/countries", (req, res) => getCountry(res, dbConn));
app.get("/countries/:country", (req, res) =>
getCountry(res, dbConn, req.params.country)
);
app.delete("/countries/:country", (req, res) =>
deleteCountry(res, dbConn, req.params.country)
);
app.put("/countries/:country", (req, res) =>
putCountry(res, dbConn, req.params.country, req.body.name)
);
const { const {
getRegion, getRegion,
deleteRegion, deleteRegion,
@@ -86,13 +106,13 @@ const {
putRegion putRegion
} = require("./restful_regions.js"); } = require("./restful_regions.js");
app.get("/regions/", (req, res) => getRegion(res, dbConn)); app.get("/regions", (req, res) => getRegion(res, dbConn));
app.get("/regions/:country/", (req, res) => app.get("/regions/:country", (req, res) =>
getRegion(res, dbConn, req.params.country) getRegion(res, dbConn, req.params.country)
); );
app.get("/regions/:country/:region/", (req, res) => app.get("/regions/:country/:region", (req, res) =>
getRegion(res, dbConn, req.params.country, req.params.region) getRegion(res, dbConn, req.params.country, req.params.region)
); );
@@ -114,6 +134,50 @@ app.put("/regions/:country/:region", (req, res) =>
) )
); );
const {
getCity,
deleteCity,
postCity,
putCity
} = require("./restful_cities.js");
// We do not allow calling /cities to get every city in the world
app.get("/cities/:city", (req, res) =>
getCity(res, dbConn, req.params.city)
);
app.delete("/cities/:city", (req, res) =>
deleteCity(res, dbConn, req.params.city)
);
app.post("/cities/:city", (req, res) =>
postCity(
res,
dbConn,
req.body.name,
req.body.latitude,
req.body.longitude,
req.body.population,
req.body.country,
req.body.region
)
);
app.put("/cities/:city", (req, res) =>
putCity(
res,
dbConn,
req.params.city,
req.body.name,
req.body.latitude,
req.body.longitude,
req.body.population,
req.body.country,
req.body.region
)
);
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => { app.use((err, req, res, next) => {
console.error("Error....", err.message); console.error("Error....", err.message);