Skip to content

Commit fca8d38

Browse files
Nisreen OweidatNisreen Oweidat
authored andcommitted
3/14
1 parent dbbe48f commit fca8d38

File tree

5 files changed

+210
-43
lines changed

5 files changed

+210
-43
lines changed

src/app.js

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,58 @@
1+
2+
/**
3+
* This is the main entry point of the application.
4+
* we call all the required libraries and paths,for working with file and directory paths.
5+
*/
6+
17
const express = require("express");
28
const path = require("path");
3-
const cookieParser = require("cookie-parser");
4-
const logger = require("morgan");
9+
const cookieParser = require("cookie-parser");
10+
const logger = require("morgan");
511
const swaggerUi = require("swagger-ui-express");
612
const YAML = require("yamljs");
713
const swaggerDocument = YAML.load("./docs/swagger.yaml");
814

9-
15+
// import home page route
1016
const indexRouter = require("./routes/index");
17+
18+
// import all pokemon routes
1119
const pokemonRouter = require("./routes/pokemon");
12-
const authRouter = require("./routes/auth");
1320

21+
// import all auth routes
22+
const authRouter = require("./routes/auth");
1423

24+
//create an express app as an object
1525
const app = express();
1626

17-
app.use(logger("dev"));
18-
app.use(express.json());
19-
app.use(express.urlencoded({ extended: false }));
20-
app.use(cookieParser());
27+
//used for logging requests to the console : GET /pokemon/type/fire 304 4.684 ms - -
28+
app.use(logger("dev"));
29+
30+
// read data from the body as json
31+
app.use(express.json());
32+
33+
// read data from the body as url
34+
app.use(express.urlencoded({ extended: false }));
35+
36+
// middeleware that makes it easier to read and manipulate cookies , to remember information about the user
37+
app.use(cookieParser());
38+
39+
// the static() : middleware function in Express. It serves static files and is based on serve-static like css , images,
2140
app.use(express.static(path.join(__dirname, "public")));
2241

23-
app.use("/", indexRouter); // localhost:3000 -> home page
24-
app.use("/auth", authRouter); // localhost:3000/auth/ -> auth page for login and register
25-
app.use("/pokemon", pokemonRouter);// localhost:3000/pokemon/ -> pokemon page for pokemon with hp / id / name/ type / create/ update/ delete
42+
// home page.
43+
app.use("/", indexRouter);
44+
45+
// auth page for login and register.
46+
app.use("/auth", authRouter);
47+
48+
// pokemon page for pokemon with hp / id / name/ type / create/ update/ delete.
49+
app.use("/pokemon", pokemonRouter);
50+
2651
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));
2752

28-
module.exports = app;
53+
// export the app object to be used in other files.
54+
module.exports = app;
55+
2956
app.listen(3000,console.log("Server running on port 3000"));
3057

3158

src/controllers/pokemon.js

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,44 @@
1+
/**
2+
* This file is for creating all the functions that are related to pokemon.
3+
* it will be called in the routes that are related to pokemon.
4+
*/
15

6+
7+
// import the pokedex db.
28
const pokedex = require("../db/pokedex.json");
39

410

511
//=======================get/begin=======================//
612

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

21+
// filter the data from the db
1022
const filteredPokemons = pokedex.filter(p =>
1123
(!gte || p.base.HP >= gte) &&
1224
(!lte || p.base.HP <= lte) &&
1325
(!gt || p.base.HP > gt) &&
1426
(!lt || p.base.HP < lt)
1527
);
1628

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

1932
};
2033

21-
34+
/**
35+
* retrieves Pokemon from the pokedex db based on a specific type.
36+
* by checking if the type is an array or not.
37+
* we used -toLowerCase()- function because the data that is saved in db is case sensitive.
38+
*/
2239
exports.getType = (req ,res) => {
2340
const queryType = req.params.type.toLowerCase();
24-
41+
2542
const pokemon = pokedex.filter(p => {
2643
if (Array.isArray(p.type)) {
2744
return p.type.some(t => t.toLowerCase() === queryType);
@@ -38,7 +55,10 @@ exports.getType = (req ,res) => {
3855
return;
3956
}
4057

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

4464
const queryName = req.params.name.toLowerCase();
@@ -49,6 +69,11 @@ exports.getName = (req ,res) => {
4969
res.json(pokemon);
5070
};
5171

72+
73+
/**
74+
* this function is for getting pokemon by id from the db
75+
* used -find()- for specific id.
76+
*/
5277
exports.getId = (req, res) => {
5378

5479
const id = req.params.id;
@@ -62,35 +87,66 @@ exports.getId = (req, res) => {
6287
//=======================get/ends=======================//
6388

6489

65-
//delete
66-
90+
/**
91+
* this function is for deleting pokemon by id from the db
92+
* using splice() function to delete spicific pokemon by id,
93+
* here it takes the -index- parameter as -start-.
94+
*/
6795
exports.deletePokemon = (req, res) => {
96+
97+
// get the id from the url params
6898
const id = req.params.id;
99+
100+
// delete the pokemon from the db by its id
69101
const index = pokedex.findIndex(p => p.id == id);
102+
103+
// if id not found return error msg as json
70104
if (index === -1) {
71105
return res.status(404).json({ error: "Pokemon not found" });
72106
}
107+
108+
// else : delete the pokemon from the db.
73109
pokedex.splice(index, 1);
74110
res.json({ message: "Pokemon deleted successfully" });
75111
};
76112

77113

78-
// create
79114

115+
116+
117+
/**
118+
* this function is for creating new pokemon in the db
119+
*/
80120
exports.createPokemon = (req, res) => {
121+
122+
// get the new pokemon data from the request body
81123
const newPokemon = req.body;
124+
125+
// from the authenticateUser middleware, it let us know the user that created this pokemon.
126+
const user = req.user;
127+
res.json(user);
128+
129+
// add the new pokemon to the db
82130
pokedex.push(newPokemon);
83131
res.status(201).json(newPokemon);
132+
84133
}
85134

86135
//update
87136

137+
138+
/**
139+
* this function is for updating pokemon by id from the db
140+
*/
88141
exports.updatePokemon = (req, res) => {
142+
89143
const id = req.params.id;
90144
const index = pokedex.findIndex(p => p.id == id);
91145
if (index === -1) {
92146
return res.status(404).json({ error: "Pokemon not found" });
93147
}
148+
149+
// takes old pokemon data from the db and updates it with the new data from the request body
94150
pokedex[index] = { ...pokedex[index], ...req.body };
95151
res.json(pokedex[index]);
96152
};

src/middleware/authMiddleware.js

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,51 @@
11

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

15+
16+
//create and check the token.
317
const jwt = require("jsonwebtoken");
418

5-
const SECRET_KEY = "nisreen`s token";
19+
require("dotenv").config();
20+
const SECRET_KEY = process.env.SECRET_KEY;
621

722

23+
// export authenticateUser middleware to the controllers
824
exports.authenticateUser = (req, res, next) => {
9-
const token = req.header("Authorization"); // Get the token from the request header
25+
26+
// Get the token from the request header.
27+
const token = req.header("Authorization");
1028

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

1533
try {
16-
const decoded = jwt.verify(token.replace("Bearer ", ""), SECRET_KEY); // splite the token from Bearer
17-
req.user = decoded;
34+
// split the token and get the payload
35+
const decoded = jwt.verify(req.header("Authorization").split(" ")[1], SECRET_KEY);
36+
37+
38+
/**
39+
* req.user = decoded; ::
40+
*
41+
* after we get the decoded payload from the token
42+
* we put it in req.user to know the user if it was authenticated or not,
43+
* this allows this middleware to sent the user data to the controllers.
44+
* (the user that we wanted to make sure he is authenticated).
45+
*/
46+
req.user = decoded;
47+
48+
// move to the next controller to do the job we called this middleware for;
1849
next();
1950
} catch (err) {
2051
res.status(401).json({ error: "Invalid token" });

src/routes/auth.js

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,84 @@
1-
1+
/**
2+
* in this file we create all the auth routes that are related to login and signup.
3+
* and generate token for authenticated users, after they verify for example their email
4+
* after log in for the first time.
5+
*/
26

37
const express = require("express");
4-
const jwt = require("jsonwebtoken"); // for generating token
5-
const bcrypt = require("bcryptjs"); // for encrypting password
68

9+
// for generating token
10+
const jwt = require("jsonwebtoken");
11+
12+
// for encrypting password
13+
const bcrypt = require("bcryptjs");
14+
15+
//create seperated paths from app.js
716
const router = express.Router();
817

9-
const users = [];
18+
// get the secret key from .env
19+
require("dotenv").config();
1020

11-
const SECRET_KEY = "nisreen`s token";
21+
// store users data insteade of database.
22+
const users = [];
1223

13-
router.post("/signup", async (req, res) => { // create new user
14-
const { username, password } = req.body;
24+
// for security uses we save the secret key in env file.
25+
const SECRET_KEY = process.env.SECRET_KEY;
1526

1627

28+
/**
29+
* This function is for creating new user,
30+
* it accept username and password from req.body and save it in users array if they are not exist,
31+
* ,it encrypt password and return success message if it works, else return error message as json,
32+
* dose not create token ,because the main idea of the signup is to create new user. not to login into the system,
33+
* so there is no need to create token, until the user login manually later.
34+
* because the user should virefy for example its email after creating account before login.
35+
*/
36+
router.post("/signup", async (req, res) => {
37+
const { username, password } = req.body;
38+
39+
//look for existing username.
1740
const existingUser = users.find(user => user.username === username);
1841
if (existingUser) {
1942
return res.status(400).json({ error: "Username already exists" });
2043
}
2144

2245
const hashedPassword = await bcrypt.hash(password, 10);
46+
47+
//save username, password in users array
2348
users.push({ username, password: hashedPassword });
2449

2550
res.status(201).json({ message: "User registered successfully" });
2651
});
2752

53+
//***************************************/
2854

29-
router.post("/login", async (req, res) => { // normal login
55+
56+
/**
57+
* This function is for login user,
58+
* it check if user exists and password is correct,
59+
* if it is correct then create token and return it to user.
60+
* dose not save token, because it`s signed with secret key,
61+
* we decode it-(token) later in middleware ,using the secret key.
62+
*/
63+
64+
65+
router.post("/login", async (req, res) => {
66+
67+
//destructuring username and password from req.body
3068
const { username, password } = req.body;
69+
70+
//look for existing username in users array in line 15.
3171
const user = users.find(user => user.username === username);
3272

3373
if (!user || !(await bcrypt.compare(password, user.password))) {
74+
// if user not found or password is incorrect
3475
return res.status(401).json({ error: "username or password is incorrect" });
3576
}
3677

37-
78+
// if user found and password is correct then create token and sign it whith the secret key.
3879
const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: "1h" });
80+
81+
// return token to user as json.
3982
res.json({ token });
4083
});
4184

0 commit comments

Comments
 (0)