diff --git a/real_estate/client/src/pages/Profile.jsx b/real_estate/client/src/pages/Profile.jsx
index b768f2d..d46d861 100644
--- a/real_estate/client/src/pages/Profile.jsx
+++ b/real_estate/client/src/pages/Profile.jsx
@@ -2,15 +2,18 @@ import {useSelector} from'react-redux'
import { useEffect, useRef, useState } from 'react'
import {getDownloadURL, getStorage, ref, uploadBytesResumable} from 'firebase/storage'
import { app } from '../firebase';
+import {updateUserStart, updateUserSuccess, updateUserFailure} from '../redux/user/userSlice.js'
+import { useDispatch } from 'react-redux';
export const Profile = () => {
const fileRef = useRef(null);
- const {currentUser} = useSelector((state) => state.user);
+ const {currentUser, loading, error} = useSelector((state) => state.user);
const [file, setFile] = useState(undefined);
const [filePercentage, setFilePercentage] = useState(0);
const [fileUploadError, setFileUploadError] = useState(false)
const [formData, setFormData] = useState({})
-
+ const [updateSuccess, setUpdateSuccess] = useState(false);
+ const dispatch = useDispatch();
useEffect (() => {
@@ -39,14 +42,40 @@ export const Profile = () => {
}
)
};
+ const handleChange = (e) => {
+ setFormData({...formData, [e.target.id]: e.target.value})
+ }
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ try {
+ dispatch(updateUserStart());
+ const res = await fetch(`/server/user/update/${currentUser._id}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(formData)
+ });
+ const data = await res.json();
+ if(data.success === false){
+ dispatch(updateUserFailure(data.message));
+ return;
+ }
+ dispatch(updateUserSuccess(data));
+ setUpdateSuccess(true);
+
+ } catch (error) {
+ dispatch(updateUserFailure(error.message));
+ }
+ };
return (
Profile
-
Delete Account
Log Out
+
{error ? error : ''}
+
{updateSuccess ? 'User profile is updated successfully' : ''}
)
}
diff --git a/real_estate/client/src/redux/user/userSlice.js b/real_estate/client/src/redux/user/userSlice.js
index fa8823b..6589e21 100644
--- a/real_estate/client/src/redux/user/userSlice.js
+++ b/real_estate/client/src/redux/user/userSlice.js
@@ -13,17 +13,29 @@ const userSlice = createSlice({
loginStart: (state) => {
state.loading = true;
},
- loginSuccess: (state, action) =>{
+ loginSuccess: (state, action) => {
state.currentUser = action.payload;
state.loading = false;
state.error = null;
},
- loginFailure: (state, action) =>{
+ loginFailure: (state, action) => {
state.error = action.payload;
state.loading = false;
- }
+ },
+ updateUserStart: (state) => {
+ state.loading = true;
+ },
+ updateUserSuccess: (state, action) => {
+ state.currentUser = action.payload;
+ state.loading = false;
+ state.error = null;
+ },
+ updateUserFailure: (state, action) => {
+ state.error = action.payload;
+ state.loading = false;
+ },
}
});
-export const {loginStart, loginSuccess, loginFailure} = userSlice.actions;
+export const {loginStart, loginSuccess, loginFailure, updateUserStart, updateUserSuccess, updateUserFailure} = userSlice.actions;
export default userSlice.reducer;
\ No newline at end of file
diff --git a/real_estate/package-lock.json b/real_estate/package-lock.json
index 5f6d069..c9d4ac9 100644
--- a/real_estate/package-lock.json
+++ b/real_estate/package-lock.json
@@ -10,6 +10,7 @@
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
+ "cookie-parser": "^1.4.6",
"dotenv": "^16.4.5",
"express": "^4.18.3",
"jsonwebtoken": "^9.0.2",
@@ -227,6 +228,26 @@
"node": ">= 0.6"
}
},
+ "node_modules/cookie-parser": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
+ "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
+ "dependencies": {
+ "cookie": "0.4.1",
+ "cookie-signature": "1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/cookie-parser/node_modules/cookie": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+ "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
diff --git a/real_estate/package.json b/real_estate/package.json
index cf89dae..e40606a 100644
--- a/real_estate/package.json
+++ b/real_estate/package.json
@@ -13,6 +13,7 @@
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
+ "cookie-parser": "^1.4.6",
"dotenv": "^16.4.5",
"express": "^4.18.3",
"jsonwebtoken": "^9.0.2",
diff --git a/real_estate/server/controllers/auth.controller.js b/real_estate/server/controllers/auth.controller.js
index e531635..3a23f71 100644
--- a/real_estate/server/controllers/auth.controller.js
+++ b/real_estate/server/controllers/auth.controller.js
@@ -2,7 +2,6 @@ import User from "../models/user.model.js";
import bcryptjs from 'bcryptjs'
import { errorHandler } from "../utils/error.js";
import jwt from 'jsonwebtoken'
-import { userInfo } from "os";
export const signup = async(req, res, next) => {
const {username, email, password} = req.body
@@ -46,7 +45,7 @@ export const google = async(req, res, next) => {
const generatedPassword = Math.random().toString(36).slice(-8) + Math.random().toString(36).slice(-8);
const hashedPassword = bcryptjs.hashSync(generatedPassword, 10);
const newUser = new User({
- username: req.body.name.split(" ").join("").toLowerCase()+Math.random().toString(36).slice(-4),
+ username: req.body.name.split(' ').join('').toLowerCase()+Math.random().toString(36).slice(-4),
email: req.body.email,
password: hashedPassword,
avatar: req.body.photo,
@@ -55,7 +54,6 @@ export const google = async(req, res, next) => {
const token = jwt.sign({id: newUser._id}, process.env.JWT_SECRET);
const {password: pass, ...rest} = newUser._doc;
res.cookie('access_token', token, {httpOnly: true}).status(200).json(rest);
-
}
} catch (error) {
next(error)
diff --git a/real_estate/server/controllers/user.controller.js b/real_estate/server/controllers/user.controller.js
index 7844dc8..5c1ee41 100644
--- a/real_estate/server/controllers/user.controller.js
+++ b/real_estate/server/controllers/user.controller.js
@@ -1,5 +1,31 @@
+import bcryptjs from 'bcryptjs';
+import User from '../models/user.model.js';
+import { errorHandler } from '../utils/error.js';
+
export const test = (req, res) => {
res.json({
message: 'API route is working',
})
+};
+
+export const updateUser = async (req, res, next) =>{
+ if(req.user.id !== req.params.id) return next(errorHandler(401, 'You can only update your account'))
+ try {
+ if(req.body.password){
+ req.body.password = bcryptjs.hashSync(req.body.password, 10)
+ }
+ const updatedUser = await User.findByIdAndUpdate(req.params.id, {
+ $set:{
+ username: req.body.username,
+ email: req.body.email,
+ password: req.body.password,
+ avatar: req.body.avatar,
+ }
+ }, {new: true})
+ const {password, ...rest} = updatedUser._doc
+ res.status(200).json(rest);
+
+ } catch (error) {
+ next(error)
+ }
}
\ No newline at end of file
diff --git a/real_estate/server/index.js b/real_estate/server/index.js
index 5b5c509..bb6d9b6 100644
--- a/real_estate/server/index.js
+++ b/real_estate/server/index.js
@@ -1,8 +1,9 @@
import express from 'express';
-import mongoose from 'mongoose'
-import dotenv from 'dotenv'
-import userRouter from './routes/user.route.js'
-import authRouter from './routes/auth.route.js'
+import mongoose from 'mongoose';
+import dotenv from 'dotenv';
+import userRouter from './routes/user.route.js';
+import authRouter from './routes/auth.route.js';
+import cookieParser from 'cookie-parser';
dotenv.config();
@@ -18,6 +19,7 @@ mongoose.connect(process.env.MONGODB).then(() => {
const app = express();
app.use(express.json());
+app.use(cookieParser());
app.listen(3000, () =>{
console.log('Server is running on port 3000')
@@ -31,9 +33,9 @@ app.use('/server/auth', authRouter)
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500
const message = err.message || "Internal server error"
- return res.status(statusCode),json({
+ return res.status(statusCode).json({
success: false,
statusCode,
message,
})
-})
\ No newline at end of file
+})
diff --git a/real_estate/server/routes/user.route.js b/real_estate/server/routes/user.route.js
index 3077860..d75ebd1 100644
--- a/real_estate/server/routes/user.route.js
+++ b/real_estate/server/routes/user.route.js
@@ -1,8 +1,10 @@
import express from 'express'
-import { test } from '../controllers/user.controller.js';
+import { test, updateUser } from '../controllers/user.controller.js';
+import { verifyToken } from '../utils/verifyUser.js';
const router = express.Router();
router.get('/test', test)
+router.post('/update/:id', verifyToken, updateUser)
export default router
\ No newline at end of file
diff --git a/real_estate/server/utils/verifyUser.js b/real_estate/server/utils/verifyUser.js
new file mode 100644
index 0000000..5441af1
--- /dev/null
+++ b/real_estate/server/utils/verifyUser.js
@@ -0,0 +1,13 @@
+import jwt from 'jsonwebtoken';
+import { errorHandler } from './error.js';
+
+export const verifyToken = (req, res, next) => {
+ const token = req.cookies.access_token;
+ if(!token) return next(errorHandler(401, 'Unauthorized'));
+
+ jwt.verify(token, process.env.JWT_SECRET, (err, user) =>{
+ if(err) return next(errorHandler(403, 'Forbidden'));
+ req.user = user;
+ next();
+ })
+}
\ No newline at end of file