Skip to content

pull request for my NisreenOweidat`s express-js task #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,464 changes: 1,464 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"dependencies": {
"cookie-parser": "^1.4.7",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"json": "^11.0.0",
"morgan": "^1.10.0",
"path": "^0.12.7",
"swagger-ui-express": "^5.0.1",
"yamljs": "^0.3.0"
},
"devDependencies": {
"nodemon": "^3.1.9"
}
}
50 changes: 42 additions & 8 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,58 @@

/**
* This is the main entry point of the application.
* we call all the required libraries and paths,for working with file and directory paths.
*/

const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");
const cookieParser = require("cookie-parser");
const logger = require("morgan");
const swaggerUi = require("swagger-ui-express");
const YAML = require("yamljs");
const swaggerDocument = YAML.load("./docs/swagger.yaml");

// import home page route
const indexRouter = require("./routes/index");

// import all pokemon routes
const pokemonRouter = require("./routes/pokemon");

// import all auth routes
const authRouter = require("./routes/auth");

//create an express app as an object
const app = express();

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
//used for logging requests to the console : GET /pokemon/type/fire 304 4.684 ms - -
app.use(logger("dev"));

// read data from the body as json
app.use(express.json());

// read data from the body as url
app.use(express.urlencoded({ extended: false }));

// middeleware that makes it easier to read and manipulate cookies , to remember information about the user
app.use(cookieParser());

// the static() : middleware function in Express. It serves static files and is based on serve-static like css , images,
app.use(express.static(path.join(__dirname, "public")));

app.use("/", indexRouter);
// home page.
app.use("/", indexRouter);

// auth page for login and register.
app.use("/auth", authRouter);

// pokemon page for pokemon with hp / id / name/ type / create/ update/ delete.
app.use("/pokemon", pokemonRouter);

app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));

module.exports = app;
// export the app object to be used in other files.
module.exports = app;

app.listen(3000,console.log("Server running on port 3000"));


153 changes: 153 additions & 0 deletions src/controllers/pokemon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* This file is for creating all the functions that are related to pokemon.
* it will be called in the routes that are related to pokemon.
*/


// import the pokedex db.
const pokedex = require("../db/pokedex.json");


//=======================get/begin=======================//

/**
* this function is for getting all the pokemon that have a specific hp from the query params,
* from the db file, after filtering the data.
*/
exports.getHp = (req, res) => {
// get the query params
const { gte, lte, gt, lt } = req.query;

// filter the data from the db
const filteredPokemons = pokedex.filter(p =>
(!gte || p.base.HP >= gte) &&
(!lte || p.base.HP <= lte) &&
(!gt || p.base.HP > gt) &&
(!lt || p.base.HP < lt)
);

//return the filtered data as json, or an error if there is no data.
res.json(filteredPokemons.length ? filteredPokemons : { message: "No Pokémon found" });

};

/**
* retrieves Pokemon from the pokedex db based on a specific type.
* by checking if the type is an array or not.
* we used -toLowerCase()- function because the data that is saved in db is case sensitive.
*/
exports.getType = (req ,res) => {
const queryType = req.params.type.toLowerCase();

const pokemon = pokedex.filter(p => {
if (Array.isArray(p.type)) {
return p.type.some(t => t.toLowerCase() === queryType);
} else {
return p.type.toLowerCase() === queryType;
}
});

if (!pokemon) {
res.status(404).json({ error: "Pokemon not found" });
return;
}
res.status(200).json(pokemon);
return;
}

/**
* this function is for getting pokemon by name from the db.
* also used -toLowerCase()- function because the data that is saved in db is case sensitive.
*/
exports.getName = (req ,res) => {

const queryName = req.params.name.toLowerCase();
const pokemon = pokedex.find(p => p.name.english.toLowerCase() === queryName);
if (!pokemon) {
return res.status(404).json({ error: "Pokemon not found" });
}
res.json(pokemon);
};


/**
* this function is for getting pokemon by id from the db
* used -find()- for specific id.
*/
exports.getId = (req, res) => {

const id = req.params.id;
const pokemon = pokedex.find(p => p.id == id);

if (!pokemon) {
return res.status(404).json({ error: "Pokemon not found" }); ;
}
res.json(pokemon);
};
//=======================get/ends=======================//


/**
* this function is for deleting pokemon by id from the db
* using splice() function to delete spicific pokemon by id,
* here it takes the -index- parameter as -start-.
*/
exports.deletePokemon = (req, res) => {

// get the id from the url params
const id = req.params.id;

// delete the pokemon from the db by its id
const index = pokedex.findIndex(p => p.id == id);

// if id not found return error msg as json
if (index === -1) {
return res.status(404).json({ error: "Pokemon not found" });
}

// else : delete the pokemon from the db.
pokedex.splice(index, 1);
res.json({ message: "Pokemon deleted successfully" });
};





/**
* this function is for creating new pokemon in the db
*/
exports.createPokemon = (req, res) => {

// get the new pokemon data from the request body
const newPokemon = req.body;

// from the authenticateUser middleware, it let us know the user that created this pokemon.
const user = req.user;
res.json(user);

// add the new pokemon to the db
pokedex.push(newPokemon);
res.status(201).json(newPokemon);

}

//update


/**
* this function is for updating pokemon by id from the db
*/
exports.updatePokemon = (req, res) => {

const id = req.params.id;
const index = pokedex.findIndex(p => p.id == id);
if (index === -1) {
return res.status(404).json({ error: "Pokemon not found" });
}

// takes old pokemon data from the db and updates it with the new data from the request body
pokedex[index] = { ...pokedex[index], ...req.body };
res.json(pokedex[index]);
};

53 changes: 53 additions & 0 deletions src/middleware/authMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

/**
* This middleware will check if the user is authenticated or not.
* if it is authenticated then it will put the user data in req.user
* and it will call the next middleware.
* if it is not authenticated then it will return error.
*
* How the midddleware comunicates with the controller:
* 1- when the request comes to the middleware, the client sent the token in the header,
* 2- this auth middleware will check the token and virify it.
* 3- if the token is valid then we will call the next() to go to he controller.
* 4- then the controller do its job.
*/


//create and check the token.
const jwt = require("jsonwebtoken");

require("dotenv").config();
const SECRET_KEY = process.env.SECRET_KEY;


// export authenticateUser middleware to the controllers
exports.authenticateUser = (req, res, next) => {

// Get the token from the request header.
const token = req.header("Authorization");

if (!token) {
return res.status(403).json({ error: "Access denied" });
}

try {
// split the token and get the payload
const decoded = jwt.verify(req.header("Authorization").split(" ")[1], SECRET_KEY);


/**
* req.user = decoded; ::
*
* after we get the decoded payload from the token
* we put it in req.user to know the user if it was authenticated or not,
* this allows this middleware to sent the user data to the controllers.
* (the user that we wanted to make sure he is authenticated).
*/
req.user = decoded;

// move to the next controller to do the job we called this middleware for;
next();
} catch (err) {
res.status(401).json({ error: "Invalid token" });
}
};
Loading
Loading