Skip to content

Commit c201239

Browse files
Pushing changes from class apr 11
1 parent 019c4fa commit c201239

14 files changed

Lines changed: 371 additions & 52 deletions

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
"dependencies": {
1010
"axios": "^0.19.2",
1111
"bcryptjs": "^2.4.3",
12+
"connect-mongo": "^3.2.0",
13+
"cookie-parser": "^1.4.5",
1214
"express": "^4.17.1",
15+
"express-session": "^1.17.0",
16+
"jsonwebtoken": "^8.5.1",
1317
"mongoose": "^5.9.7",
1418
"node-env-run": "^3.0.2",
1519
"nodemon": "^2.0.2",
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const express = require('express');
2+
const router = express.Router();
3+
4+
const PokedexAccessor = require('../model/pokedex.model');
5+
6+
7+
8+
9+
10+
router.get('/', (req, res) => {
11+
return PokedexAccessor.getAllPokedexEntries()
12+
.then((entries) => res.send(entries[0]))
13+
})
14+
15+
router.post('/', async (req, res) => {
16+
try {
17+
let entry = await PokedexAccessor.findPokedexEntryByName(req.body.name);
18+
if (entry) {
19+
return res.status(403).send('Pokedex entry with that name already exists');
20+
}
21+
entry = await PokedexAccessor.insertPokedexEntry(req.body);
22+
res.status(200).send(entry)
23+
} catch (error) {
24+
res.status(404).send(`Error inserting Pokedex Entry:${error}`)
25+
}
26+
});
27+
28+
router.put('/:id', (req, res) => {
29+
const id = req.params.id;
30+
return PokedexAccessor.updatePokedexEntry(req.body)
31+
.then((entry) => res.send(entry),
32+
(error) => res.status(500).send(error));
33+
})
34+
35+
router.post('/', (req, res) => {
36+
return PokedexAccessor.findPokedexEntryByName(req.body.name)
37+
.then((entry) => {
38+
if (entry) {
39+
res.status(403).send('Entry with that name already exists!')
40+
} else {
41+
return PokedexAccessor.insertPokedexEntry(req.body)
42+
.then((entry) => {
43+
res.status(200).send(entry)
44+
})
45+
}
46+
})
47+
.catch((error) => res.status(500).send(`Error inserting Pokedex Entry:${error}`))
48+
});
49+
50+
51+
module.exports = router

server/controller/pokemon.controller.js

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,17 @@ const router = express.Router();
33

44
const PokemonAccessor = require('../model/pokemon.model');
55

6-
router.get('/', (req, res) => {
7-
if (req.query.username) {
8-
PokemonAccessor.findPokemonByOwner(req.query.username)
9-
.then((response) => res.status(200).send(response),
10-
(error) => res.status(404).send(`Error finding Pokemon:${error}`));
11-
} else {
12-
return PokemonAccessor.getAllPokemon()
13-
.then((response) => res.status(200).send(response),
14-
(error) => res.status(404).send(`Error finding Pokemon:${error}`));
15-
}
6+
const authParser = require('../middleware/middleware_auth.middleware');
7+
8+
9+
router.get('/', authParser, function(req, res) {
10+
PokemonAccessor.findPokemonByOwner(req.username)
11+
.then((response) => res.status(200).send(response),
12+
(error) => res.status(404).send(`Error finding Pokemon:${error}`));
1613
});
1714

18-
router.post('/', (req, res) => {
19-
// NOTE: because we're using Mongoose, it will
20-
// filter out any data that we DON'T want
21-
// So we can safely pass it the entire body
15+
router.post('/', authParser, (req, res) => {
16+
req.body.owner = req.username;
2217
return PokemonAccessor.insertPokemon(req.body)
2318
.then((response) => res.status(200).send(response),
2419
(error) => res.status(404).send(`Error finding Pokemon:${error}`))

server/controller/user.controller.js

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,114 @@ const UserModel = require('../model/user.model');
55
// import bcrypt
66
const bcrypt = require("bcryptjs");
77

8+
const jwt = require('jsonwebtoken');
9+
const authParser = require('../middleware/middleware_auth.middleware');
810

9-
router.post('/', (req, res) => {
10-
if(!req.body.username || !req.body.password) {
11+
12+
13+
router.post('/', async (req, res) => {
14+
const {username, password} = req.body;
15+
if (!username || !password) {
1116
return res.status(404).send({message: "Must include username AND password"});
1217
}
1318

14-
// req.body.password = bcrypt.hashSync(req.body.password, 10);
15-
1619
return UserModel.addUser(req.body)
1720
.then((user) => {
18-
// console.dir(user);
19-
return res.status(200).send(user)
21+
// COMMENT: I am leaving the JWT logic in so you can see the difference
22+
// Why do we not need to encode the username in session?
23+
// Why do we not need to set the cookie anymore?
24+
//
25+
// const payload = {username};
26+
// const token = jwt.sign(payload, process.env.SUPER_SECRET, {
27+
// expiresIn: '14d'
28+
// });
29+
req.session.username = username;
30+
return res//.cookie('token', token, {httpOnly: true})
31+
.status(200).send({username});
2032
},
2133
error => res.status(500).send(error));
2234
});
2335

2436
router.post('/authenticate', function (req, res) {
25-
UserModel.getUserByUserName(req.body.username)
37+
const {username, password} = req.body;
38+
UserModel.getUserByUserName(username)
2639
.then((user) => {
27-
// Notice that we're not using bcrypt directly anywhere in the controller.
28-
// All of that behavior is getting handled closer to the database level/layer
29-
user.comparePassword(req.body.password, (error, match) => {
40+
user.comparePassword(password, (error, match) => {
3041
if (match) {
31-
res.send(user);
42+
// Comment: This is the same as above!
43+
//
44+
// const payload = {username};
45+
// const token = jwt.sign(payload, process.env.SUPER_SECRET, {
46+
// expiresIn: '14d'
47+
// });
48+
req.session.username = username;
49+
return res//.cookie('token', token, {httpOnly: true})
50+
.status(200).send({username});
3251
}
3352
return res.status(400).send("The password does not match");
3453
});
3554
})
3655
.catch((error) => console.error(`Something went wrong: ${error}`));
37-
});
56+
})
57+
// router.post('/', (req, res) => {
58+
// if(!req.body.username || !req.body.password) {
59+
// return res.status(404).send({message: "Must include username AND password"});
60+
// }
61+
//
62+
// // req.body.password = bcrypt.hashSync(req.body.password, 10);
63+
//
64+
// return UserModel.addUser(req.body)
65+
// .then((user) => {
66+
// // console.dir(user);
67+
// const {username} = user;
68+
// const payload = {username};
69+
// // JWT is encrypting our payload (which is whatever data we want
70+
// // to carry across sessions: in this case, just the username)
71+
// // into the cookie based on our SECRET
72+
// const token = jwt.sign(payload, process.env.SUPER_SECRET, {
73+
// expiresIn: '14d' // optional cookie expiration date
74+
// });
75+
// // Here we are setting the cookie on our response obect.
76+
// // Note that we are returning the username, but that isn't as necessary anymore
77+
// // unless we want to reference that on the frontend
78+
// return res.cookie('token', token, {httpOnly: true})
79+
// .status(200).send({username});
80+
// // return res.status(200).send(user)
81+
// },
82+
// error => res.status(500).send(error));
83+
// });
84+
85+
router.get('/loggedIn', authParser, function(req, res) {
86+
return res.sendStatus(200);
87+
})
88+
89+
//...
90+
91+
// Can you figure out why authenticate is POST now?
92+
// router.post('/authenticate', function (req, res) {
93+
// const {username, password} = req.body;
94+
// UserModel.getUserByUserName(username)
95+
// .then((user) => {
96+
// user.comparePassword(password, (error, match) => {
97+
// if (match) {
98+
// const payload = {username};
99+
// // JWT is encrypting our payload (which is whatever data we want
100+
// // to carry across sessions: in this case, just the username)
101+
// // into the cookie based on our SECRET
102+
// const token = jwt.sign(payload, process.env.SUPER_SECRET, {
103+
// expiresIn: '14d' // optional cookie expiration date
104+
// });
105+
// // Here we are setting the cookie on our response obect.
106+
// // Note that we are returning the username, but that isn't as necessary anymore
107+
// // unless we want to reference that on the frontend
108+
// return res.cookie('token', token, {httpOnly: true})
109+
// .status(200).send({username});
110+
// }
111+
// return res.status(400).send("The password does not match");
112+
// });
113+
// })
114+
// .catch((error) => console.error(`Something went wrong: ${error}`));
115+
// });
38116

39117
router.get('/', (req, res) => UserModel.getAllUsers()
40118
.then(users => res.send(users)));
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const jwt = require('jsonwebtoken');
2+
3+
module.exports = function(req, res, next) {
4+
const username = req.session.username;
5+
if (!username) {
6+
res.status(401).send('Unauthorized: No session available');
7+
} else {
8+
req.username = username;
9+
next();
10+
}}
11+
// }module.exports = function(req, res, next) {
12+
// const token = req.cookies.token;
13+
// // Get the token out of the cookie and request. This is made easy to ready by cookie-parser
14+
// if (!token) {
15+
// // If the cookie is missue, send back an error
16+
// res.status(401).send('Unauthorized: No token provided');
17+
// } else {
18+
// // Check that the token is valid and not expired
19+
// jwt.verify(token, process.env.SUPER_SECRET, function(err, decoded) {
20+
// // If it's not a good token, send an exception!
21+
// if (err) {
22+
// res.status(401).send('Unauthorized: Invalid token');
23+
// } else {
24+
// // Add 'username' as part of the request object so
25+
// // so that the next function can use it
26+
// req.username = decoded.username;
27+
// // next calls the following function in the route chain
28+
// next();
29+
// }
30+
// });
31+
// }
32+
// }

server/model/pokedex.model.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const mongoose = require("mongoose")
2+
const PokedexSchema = require('./pokedex.schema').PokedexSchema;
3+
4+
const PokedexModel = mongoose.model("Pokedex", PokedexSchema);
5+
6+
function insertPokedexEntry(pokedexEntry) {
7+
return PokedexModel.create(pokedexEntry);
8+
}
9+
10+
function getAllPokedexEntries() {
11+
return PokedexModel.find().exec();
12+
}
13+
14+
function findPokedexEntryByName(name) {
15+
return PokedexModel.findOne({name}).exec();
16+
}
17+
18+
function findPokedexEntryById(id) {
19+
return PokedexModel.findById(id).exec();
20+
}
21+
22+
function deletePokedexEntry(id) {
23+
return PokedexModel.findByIdAndDelete(id).exec();
24+
}
25+
26+
function updatePokedexEntry(pokedexEntry) {
27+
return PokedexModel.findByIdAndUpdate(pokedexEntry._id, pokedexEntry).exec();
28+
}
29+
30+
31+
module.exports = {
32+
insertPokedexEntry,
33+
getAllPokedexEntries,
34+
findPokedexEntryByName,
35+
findPokedexEntryById,
36+
deletePokedexEntry,
37+
updatePokedexEntry,
38+
};

server/model/pokedex.schema.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const Schema = require('mongoose').Schema;
2+
3+
exports.PokedexSchema = new Schema({
4+
// recall that _id is provided for us, though we can add other indices
5+
name: { type: String, index: {unique: true}},
6+
heightInCentimeters: { type: Number, required: true},
7+
category: String,
8+
ability: String,
9+
weightInKilos: Number,
10+
type: [String],
11+
// set the collection (i.e., 'table') name below
12+
}, { collection : 'pokedex' });

server/server.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,35 @@ const express = require('express');
22
const user = require('./controller/user.controller');
33
const pokemon = require('./controller/pokemon.controller');
44
const item = require('./controller/items.controller');
5+
const pokedex = require('./controller/pokedex.controller');
56

67
const app = express();
78

89
const mongoose = require('mongoose');
9-
10+
const cookieParse = require('cookie-parser')
1011

1112
// This is the default address for MongoDB.
1213
// Make sure MongoDB is running!
1314
const mongoEndpoint = 'mongodb://127.0.0.1/pokemon_app';
1415
// useNewUrlParser is not required, but the old parser is deprecated
1516
mongoose.connect(mongoEndpoint, { useNewUrlParser: true });
16-
1717
// Get the connection string
1818
const db = mongoose.connection;
1919

20+
const session = require('express-session')
21+
//...
22+
// This will manage our sesssion data.
23+
// We can use our secret from our JWT tokens
24+
const MongoStore = require('connect-mongo')(session);
25+
26+
app.use(session({secret: process.env.SUPER_SECRET,
27+
store: new MongoStore({
28+
mongooseConnection : db,
29+
})}));
2030
// This will create the connection, and throw an error if it doesn't work
2131
db.on('error', console.error.bind(console, 'Error connecting to MongoDB:'));
2232

23-
33+
app.use(cookieParse());
2434
app.use(express.json());
2535
app.use(express.urlencoded({ extended: true }));
2636

@@ -29,6 +39,7 @@ app.use(express.urlencoded({ extended: true }));
2939
app.use('/api/pokemon', pokemon);
3040
app.use('/api/user', user);
3141
app.use('/api/items', item);
42+
app.use('/api/pokedex', pokedex);
3243

3344
app.listen(3001, function() {
3445
console.log('Starting server');

src/actions/pokemon.action.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,21 @@ function inFlight() {
2020
}
2121

2222

23-
export function fetchPokemon(username) {
23+
export function fetchPokemon() {
2424
return function(dispatch) {
2525
dispatch(loadingPokemons());
26-
return Axios.get(`/api/pokemon?username=${username}`)
26+
return Axios.get(`/api/pokemon`)
2727
.then(response => dispatch(receivePokemonList(response.data)),
2828
error => console.log('An error occurred.', error)
2929
);
3030
}
3131
}
3232

33-
export function addPokemon(pokemon, username) {
34-
pokemon.owner = username;
33+
export function addPokemon(pokemon) {
3534
return function(dispatch) {
3635
dispatch(inFlight());
3736
return Axios.post(`/api/pokemon`, pokemon)
38-
.then(() => Axios.get(`/api/pokemon?username=${username}`),
37+
.then(() => Axios.get(`/api/pokemon`),
3938
error => console.log('An error occurred.', error))
4039
.then(
4140
response => dispatch(receivePokemonList(response.data)),
@@ -44,11 +43,11 @@ export function addPokemon(pokemon, username) {
4443
}
4544
}
4645

47-
export function deletePokemon(pokemonId, username) {
46+
export function deletePokemon(pokemonId) {
4847
return function(dispatch) {
4948
dispatch(inFlight());
5049
return Axios.delete(`/api/pokemon/` + pokemonId)
51-
.then(() => Axios.get(`/api/pokemon?username=${username}`),
50+
.then(() => Axios.get(`/api/pokemon`),
5251
error => console.log('An error occurred.', error))
5352
.then(
5453
response => dispatch(receivePokemonList(response.data)),

0 commit comments

Comments
 (0)