일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 웹개발
- NavBar
- MongoDB
- 이진탐색트리
- 웹해킹기초
- 자료구조
- nodeJS
- gitbash
- materialize
- 웹해킹
- bootstrap
- 웹기초
- 포렌식
- CTF
- mongoose
- node
- wargame.kr
- 워게임추천
- 이진트리
- 포렌식워게임
- 자바
- GIT
- 뷰
- 워게임
- 써니나타스
- Express
- 자바문제풀이
- node.js
- 자바기초
- 그래프
- Today
- Total
보안 전공생의 공부
게시판 만들기 - post error 본문
routes/userjs에서 사용한 parseError함수를 post에서도 사용하여 post의 error를 처리한다.
-> 여러 파일에서 사용하게 될 함수들을 하나의 module로 분리
// util.js
const util = {};
util.parseError = function(errors){
const parsed = {};
if(errors.name == 'ValidationError'){
for(const name in errors.errors){
const validationError = errors.errors[name];
parsed[name] = { message:validationError.message };
}
}
else if(errors.code == '11000' && errors.errmsg.indexOf('username') > 0) {
parsed.username = { message:'This username already exists!' };
}
else {
parsed.unhandled = JSON.stringify(errors);
}
return parsed;
}
module.exports = util;
routes/users.js에 있던 parseError함수를 module로 만들어 util.js파일로 분리한다.
util.js <- 여러 곳에서 공통으로 쓰게 될 함수들을 기록
· user.js 수정
// routes/users.js
const express = require('express');
const router = express.Router();
const User = require('../models/User');
const util=require('../util');
// Index
router.get('/', function(req, res){
User.find({})
.sort({username:1})
.exec(function(err, users){
if(err) return res.json(err);
res.render('users/index', {users:users});
});
});
// New
router.get('/new', function(req, res){
const user = req.flash('user')[0] || {};
const errors = req.flash('errors')[0] || {};
res.render('users/new', { user:user, errors:errors });
});
// create
router.post('/', function(req, res){
User.create(req.body, function(err, user){
if(err){
req.flash('user', req.body);
req.flash('errors', util.parseError(err));
return res.redirect('/users/new');
}
res.redirect('/users');
});
});
// show
router.get('/:username', function(req, res){
User.findOne({username:req.params.username}, function(err, user){
if(err) return res.json(err);
res.render('users/show', {user:user});
});
});
// edit
router.get('/:username/edit', function(req, res){
const user = req.flash('user')[0];
const errors = req.flash('errors')[0] || {};
if(!user){
User.findOne({username:req.params.username}, function(err, user){
if(err) return res.json(err);
res.render('users/edit', { username:req.params.username, user:user, errors:errors });
});
}
else {
res.render('users/edit', { username:req.params.username, user:user, errors:errors });
}
});
// update
router.put('/:username', function(req, res, next){
User.findOne({username:req.params.username})
.select('password')
.exec(function(err, user){
if(err) return res.json(err);
// update user object
user.originalPassword = user.password;
user.password = req.body.newPassword? req.body.newPassword : user.password;
for(var p in req.body){
user[p] = req.body[p];
}
// save updated user
user.save(function(err, user){
if(err){
req.flash('user', req.body);
req.flash('errors', util.parseError(err));
return res.redirect('/users/'+req.params.username+'/edit');
}
res.redirect('/users/'+user.username);
});
});
});
// destroy
router.delete('/:username', function(req, res){
User.deleteOne({username:req.params.username}, function(err){
if(err) return res.json(err);
res.redirect('/users');
});
});
module.exports = router;
// functions
function parseError(errors){
const parsed = {};
if(errors.name == 'ValidationError'){
for(const name in errors.errors){
const validationError = errors.errors[name];
parsed[name] = { message:validationError.message };
}
}
else if(errors.code == '11000' && errors.errmsg.indexOf('username') > 0) {
parsed.username = { message:'This username already exists!' };
}
else {
parsed.unhandled = JSON.stringify(errors);
}
return parsed;
}
const util=require('../util');
util을 require했다.
// create
// update // save updated user
parseError -> util.parseError로 변경했다.
· Post.js 수정
//models/Post.js
const mongoose = require('mongoose');
const postSchema = mongoose.Schema({
title:{type:String, required:[true,'Title is required']},
body:{type:String, required:[true,'Body is required']},
createdAt:{type:Date, default:Date.now},
updatedAt:{type:Date},
});
const Post = mongoose.model('post', postSchema);
module.exports = Post;
post schema의 custom error message를 추가한다.
· posts.js 수정
2021.12.01 - [개발/node.js] - 게시판 만들기 / User 생성, 수정 시 error 처리 (1)와 처리방식이 유사하다.
//routes/posts.js
const express = require('express');
const router = express.Router();
const Post = require('../models/Post');
const util=require('../util');
// Index
router.get('/', function(req, res){
Post.find({})
.sort('-createdAt')
.exec(function(err, posts){
if(err) return res.json(err);
res.render('posts/index', {posts:posts});
});
});
// New
router.get('/new', function(req, res){
const post=req.flash('post')[0]||{};
const errors=req.flash('errors')[0]||{};
res.render('posts/new',{post:post, errors:errors});
});
// create
router.post('/', function(req, res){
Post.create(req.body, function(err, post){
if(err){
req.flash('post',req.body);
req.flash('errors',util.parseError(err));
return res.redirect('/posts/new');
}
res.redirect('/posts');
});
});
// show
router.get('/:id', function(req, res){
Post.findOne({_id:req.params.id}, function(err, post){
if(err) return res.json(err);
res.render('posts/show', {post:post});
});
});
// edit
router.get('/:id/edit', function(req, res){
const post=req.flash('post')[0];
const errors=req.flash('errors')[0]||{};
if(!post){
Post.findOne({_id:req.params.id},function(err,post){
if(err) return res.json(err);
res.render('post/edit',{post:post, errors:errors});
})
}
else{
post._id=req.params.id;
res.render('posts/edit',{post:post, errors:errors});
}
});
// update
router.put('/:id', function(req, res){
req.body.updatedAt = Date.now();
Post.findOneAndUpdate({_id:req.params.id}, req.body, {runValidators:true}, function(err, post){
if(err) {
req.flash('post',req.body)
req.flash('errors',util.parseError(err))
return res.redirect('/posts'+req.params.id+'/edit')
}
res.redirect("/posts/"+req.params.id);
});
});
// destroy
router.delete('/:id', function(req, res){
Post.deleteOne({_id:req.params.id}, function(err){
if(err) return res.json(err);
res.redirect('/posts');
});
});
module.exports = router;
const util=require('../util');
util을 require했다.
post 생성시 에러가 있는 경우 new페이지에 에러와 기존에 입력했던 값들을 보여준다.
(이때, 이 값들은 create route에서 생성된 flash로부터 받아옴)
flash는 배열이 오는데 이 프로그램에서는 하나 이상의 값이 저장되는 경우가 없고 ,
있더라도 오류이므로 무조건 [0]의 값을 읽어오게 했다.
값이 없으면(처음 new페이지에 들어온 경우)에는 | | { }를 사용해 빈 오브젝트를 넣어 posts/new페이지 생성한다.
req.flash(문자열, 저장할 값)형태로 저장할 값(숫자, 문자열, 오브젝트 등 가능)을 해당 문자열에 저장한다.
이때 배열로 저장되기 때문에 같은 문자열을 중복해서 사용하면 순서대로 배열에 저장된다.
req.flash(문자열)인 경우 - 해당 문자열에 저장된 값들을 배열로 불러온다.
<- 저장된 값이 없으면 빈 배열([ ])을 return
post 생성시 오류가 있으면 post, error flash를 만들고 new페이지로 redirect한다.
post 생성시 발생하는 오류는
Post.findOneAndUpdate에 {runValidators:true}가 기존 코드에서 추가되었다.
findOneAndUpdate는 기본설정이 schema에 있는 validation이 작동하지 않도록 되어있어 이 option을 통해
validation이 작동하도록 설정해줘야 한다.
· edit.ejs & new.ejs 수정
<!-- views/posts/edit.ejs -->
<!DOCTYPE html>
<html>
<head>
<%- include('../partials/head') %>
</head>
<body>
<%- include('../partials/nav') %>
<div class="container mb-3">
<nav aria-label="breadcrumb">
<ol class="breadcrumb p-1 pl-2 pr-2">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item"><a href="/posts">Board</a></li>
<li class="breadcrumb-item"><a href="/posts/<%= post._id %>"><%= post.title %></a></li>
<li class="breadcrumb-item active" aria-current="page">Edit Post</li>
</ol>
</nav>
<form action="/posts/<%= post._id %>?_method=put" method="post">
<div class="form-group">
<label for="title">Title</label>
<input type="text" id="title" name="title" value="<%= post.title %>" class="form-control <%= (errors.title)?'is-invalid':'' %>">
<% if(errors.title){ %>
<span class="invalid-feedback"><%= errors.title.message %></span>
<% } %>
</div>
<div class="form-group">
<label for="body">Body</label>
<textarea id="body" name="body" rows="5" class="form-control <%= (errors.body)?'is-invalid':'' %>"><%= post.body %></textarea>
<% if(errors.body){ %>
<span class="invalid-feedback"><%= errors.body.message %></span>
<% } %>
</div>
<% if(errors.unhandled){ %>
<div class="invalid-feedback d-block">
<%= errors.unhandled %>
</div>
<% } %>
<div>
<a class="btn btn-primary" href="/posts/<%= post._id %>">Back</a>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</body>
</html>
각 항목의 form-group class가 있는 div에 위의 코드를 추가하였다.
만약 error가 있다면 bootstrap의 invalid-feedback class를 사용한다.
error.unhandled는 따로 표시한다.
<!-- views/posts/new.ejs -->
<!DOCTYPE html>
<html>
<head>
<%- include('../partials/head') %>
</head>
<body>
<%- include('../partials/nav') %>
<div class="container mb-3">
<nav aria-label="breadcrumb">
<ol class="breadcrumb p-1 pl-2 pr-2">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item"><a href="/posts">Board</a></li>
<li class="breadcrumb-item active" aria-current="page">New Post</li>
</ol>
</nav>
<form action="/posts" method="post">
<div class="form-group">
<label for="title">Title</label>
<input type="text" id="title" name="title" value="<%= post.title %>" class="form-control <%= (errors.title)?'is-invalid':'' %>">
<% if(errors.title){ %>
<span class="invalid-feedback"><%= errors.title.message %></span>
<% } %>
</div>
<div class="form-group">
<label for="body">Body</label>
<textarea id="body" name="body" rows="5" class="form-control <%= (errors.body)?'is-invalid':'' %>"><%= post.body %></textarea>
<% if(errors.body){ %>
<span class="invalid-feedback"><%= errors.body.message %></span>
<% } %>
</div>
<% if(errors.unhandled){ %>
<div class="invalid-feedback d-block">
<%= errors.unhandled %>
</div>
<% } %>
<div>
<a class="btn btn-primary" href="/posts">Back</a>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</body>
</html>
위의 edit.ejs와 같다.
<실행결과>
post 작성시 Title과 Body를 작성하지 않고 Submit하면 이렇게 error message가 뜬다.
'WEB > Node' 카테고리의 다른 글
중간 정리 (2) | 2021.12.28 |
---|---|
게시판 만들기 - Post-User 관계 만들기 (1) 게시물에 작성자 만들기 (0) | 2021.12.19 |
게시판 만들기 / login 기능 - passport package (0) | 2021.12.07 |
게시판 만들기 / User 생성, 수정 시 error 처리 (2) (0) | 2021.12.01 |
게시판 만들기 / User 생성, 수정 시 error 처리 (1) (0) | 2021.12.01 |