304 lines
10 KiB
Java
304 lines
10 KiB
Java
/************************************************************
|
|
*
|
|
* @packageName : io.company.localhost.controller.api
|
|
* @fileName : BoardController.java
|
|
* @author : 서지희
|
|
* @date : 25.01.07
|
|
* @description : 게시판
|
|
*
|
|
* ===========================================================
|
|
* DATE AUTHOR NOTE
|
|
* -----------------------------------------------------------
|
|
* 24.01.02 서지희 최초 생성
|
|
*
|
|
*************************************************************/
|
|
|
|
package io.company.localhost.controller.api;
|
|
|
|
import java.math.BigInteger;
|
|
import java.util.List;
|
|
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import com.github.pagehelper.PageInfo;
|
|
|
|
import io.company.localhost.common.annotation.Member;
|
|
import io.company.localhost.common.annotation.ParameterCheck;
|
|
import io.company.localhost.common.annotation.ReqMap;
|
|
import io.company.localhost.common.dto.ApiResponse;
|
|
import io.company.localhost.common.dto.MapDto;
|
|
import io.company.localhost.common.exception.InvalidPasswordException;
|
|
import io.company.localhost.common.exception.NotFoundHandler;
|
|
import io.company.localhost.service.commoncodService;
|
|
import io.company.localhost.service.localbordService;
|
|
import io.company.localhost.utils.AuthUtil;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
@RestController
|
|
@RequestMapping("/api/board")
|
|
@RequiredArgsConstructor
|
|
@Slf4j
|
|
public class BoardController {
|
|
|
|
private final localbordService boardService;
|
|
private final commoncodService commoncodService;
|
|
private final PasswordEncoder passwordEncoder;
|
|
|
|
/**
|
|
* 공지사항 목록 조회
|
|
* @ReqMap map 요청 파라미터 (searchKeyword)
|
|
* @return 전체 공지사항 목록
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@GetMapping("/notices")
|
|
public ApiResponse<List<MapDto>> getNotices(@ReqMap MapDto map) {
|
|
return ApiResponse.ok(boardService.selectNotices(map));
|
|
}
|
|
|
|
/**
|
|
* 자유/익명 게시판 목록 조회
|
|
* @ReqMap map 요청 파라미터 (page, searchKeyword, orderBy, size)
|
|
* @return 페이징된 자유/익명 게시판 목록
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@GetMapping("/general")
|
|
public ApiResponse<PageInfo<MapDto>> getGeneralPosts(@ReqMap MapDto map) {
|
|
return ApiResponse.ok(boardService.selectGeneralPosts(map));
|
|
}
|
|
|
|
/**
|
|
* 게시물 작성
|
|
* @ReqMap map 요청 파라미터 (LOCBRDTTL, LOCBRDCON, MEMBERSEQ, LOCBRDTYP,
|
|
* LOCBRDPWD(익명일 때만), LOCBRDCAT(지식커뮤니티만))
|
|
* @return 작성된 게시물의 ID
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PostMapping
|
|
public ApiResponse<BigInteger> createBoard(@ReqMap MapDto map) {
|
|
Long userId = AuthUtil.getUser().getId();
|
|
map.put("MEMBERSEQ", userId);
|
|
|
|
if (map.containsKey("LOCBRDPWD") && !map.getString("LOCBRDPWD").trim().isEmpty()) { // 빈 값 체크
|
|
String rawPassword = map.getString("LOCBRDPWD");
|
|
String hashedPassword = passwordEncoder.encode(rawPassword);
|
|
map.put("LOCBRDPWD", hashedPassword);
|
|
}
|
|
|
|
return ApiResponse.ok(boardService.insertBoard(map));
|
|
}
|
|
|
|
/**
|
|
* 게시물 상세보기
|
|
* @param boardId 게시물 ID
|
|
* @return 게시물 상세정보
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@GetMapping("/{boardId}")
|
|
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
|
|
MapDto board = boardService.selectBoardDetail(boardId);
|
|
if (board == null) {
|
|
throw new NotFoundHandler("게시물 ID " + boardId + "을(를) 찾을 수 없습니다.");
|
|
}
|
|
return ApiResponse.ok(board);
|
|
}
|
|
|
|
/**
|
|
* 게시물 삭제
|
|
* @ReqMap map 수정 데이터 (LOCBRDSEQ)
|
|
* @return 삭제 결과 메시지
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@DeleteMapping("/{boardId}")
|
|
public ApiResponse<String> deleteBoard(@ReqMap MapDto map) {
|
|
boardService.deleteBoard(map);
|
|
return ApiResponse.ok("게시물이 삭제되었습니다.");
|
|
}
|
|
|
|
/**
|
|
* 게시물 수정
|
|
* @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON, LOCBRDSEQ)
|
|
* @return 수정 결과 메시지
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PutMapping("/{boardId}")
|
|
public ApiResponse<String> updateBoard(@ReqMap MapDto map) {
|
|
boardService.updateBoard(map);
|
|
return ApiResponse.ok("게시물이 수정되었습니다.");
|
|
}
|
|
|
|
/**
|
|
* 첨부파일 추가
|
|
* @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ)
|
|
* @return 첨부파일 저장 결과 메시지
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PostMapping("/{CMNBRDSEQ}/attachments")
|
|
public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) {
|
|
Long userId = AuthUtil.getUser().getId();
|
|
map.put("CMNFLEREG", userId);
|
|
boardService.insertAttachment(map);
|
|
return ApiResponse.ok("첨부파일이 저장되었습니다.");
|
|
}
|
|
|
|
/**
|
|
* 게시물, 댓글 좋아요/싫어요 추가
|
|
* @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ)
|
|
* @return 반응 추가 결과 메시지
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction")
|
|
public ApiResponse<String> reactToBoard(@ReqMap MapDto map) {
|
|
Long userId = AuthUtil.getUser().getId();
|
|
map.put("MEMBERSEQ", userId);
|
|
boardService.procReactToBoard(map);
|
|
return ApiResponse.ok("반응이 성공적으로 처리되었습니다.");
|
|
}
|
|
|
|
/**
|
|
* 댓글/대댓글 조회
|
|
* @ReqMap map 수정 데이터 (LOCBRDSEQ)
|
|
* @return 댓글과 대댓글의 계층 구조 데이터
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@GetMapping("/{boardId}/comments")
|
|
public ApiResponse<PageInfo<MapDto>> getComments(@ReqMap MapDto map) {
|
|
return ApiResponse.ok(boardService.selectComments(map));
|
|
}
|
|
|
|
/**
|
|
* 댓글/대댓글 작성
|
|
* @param boardId 게시물 ID
|
|
* @ReqMap map 댓글 데이터 (LOCBRDSEQ, LOCCMTRPY, LOCCMTPNT, LOCCMTPWD, MEMBERSEQ )
|
|
* @return 작성 결과 메시지
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PostMapping("/{LOCBRDSEQ}/comment")
|
|
public ApiResponse<String> addCommentOrReply(@ReqMap MapDto map) {
|
|
Long userId = AuthUtil.getUser().getId();
|
|
map.put("MEMBERSEQ", userId);
|
|
|
|
if (map.containsKey("LOCCMTPWD") && !map.getString("LOCCMTPWD").trim().isEmpty()) { // 빈 값 체크
|
|
String rawPassword = map.getString("LOCCMTPWD");
|
|
String hashedPassword = passwordEncoder.encode(rawPassword);
|
|
map.put("LOCCMTPWD", hashedPassword);
|
|
}
|
|
boardService.insertCommentOrReply(map);
|
|
return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다.");
|
|
}
|
|
|
|
/**
|
|
* 댓글/대댓글 수정
|
|
* @param commentId 댓글 ID
|
|
* @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTRPY)
|
|
* @return 수정 결과 메시지
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PutMapping("/comment/{commentId}")
|
|
public ApiResponse<String> updateComment(@ReqMap MapDto map) {
|
|
boardService.updateComment(map);
|
|
return ApiResponse.ok("댓글이 수정되었습니다.");
|
|
}
|
|
|
|
/**
|
|
* 댓글/대댓글 삭제
|
|
* @ReqMap map 수정 데이터 (LOCCMTSEQ)
|
|
* @return 삭제 결과 메시지
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@DeleteMapping("/comment/{commentId}")
|
|
public ApiResponse<String> deleteComment(@ReqMap MapDto map) {
|
|
boardService.deleteComment(map);
|
|
return ApiResponse.ok("댓글이 삭제되었습니다.");
|
|
}
|
|
|
|
/**
|
|
* 게시물 비밀번호 확인 (해싱된 비밀번호 비교 적용)
|
|
* @ReqMap map 수정 데이터 (LOCBRDSEQ, LOCBRDPWD)
|
|
* @return 비밀번호 확인 결과
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PostMapping("/{boardId}/password")
|
|
public ApiResponse<Boolean> checkBoardPassword(@ReqMap MapDto map) {
|
|
// boardId 데이터 타입 변환
|
|
Object boardIdObj = map.get("LOCBRDSEQ");
|
|
int boardId = 0;
|
|
|
|
if (boardIdObj instanceof Integer) {
|
|
boardId = (Integer) boardIdObj;
|
|
} else if (boardIdObj instanceof String) {
|
|
boardId = Integer.parseInt((String) boardIdObj);
|
|
}
|
|
|
|
String rawPassword = map.getString("LOCBRDPWD");
|
|
|
|
String storedHashedPassword = boardService.selectBoardPassword(boardId);
|
|
if (storedHashedPassword == null) {
|
|
throw new NotFoundHandler("해당 게시물이 존재하지 않습니다.");
|
|
}
|
|
|
|
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
|
|
if (!isMatch) {
|
|
throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
|
|
}
|
|
|
|
return ApiResponse.ok(true);
|
|
}
|
|
|
|
/**
|
|
* 댓글 비밀번호 확인 (해싱된 비밀번호 비교 적용)
|
|
* @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTPWD)
|
|
* @return 비밀번호 확인 결과
|
|
*/
|
|
@Member
|
|
@ParameterCheck
|
|
@PostMapping("/comment/{commentId}/password")
|
|
public ApiResponse<Boolean> checkCommentPassword(@ReqMap MapDto map) {
|
|
// commentId 데이터 타입 변환
|
|
Object commentIdObj = map.get("LOCCMTSEQ");
|
|
int commentId = 0;
|
|
|
|
if (commentIdObj instanceof Integer) {
|
|
commentId = (Integer) commentIdObj;
|
|
} else if (commentIdObj instanceof String) {
|
|
commentId = Integer.parseInt((String) commentIdObj);
|
|
}
|
|
String rawPassword = map.getString("LOCCMTPWD");
|
|
|
|
String storedHashedPassword = boardService.selectCommentPassword(commentId);
|
|
if (storedHashedPassword == null) {
|
|
throw new NotFoundHandler("해당 댓글이 존재하지 않습니다.");
|
|
}
|
|
|
|
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
|
|
if (!isMatch) {
|
|
throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
|
|
}
|
|
|
|
return ApiResponse.ok(true);
|
|
}
|
|
|
|
/**
|
|
* 카테고리 목록 조회
|
|
* @return 카테고리 리스트
|
|
*/
|
|
@GetMapping("/categories")
|
|
public ApiResponse<List<MapDto>> getCategories() {
|
|
List<MapDto> categories = commoncodService.selectCategoryList();
|
|
return ApiResponse.ok(categories);
|
|
}
|
|
} |