일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 포렌식워게임
- GIT
- CTF
- MongoDB
- NavBar
- gitbash
- 자바기초
- 워게임
- Express
- wargame.kr
- 뷰
- 웹해킹
- 자료구조
- 워게임추천
- 포렌식
- 자바문제풀이
- 이진탐색트리
- 웹기초
- 웹개발
- materialize
- node.js
- 써니나타스
- mongoose
- 그래프
- 자바
- 웹해킹기초
- node
- bootstrap
- 이진트리
- nodeJS
- Today
- Total
보안 전공생의 공부
게시판 만들기 / 회원가입 본문
회원가입은 회원(user) model을 만들고,
회원 데이터를 생성해(CRUD-create) DB에 저장하면 된다.
다만 주의해야할 점이 비밀번호가 추가된다는 점이다.
// models/User.js
const mongoose = require('mongoose');
// schema
const userSchema = mongoose.Schema({
username:{type:String, required:[true,'Username is required!'], unique:true},
password:{type:String, required:[true,'Password is required!'], select:false},
name:{type:String, required:[true,'Name is required!']},
email:{type:String}
},{
toObject:{virtuals:true}
});
// virtuals
userSchema.virtual('passwordConfirmation')
.get(function(){ return this._passwordConfirmation; })
.set(function(value){ this._passwordConfirmation=value; });
userSchema.virtual('originalPassword')
.get(function(){ return this._originalPassword; })
.set(function(value){ this._originalPassword=value; });
userSchema.virtual('currentPassword')
.get(function(){ return this._currentPassword; })
.set(function(value){ this._currentPassword=value; });
userSchema.virtual('newPassword')
.get(function(){ return this._newPassword; })
.set(function(value){ this._newPassword=value; });
// password validation
userSchema.path('password').validate(function(v) {
const user = this;
// create user
if(user.isNew){
if(!user.passwordConfirmation){
user.invalidate('passwordConfirmation', 'Password Confirmation is required.');
}
if(user.password !== user.passwordConfirmation) {
user.invalidate('passwordConfirmation', 'Password Confirmation does not matched!');
}
}
// update user
if(!user.isNew){
if(!user.currentPassword){
user.invalidate('currentPassword', 'Current Password is required!');
}
else if(user.currentPassword != user.originalPassword){
user.invalidate('currentPassword', 'Current Password is invalid!');
}
if(user.newPassword !== user.passwordConfirmation) {
user.invalidate('passwordConfirmation', 'Password Confirmation does not matched!');
}
}
});
// model & export
const User = mongoose.model('user',userSchema);
module.exports = User;
required:[true,'별명 필요행 ㅇㅅㅇ!']
required:true/fase 대신 배열([ ])이 들어갔다. 첫번째는 true/false값이고, 두번째는 에러메세지이다.
-> 배열을 이용해 에러메세지의 내용을 원하는대로 작성 가능
select:false
DB에서 해당 모델을 읽어올 때, 해당 값을 읽어오지 않는다.
-> DB에서 비밀번호 값을 읽어오지 않게 설정
DB에 저장되는 값 이외의 항목이 필요한 경우 virtual 항목으로 만든다.
userSchema.virtual('...')
DB에 저장될 필요는 없지만, model에서 사용하고 싶은 항목들을 virtual로 만들면 된다.
DB에 user을 create, update 하기 전에 pw 값이 유효한지 확인하는 코드이다.
이때 사용되는 this는 user model이다.
user.isnew를 통해 현재 pw validation이 회원가입 단계인지, 회원정보 수정 단계인지 확인한다.
회원가입 단계인 경우 -> pwconfirm값이 없는 경우 / pwconfirm값과 pw값이 일치하지 않는 경우
회원정보 수정 단계인 경우 -> pw값이 없는 경우 / 현재pw값과 원래pw값이 일치하지 않는 경우 / 새pw값과 pwconfirm값이 다른 경우
로 분류하여 invalidate(유효하지 않음)처리를 하게 된다.
user.invalidate함수를 사용하는데
이때 첫 번째 인자는 항목이름, 두 번째 인자는 에러메시지를 받는다.
// routes/users.js
const express = require('express');
const router = express.Router();
const User = require('../models/User');
// 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){
res.render('users/new');
});
// create
router.post('/', function(req, res){
User.create(req.body, function(err, user){
if(err) return res.json(err);
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){
User.findOne({username:req.params.username}, function(err, user){
if(err) return res.json(err);
res.render('users/edit', {user:user});
});
});
// 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; // 2-3
for(const p in req.body){
user[p] = req.body[p];
}
// save updated user
user.save(function(err, user){
if(err) return res.json(err);
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;
index route에 보면 sort함수가 있다.
<select함수 이용>
- 항목이름 앞에 -를 붙이면 기본적으로 읽어오게 되어 있는 항목을 안 읽어오게 할 수 있다.
- 하나의 select 함수로 여러 항목을 동시에 정할 수도 있다.
ex) password 읽어오기 & name 안 읽어오기
->.select('password - name')
삼항연산자를 이용하여 정보를 update할 때 password를 처리하는 것에 대해 정의하고 있다.
사용자가 password를 update했으면 이를 user.password에 담고, 아니면 그대로 user.password를 담는다.
req.body는 form에 입력되는 값이다.
· for...in반복문 : 객체의 속성들에 대해 반복
req.body 속성값(username, password, name, email)을 user model 속성값(username, password, name, email)에서 순환을 돌면서 적용한다.
index.js에 users route를 추가한다.
views/partials/nav.ejs 에 Users와 Sign up메뉴를 추가하였다.
ml-auto클래스를 통해 우측정렬을 시켰다.
ejs파일들
<!-- views/users/index.ejs -->
<!DOCTYPE html>
<html>
<head>
<%- include('../partials/head') %>
</head>
<body>
<%- include('../partials/nav') %>
<div class="container mb-3">
<h3 class="mb-3">Users</h3>
<ul class="list-group">
<% if(users == null || users.length == 0){ %>
<li class="list-group-item"> There is no user yet.</li>
<% } %>
<% users.forEach(function(user) { %>
<li class="list-group-item">
<a href="/users/<%= user.username %>"><%= user.username %></a>
</li>
<% }) %>
</ul>
</div>
</body>
</html>
<!-- views/users/new.ejs -->
<!DOCTYPE html>
<html>
<head>
<%- include('../partials/head') %>
</head>
<body>
<%- include('../partials/nav') %>
<div class="container mb-3">
<h3 class="contentBoxTop mb-3">New User</h3>
<form action="/users" method="post">
<div class="form-group row">
<label for="username" class="col-sm-3 col-form-label">Username*</label>
<div class="col-sm-9">
<input type="text" id="username" name="username" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-3 col-form-label">Name*</label>
<div class="col-sm-9">
<input type="text" id="name" name="name" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-3 col-form-label">Email</label>
<div class="col-sm-9">
<input type="text" id="email" name="email" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="password" class="col-sm-3 col-form-label">Password*</label>
<div class="col-sm-9">
<input type="password" id="password" name="password" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="passwordConfirmation" class="col-sm-3 col-form-label">Password Confirmation*</label>
<div class="col-sm-9 col-sm-offset-3">
<input type="password" id="passwordConfirmation" name="passwordConfirmation" value="" class="form-control">
</div>
</div>
<p>
<small>*Required</small>
</p>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</body>
</html>
<!-- views/users/edit.ejs -->
<!DOCTYPE html>
<html>
<head>
<%- include('../partials/head') %>
</head>
<body>
<%- include('../partials/nav') %>
<div class="container mb-3">
<h3 class="mb-3">Edit User</h3>
<form action="/users/<%= user.username %>?_method=put" method="post">
<div class="form-group row">
<label for="currentPassword" class="col-sm-3 col-form-label">Current Password*</label>
<div class="col-sm-9 col-sm-offset-3">
<input type="password" id="currentPassword" name="currentPassword" value="" class="form-control">
</div>
</div>
<hr></hr>
<div class="form-group row">
<label for="username" class="col-sm-3 col-form-label">Username*</label>
<div class="col-sm-9">
<input type="text" id="username" name="username" value="<%= user.username %>" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="name" class="col-sm-3 col-form-label">Name*</label>
<div class="col-sm-9">
<input type="text" id="name" name="name" value="<%= user.name %>" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-3 col-form-label">Email</label>
<div class="col-sm-9">
<input type="text" id="email" name="email" value="<%= user.email %>" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="newPassword" class="col-sm-3 col-form-label">New Password</label>
<div class="col-sm-9 col-sm-offset-3">
<input type="password" id="newPassword" name="newPassword" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="passwordConfirmation" class="col-sm-3 col-form-label">Password Confirmation</label>
<div class="col-sm-9 col-sm-offset-3">
<input type="password" id="passwordConfirmation" name="passwordConfirmation" value="" class="form-control">
</div>
</div>
<p>
<small>*Required</small>
</p>
<div class="buttons">
<a class="btn btn-primary" href="/users/<%= user.username %>">Back</a>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</body>
</html>
<!-- views/users/show.ejs -->
<!DOCTYPE html>
<html>
<head>
<%- include('../partials/head') %>
</head>
<body>
<%- include('../partials/nav') %>
<div class="container mb-3">
<h3 class="contentBoxTop"><%= user.username %></h3>
<form class="user-form" action="/users" method="post">
<fieldset disabled>
<div class="form-group row">
<label for="name" class="col-sm-3 col-form-label">Name</label>
<div class="col-sm-9">
<input class="form-control" type="text" id="name" name="name" value="<%= user.name %>">
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-3 col-form-label">Email</label>
<div class="col-sm-9">
<input class="form-control" type="text" id="email" name="email" value="<%= user.email %>">
</div>
</div>
</fieldset>
</form>
<div>
<a class="btn btn-primary" href="/users">Back</a>
<a class="btn btn-primary" href="/users/<%= user.username %>/edit">Edit</a>
<form action="/users/<%= user.username %>?_method=delete" method="post" class="d-inline">
<a class="btn btn-primary" href="javascript:void(0)" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a>
</form>
</div>
</div>
</body>
</html>
<실행결과>
current password가 현재 DB에 저장된 password와 일치해야 한다.
'WEB > Node' 카테고리의 다른 글
게시판 만들기 / User 생성, 수정 시 error 처리 (1) (0) | 2021.12.01 |
---|---|
게시판 만들기 / password 암호화 -bcrypt (0) | 2021.11.17 |
게시판 만들기 / front end + scope + breadcrumb +bootstrap grid (0) | 2021.10.19 |
게시판 만들기 / back end + mongoose 정리 (0) | 2021.10.18 |
주소록 만들기 / bootstrap, static 파일 서비스+경로 규칙 (2) | 2021.10.17 |