join은 끝났다.
어떻게 계정을 만드는지 해봤고 에러를 처리하고 상태 코드는 어떻게 보내는지도 해봤다.
계정을 성공적으로 생성했으면 로그인을 해야한다.
원한다면 이 부분을
userController.js에서
const exists = await User.exists({ $or: [{ username }, { email }] });
if (exists) {
return res.status(400).render("join", {
pageTitle,
errorMessage: "This username/email is already taken.",
});
}
try {
await User.create({
name,
username,
email,
password,
location,
});
return res.redirect("/login");
} catch (error) {
return res.status(400).render("join", {
pageTitle: "join",
errorMessage: error._message,
});
}
};
try ~ catch 구문 안에 넣었다. videoController.js에서 했던 것처럼 만들었다.
거의 똑같이 해주었다. 처리하지 못한 에러가 있을수도 있으니까 지금 최대한 많은 에러를
처리를 하고 있다. 이미 사용중인 username과 password가 일치 하는지 확인하고 있다.
그래도 다른 에럭가 있을 수도 있다. videoController에서 했던 것처럼 try~catch를 사용해서
에러를 방지 할수 있다. DB에러가 발생 했을때 upload가 아니라 join을 render하면 된다.
더 안전해 지는 거다. User를 만들때도 try~catch를 쓰고 있는거다.
그런데 이건 직접 에러를 처리하고 난 다음에 쓰는 거다.
if (password !== password2) {
return res.status(400).render("join", {
pageTitle,
errorMessage: "Password confirmation does not match.",
});
}
const exists = await User.exists({ $or: [{ username }, { email }] });
if (exists) {
return res.status(400).render("join", {
pageTitle,
errorMessage: "This username/email is already taken.",
});
}
이제 로그인 페이지를 만들어 보도록 한다.
먼저 join파일에서 시작해 보도록 한다.
join.pug에서
hr
div
span Already have an account?
a(href="/login") Log in now →
새로고침 하면 하단에 "이미 계정이 있습니까? 로그인 하세요 ->" 까지 잘 나온다.
이제 login을 클릭하면 /login으로 넘어가게 된다. 아직은 텍스트만 나온다.
userController.js에서
export const getLogin = (req, res) => res.send("Login");
export const edit = (req, res) => res.send("Edit User");
export const remove = (req, res) => res.send("Remove User");
export const logout = (req, res) => res.send("Log out");
export const see = (req, res) => res.send("See User");
순서를 바꿔 주고 router를 만들 필요는 없다. 이미 router가 있으니까
routers폴더에서 rootRouter로 이동하면
import { getJoin, postJoin, getLogin } from "../controllers/userController";
rootRouter.route("/login").get(getLogin);
get("/login")이 login function을 호출한다.
이제 여기서 get과 post를 써야 된다는걸 알고 있다.
그래서 import 부분의 login을 getLogin으로 바꿔 주고
rootRouter 부분도 바꿔 준다. get이 아니라 route로 변경해준다.
rootRouter.route("/login").get(getLogin);
userController.js에서도 getLogin으로 변경해준다.
이제 새로고침을 했을때 아무것도 바뀌는게 있으면 안된다. 다행히 바뀐게 없다.
지금 controller의 이름만 바꿔 주었다. route구조로 바꾸기도 했는데 내용은 바꾸지 않았다.
이제
login template을render한다.
userController의 getLogin에서
export const getLogin = (req, res) => res.render("login");
res.send()를 res.render()로 바꿔 주었다. Loing은 소문자로 변경한다.
이제 login이라는 이름을 가진 파일을 만들어야 한다.
views폴더로 가서 login.pug파일을 만든다. login template은 join이랑 엄청 비슷한거다.
그래서 모두 복붙해준다.
extends base
block content
if errorMessage
span=errorMessage
form(method="POST")
input(placeholder="Username",name="username", type="text", requeired)
input(placeholder="Password",name="password", type="password", requeired)
input(type="submit", value="Join")
hr
div
span Don't have an account?
a(href="/login") Create one now →
login template에 붙여 넣고 내용을 바꿔준다.
그리고 로그인 할때는 name과 email을 입력하지 않아도 된다.
그저 username과 password만 있으면 된다. 나머지는 삭제해 준다.
전에 했던거랑 크게 다를게 없다. HTML을 코드를 지워서 template만 수정 했을 뿐이다.
새로고침을 해주면 username과 password 입력하는 칸만 남았다.
Create one now를 누르면 /join으로 가게 만들어 준다.
a(href="/join") Create one now →
아직 template에는 pageTitle이 없다.
pageTitle을 만들어 준다.
userControoller로 가서 pageTitle을 써주면 된다.
export const getLogin = (req, res) =>
res.render("login", { pageTitle: "Login" });
새로고침하면 잘 작동한다. 그리고 join버튼도 거슬리니 Login버튼으로 바꿔 준다.
login.pug에서
input(type="submit", value="Login")
이제
/login으로post요청을 받았을때 어떻게 하면 될까??
우선 입력한 username을 가진 User가 존재하는지 확인해야한다.
해당 계정이 존재하지 않을수도 있다. 그리고 password를 확인하면 된다.
우선 post controller를 만들어 본다.
export const getLogin = (req, res) =>
res.render("login", { pageTitle: "Login" });
export const postLogin = (req, res) => {
// check if account exists
// check if password correct
res.end();
};
일단 res.end()만 써준다. 그리고 주석처리를 해서 '계정이 존재하는지 체크',
'패스워드가 일치하는지 체크 ' 이렇게 적어 줬다.
이제 이 postlogin controller를 router에서 사용하도록 한다.
import {
getJoin,
postJoin,
getLogin,
postLogin,
} from "../controllers/userController";
rootRouter.route("/login").get(getLogin).post(postLogin);
/login으로 post요청을 보내면 postLogin을 호출하게 만든다. import도 해준다.
이제 route("/join"),getJoin... route("/login"),getLogin,postLogin
이 생겼다. 어느 정도 구조가 생긴게 보인다.
이제 post요청을 보내면 body에서 username과 password를 받게 된다.
그러면 body에서 username과 password를 꺼내보도록 한다.
userController.js에서
export const postLogin = (req, res) => {
const { username, password } = req.body;
// check if account exists
// check if password correct
res.end();
};
다음으로
mongoose를 사용할 차례이다.
그래서 async,await를 써서
export const postLogin = async (req, res) => {
const { username, password } = req.body;
const exists = await User.exists({ username });
if (!exists) {
return res
.status(400)
.render("login", {
pageTitle: "Login",
errorMessage: "An account with this username does not exists.",
});
}
받은 username과 일치하는 User가 있는지 확인해 본다.
const exists를 만들고 mongoose에서 가져온 await User를 쓴다.
User.exists() 그리고 username이 받은 username과 같은 User를 찾을거다.
그리고 에러를 체크한다. 만약 존재하지 않는다면 res.status(400)을 return하고
Bad Request인 400을 보내고 login form을 render한다.
pageTitle도 추가한다. 그리고 errorMessage도 써줬다.
"입력한 username을 가진 User가 존재하지 않습니다."
이제 에러가 발생하는지 테스트해 본다. 에러메세지가 잘 작동한다.
이번에는 존재하는 username을 입력해 본다. 아무것도 나오지 않는다.
왜냐하면 res.end()만 썼으니까 그렇다.