app.js
const express = require("express");
// const mongoose = require("mongoose");
// mongoose.set('strictQuery', true);
const { post } = require("./models");
const { User } = require("./models");
const { comment } = require("./models");
const jwt = require('jsonwebtoken');
const router = express.Router();
const app = express();
const { Op } = require("sequelize");
const authMiddleware = require('./middlewares/auth-middlewares');
// mongoose.connect("mongodb://127.0.0.1:27017/shopping-demo", {
// useNewUrlParser: true,
// useUnifiedTopology: true,
// });
// const db = mongoose.connection;
// db.on("error", console.error.bind(console, "connection error:"));
app.use(express.json());
app.use("/api", express.urlencoded({ extended: false }), router); // urlencoded는 미들웨어, 즉 /api로 들어온것은 urlencoded 미들웨어를 거친다음 라우터로 가라 라는 뜻
app.use(express.static("assets")); // 정적 파일을 서빙해준다.
// 회원가입 기능 몽구스 버전
// const User = require('./models/user')
// router.post('/users', async(req,res) => {
// const {nickname, email, password, confirmPassword} = req.body;
// // 1. 패스워드와 패스워드확인 값이 일치하는가
// // 2. 이메일과 닉네임 중복인가
// // 3. db에 삽입
// if (password !== confirmPassword) {
// res.status(400).json({errorMessage:"비밀번호 확인이 일치하지 않습니다."});
// return; // 위에 패스워드가 일치하지 않으면 밑에 코드를 더 실행하면 안되니까 여기서 리턴해준다
// }
// const existUser = await User.findOne({
// $or: [{email: email},{nickname:nickname}] // $or << 이안에 있는 값중에 하나라도 일치했을 때 보여준다.
// }); // 그리고 값중에 하나라도 일치한다는 뜻은 이메일이나 닉네임 중 중복이 있다는 뜻이기에 더 진행해선 안된다.
// if (existUser) {
// res.status(400).json({errorMessage:"이메일이나 닉네임이 중복됩니다."})
// return; // 중복되면 회원가입이 되면 안되기에 여기서 리턴하여 코드를 종료시킨다.
// }
// // 여기까지 위의 두 if문을 거치지 않았다면 회원가입이 정상적으로 실행되어야 한다.
// const user = new User({nickname,email,password});
// await user.save();
// res.status(201).json({}); // 스테이터스 201은 무언가를 만들었다는 creat 생성 코드! 기억하면 좋음
// });
// 위 부터 회원가입 mysql 시퀄라이즈 버전
router.post("/users", async (req, res) => {
const { email, nickname, password, confirmPassword } = req.body;
console.log('콘솔로그 :' , req.body)
if (password !== confirmPassword) {
res.status(400).send({
errorMessage: "패스워드가 패스워드 확인란과 다릅니다.",
});
return;
}
if (nickname.length < 3){
res.status(400).send({
errorMessage: "닉네임은 최소 3글자 이상이어야 합니다."
})
return;
}
if (password.length < 4) {
res.status(400).send({
errorMessage: "비밀번호는 최소 4자 이상이어야 합니다."
})
return;
}
if (password.includes(nickname) === true) {
res.status(400).send({
errorMessage: "비밀번호 안에 닉네임이 포함될 수 없습니다."
})
return;
}
// email or nickname이 동일한게 이미 있는지 확인하기 위해 가져온다.
const existsUsers = await User.findAll({
where: {
[Op.or]: [{ email }, { nickname }],
},
});
if (existsUsers.length) {
res.status(400).send({
errorMessage: "이메일 또는 닉네임이 이미 사용중입니다.",
});
return;
}
await User.create({ email, nickname, password });
res.status(201).json({message:"회원가입 완료!"});
}); // 회원가입
// 로그인 기능 몽구스버전
// router.post('/auth', async(req,res) => {
// const {email,password} = req.body;
// const user = await User.findOne({email}); // 특정 사용자를 이메일을 바탕으로 먼저 찾을 것 .
// // 1. 로그인이 가능하지 않을 경우를 먼저 구현하는데 우선 사용자가 존재하지 않거나
// // 2. 입력받은 패스워드와 사용자의 패스워드가 다를 때 에러 메세지를 발생 시켜야 한다.
// if (!user || password !== user.password) {
// res.status(400).json({errorMessage:"로그인 정보가 일치하지 않습니다."})
// return;
// }
// // 이제는 위의 if문을 거치지 않는다면 사용자 정보가 일치한다는 뜻이니 로그인이 되어야한다.
// const token = jwt.sign({userId:user.userId},'juho-secretkey') // 여기서 user.userId의 userId는 /models/user.js에서 8번줄인 _id값이란 뜻이다.
// // 즉, user.userId는 user._id와 같다는 뜻!
// res.status(200).json({
// "token":token,
// })
// })
router.post("/auth", async (req, res) => {
// 로그인 기능 mysql 시퀄라이저버전
const { email, password } = req.body;
const user = await User.findOne({
where: {
email,
},
});
// NOTE: 인증 메세지는 자세히 설명하지 않는것을 원칙으로 한다: https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html#authentication-responses
if (!user || password !== user.password) {
res.status(400).send({
errorMessage: "이메일 또는 패스워드가 틀렸습니다.",
});
return;
}
res.send({
token: jwt.sign({ userId: user.userId }, "customized-secret-key"),
});
console.log(token)
}); // 로그인
// 전체 게시글 보기
router.get('/post', async (req,res) => {
const all_post = await post.findAll({})
res.status(200).json({all_post})
})
// 게시글 작성
router.post("/post", async (req, res) => {
const { post_title, post_content, post_user } = req.body;
await post.create({ post_title, post_content, post_user });
res.status(201).json({message:"게시글 작성 완료!"})
});
// 모든 댓글 보기
router.get('/comment', async (req,res) => {
const all_comment = await comment.findAll({})
res.status(200).json({success:all_comment})
})
// 댓글 작성
router.post('/comment', async (req,res) => {
// const {post_id} = req.params;
const {comment_content,comment_user} = req.body;
if (comment_content === undefined){
return res.status(400).json({errorMessage:"댓글 내용을 입력해주세요."})
}
await comment.create({
comment_content,comment_user
})
res.status(201).json({message:"댓글 작성 완료!!"});
})
// 댓글 삭제
router.delete('/comment/:comment_id', async (req,res) => {
const {comment_id} = req.params
console.log(comment_id);
await comment.destroy({
where: { comment_id: comment_id },
});
res.status(200).json({success:"댓글을 삭제하였습니다."})
})
// 댓글 수정
router.put('/comment/:comment_id', async (req,res) => {
const {comment_id} = req.params
const {comment_content} = req.body
if (comment_content === undefined){
return res.status(400).json({errorMessage:"수정할 내용을 입력해주세요."})
}
await comment.update({comment_content: comment_content}, {
where: { comment_id: comment_id },
});
res.status(200).json({success:"댓글을 수정하였습니다."})
})
app.listen(8080, () => {
console.log("서버가 요청을 받을 준비가 됐어요");
});
./models/user.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
User.init({
userId: {
primaryKey: true,
type: DataTypes.INTEGER,
},
email: DataTypes.STRING,
nickname: DataTypes.STRING,
password: DataTypes.STRING
}, {
sequelize,
modelName: 'User',
});
return User;
};
./models/post.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class post extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
}
post.init({
post_id: {
primaryKey: true,
type: DataTypes.INTEGER,
},
post_title: DataTypes.STRING,
post_content: DataTypes.TEXT,
post_user: DataTypes.INTEGER
}, {
sequelize,
modelName: 'post',
});
return post;
};
./models/comment
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class comment extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
}
comment.init({
comment_id: {
primaryKey: true,
type: DataTypes.INTEGER,
},
comment_content: DataTypes.TEXT,
comment_user: DataTypes.INTEGER
}, {
sequelize,
modelName: 'comment',
});
return comment;
};
./migrations/create-user.js
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Users', {
userId: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
email: {
type: Sequelize.STRING
},
nickname: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Users');
}
};
./migrations/create-comment
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('comments', {
comment_id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
comment_content: {
type: Sequelize.TEXT
},
comment_user: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('comments');
}
};
./migrations/create-post.js
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('posts', {
post_id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
post_title: {
type: Sequelize.STRING
},
post_content: {
type: Sequelize.TEXT
},
post_user: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('posts');
}
};