const mongoose = require("mongoose");
// schema
const userSchema = mongoose.Schema(
{
userid: { type: String, required: true, unique: true },
// select : false -> DB에서 데이터 읽어올 떄 password는 읽어오지 않는다.
password: { type: String, required: true , select : false},
name: { type: String, required: true },
email: { type: String },
},
{
toObject: { virtuals: true },
}
);
// virtuals
userSchema
.virtual("pwConfirm")
.get(function () {
return this._pwConfirm;
})
.set(function (value) {
this._pwConfirm = value;
});
userSchema
.virtual("originPw")
.get(function () {
return this._originPw;
})
.set(function (value) {
this._originPw = value;
});
userSchema
.virtual("currPw")
.get(function () {
return this._currPw;
})
.set(function (value) {
this._currPw = value;
});
userSchema
.virtual("newPw")
.get(function () {
return this._newPw;
})
.set(function (value) {
this._newPw = value;
});
// password validation
userSchema.path("password").validate(function (value) {
// this 는 유저 모델
const user = this;
// 유저 생성
if (user.isNew) {
// user가 새로운 document인 경우 -> 생성
if (!user.pwConfirm) {
// 모댈.invalidate : 첫번쨰로 인자 항목이름, 두번쨰로 인자 에러메세지
user.invalidate("pwConfirm", "비밀번호 확인 칸을 입력하세요!");
}
if (user.password !== user.pwConfirm) {
user.invalidate(
"pwConfirm",
"비밀번호와 비밀번호 확인이 일치하지 않습니다!"
);
}
// 기존 유저 정보 수정
} else {
if (!user.currPw) {
user.invalidate("currPw", "현재 패스워드를 입력하세요");
} else if (user.currPw != user.originPw) {
user.invalidate("currPw", "현재 패스워드가 틀렸습니다");
}
if (user.newPw !== user.pwConfirm) {
user.invalidate("pwConfirm", "비밀번호 확인이 일치하지 않습니다!");
}
}
});
const User = mongoose.model("user", userSchema);
module.exports = User;
Schema.path
SchemaType을 반환한다.
password validation
패스워드를 데이터베이스에 생성 또는 수정하기 전 값이 유효한지 확인한다.
model.isNew
true
, 아닌 경우에는 false
HTTP Verb | Action | Path | 설명 |
---|---|---|---|
GET | index | /users | 모든 유저 리스트 조회 |
GET | retrieve | /users/:id | 특정 유저 조회 |
POST | create | /users | 신규 유저 생성 |
PUT | replace | /users/:id | 특정 유저 갱신 |
DELETE | delete | /users/:id | 특정 유저 삭제 |
전체 코드
const express = require("express");
const router = express.Router();
const User = require("../models/User");
router.get("/", (req, res) => {
User.find({})
.sort({ username: 1 })
.exec((err, users) => {
if (err) return res.json(err);
res.json(users);
});
});
router.get("/:_id", (req, res) => {
User.findOne({ _id: req.params._id }, (err, user) => {
if (err) res.json(err);
res.json(user);
});
});
router.post("/", (req, res) => {
console.log(req.body);
User.create(req.body, (err, user) => {
if (err) res.json(err);
res.json(user);
});
});
router.put("/:_id", (req, res) => {
User.findOne({ _id: req.params._id })
.select("password")
.exec((err, user) => {
if (err) return res.json(err);
// 유저 업데이트하기
user.originPw = user.password;
user.password = req.body.newPw ? req.body.newPw : user.password;
for (para in req.body) {
user[para] = req.body[para];
}
user.save((err, user) => {
if (err) return res.json(err);
res.json(user);
});
});
});
router.delete("/:_id", (req, res) => {
User.deleteOne({ _id: req.params._id }, (err) => {
if (err) return res.json(err);
res.status(204).end();
});
});
module.exports = router;
router.get("/", (req, res) => {
// 모든 다큐먼트 검색
User.find({})
.sort({ name: 1 }) // 유저의 이름을 기준으로 정렬한다. (역순 정렬은 -1)
.exec((err, users) => { // 실행
if (err) return res.json(err);
res.json(users);
});
});
데이터베이스에 저장된 모든 유저의 목록을 반환한다.
생성된 유저들을 보면 virtual로 설정한 값들은 저장되지 않은 것이 확인된다.
// /users/ObjectId
router.get("/:_id", (req, res) => {
// url로 넘어온 파라미터를 _id로 저장하여, 해당 아이디를 가지는 유저를 찾는다
User.findOne({ _id: req.params._id }, (err, user) => {
if (err) res.json(err);
res.json(user);
});
});
파라미터로 유저의 아이디를 전달받고 이를 이용하여 유저를 검색하여 반환한다.
router.post("/", (req, res) => {
console.log(req.body);
User.create(req.body, (err, user) => {
if (err) res.json(err);
res.json(user);
});
});
유저 생성 시 password와 pwConfirm이 필요하다. 유저 스키마를 살펴보면 virtual에서 pwConfirm을 생성하여 두었다.
userSchema
.virtual("pwConfirm")
.get(function () {
return this._pwConfirm;
})
.set(function (value) {
this._pwConfirm = value;
});
validate
함수를 사용하여 유저 생성 시 패스워드 필드를 검증한다.
userSchema.path("password").validate(function (value) {
// this 는 유저 모델
const user = this;
// 유저 생성
if (user.isNew) {
// user가 새로운 document인 경우 -> 생성
if (!user.pwConfirm) {
// 모댈.invalidate : 첫번쨰로 인자 항목이름, 두번쨰로 인자 에러메세지
user.invalidate("pwConfirm", "비밀번호 확인 칸을 입력하세요!");
}
if (user.password !== user.pwConfirm) {
user.invalidate(
"pwConfirm",
"비밀번호와 비밀번호 확인이 일치하지 않습니다!"
);
}
router.put("/:_id", (req, res) => {
User.findOne({ _id: req.params._id }) // 1
.select("password") // 2
.exec((err, user) => {
if (err) return res.json(err);
// 유저 업데이트하기
user.originPw = user.password;
user.password = req.body.newPw ? req.body.newPw : user.password; // 3
for (para in req.body) { // 4
user[para] = req.body[para];
}
user.save((err, user) => { // 5
if (err) return res.json(err);
res.json(user);
});
});
});
파라미터를 전달받아서 이를 _id 변수로 넘겨서 해당 아이디를 이용하여 유저를 검색한다.
검색된 유저정보 중 패스워드만 선택한다.
요청 바디로 새로운 패스워드가 전달되었을 시 유저의 패스워드를 업데이트한다.
3.1 이 때 유저 스키마에 지정한 검증 단계로 인해서 우선 현재 비밀번호를 (currPw) 확인한다.
3.2 현재 비밀번호가 일치 할 시 새로운 비밀번호 (newPw) 와 비밀번호 재확인(pwConfirm)을 확인한다
3.3 검증이 성공하면 유저 정보를 업데이트 한다.
요청 바디로 넘겨받은 데이터들로 유저의 정보를 업데이트 한다.
Model.save
함수를 이용하여 정보를 저장한다.
router.delete("/:_id", (req, res) => {
User.deleteOne({ _id: req.params._id }, (err) => {
if (err) return res.json(err);
res.status(204).end();
});
});
삭제가 성공하면 반환하는 값이 없기 때문에 성공했다는 상태값을 반환하도록 설정한다.