diff --git a/README.md b/README.md deleted file mode 100644 index 07fe99e..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# murakano-be -개발 용어 발음 검색 서비스 "머라카노"의 백엔드 레포지토리 입니다. diff --git a/src/common/constants/error-message.js b/src/common/constants/error-message.js index 5b0cbcb..e825ffe 100644 --- a/src/common/constants/error-message.js +++ b/src/common/constants/error-message.js @@ -31,7 +31,11 @@ const ErrorMessage = Object.freeze({ DELETE_RECENT_WORD_ERROR: '최근 검색어 삭제중 오류가 발생하였습니다.', SEARCH_WORDS_ERROR: '검색 결과 조회 중 오류가 발생하였습니다.', RANK_WORDS_ERROR: '인기 검색어 조회 중 오류가 발생하였습니다.', - RELATED_WORDS_ERROR: '연관 검색어 조회 중 오류가 발생하였습니다.', + + // REQUEST + GET_REQUESTS_ERROR: '요청 조회중 오류가 발생하였습니다.', + DELETE_REQUEST_ERROR: '요청 삭제중 오류가 발생하였습니다.', + UPDATE_REQUEST_STATE_ERROR: '요청 상태 변경중 오류가 발생하였습니다.', }); module.exports = ErrorMessage; diff --git a/src/common/constants/success-message.js b/src/common/constants/success-message.js index f4a4ea2..c1ff2f7 100644 --- a/src/common/constants/success-message.js +++ b/src/common/constants/success-message.js @@ -1,4 +1,4 @@ -const SucesssMessage = Object.freeze({ +const SuccessMessage = Object.freeze({ // USER - 회원가입 REGISTER_SUCCESSS: '회원가입 성공', AVAILABLE_NICKNAME: '사용 가능한 닉네임입니다.', @@ -20,7 +20,13 @@ const SucesssMessage = Object.freeze({ SEARCH_WORDS_SUCCESS: '검색어 조회 성공', SEARCH_WORDS_NONE: '검색 결과가 없습니다.', RANK_WORDS_SUCCESS: '인기 검색어 조회 성공', - RELATED_WORDS_SUCCESS: '연관 검색어 조회 성공', + + // REQUEST - 요청 + DELETE_REQUEST_SUCCESS: '요청 삭제 성공', + GET_REQUESTS_SUCCESS: '요청 조회 성공', + GET_ROLE_SUCCESS: '사용자 역할 조회 성공', + UPDATE_REQUEST_SUCCESS: '요청 수정 성공', + UPDATE_REQUEST_STATE_SUCCESS: '요청 상태 변경 성공', }); -module.exports = SucesssMessage; +module.exports = SuccessMessage; diff --git a/src/routes/index.js b/src/routes/index.js index 4e99e88..52d8aab 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -11,6 +11,7 @@ router.use('/users', userRouter); router.use('/words', wordRouter); + // EB health check router.get('/', (_, res) => { res.status(200).json({ message: 'Success' }); diff --git a/src/routes/user/user.controller.js b/src/routes/user/user.controller.js index 509a8d1..29d1410 100755 --- a/src/routes/user/user.controller.js +++ b/src/routes/user/user.controller.js @@ -2,6 +2,7 @@ const passport = require('passport'); const jwt = require('jsonwebtoken'); const config = require('../../common/config'); + const userService = require('./user.service'); const sendResponse = require('../../common/utils/response-handler'); const ErrorMessage = require('../../common/constants/error-message'); @@ -218,3 +219,82 @@ exports.delRecentSearch = async (req, res) => { sendResponse.fail(req, res, ErrorMessage.DELETE_RECENT_WORD_ERROR); } }; + +exports.UserRequests = async (req, res) => { + try{ + const { _id } = req.user; + const requests = await userService.getUserRequests(_id); + sendResponse.ok(res, { + message: SuccessMessage.GET_REQUESTS_SUCCESS, + data: { requests }, + }); + } catch (err) { + console.log(err); + sendResponse.fail(req, res, ErrorMessage.GET_REQUESTS_ERROR); + } +}; + +exports.UserRequestsAll = async (req, res) => { + try{ + const requests = await userService.getUserRequestsAll(); + sendResponse.ok(res, { + message: SuccessMessage.GET_REQUESTS_SUCCESS, + data: { requests }, + }); + } catch (err) { + console.log(err); + sendResponse.fail(req, res, ErrorMessage.GET_REQUESTS_ERROR); + } +} + +exports.deleteRequest = async (req, res) => { + try{ + const { _id } = req.user; // 현재 로그인한 사용자의 고유 식별자 + const { word } = req.params; + await userService.deleteRequest(_id, word); + sendResponse.ok(res, { + message: SuccessMessage.DELETE_REQUEST_SUCCESS, + }); + } catch (err) { + console.log(err); + sendResponse.fail(req, res, ErrorMessage.DELETE_REQUEST_ERROR); + } +} + +exports.getRole = async (req, res) => { + const { _id } = req.user; + const role = await userService.getRole(_id); + sendResponse.ok(res, { + message: SuccessMessage.GET_ROLE_SUCCESS, + data: { role }, + }); +} + +exports.updateRequest = async (req, res) => { + const { _id } = req.user; + const { word } = req.params; + const { formData } = req.body; + await userService.updateRequest(_id, word, formData); + sendResponse.ok(res, { + message: SuccessMessage.UPDATE_REQUEST_SUCCESS + }); +} + +exports.updateRequestState = async (req, res) => { + try { + const { _id} = req.user; + const { requestId } = req.params; + const { status } = req.body; + + console.log("요청업데이트컨트롤러 진입!!!!", _id, requestId, status) + + await userService.updateRequestState(_id, requestId, status); + sendResponse.ok(res, { + message: SuccessMessage.UPDATE_REQUEST_STATE_SUCCESS, + }); + } catch (err) { + console.log(err); + sendResponse.fail(req, res, ErrorMessage.UPDATE_REQUEST_STATE_ERROR); + } +} + diff --git a/src/routes/user/user.model.js b/src/routes/user/user.model.js index b39fcde..fabaff8 100644 --- a/src/routes/user/user.model.js +++ b/src/routes/user/user.model.js @@ -14,6 +14,7 @@ const requestSchema = new mongoose.Schema( }, ], info: { type: String }, + suggestedBy: { type: String, required: true }, type: { type: String, enum: ['add', 'mod'], required: true }, status: { type: String, enum: ['pend', 'rej', 'app'], default: 'pend' }, deletedAt: { type: Date, default: null }, diff --git a/src/routes/user/user.repository.js b/src/routes/user/user.repository.js index f42879d..883b299 100644 --- a/src/routes/user/user.repository.js +++ b/src/routes/user/user.repository.js @@ -1,4 +1,6 @@ const User = require('./user.model'); +const mongoose = require('mongoose'); +const { ObjectId } = mongoose.Types; exports.createUser = async (userData) => { try { @@ -57,11 +59,14 @@ exports.delRecentSearch = async (_id, searchTerm) => { exports.updateRecentSearch = async (_id, searchTerm) => { try { + console.log("id", _id) + console.log("searchTerm", searchTerm) const user = await User.findById(_id).exec(); if (!user) { console.log('User not found'); } const recentSearch = user.recentSearches.find((search) => search.searchTerm === searchTerm); + console.log("recentSearch", recentSearch) if (recentSearch) { // 검색어가 이미 존재하는 경우 if (recentSearch.deletedAt) { @@ -80,3 +85,117 @@ exports.updateRecentSearch = async (_id, searchTerm) => { console.error(err); } }; + +exports.getUserRequests = async (userId) => { + try { + const user = await User.findById(userId).select('requests').exec(); + if (!user) { + throw new Error('User not found'); + } + // requests 배열에서 deletedAt이 null인 항목만 필터링 + const activeRequests = user.requests.filter(request => request.deletedAt === null); + return activeRequests; + + } catch (err) { + console.error(err); + } +}; + +exports.getUserRequestsAll = async () => { + try { + const users = await User.find({}, { requests: 1, _id: 0 }); // 모든 유저의 requests 필드만 가져옴 + const allRequests = []; + + users.forEach(user => { + user.requests.forEach(request => { + if (request.deletedAt === null) { + allRequests.push(request); + } + }); + }); + + return allRequests; + } catch (err) { + console.error(err); + } +} + +exports.deleteRequest = async (userId, requestWord) => { + try { + const user = await User.findById(userId).select('requests').exec(); + if (!user) { + console.log("사용자를 찾을 수 없음"); + throw new Error('User not found'); + } + + const request = user.requests.find(req => req.word === requestWord && req.deletedAt === null); + if (request) { + console.log("삭제할 요청 찾음:", request); + request.deletedAt = Date.now(); // 요청을 삭제로 표시 + await user.save(); + + console.log("요청 삭제 성공"); + } else { + } + } catch (err) { + console.error(err); + } +} + +exports.getRole = async (userId) => { + try { + const user = await User.findById(userId).select('role').exec(); + return user.role; + } catch (err) { + console.error(err); + } +} + +exports.updateRequest = async (userId, requestWord, formData) => { + try { + const user = await User.findById(userId).select('requests').exec(); + if (!user) { + throw new Error('User not found'); + } + + const request = user.requests.find(req => req.word === requestWord && req.deletedAt === null); + if (request) { + // formData의 각 속성 값으로 request의 해당 속성 값 업데이트 + + if (formData.addInfo !== undefined) { + request.info = formData.addInfo;} + if (formData.awkPron !== undefined) { + request.awkPron = formData.awkPron;} + if (formData.commonPron !== undefined) { + request.comPron = formData.commonPron;} + if (formData.devTerm !== undefined) { + request.word = formData.devTerm;} + + await user.save(); + + } else { + } + } catch (err) { + console.error(err); + } +} + +exports.updateRequestState = async (userId, requestId, status) => { + try { + + const user = await User.findOneAndUpdate( + { 'requests._id': requestId }, + { $set: { 'requests.$.status': status } }, + { new: true } + ).exec(); + + if (!user) { + console.log('Request not found'); + } else { + console.log('Request status updated successfully'); + } + + } catch (err) { + console.error(err); + } +}; \ No newline at end of file diff --git a/src/routes/user/user.route.js b/src/routes/user/user.route.js index bd7f20d..661e981 100644 --- a/src/routes/user/user.route.js +++ b/src/routes/user/user.route.js @@ -10,6 +10,12 @@ const { logout, recentSearches, delRecentSearch, + UserRequests, + UserRequestsAll, + deleteRequest, + updateRequest, + getRole, + updateRequestState, } = require('./user.controller'); const { isLoggedIn, isNotLoggedIn } = require('../../common/utils/auth'); const userRouter = express.Router(); @@ -31,4 +37,15 @@ userRouter.get('/profile', isLoggedIn, getProfile); userRouter.get('/recent', isLoggedIn, recentSearches); // 최근 검색어 조회 userRouter.delete('/:searchTerm', isLoggedIn, delRecentSearch); // 최근 검색어 삭제 +// 요청 조회 +userRouter.get('/requests', isLoggedIn, UserRequests); // 요청 목록 조회 +userRouter.get('/requests/all', isLoggedIn, UserRequestsAll); // 모든 요청 목록 조회 +userRouter.get('/role', isLoggedIn, getRole); // 사용자 역할 가져오기 +userRouter.delete('/requests/:word', isLoggedIn, deleteRequest); // 사용자 요청 삭제 +userRouter.post('/requests/:word', isLoggedIn, updateRequest); // 사용자 요청 수정 + + +//요청 상태 변경 +userRouter.post('/requests/:requestId/status', isLoggedIn, updateRequestState); // 사용자 요청 status 변경 + module.exports = userRouter; diff --git a/src/routes/user/user.service.js b/src/routes/user/user.service.js index fb9cbbd..a3b7e27 100644 --- a/src/routes/user/user.service.js +++ b/src/routes/user/user.service.js @@ -1,4 +1,5 @@ const userRepository = require('./user.repository'); +const wordRepository = require('../word/word.repository'); exports.register = async (userData) => { const newUser = { @@ -43,3 +44,37 @@ exports.updateRecentSearch = async (userID, searchTerm) => { await userRepository.updateRecentSearch(userID, searchTerm); } }; + +exports.getUserRequests = async (userId) => { + const requests = await userRepository.getUserRequests(userId); + return requests; +}; + +exports.getUserRequestsAll = async () => { + const requests = await userRepository.getUserRequestsAll(); + return requests; +}; + +exports.deleteRequest = async (userId, requestWord) => { + const result = await userRepository.deleteRequest(userId, requestWord); + return result; +}; + +exports.getRole = async (userId) => { + const role = await userRepository.getRole(userId); + return role; +}; + +exports.updateRequest = async (userId, requestWord, formData) => { + if(userId) { + await userRepository.updateRequest(userId, requestWord, formData); + } +}; + +exports.updateRequestState = async (userId, requestId, status) => { + if(userId) { + await userRepository.updateRequestState(userId, requestId, status); + await wordRepository.addWord(requestId); + } + //promise.all 사용 +}; diff --git a/src/routes/word/word.model.js b/src/routes/word/word.model.js index 57702bc..aba4321 100644 --- a/src/routes/word/word.model.js +++ b/src/routes/word/word.model.js @@ -6,7 +6,7 @@ const wordSchema = new mongoose.Schema( awkPron: { type: String }, // 어색한 발음 comPron: { type: String, required: true }, // 일반적인 발음 info: { type: String }, //추가정보 - suggestedBy: { type: String }, // 제안한 사용자의 닉네임 + suggestedBy: { type: String, required: true }, // 제안한 사용자의 닉네임 freq: { type: Number, default: 0 }, // 인기검색어 }, { timestamps: true } @@ -18,4 +18,6 @@ wordSchema.pre(/^findOne/, async function (next) { next(); }); + + module.exports = mongoose.model('Word', wordSchema); diff --git a/src/routes/word/word.repository.js b/src/routes/word/word.repository.js index 3eb9c00..2cfdf76 100644 --- a/src/routes/word/word.repository.js +++ b/src/routes/word/word.repository.js @@ -1,4 +1,5 @@ const Word = require('./word.model'); +const User = require('../user/user.model'); exports.getSearchWords = async (searchTerm) => { try { @@ -40,3 +41,35 @@ exports.getRelatedWords = async (searchTerm, limit) => { return null; } }; + +exports.addWord = async (requestId) => { + try { + // requestId에 해당하는 request를 찾습니다. + const user = await User.findOne({ 'requests._id': requestId }); + if (!user) { + console.log('User with the given request not found'); + return null; + } + + const request = user.requests.id(requestId); + if (!request) { + console.log('Request not found'); + return null; + } + + const newWord = new Word({ + word: request.word, + awkPron: request.awkPron, + comPron: request.comPron, + info: request.info, + suggestedBy: request.suggestedBy, + }); + + await newWord.save(); + console.log('Word added successfully'); + + } catch (error) { + console.log('Error while adding word:', error); + return null; + } +}; \ No newline at end of file