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 { 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