Skip to content

Commit 24bda5a

Browse files
authored
Video-21-Signin-Screen-Backend (basir#21)
1 parent 92a8325 commit 24bda5a

File tree

6 files changed

+122
-37
lines changed

6 files changed

+122
-37
lines changed

README.md

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -177,83 +177,118 @@ JS AMAZONA
177177
2. create SigninScreen
178178
3. render email and password fields
179179
4. style signin form
180-
21. Sign-in Screen Action
180+
21. Sign-in Screen Backend
181+
3. create signin api in backend
182+
4. create route for /api/users/signin
183+
5. create check user name and password
184+
6. if it is not ok the return 401 error
185+
7. install express-async-handler
186+
8. wrap it in expressAsyncHandler
187+
9. add error middleware in server.js
188+
10. install Postman
189+
11. send post request
190+
12. test with invalid user password
191+
13. otherwise generate token
192+
14. install jsonwebtoken
193+
15. set config.JWT_SECRET to somethingsecret
194+
16. add generateToken to utils.js
195+
17. return token
196+
18. test with correct user and password
197+
22. Sign-in Screen Action
181198
1. after_render handle form submit
182199
2. create signin request in frontend
183-
3. create signin api in backend
184-
22. Create Header Component
200+
3. show alert if email or password is incorrect
201+
4. Add getUserInfo and setUserInfo to localStorage
202+
5. create Header component
203+
6. if userInfo.email exist show user name otherwise show signin
204+
23. Create Progress Indicator and Alert Component
205+
1. create overlay loading div in index.html
206+
2. Style overlay loading
207+
3. create showLoading() function
208+
4. set loading-overlay classList add active
209+
5. create hideLoading() function
210+
6. create overlay message div in index.html
211+
7. add style overlay message
212+
8. create showMessage(message, callback)
213+
9. document message-overlay set inner HTML
214+
10. div > div id message-overlay-content
215+
11. show message
216+
12. button id message-overlay-close-button OK
217+
13. add class active to it
218+
14. add event listener for button to call callback
219+
24. Create Header Component
185220
1. update index.html
186-
1. add header render and after render to router function
187-
1. show header menu based on user logged in or not
188-
23. Register Screen Action
221+
2. add header render and after render to router function
222+
3. show header menu based on user logged in or not
223+
25. Register Screen Action
189224
1. after_render handle form submit
190225
2. create register request in frontend
191226
3. create register api in backend
192-
24. Create Checkout Wizard Header Component
227+
26. Create Checkout Wizard Header Component
193228
1. create component
194229
2. style component
195-
25. Shipping Screen
230+
27. Shipping Screen
196231
1. create ShippingScreen.js
197232
2. style elements
198233
3. handle form submit
199-
26. Payment Screen
234+
28. Payment Screen
200235
1. create PaymentScreen.js
201236
2. style elements
202237
3. handle form submit
203-
27. PlaceOrder Screen UI
238+
29. PlaceOrder Screen UI
204239
1. create PlaceOrder.js
205240
2. style elements
206-
28. PlaceOrder Screen Action
241+
30. PlaceOrder Screen Action
207242
1. handle form submit
208243
2. create backend api to create order
209-
29. Order Screen
244+
31. Order Screen
210245
1. create OrderScreen.js
211246
2. style elements
212-
30. PayPal Payment
247+
32. PayPal Payment
213248
1. add paypal checkout script
214249
2. show paypal button
215250
3. update order after payment
216-
31. User Profile UI
251+
33. User Profile UI
217252
1. create ProfileScreen.js
218253
2. style elements
219-
32. User Profile Data
254+
34. User Profile Data
220255
1. Create profile info backend api
221256
2. Create user orders api
222257
3. Call apis in the backend
223-
33. Update Profile
258+
35. Update Profile
224259
1. handle form submit
225260
2. send request to backend
226261
3. create api to update profile
227-
34. Admin Products UI
262+
36. Admin Products UI
228263
1. create Admin Order menu in header
229264
2. create ProductListScreen.js
230265
3. show products with edit and delete button
231266
4. show create product button
232267
5. implement create product backend
233268
6. redirect user to edit product screen
234-
35. Edit Product
269+
37. Edit Product
235270
1. create ProductListScreen.js
236271
2. load product data from backend
237272
3. handle form submit
238273
4. save product in backend
239-
36. Delete Product
274+
38. Delete Product
240275
1. update ProductListScreen.js
241276
2. handle delete button
242277
3. rerender after deletion
243-
37. Admin Orders
278+
39. Admin Orders
244279
1. create Admin Order menu in header
245280
2. create AdminOrder.js
246281
3. load orders from backend
247282
4. list them in the screen
248283
5. show delete and edit button
249284
6. redirect to order details on edit action
250-
38. Edit Order
285+
40. Edit Order
251286
1. if order is payed show deliver button for admin
252287
2. handle click on deliver button
253288
3. set state to delivered
254-
39. Delete Order
289+
41. Delete Order
255290
1. update OrderListScreen.js
256291
2. handle delete button
257292
3. rerender after deletion
258-
40. Publish heroku
293+
42. Publish heroku
259294
1. publish steps

backend/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ dotenv.config();
44

55
export default {
66
MONGODB_URL: process.env.MONGODB_URL,
7+
JWT_SECRET: process.env.JWT_SECRET,
78
};

backend/routers/userRouter.js

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,47 @@
11
import express from 'express';
2+
import expressAsyncHandler from 'express-async-handler';
23
import User from '../models/userModel';
4+
import { generateToken } from '../utils';
35

46
const userRouter = express.Router();
57

6-
userRouter.get('/createadmin', async (req, res) => {
7-
try {
8-
const user = new User({
9-
name: 'admin',
10-
email: 'admin@example.com',
11-
password: 'jsamazona',
12-
isAdmin: true,
8+
userRouter.get(
9+
'/createadmin',
10+
expressAsyncHandler(async (req, res) => {
11+
try {
12+
const user = new User({
13+
name: 'admin',
14+
email: 'admin@example.com',
15+
password: 'jsamazona',
16+
isAdmin: true,
17+
});
18+
const createdUser = await user.save();
19+
res.send(createdUser);
20+
} catch (err) {
21+
res.status(500).send({ message: err.message });
22+
}
23+
})
24+
);
25+
userRouter.post(
26+
'/signin',
27+
expressAsyncHandler(async (req, res) => {
28+
const signinUser = await User.findOne({
29+
email: req.body.email,
30+
password: req.body.password,
1331
});
14-
const createdUser = await user.save();
15-
res.send(createdUser);
16-
} catch (err) {
17-
res.status(500).send({ message: err.message });
18-
}
19-
});
32+
if (!signinUser) {
33+
res.status(401).send({
34+
message: 'Invalid Email or Password',
35+
});
36+
} else {
37+
res.send({
38+
_id: signinUser._id,
39+
name: signinUser.name,
40+
email: signinUser.email,
41+
isAdmin: signinUser.isAdmin,
42+
token: generateToken(signinUser),
43+
});
44+
}
45+
})
46+
);
2047
export default userRouter;

backend/server.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import express from 'express';
22
import cors from 'cors';
33
import mongoose from 'mongoose';
4+
import bodyParser from 'body-parser';
45
import data from './data';
56
import config from './config';
67
import userRouter from './routers/userRouter';
@@ -19,6 +20,7 @@ mongoose
1920
});
2021
const app = express();
2122
app.use(cors());
23+
app.use(bodyParser.json());
2224
app.use('/api/users', userRouter);
2325
app.get('/api/products', (req, res) => {
2426
res.send(data.products);
@@ -31,7 +33,10 @@ app.get('/api/products/:id', (req, res) => {
3133
res.status(404).send({ message: 'Product Not Found!' });
3234
}
3335
});
34-
36+
app.use((err, req, res, next) => {
37+
const status = err.name && err.name === 'ValidationError' ? 400 : 500;
38+
res.status(status).send({ message: err.message });
39+
});
3540
app.listen(5000, () => {
3641
console.log('serve at http://localhost:5000');
3742
});

backend/utils.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import jwt from 'jsonwebtoken';
2+
import config from './config';
3+
4+
export const generateToken = (user) => {
5+
return jwt.sign(
6+
{
7+
_id: user._id,
8+
name: user.name,
9+
email: user.email,
10+
isAdmin: user.isAdmin,
11+
},
12+
config.JWT_SECRET
13+
);
14+
};

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
},
1919
"homepage": "https://github.com/basir/node-javascript-ecommerce#readme",
2020
"dependencies": {
21+
"body-parser": "^1.19.0",
2122
"cors": "^2.8.5",
2223
"dotenv": "^8.2.0",
2324
"express": "^4.17.1",
25+
"express-async-handler": "^1.1.4",
26+
"jsonwebtoken": "^8.5.1",
2427
"mongoose": "^5.9.21"
2528
},
2629
"devDependencies": {

0 commit comments

Comments
 (0)