DB
에서의 업데이트가 프론트엔드에 반영되지 않았다.
프론트엔드는 session
으로부터 정보를 얻기 때문이다. session
은 로그인 할때 한번만 작성되고 있다.
로그인 하고 나서는 session
이 아무것도 안하기 때문이다. 로그인 했을때의 user
가 그대로 남아 있는거다.
그래서 DB
에 있는 user
정보를 업데이트해도 session
은 업데이트 되지 않는다.
이제 session
을 업데이트 해주면 된다.
두가지 옵션이 있다.
하나는 직접 하는거 req.session.user
를 해주고 여기에 정보를 넣어준다.
userController.js
에서
await User.findByIdAndUpdate(_id, {
name,
email,
username,
location,
});
req.session.user ={
name,
email,
username,
location,
}
return res.render("edit-profile");
};
이 방법도 괜찮긴 하지만 별로 보기 좋지 않다. 그리고 나머지도 추가해 줘야한다.
이거 말고도 avatarUrl
,socialOnly
등 더 있다. 이 정보들도 session
에 있다.
그래서 req.session.user
가 form
의 value
들이랑 같고 나머지는 기존의 것과 같다고 할거다.
...req.session.user,
무엇을 나타내냐면 req.session.user
안에 있는 내용을 전해주는 거다.
req.session.user
안의 내용을 밖으로 꺼내주는 거다.
이걸 첫줄로 옮겨야 한다. ...req.session.user,
에 있는 email
,username
을 덮어 쓰기에 그렇다.
업데이트를 해주는 거다. 새로고침해서 테스트 해보면 업데이트가 되는걸 확인 할수 있다.
req.session.user = {
...req.session.user,
name,
email,
username,
location,
};
return res.redirect("/users/edit");
이렇게 수정해 준다. DB
에 있는 session
도 업데이트 해준다.
session
은DB
에 저장돼 있다는걸 기억한다.
DB
랑 req.session
을 똑같이 유지 할수 있는거다.
그리고 직접 하는 방법 말고 다른 방법도 있다.
updatedUser
를 만드는 거다.
const updatedUser = await User.findByIdAndUpdate(
_id,
{
name,
email,
username,
location,
},
{ new: true }
);
req.session.user = updatedUser;
return res.redirect("/users/edit");
};
finByIdAndUpdate
가 updatedUser
를 주기 때문에 req.session.user = updatedUser
를 해주면 된다.
그리고 이것만으로는 새로운 updatedUser
가 만들어 지지 않는다.
option
을 보면 보낼수 있는 object
가 하나 있는데
https://mongoosejs.com/docs/api/model.html#model_Model.findByIdAndUpdate
Boolean
값을 가진 new
이다. 기본적으로 findByIdAndUpdate
는 update
되기전의 데이터를 return
해주고
new:true
를 설정해주면 findByIdAndUpdate
가 업데이트 된 데이터를 return
해준다.
무슨 뜻이냐면 mongoose
한테 가장 최근 업데이트 된 object
를 원한다고 말하는 거다.
그 이전 데이터는 필요 없고 말이다. 그래서 { new:true}
를 추가해 주었다.
findByIdAndUpdate
에 세개의 argument
를 주고 있다.
첫번째는 업데이트 하려는 user
의 id
이고 두번째는 업데이트하려는 정보(object
)이고
세번째는 option
이다. { new:true}
바로 이거다.
일일이 업데이트 하는것보다 훨씬 나아 보인다. 다시 테스트 하면 여전히 업데이트는 잘 되고 있다.
하지만 문제가 있다. 만약
username
을 바꾸려는데 이미 있는username
이거나
user
을 생성 할때 이미 해봤었다. 그걸 활용해서 해본다.
const exists = await User.exists({ $or: [{ username }, { email }] });
이미 있는 username
이나 email
이면 업데이트 할수 없게 해줘야 한다.
사용자가 username
이나 email
을 업데이트하려는걸 어떻게 알수 있냐면
body
는 form
으로부터 정보를 받아온다. form
의 정보는 현재 사용자의 정보이고
그래서 form
의 정보가 session
의 user
정보와 같은지 확인해야 될거다.
그러면 사용자가 username
이나 email
을 바꾸려 한다는 걸 알수 있다.
join
에서 했던 exists
방식을 사용하면 항상 true
가 될거다.
왜냐하면 postEdit
에서 사용한 username
이랑 email
은 현재 session
에 있는 사용자의 것이기 때문이다.
그래서 사용자가 이 내용을 변경했는지 알아낼수 있어야 한다.
한가지 방법은 body
의 username
,email
이 session.user
에 있는
username
,email
이랑 다른지 확인해 보는거다.
다르다면 사용자가 username
이나 email
을 변경하고 싶다는거다.
userController.js
에서
export const postEdit = async (req, res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
} = req;
const exists = await User.exists({
_id: { $ne: { _id } },
$or: [{ username }, { email }],
});
if (exists) {
return res.status(400).render("edit-profile", {
pageTitle: "Edit Profile",
errorMessage: "This username/email is already taken.",
});
}
edit-profile.pug
에서
block content
if errorMessage
span=errorMessage
이렇게 해주면 에러 메세지까지 join
페이지 처럼 똑같지 구현하였다.