You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

334 lines
11 KiB

const repl = require("repl");
const boardController = {};
/**
* 게시판 정보를 가져옵니다.
*/
boardController.getBoardInfo = async(req, res) => {
const boardKey = req.params?.boardKey ?? ''
// 게시판 키가 올바르게 넘어왔는지 확인합니다.
if(! boardKey) {
return res.status(400).json({error:'존재 하지 않거나 삭제된 게시판입니다.'});
}
// 게시판 모델 불러오기
const boardModel = loadModule('board', 'model')
// 게시판 정보 가져오기
const boardInfo = await boardModel.getBoard(boardKey)
if(!boardInfo || boardInfo === {} )
{
return res.status(400).json({error:'존재 하지 않거나 삭제된 게시판입니다.'})
}
return res.json({result: boardInfo})
}
boardController.getPost = async(req, res) => {
const postId = req.params?.postId
const boardModel = loadModule('board', 'model')
const result = await boardModel.getPostOne(postId)
if(result) {
// 문자열 형태로 되어있는 attach_list는 JSON형태로 변환해준다.
result.attach_list = JSON.parse(result.attach_list);
result.is_notice = result.is_notice === 'Y'
}
return res.json({result})
}
boardController.getPostList = async(req, res) => {
const params = {}
params.key = req.params?.boardKey ?? ''
params.page = req.query?.page ?? 1
params.page_rows = req.query?.page_rows ?? 10
params.searchColumn = req.query?.searchColumn ?? ''
params.searchQuery = req.query?.searchQuery ?? ''
// 게시판 모델 불러오기
const boardModel = loadModule('board', 'model')
// 먼저 공지글 부터 불러온다
params.isNotice = true;
const noticeList = await boardModel.getPost(params);
// 일반 게시글을 불러온다.
params.isNotice = false;
const list = await boardModel.getPost(params);
// 반환할 객체를 반든다.
const result = {
result: [...noticeList.result, ...list.result], // 공지사항 목록과 일반게시글 목록을 합친다.
totalCount: list.totalCount
}
return res.json(result)
}
/**
* 게시글 작성 / 수정 / 답글 처리
*/
boardController.writeBoardPost = async(req, res) => {
const boardKey = req.params?.boardKey ?? ""
let postId = req.params?.postId ?? 0
postId = postId * 1;
const postParentId = req.body?.parent_id * 1 ?? 0
// 넘어온 데이타에 따라 수정인지 신규인지 답글인지 미리 정의해둔다
const isEdit = postId > 0
const isReply = postId === 0 && postParentId > 0
// 저장할 데이타를 먼저 정리한다.
const updateData = {};
updateData.title = req.body?.title ?? ''
updateData.content = req.body?.content ?? ''
updateData.category = req.body?.category ?? ''
updateData.author_name = req.body?.author_name ?? ''
updateData.author_pass = req.body?.author_pass ?? ''
updateData.is_notice = req.body?.is_notice === true ? 'Y' : 'N'
updateData.updated_at = new Date()
updateData.updated_user = req.loginUser.id
updateData.updated_ip = req.loginUser.ip
// 첨부파일 목록
const attach_list = req.body?.attach_list ?? []
updateData.attach_list = JSON.stringify(attach_list);
// 게시판 모델 불러오기
const boardModel = loadModule('board','model');
// 답글이거나, 수정일 경우 원본 글을 가져와야 한다.
let refData = null;
if(isEdit) {
refData = await boardModel.getPostOne(postId);
if(! refData) {
return res.status(400).json({error:'수정하려는 원본글이 존재하지 않거나 이미 삭제되었습니다.'})
}
}
else if (isReply) {
refData = await boardModel.getPostOne(postParentId);
if(! refData) {
return res.status(400).json({error:'답글을 작성하려는 원본글이 존재하지 않거나 이미 삭제되었습니다.'})
}
}
// 로그인된 사용자의 경우, 비밀번호와 작성자이름은 비워둔다.
if(req.loginUser.id > 0) {
updateData.author_name = ''
updateData.author_pass = ''
}
// 비로그인 사용자의 경우, 이름과 비밀번호를 작성하였는지 체크한다.
else {
if(updateData.author_name.length === 0) {
return res.status(400).json({error:'닉네임을 입력하셔야 합니다.'});
}
if(updateData.author_pass.length === 0) {
return res.status(400).json({error:'비밀번호를 입력하셔야 합니다.'});
}
// 입력받은 비밀번호를 암호화 한다.
updateData.author_pass = require('sha256')(require('md5')(appConfig.secretKey + updateData.author_pass))
// 수정글인 경우 입력한 비밀번호와 기존 글의 비밀번호가 동일한지 확인한다.
if(isEdit) {
if (updateData.author_pass !== refData?.author_pass) {
return res.status(400).json({error:'수정하려는 글의 비밀번호가 맞지않습니다.'})
}
}
}
// 신규등록일 경우 필수 정보를 추가해준다.
if(! isEdit) {
updateData.board_key = boardKey;
updateData.type = req.body?.type ?? 'POST' // DEFAULT 로 'POST' 입력, 댓글일경우 명시해줘야함
updateData.created_at = updateData.updated_at
updateData.created_user = updateData.updated_user
updateData.created_ip = updateData.updated_ip
if(isReply) {
updateData.parent_id = postParentId
}
}
// 첨부된 파일중 이미지 파일이 있다면 썸네일로 지정함
updateData.thumbnail = ''
// 첨부파일 배열을 돌면서 검사
for(let i=0; i<attach_list.length; i++) {
if(attach_list[i].isImage) {
// 해당 첨부파일이 이미지이면 첨부파일로 값을 넣고, for문 break;
updateData.thumbnail = attach_list[i].file_url;
break;
}
}
updateData.attach_count = attach_list.length;
// 데이타베이스 처리 객체
const db = database()
// 멀티뎁스 게시판을 위한 처리
// 신규작성일때만 처리한다.
if(! isEdit)
{
// 부모게시글이 없다면?
if(! isReply) {
updateData.reply = ''
// num은 게시글의 가장 큰 num 값을 가져와 1을 더한다.
updateData.num = 1
await db('tbl_board_posts').max('num', {as: 'max'})
.then((rows) => {
if(rows && rows[0]) {
updateData.num = (rows[0]?.max ?? 0) + 1
}
})
}
else {
// num은 부모의 num을 그대로 따른다.
updateData.num = refData.num
// reply를 계산하자. reply의 컬럼 길이가 10이므로 최대 10단계까지 답변가능
if(refData.reply.length >= 10) {
return res.status(400).json({error:'더 이상 답변할 수 없습니다. 답변은 10단계 까지만 가능합니다.'})
}
const replyLen = refData.reply.length + 1;
const begin_reply_char = 'A';
const end_reply_char = 'Z';
let replyChar = begin_reply_char;
let query = `SELECT MAX(SUBSTRING(reply, ${replyLen}, 1)) AS reply FROM tbl_board_posts WHERE board_key = ? AND num = ? AND SUBSTRING(reply, ${replyLen}, 1) <> '' `
let bindList = [boardKey, refData.num]
if(replyLen >0) {
query += " AND reply LIKE ? "
bindList.push( refData.reply + '%' );
}
await db.raw(query, bindList)
.then(rows => {
if(rows && rows[0]) {
if(rows[0].reply === end_reply_char ) {
return res.status(500).json({error: '더 이상 답변할 수 없습니다. 답변은 26개까지만 가능합니다.'})
}
else if (rows[0].reply){
replyChar = String.fromCharCode(rows[0].reply.charCodeAt(0) + 1);
}
}
})
}
}
// 실제 DB 입력처리
try {
if(isEdit) {
await db('tbl_board_posts').where('id', postId).update(updateData);
}
else {
await db('tbl_board_posts').insert(updateData).then(id => {
postId = id;
});
}
}
catch {
return res.status(500).json({error:'DB 입력도중 오류가 발생하였습니다.'});
}
return res.status(200).json({result: {id: postId}})
}
/**
* 게시판 조회수 처리하기
*/
boardController.increasePostHit = async(req, res) => {
// 패러미터에서 값을 받습니다.
const boardKey = req.params?.boardKey ?? ''
const postId = (req.params?.postId?? 0) * 1
console.log(boardKey, postId);
if(! boardKey || postId < 0) {
// 조회수를 올리는 작업의 경우 실패하여도 사용자에겐 보이지 않도록 silent 하게 처리해야하므로 오류일 경우에도 STATUS 200처리.
return res.json({})
}
try {
const db = database()
await db.raw("UPDATE tbl_board_posts SET `hit` = `hit` + 1 WHERE id = ?", [postId]);
}
catch {}
return res.json({})
}
/**
* 게시글 삭제하기
*/
boardController.deletePost = async(req, res) => {
// 패러미터에서 값을 받습니다.
const boardKey = req.params?.boardKey ?? ''
const postId = (req.params?.postId?? 0) * 1
// 먼저 원본 게시글 데이타를 가져옵니다.
const boardModel = loadModule('board', 'model');
const original = boardModel.getPostOne(postId);
// 원본글이 없거나 이미 삭제된 글의 경우 처리
if(! original || original.status === 'N' ) {
return res.status(400).json({error: '존재하지 않거나 이미 삭제된 글입니다.'});
}
// 삭제 권한을 체크합니다.
if(this.loginUser.auth < 10 ) {
// 관리자 권한이 아닌경우
if( original.created_user === 0 && this.loginUser.id === 0 )
{
// 작성자도 비회원, 현재 사용자도 비회원일경우 비밀번호 체크
const password = req.body?.password ?? ''
const encryptedPassword = require('sha256')(require('md5')(appConfig.secretKey + password))
// 비밀번호가 다를경우
if(encryptedPassword !== original.author_pass) {
return res.status(400).json({error :'해당 글을 삭제할 권한이 없습니다.'});
}
}
else if (original.created_user !== this.loginUser.id)
{
// 작성자와 현재 로그인 회원이 다른경우
return res.status(400).json({error :'해당 글을 삭제할 권한이 없습니다.'});
}
}
// STATUS를 N 처리해준다.
try {
const db = database()
await db(boardModel.postTableName)
.where('id', postId)
.update({
status: 'N',
updated_at: new Date(),
updated_user: this.loginUser.id,
updated_ip : this.loginUser.ip``
})
}
catch {
return res.status(500).json({error:'DB 에러'});
}
return res.json({})
}
module.exports = boardController