Edit Profile POST #02

0_CyberLover_0·2022년 4월 26일
0

Node.JS #05

목록 보기
12/19

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.userformvalue들이랑 같고 나머지는 기존의 것과 같다고 할거다.

    ...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도 업데이트 해준다.

sessionDB에 저장돼 있다는걸 기억한다.

DBreq.session을 똑같이 유지 할수 있는거다.

그리고 직접 하는 방법 말고 다른 방법도 있다.

updatedUser를 만드는 거다.

const updatedUser = await User.findByIdAndUpdate(
    _id,
    {
      name,
      email,
      username,
      location,
    },
    { new: true }
  );
  req.session.user = updatedUser;
  return res.redirect("/users/edit");
};

finByIdAndUpdateupdatedUser를 주기 때문에 req.session.user = updatedUser를 해주면 된다.

그리고 이것만으로는 새로운 updatedUser가 만들어 지지 않는다.

option을 보면 보낼수 있는 object가 하나 있는데

https://mongoosejs.com/docs/api/model.html#model_Model.findByIdAndUpdate

Boolean값을 가진 new이다. 기본적으로 findByIdAndUpdateupdate되기전의 데이터를 return해주고

new:true를 설정해주면 findByIdAndUpdate가 업데이트 된 데이터를 return해준다.

무슨 뜻이냐면 mongoose한테 가장 최근 업데이트 된 object를 원한다고 말하는 거다.

그 이전 데이터는 필요 없고 말이다. 그래서 { new:true}를 추가해 주었다.

findByIdAndUpdate에 세개의 argument를 주고 있다.

첫번째는 업데이트 하려는 userid 이고 두번째는 업데이트하려는 정보(object)이고

세번째는 option이다. { new:true} 바로 이거다.

일일이 업데이트 하는것보다 훨씬 나아 보인다. 다시 테스트 하면 여전히 업데이트는 잘 되고 있다.

하지만 문제가 있다. 만약 username을 바꾸려는데 이미 있는 username이거나
email을 바꾸려는데 이미 있는 email이면 어떻게 해주는게 좋을까

user을 생성 할때 이미 해봤었다. 그걸 활용해서 해본다.

  const exists = await User.exists({ $or: [{ username }, { email }] });

이미 있는 username이나 email이면 업데이트 할수 없게 해줘야 한다.

사용자가 username이나 email을 업데이트하려는걸 어떻게 알수 있냐면

bodyform으로부터 정보를 받아온다. form의 정보는 현재 사용자의 정보이고

그래서 form의 정보가 sessionuser정보와 같은지 확인해야 될거다.

그러면 사용자가 username이나 email을 바꾸려 한다는 걸 알수 있다.

join에서 했던 exists방식을 사용하면 항상 true가 될거다.

왜냐하면 postEdit에서 사용한 username이랑 email은 현재 session에 있는 사용자의 것이기 때문이다.

그래서 사용자가 이 내용을 변경했는지 알아낼수 있어야 한다.

한가지 방법은 bodyusername,emailsession.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페이지 처럼 똑같지 구현하였다.

profile
꿈꾸는 개발자

0개의 댓글