From 8eecefe0edc972c7eaa7132fb56a5759aaea4af6 Mon Sep 17 00:00:00 2001 From: jorgeluismorales <53586348+jorgeluismorales@users.noreply.github.com> Date: Sat, 26 Jun 2021 00:54:01 -0300 Subject: [PATCH] final task node --- .env.example | 4 ++ .gitignore | 3 +- app/config/auth.config.js | 2 +- app/config/db.config.js | 2 +- app/controllers/city.controller.js | 104 +++++++++++++++++++++++++++++ app/middlewares/authJwt.js | 34 +++++++++- app/models/city.model.js | 16 +++++ app/routes/city.routes.js | 24 +++++++ package.json | 5 +- server.js | 2 + 10 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 .env.example create mode 100644 app/controllers/city.controller.js create mode 100644 app/models/city.model.js create mode 100644 app/routes/city.routes.js diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..541bebe --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +DB_USER= +DB_PASSWORD= +SECRET= +WEATHER_API_KEY= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 25c8fdb..8f5e467 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -package-lock.json \ No newline at end of file +package-lock.json +.env \ No newline at end of file diff --git a/app/config/auth.config.js b/app/config/auth.config.js index 1471b9e..e899c3f 100644 --- a/app/config/auth.config.js +++ b/app/config/auth.config.js @@ -1,5 +1,5 @@ module.exports = { - secret: "bezkoder-secret-key", + secret: process.env.SECRET, jwtExpiration: 3600, // 1 hour jwtRefreshExpiration: 86400, // 24 hours diff --git a/app/config/db.config.js b/app/config/db.config.js index c3b0a16..eadb8e0 100644 --- a/app/config/db.config.js +++ b/app/config/db.config.js @@ -1,7 +1,7 @@ const dbUser = process.env.DB_USER; const dbPass = process.env.DB_PASSWORD; const dbName = 'PilarTecno' -const dbUri = `mongodb+srv://${dbUser}:${dbPass}@cluster0.qtcrz.mongodb.net/${dbName}?retryWrites=true&w=majority`; +const dbUri = `mongodb+srv://${dbUser}:${dbPass}@cluster0.rr5jw.mongodb.net/${dbName}?retryWrites=true&w=majority`; const mongooseOptions = {useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true}; diff --git a/app/controllers/city.controller.js b/app/controllers/city.controller.js new file mode 100644 index 0000000..6712fe6 --- /dev/null +++ b/app/controllers/city.controller.js @@ -0,0 +1,104 @@ +const axios = require("axios"); +const City = require("../models/city.model"); +const apiKey = process.env.WEATHER_API_KEY; + +exports.getAllcities = async (req, res) => { + try { + const cities = await City.find({}) + res.status(200).json({ + ok: true, + message: "Results", + body: cities + }) + + } catch (error) { + res.status(400).json({ + ok: false, + message: "Something goes wrong" + }) + } +} + +exports.getOneCityByID = async (req, res) => { + try { + const city = await City.findById({ _id: req.params.id }); + res.status(200).json({ + ok: true, + message: "Search results", + body: city + }) + } catch (error) { + res.status(400).json({ + ok: false, + message: "City not found" + }) + } +} + +exports.searchCity = async (req, res) => { + const { city, country } = req.body; + + try { + const response = await axios.get(`http://api.openweathermap.org/data/2.5/weather?q=${city},${country}&units=metric&appid=${apiKey}`); + const newCity = new City({ + temp: response.data.main.temp, + feels_like: response.data.main.feels_like, + temp_min: response.data.main.temp_min, + temp_max: response.data.main.temp_max, + pressure: response.data.main.pressure, + humidity: response.data.main.humidity, + sea_level: response.data.main.sea_level, + grnd_level: response.data.main.grnd_level, + name: response.data.name + }); + await newCity.save(); + res.status(200).json({ + ok: true, + message: "City was saved", + body: newCity + }) + + } catch (error) { + res.status(400).json({ + ok: false, + message: "Error" + }) + } + +} + +exports.deleteCity = async (req, res) => { + try { + await City.findByIdAndDelete({ _id: req.params.id }); + res.status(200).json({ + ok: true, + message: "The city was deleted" + }) + } catch (error) { + res.status(400).json({ + ok: false, + message: "Error: The city cannot been deleted" + }) + } +} + +exports.editCity = async (req, res) => { + try { + const cityEdited = await City.findByIdAndUpdate({ _id: req.params.id }, req.body, + { + new: true, + } + ); + res.status(200).json({ + ok: true, + message: "City was edited", + body: cityEdited + }) + + } catch (error) { + res.status(400).json({ + ok: false, + message: "Error: The city cannot been edited" + }) + } +} \ No newline at end of file diff --git a/app/middlewares/authJwt.js b/app/middlewares/authJwt.js index 3a02e98..c518297 100644 --- a/app/middlewares/authJwt.js +++ b/app/middlewares/authJwt.js @@ -92,9 +92,41 @@ const isModerator = (req, res, next) => { }); }; +const isUser = (req, res, next) => { + User.findById(req.userId).exec((err, user) => { + if (err) { + res.status(500).send({ message: err }); + return; + } + + Role.find( + { + _id: { $in: user.roles } + }, + (err, roles) => { + if (err) { + res.status(500).send({ message: err }); + return; + } + + for (let i = 0; i < roles.length; i++) { + if (roles[i].name === "user") { + next(); + return; + } + } + + res.status(403).send({ message: "Require User Role!" }); + return; + } + ); + }); +}; + const authJwt = { verifyToken, isAdmin, - isModerator + isModerator, + isUser }; module.exports = authJwt; diff --git a/app/models/city.model.js b/app/models/city.model.js new file mode 100644 index 0000000..1bc2877 --- /dev/null +++ b/app/models/city.model.js @@ -0,0 +1,16 @@ +const mongoose = require("mongoose"); + +const CitySchema = new mongoose.Schema({ + temp: Number, + feels_like: Number, + temp_min: Number, + temp_max: Number, + pressure: Number, + humidity: Number, + sea_level: Number, + grnd_level: Number, + name: String +}); + + +module.exports = mongoose.model("City", CitySchema); \ No newline at end of file diff --git a/app/routes/city.routes.js b/app/routes/city.routes.js new file mode 100644 index 0000000..92e9084 --- /dev/null +++ b/app/routes/city.routes.js @@ -0,0 +1,24 @@ +const { searchCity, deleteCity, getAllcities, getOneCityByID, editCity } = require("../controllers/city.controller"); +const { authJwt } = require("../middlewares"); + + +module.exports = function (app) { + app.use(function (req, res, next) { + res.header( + "Access-Control-Allow-Headers", + "x-access-token, Origin, Content-Type, Accept" + ); + next(); + }); + + app.get("/api/city", [authJwt.verifyToken, authJwt.isUser], getAllcities); + + app.get("/api/city/:id", [authJwt.verifyToken, authJwt.isUser], getOneCityByID); + + app.put("/api/city/:id", [authJwt.verifyToken, authJwt.isUser], editCity); + + app.delete("/api/city/:id", [authJwt.verifyToken, authJwt.isUser], deleteCity); + + app.post("/api/city", [authJwt.verifyToken, authJwt.isUser], searchCity) + +}; diff --git a/package.json b/package.json index 2497f27..40db2eb 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Node.js JWT Refresh Token with MongoDB", "main": "server.js", "scripts": { - "start": "nodemon server.js", + "dev": "nodemon server.js", + "start": "node server.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ @@ -19,9 +20,11 @@ "author": "bezkoder", "license": "ISC", "dependencies": { + "axios": "^0.21.1", "bcryptjs": "^2.4.3", "body-parser": "^1.19.0", "cors": "^2.8.5", + "dotenv": "^10.0.0", "express": "^4.17.1", "jsonwebtoken": "^8.5.1", "mongoose": "^5.12.10", diff --git a/server.js b/server.js index 17d6283..ec76749 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,6 @@ const express = require("express"); const cors = require("cors"); +require("dotenv").config(); const dbConfig = require("./app/config/db.config"); const app = express(); @@ -38,6 +39,7 @@ app.get("/", (req, res) => { // routes require("./app/routes/auth.routes")(app); require("./app/routes/user.routes")(app); +require("./app/routes/city.routes")(app); // set port, listen for requests const PORT = process.env.PORT || 3000;