memberseq 임의값으로 수정(임시)

This commit is contained in:
dyhj625 2025-02-10 14:28:44 +09:00
parent 8d88545c2b
commit d8c653618c
6 changed files with 147 additions and 78 deletions

View File

@ -10,6 +10,7 @@
* DATE AUTHOR NOTE * DATE AUTHOR NOTE
* ----------------------------------------------------------- * -----------------------------------------------------------
* 24.12.06 조인제 최초 생성 * 24.12.06 조인제 최초 생성
* 25.02.10 서지희 InvalidPasswordException추가
* *
*************************************************************/ *************************************************************/
package io.company.localhost.common.exception; package io.company.localhost.common.exception;
@ -28,12 +29,18 @@ import lombok.extern.slf4j.Slf4j;
@RestControllerAdvice(annotations = RestController.class) @RestControllerAdvice(annotations = RestController.class)
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
/**
* 사용자 정의 API 예외 처리 (RestApiException)
*/
@ExceptionHandler(RestApiException.class) @ExceptionHandler(RestApiException.class)
public ResponseEntity<Object> handleCustomException(RestApiException e) { public ResponseEntity<Object> handleCustomException(RestApiException e) {
ErrorCode errorCode = e.getErrorCode(); ErrorCode errorCode = e.getErrorCode();
return ErrorResult.handleExceptionInternal(errorCode); return ErrorResult.handleExceptionInternal(errorCode);
} }
/**
* 잘못된 요청 (IllegalArgumentException) 처리
*/
@ExceptionHandler(IllegalArgumentException.class) @ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<Object> handleIllegalArgument(IllegalArgumentException e) { public ResponseEntity<Object> handleIllegalArgument(IllegalArgumentException e) {
log.warn("handleIllegalArgument", e); log.warn("handleIllegalArgument", e);
@ -41,13 +48,33 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
return ErrorResult.handleExceptionInternal(errorCode, e.getMessage()); return ErrorResult.handleExceptionInternal(errorCode, e.getMessage());
} }
/**
* 게시물을 찾을 없는 경우 (NotFoundHandler)
*/
@ExceptionHandler(NotFoundHandler.class)
public ResponseEntity<Object> handleBoardNotFoundException(NotFoundHandler e) {
log.warn("handleBoardNotFoundException: {}", e.getMessage());
ErrorCode errorCode = CommonErrorCode.RESOURCE_NOT_FOUND;
return ErrorResult.handleExceptionInternal(errorCode, e.getMessage());
}
/**
* 비밀번호가 틀린 경우 예외 처리 (InvalidPasswordException)
*/
@ExceptionHandler(InvalidPasswordException.class)
public ResponseEntity<Object> handleInvalidPasswordException(InvalidPasswordException e) {
log.warn("handleInvalidPasswordException: {}", e.getMessage());
ErrorCode errorCode = CommonErrorCode.UNAUTHORIZED;
return ErrorResult.handleExceptionInternal(errorCode, e.getMessage());
}
/**
* 서버 내부 오류 처리 (Exception)
*/
@ExceptionHandler({Exception.class}) @ExceptionHandler({Exception.class})
public ResponseEntity<Object> handleAllException(Exception ex) { public ResponseEntity<Object> handleAllException(Exception ex) {
log.warn("handleAllException", ex); log.warn("handleAllException", ex);
ErrorCode errorCode = CommonErrorCode.INTERNAL_SERVER_ERROR; ErrorCode errorCode = CommonErrorCode.INTERNAL_SERVER_ERROR;
return ErrorResult.handleExceptionInternal(errorCode); return ErrorResult.handleExceptionInternal(errorCode);
} }
} }

View File

@ -0,0 +1,7 @@
package io.company.localhost.common.exception;
public class InvalidPasswordException extends RuntimeException {
public InvalidPasswordException(String message) {
super(message);
}
}

View File

@ -25,15 +25,8 @@ import io.company.localhost.common.exception.code.CommonErrorCode;
import io.company.localhost.common.exception.code.ErrorCode; import io.company.localhost.common.exception.code.ErrorCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@Slf4j public class NotFoundHandler extends RuntimeException {
@RestControllerAdvice public NotFoundHandler(String message) {
public class NotFoundHandler { super(message);
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<Object> noHandlerFoundArgument(NoHandlerFoundException e) {
log.warn("NoHandlerFoundException", e);
ErrorCode errorCode = CommonErrorCode.RESOURCE_NOT_FOUND;
return ErrorResult.handleExceptionInternal(errorCode, errorCode.getMessage());
} }
} }

View File

@ -10,6 +10,7 @@
* DATE AUTHOR NOTE * DATE AUTHOR NOTE
* ----------------------------------------------------------- * -----------------------------------------------------------
* 24.12.06 조인제 최초 생성 * 24.12.06 조인제 최초 생성
* 24.02.10 서지희 비밀번호 불일치 권한없음 추가
* *
*************************************************************/ *************************************************************/
package io.company.localhost.common.exception.code; package io.company.localhost.common.exception.code;
@ -26,6 +27,7 @@ public enum CommonErrorCode implements ErrorCode {
INVALID_PARAMETER(HttpStatus.BAD_REQUEST,"잘못된 매개변수가 포함되었습니다."), INVALID_PARAMETER(HttpStatus.BAD_REQUEST,"잘못된 매개변수가 포함되었습니다."),
RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND,"리소스가 존재하지 않습니다"), RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND,"리소스가 존재하지 않습니다"),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,"내부 서버 오류"), INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,"내부 서버 오류"),
UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"권한없음"),
; ;
private final long code; private final long code;

View File

@ -18,6 +18,7 @@ package io.company.localhost.controller.api;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List; import java.util.List;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -27,6 +28,8 @@ import io.company.localhost.common.annotation.ParameterCheck;
import io.company.localhost.common.annotation.ReqMap; import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse; import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto; 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.commoncodService;
import io.company.localhost.service.localbordService; import io.company.localhost.service.localbordService;
import io.company.localhost.utils.AuthUtil; import io.company.localhost.utils.AuthUtil;
@ -41,6 +44,7 @@ public class BoardController {
private final localbordService boardService; private final localbordService boardService;
private final commoncodService commoncodService; private final commoncodService commoncodService;
private final PasswordEncoder passwordEncoder;
/** /**
* 공지사항 목록 조회 * 공지사항 목록 조회
@ -77,7 +81,14 @@ public class BoardController {
@PostMapping @PostMapping
public ApiResponse<BigInteger> createBoard(@ReqMap MapDto map) { public ApiResponse<BigInteger> createBoard(@ReqMap MapDto map) {
Long userId = AuthUtil.getUser().getId(); Long userId = AuthUtil.getUser().getId();
map.put("MEMBERSEQ", userId); map.put("MEMBERSEQ", 22);
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.createBoard(map)); return ApiResponse.ok(boardService.createBoard(map));
} }
@ -90,7 +101,11 @@ public class BoardController {
@ParameterCheck @ParameterCheck
@GetMapping("/{boardId}") @GetMapping("/{boardId}")
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) { public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
return ApiResponse.ok(boardService.getBoardDetail(boardId)); MapDto board = boardService.getBoardDetail(boardId);
if (board == null) {
throw new NotFoundHandler("게시물 ID " + boardId + "을(를) 찾을 수 없습니다.");
}
return ApiResponse.ok(board);
} }
/** /**
@ -129,7 +144,7 @@ public class BoardController {
@PostMapping("/{CMNBRDSEQ}/attachments") @PostMapping("/{CMNBRDSEQ}/attachments")
public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) { public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) {
Long userId = AuthUtil.getUser().getId(); Long userId = AuthUtil.getUser().getId();
map.put("CMNFLEREG", userId); map.put("CMNFLEREG", 22);
boardService.addAttachment(map); boardService.addAttachment(map);
return ApiResponse.ok("첨부파일이 저장되었습니다."); return ApiResponse.ok("첨부파일이 저장되었습니다.");
} }
@ -144,7 +159,7 @@ public class BoardController {
@PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction") @PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction")
public ApiResponse<String> reactToBoard(@ReqMap MapDto map) { public ApiResponse<String> reactToBoard(@ReqMap MapDto map) {
Long userId = AuthUtil.getUser().getId(); Long userId = AuthUtil.getUser().getId();
map.put("MEMBERSEQ", userId); map.put("MEMBERSEQ", 22);
boardService.reactToBoard(map); boardService.reactToBoard(map);
return ApiResponse.ok("반응이 성공적으로 처리되었습니다."); return ApiResponse.ok("반응이 성공적으로 처리되었습니다.");
} }
@ -172,7 +187,13 @@ public class BoardController {
@PostMapping("/{LOCBRDSEQ}/comment") @PostMapping("/{LOCBRDSEQ}/comment")
public ApiResponse<String> addCommentOrReply(@ReqMap MapDto map) { public ApiResponse<String> addCommentOrReply(@ReqMap MapDto map) {
Long userId = AuthUtil.getUser().getId(); Long userId = AuthUtil.getUser().getId();
map.put("MEMBERSEQ", userId); map.put("MEMBERSEQ", 22);
if (map.containsKey("LOCCMTPWD") && !map.getString("LOCCMTPWD").trim().isEmpty()) { // 체크
String rawPassword = map.getString("LOCCMTPWD");
String hashedPassword = passwordEncoder.encode(rawPassword);
map.put("LOCCMTPWD", hashedPassword);
}
boardService.addCommentOrReply(map); boardService.addCommentOrReply(map);
return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다."); return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다.");
} }
@ -205,20 +226,7 @@ public class BoardController {
} }
/** /**
* 댓글 비밀번호 확인 * 게시물 비밀번호 확인 (해싱된 비밀번호 비교 적용)
* @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTPWD)
* @return 비밀번호 확인 결과
*/
@Member
@ParameterCheck
@PostMapping("/comment/{commentId}/password")
public ApiResponse<Boolean> checkCommentPassword(@ReqMap MapDto map) {
int commentId = (int) map.get("LOCCMTPWD");
return ApiResponse.ok(boardService.getCommentPassword(commentId).equals(map.getString("LOCCMTPWD")));
}
/**
* 게시물 비밀번호 확인
* @ReqMap map 수정 데이터 (LOCBRDSEQ, LOCBRDPWD) * @ReqMap map 수정 데이터 (LOCBRDSEQ, LOCBRDPWD)
* @return 비밀번호 확인 결과 * @return 비밀번호 확인 결과
*/ */
@ -227,7 +235,44 @@ public class BoardController {
@PostMapping("/{boardId}/password") @PostMapping("/{boardId}/password")
public ApiResponse<Boolean> checkBoardPassword(@ReqMap MapDto map) { public ApiResponse<Boolean> checkBoardPassword(@ReqMap MapDto map) {
int boardId = (int) map.get("LOCBRDSEQ"); int boardId = (int) map.get("LOCBRDSEQ");
return ApiResponse.ok(boardService.getBoardPassword(boardId).equals(map.getString("LOCBRDPWD"))); String rawPassword = map.getString("LOCBRDPWD");
String storedHashedPassword = boardService.getBoardPassword(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) {
int commentId = (int) map.get("LOCCMTSEQ");
String rawPassword = map.getString("LOCCMTPWD");
String storedHashedPassword = boardService.getCommentPassword(commentId);
if (storedHashedPassword == null) {
throw new NotFoundHandler("해당 댓글이 존재하지 않습니다.");
}
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
if (!isMatch) {
throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
}
return ApiResponse.ok(true);
} }
/** /**

View File

@ -171,45 +171,24 @@ public class localbordService {
return boardMapper.getCommentReactions(boardId); return boardMapper.getCommentReactions(boardId);
} }
private void enrichBoardDetail(MapDto boardDetail) {
long boardId = ((Number) boardDetail.get("id")).longValue();
boardDetail.put("hasAttachment", hasAttachments(boardId));
boardDetail.put("commentCount", getCommentCount(boardId));
MapDto reactions = getBoardReactions(boardId);
boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0));
boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
// Blob 데이터를 문자열로 변환
Object content = boardDetail.get("content");
if (content != null) {
String contentString = convertBlobToString(content); // Blob을 문자열로 변환
boardDetail.put("content", contentString); // JSON 변환 가능
}
}
private String convertBlobToString(Object blob) { private String convertBlobToString(Object blob) {
try { try {
if (blob instanceof String) { if (blob instanceof String) {
return (String) blob; // 이미 문자열 경우 반환 return (String) blob; // 이미 문자열이면 그대로 반환
} else if (blob instanceof java.sql.Blob) { } else if (blob instanceof java.sql.Blob) {
java.sql.Blob sqlBlob = (java.sql.Blob) blob; java.sql.Blob sqlBlob = (java.sql.Blob) blob;
long blobLength = sqlBlob.length(); long blobLength = sqlBlob.length();
byte[] blobBytes = sqlBlob.getBytes(1, (int) blobLength); byte[] blobBytes = sqlBlob.getBytes(1, (int) blobLength);
return new String(blobBytes, StandardCharsets.UTF_8); return new String(blobBytes, StandardCharsets.UTF_8); // SQL BLOB 바이트 배열 문자열 변환
} else if (blob instanceof ByteArrayInputStream) {
ByteArrayInputStream inputStream = (ByteArrayInputStream) blob;
byte[] bytes = inputStream.readAllBytes();
return new String(bytes, StandardCharsets.UTF_8);
} else { } else {
System.err.println("Unsupported blob type: " + blob.getClass()); throw new UnsupportedOperationException("Unsupported blob type: " + blob.getClass()); // 지원되지 않는 타입이면 예외 발생
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throw new RuntimeException("Failed to convert Blob to String: " + e.getMessage(), e); // 변환 실패 예외 처리
throw new RuntimeException("Failed to convert Blob to String: " + e.getMessage(), e);
} }
return null;
} }
private String extractFirstImageUrl(String jsonContent) { private String extractFirstImageUrl(String jsonContent) {
try { try {
// JSON 유효성 검사 // JSON 유효성 검사
@ -277,6 +256,22 @@ public class localbordService {
return plainTextBuilder.toString(); return plainTextBuilder.toString();
} }
private void enrichBoardDetail(MapDto boardDetail) {
long boardId = ((Number) boardDetail.get("id")).longValue();
boardDetail.put("hasAttachment", hasAttachments(boardId));
boardDetail.put("commentCount", getCommentCount(boardId));
MapDto reactions = getBoardReactions(boardId);
boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0));
boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
// Blob 데이터를 문자열로 변환
Object content = boardDetail.get("content");
if (content != null) {
String contentString = convertBlobToString(content); // Blob을 문자열로 변환
boardDetail.put("content", contentString); // JSON 변환 가능
}
}
private void enrichPostsWithAdditionalData(List<MapDto> posts) { private void enrichPostsWithAdditionalData(List<MapDto> posts) {
for (MapDto post : posts) { for (MapDto post : posts) {
Object idObject = post.get("id"); Object idObject = post.get("id");