From 461bdff699e4717155451afb10bd248dd9bd59e5 Mon Sep 17 00:00:00 2001 From: JUN Date: Sun, 7 May 2023 02:11:18 +0900 Subject: [PATCH] =?UTF-8?q?4=EC=B0=A8=20=EC=84=B8=EB=AF=B8=EB=82=98=20#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/fourthSeminar/AuditingTimeEntity.java | 23 +++++++++ .../FourthSeminarApplication.java | 4 +- .../controller/BoardController.java | 26 ++++++++++ .../controller/UserController.java | 28 +++++++++++ .../advice/ControllerExceptionAdvice.java | 47 +++++++++++++++++++ .../controller/common/dto/ApiResponse.java | 34 ++++++++++++++ .../dto/request/BoardRequestDto.java | 27 +++++++++++ .../dto/request/UserRequestDto.java | 26 +++++----- .../dto/response/UserResponseDto.java | 6 ++- .../controller/exception/Error.java | 40 ++++++++++++++++ .../controller/exception/ErrorStatus.java | 2 +- .../controller/exception/Success.java | 25 ++++++++++ .../controller/exception/SuccessStatus.java | 2 +- .../exception/model/ConflictException.java | 9 ++++ .../exception/model/NotFoundException.java | 10 ++++ .../exception/model/SoptException.java | 19 ++++++++ .../sopt/org/fourthSeminar/domain/Board.java | 43 +++++++++++++++++ .../domain/User.java | 9 +++- .../infrastructure/BoardRepository.java | 16 +++++++ .../infrastructure/UserRepository.java | 20 ++++++++ .../fourthSeminar/service/BoardService.java | 36 ++++++++++++++ .../fourthSeminar/service/UserService.java | 36 ++++++++++++++ .../controller/UserController.java | 29 ------------ .../advice/ControllerExceptionAdvice.java | 22 --------- .../controller/common/dto/ApiResponseDto.java | 32 ------------- .../infrastructure/UserRepository.java | 9 ---- .../org/thirdSeminar/service/UserService.java | 31 ------------ 27 files changed, 468 insertions(+), 143 deletions(-) create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/AuditingTimeEntity.java rename fourthSeminar/src/main/java/sopt/org/{thirdSeminar => fourthSeminar}/FourthSeminarApplication.java (70%) create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/BoardController.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/UserController.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/advice/ControllerExceptionAdvice.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/dto/ApiResponse.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/request/BoardRequestDto.java rename fourthSeminar/src/main/java/sopt/org/{thirdSeminar => fourthSeminar}/controller/dto/request/UserRequestDto.java (53%) rename fourthSeminar/src/main/java/sopt/org/{thirdSeminar => fourthSeminar}/controller/dto/response/UserResponseDto.java (72%) create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Error.java rename fourthSeminar/src/main/java/sopt/org/{thirdSeminar => fourthSeminar}/controller/exception/ErrorStatus.java (95%) create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Success.java rename fourthSeminar/src/main/java/sopt/org/{thirdSeminar => fourthSeminar}/controller/exception/SuccessStatus.java (88%) create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/ConflictException.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/NotFoundException.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/SoptException.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/domain/Board.java rename fourthSeminar/src/main/java/sopt/org/{thirdSeminar => fourthSeminar}/domain/User.java (69%) create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/BoardRepository.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/UserRepository.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/BoardService.java create mode 100644 fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/UserService.java delete mode 100644 fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/UserController.java delete mode 100644 fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/advice/ControllerExceptionAdvice.java delete mode 100644 fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/dto/ApiResponseDto.java delete mode 100644 fourthSeminar/src/main/java/sopt/org/thirdSeminar/infrastructure/UserRepository.java delete mode 100644 fourthSeminar/src/main/java/sopt/org/thirdSeminar/service/UserService.java diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/AuditingTimeEntity.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/AuditingTimeEntity.java new file mode 100644 index 0000000..6a7b3e1 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/AuditingTimeEntity.java @@ -0,0 +1,23 @@ +package sopt.org.fourthSeminar; + +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.time.LocalDateTime; + +@Getter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class AuditingTimeEntity { + + @CreatedDate + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime updatedAt; + +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/FourthSeminarApplication.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/FourthSeminarApplication.java similarity index 70% rename from fourthSeminar/src/main/java/sopt/org/thirdSeminar/FourthSeminarApplication.java rename to fourthSeminar/src/main/java/sopt/org/fourthSeminar/FourthSeminarApplication.java index 5747fc6..ea76cb5 100644 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/FourthSeminarApplication.java +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/FourthSeminarApplication.java @@ -1,8 +1,10 @@ -package sopt.org.thirdSeminar; +package sopt.org.fourthSeminar; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class FourthSeminarApplication { public static void main(String[] args) { diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/BoardController.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/BoardController.java new file mode 100644 index 0000000..788c4e1 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/BoardController.java @@ -0,0 +1,26 @@ +package sopt.org.fourthSeminar.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import sopt.org.fourthSeminar.controller.common.dto.ApiResponse; +import sopt.org.fourthSeminar.controller.dto.request.BoardRequestDto; +import sopt.org.fourthSeminar.controller.exception.Success; +import sopt.org.fourthSeminar.service.BoardService; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/board") +public class BoardController { + + private final BoardService boardService; + + @PostMapping("/create") + @ResponseStatus(HttpStatus.CREATED) + public ApiResponse create(@RequestBody @Valid final BoardRequestDto request) { + boardService.create(request); + return ApiResponse.success(Success.CREATE_BOARD_SUCCESS); + } +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/UserController.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/UserController.java new file mode 100644 index 0000000..70a83f2 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/UserController.java @@ -0,0 +1,28 @@ +package sopt.org.fourthSeminar.controller; + + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import sopt.org.fourthSeminar.controller.common.dto.ApiResponse; +import sopt.org.fourthSeminar.controller.dto.request.UserRequestDto; +import sopt.org.fourthSeminar.controller.dto.response.UserResponseDto; +import sopt.org.fourthSeminar.controller.exception.Success; +import sopt.org.fourthSeminar.controller.exception.SuccessStatus; +import sopt.org.fourthSeminar.service.UserService; + +import javax.validation.Valid; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/user") +public class UserController { + + private final UserService userService; + + @PostMapping("/signup") + @ResponseStatus(HttpStatus.CREATED) + public ApiResponse create(@RequestBody @Valid final UserRequestDto request) { + return ApiResponse.success(Success.SIGNUP_SUCCESS, userService.create(request)); + } +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/advice/ControllerExceptionAdvice.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/advice/ControllerExceptionAdvice.java new file mode 100644 index 0000000..fa4fd58 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/advice/ControllerExceptionAdvice.java @@ -0,0 +1,47 @@ +package sopt.org.fourthSeminar.controller.common.advice; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import sopt.org.fourthSeminar.controller.common.dto.ApiResponse; +import sopt.org.fourthSeminar.controller.exception.model.SoptException; +import sopt.org.fourthSeminar.controller.exception.Error; + +import java.util.Objects; + +@RestControllerAdvice +public class ControllerExceptionAdvice { + + /** + * 400 BAD_REQUEST + */ + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentNotValidException.class) + protected ApiResponse handleMethodArgumentNotValidException(final MethodArgumentNotValidException e) { + FieldError fieldError = Objects.requireNonNull(e.getFieldError()); + return ApiResponse.error(Error.REQUEST_VALIDATION_EXCEPTION, String.format("%s. (%s)", fieldError.getDefaultMessage(), fieldError.getField())); + } + + /** + * 500 Internal Server + */ + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(Exception.class) + protected ApiResponse handleException(final Exception e) { + return ApiResponse.error(Error.INTERNAL_SERVER_ERROR); + } + + /** + * Sopt custom error + */ + @ExceptionHandler(SoptException.class) + protected ResponseEntity handleSoptException(SoptException e) { + return ResponseEntity.status(e.getHttpStatus()) + .body(ApiResponse.error(e.getError(), e.getMessage())); + } +} diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/dto/ApiResponse.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/dto/ApiResponse.java new file mode 100644 index 0000000..08f98c8 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/common/dto/ApiResponse.java @@ -0,0 +1,34 @@ +package sopt.org.fourthSeminar.controller.common.dto; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import sopt.org.fourthSeminar.controller.exception.Error; +import sopt.org.fourthSeminar.controller.exception.Success; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class ApiResponse { + + private final int code; + private final String message; + private T data; + + public static ApiResponse success(Success success) { + return new ApiResponse<>(success.getHttpStatusCode(), success.getMessage()); + } + + public static ApiResponse success(Success success, T data) { + return new ApiResponse(success.getHttpStatusCode(), success.getMessage(), data); + } + + public static ApiResponse error(Error error) { + return new ApiResponse<>(error.getHttpStatusCode(), error.getMessage()); + } + + public static ApiResponse error(Error error, String message) { + return new ApiResponse<>(error.getHttpStatusCode(), message); + } +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/request/BoardRequestDto.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/request/BoardRequestDto.java new file mode 100644 index 0000000..0ebdd4e --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/request/BoardRequestDto.java @@ -0,0 +1,27 @@ +package sopt.org.fourthSeminar.controller.dto.request; + + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class BoardRequestDto { + + @Email(message = "이메일 형식에 맞지 않습니다") + private String email; + + @NotBlank + private String title; + + @NotBlank + private String content; + + @NotNull + private Boolean isPublic; +} diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/dto/request/UserRequestDto.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/request/UserRequestDto.java similarity index 53% rename from fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/dto/request/UserRequestDto.java rename to fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/request/UserRequestDto.java index eb59a68..54efe81 100644 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/dto/request/UserRequestDto.java +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/request/UserRequestDto.java @@ -1,8 +1,8 @@ -package sopt.org.thirdSeminar.controller.dto.request; +package sopt.org.fourthSeminar.controller.dto.request; import lombok.AccessLevel; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; @@ -10,21 +10,21 @@ import javax.validation.constraints.Pattern; @Getter -@AllArgsConstructor(access = AccessLevel.PRIVATE) +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class UserRequestDto { - @Email(message = "이메일 형식에 맞지 않습니다.") - @NotNull - private final String email; - @NotBlank - @Pattern(regexp = "^[가-힣a-zA-Z]{2,10}$", message = "닉네임 형식에 맞지 않습니다.") - private final String nickname; + @Pattern(regexp = "^[가-힣a-zA-Z]{2,10}$", message = "닉네임 형식에 맞지 않습니다") + private String nickname; + @Email(message = "이메일 형식에 맞지 않습니다") @NotBlank + private String email; + + @NotNull @Pattern( - regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,20}", - message = "비밀번호는 영문 대,소문자와 숫자, 특수기호가 적어도 1개 이상씩 포함된 8자 ~ 20자의 비밀번호여야 합니다." + regexp="(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\W)(?=\\S+$).{8,20}", + message = "비밀번호는 영문 대,소문자와 숫자, 특수기호가 적어도 1개 이상씩 포함된 8자 ~ 20자의 비밀번호여야 합니다" ) - private final String password; -} + private String password; +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/dto/response/UserResponseDto.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/response/UserResponseDto.java similarity index 72% rename from fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/dto/response/UserResponseDto.java rename to fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/response/UserResponseDto.java index 4c09faf..7ea0f2a 100644 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/dto/response/UserResponseDto.java +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/dto/response/UserResponseDto.java @@ -1,10 +1,12 @@ -package sopt.org.thirdSeminar.controller.dto.response; +package sopt.org.fourthSeminar.controller.dto.response; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE) public class UserResponseDto { @@ -14,4 +16,4 @@ public class UserResponseDto { public static UserResponseDto of(Long userId, String nickname) { return new UserResponseDto(userId, nickname); } -} +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Error.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Error.java new file mode 100644 index 0000000..1c166f1 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Error.java @@ -0,0 +1,40 @@ +package sopt.org.fourthSeminar.controller.exception; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum Error { + + /** + * 400 BAD REQUEST + */ + REQUEST_VALIDATION_EXCEPTION(HttpStatus.BAD_REQUEST, "잘못된 요청입니다"), + + /** + * 404 NOT FOUND + */ + NOT_FOUND_USER_EXCEPTION(HttpStatus.NOT_FOUND, "존재하지 않는 유저입니다"), + + /** + * 409 CONFLICT + */ + ALREADY_EXIST_USER_EXCEPTION(HttpStatus.CONFLICT, "이미 존재하는 유저입니다"), + + + /** + * 500 INTERNAL SERVER ERROR + */ + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "알 수 없는 서버 에러가 발생했습니다"), + ; + + private final HttpStatus httpStatus; + private final String message; + + public int getHttpStatusCode() { + return httpStatus.value(); + } +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/exception/ErrorStatus.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/ErrorStatus.java similarity index 95% rename from fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/exception/ErrorStatus.java rename to fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/ErrorStatus.java index 221d9a8..1074abc 100644 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/exception/ErrorStatus.java +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/ErrorStatus.java @@ -1,4 +1,4 @@ -package sopt.org.thirdSeminar.controller.exception; +package sopt.org.fourthSeminar.controller.exception; import lombok.AccessLevel; diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Success.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Success.java new file mode 100644 index 0000000..5682de6 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/Success.java @@ -0,0 +1,25 @@ +package sopt.org.fourthSeminar.controller.exception; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public enum Success { + + /** + * 201 CREATED + */ + SIGNUP_SUCCESS(HttpStatus.CREATED, "회원가입이 완료됐습니다."), + CREATE_BOARD_SUCCESS(HttpStatus.CREATED, "게시물 생성이 완료됐습니다."), + ; + + private final HttpStatus httpStatus; + private final String message; + + public int getHttpStatusCode() { + return httpStatus.value(); + } +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/exception/SuccessStatus.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/SuccessStatus.java similarity index 88% rename from fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/exception/SuccessStatus.java rename to fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/SuccessStatus.java index a13ab94..f1485f0 100644 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/exception/SuccessStatus.java +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/SuccessStatus.java @@ -1,4 +1,4 @@ -package sopt.org.thirdSeminar.controller.exception; +package sopt.org.fourthSeminar.controller.exception; import lombok.AccessLevel; import lombok.Getter; diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/ConflictException.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/ConflictException.java new file mode 100644 index 0000000..9fa800a --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/ConflictException.java @@ -0,0 +1,9 @@ +package sopt.org.fourthSeminar.controller.exception.model; + +import sopt.org.fourthSeminar.controller.exception.Error; + +public class ConflictException extends SoptException { + public ConflictException(Error error, String message) { + super(error, message); + } +} diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/NotFoundException.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/NotFoundException.java new file mode 100644 index 0000000..e0caf12 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/NotFoundException.java @@ -0,0 +1,10 @@ +package sopt.org.fourthSeminar.controller.exception.model; + + +import sopt.org.fourthSeminar.controller.exception.Error; + +public class NotFoundException extends SoptException { + public NotFoundException(Error error, String message) { + super(error, message); + } +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/SoptException.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/SoptException.java new file mode 100644 index 0000000..2c5cc79 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/controller/exception/model/SoptException.java @@ -0,0 +1,19 @@ +package sopt.org.fourthSeminar.controller.exception.model; + +import lombok.Getter; +import sopt.org.fourthSeminar.controller.exception.Error; + +@Getter +public class SoptException extends RuntimeException { + + private final Error error; + + public SoptException(Error error, String message) { + super(message); + this.error = error; + } + + public int getHttpStatus() { + return error.getHttpStatusCode(); + } +} diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/domain/Board.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/domain/Board.java new file mode 100644 index 0000000..4ca0b52 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/domain/Board.java @@ -0,0 +1,43 @@ +package sopt.org.fourthSeminar.domain; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import sopt.org.fourthSeminar.AuditingTimeEntity; + +import javax.persistence.*; + + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Board extends AuditingTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false, foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT)) + private User user; + + @Column(nullable = false) + private String title; + + @Column(nullable = false) + private String content; + + @Column(nullable = false) + private Boolean isPublic; + + private Board(User user, String title, String content, Boolean isPublic) { + this.user = user; + this.title =title; + this.content = content; + this.isPublic = isPublic; + } + + public static Board newInstance(User user, String title, String content, Boolean isPublic) { + return new Board(user, title, content, isPublic); + } +} diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/domain/User.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/domain/User.java similarity index 69% rename from fourthSeminar/src/main/java/sopt/org/thirdSeminar/domain/User.java rename to fourthSeminar/src/main/java/sopt/org/fourthSeminar/domain/User.java index 5094641..24502d3 100644 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/domain/User.java +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/domain/User.java @@ -1,16 +1,17 @@ -package sopt.org.thirdSeminar.domain; +package sopt.org.fourthSeminar.domain; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import sopt.org.fourthSeminar.AuditingTimeEntity; import javax.persistence.*; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class User { +public class User extends AuditingTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -31,4 +32,8 @@ public User(String nickname, String email, String password) { this.email = email; this.password = password; } + + public static User newInstance(String nickname, String email, String password) { + return new User(nickname, email, password); + } } diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/BoardRepository.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/BoardRepository.java new file mode 100644 index 0000000..1488ff9 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/BoardRepository.java @@ -0,0 +1,16 @@ +package sopt.org.fourthSeminar.infrastructure; + +import org.springframework.data.repository.Repository; +import sopt.org.fourthSeminar.domain.Board; + +public interface BoardRepository extends Repository { + + // CREATE + void save(Board board); + + // READ + + // UPDATE + + // DELETE +} diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/UserRepository.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/UserRepository.java new file mode 100644 index 0000000..3130d22 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/infrastructure/UserRepository.java @@ -0,0 +1,20 @@ +package sopt.org.fourthSeminar.infrastructure; + +import org.springframework.data.repository.Repository; +import sopt.org.fourthSeminar.domain.User; + +import java.util.Optional; + +public interface UserRepository extends Repository { + + // CREATE + void save(User user); + + // READ + Optional findByEmail(String email); + boolean existsByEmail(String email); + + // UPDATE + + // DELETE +} diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/BoardService.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/BoardService.java new file mode 100644 index 0000000..fe2f3a0 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/BoardService.java @@ -0,0 +1,36 @@ +package sopt.org.fourthSeminar.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import sopt.org.fourthSeminar.controller.dto.request.BoardRequestDto; +import sopt.org.fourthSeminar.controller.exception.Error; +import sopt.org.fourthSeminar.controller.exception.model.NotFoundException; +import sopt.org.fourthSeminar.domain.Board; +import sopt.org.fourthSeminar.domain.User; +import sopt.org.fourthSeminar.infrastructure.BoardRepository; +import sopt.org.fourthSeminar.infrastructure.UserRepository; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +public class BoardService { + + private final UserRepository userRepository; + private final BoardRepository boardRepository; + + @Transactional + public void create(BoardRequestDto request) { + User user = userRepository.findByEmail(request.getEmail()) + .orElseThrow(() -> new NotFoundException(Error.NOT_FOUND_USER_EXCEPTION, Error.NOT_FOUND_USER_EXCEPTION.getMessage())); + + Board newBoard = Board.newInstance( + user, + request.getTitle(), + request.getContent(), + request.getIsPublic() + ); + + boardRepository.save(newBoard); + } +} \ No newline at end of file diff --git a/fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/UserService.java b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/UserService.java new file mode 100644 index 0000000..00c5943 --- /dev/null +++ b/fourthSeminar/src/main/java/sopt/org/fourthSeminar/service/UserService.java @@ -0,0 +1,36 @@ +package sopt.org.fourthSeminar.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import sopt.org.fourthSeminar.controller.dto.request.UserRequestDto; +import sopt.org.fourthSeminar.controller.dto.response.UserResponseDto; +import sopt.org.fourthSeminar.controller.exception.Error; +import sopt.org.fourthSeminar.controller.exception.model.ConflictException; +import sopt.org.fourthSeminar.domain.User; +import sopt.org.fourthSeminar.infrastructure.UserRepository; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserRepository userRepository; + + @Transactional + public UserResponseDto create(UserRequestDto request) { + if (userRepository.existsByEmail(request.getEmail())) { + throw new ConflictException(Error.ALREADY_EXIST_USER_EXCEPTION, Error.ALREADY_EXIST_USER_EXCEPTION.getMessage()); + } + + User newUser = User.newInstance( + request.getNickname(), + request.getEmail(), + request.getPassword() + ); + + userRepository.save(newUser); + + return UserResponseDto.of(newUser.getId(), newUser.getNickname()); + } +} diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/UserController.java b/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/UserController.java deleted file mode 100644 index 7289ea0..0000000 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/UserController.java +++ /dev/null @@ -1,29 +0,0 @@ -package sopt.org.thirdSeminar.controller; - - -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import sopt.org.thirdSeminar.controller.common.dto.ApiResponseDto; -import sopt.org.thirdSeminar.controller.dto.request.UserRequestDto; -import sopt.org.thirdSeminar.controller.dto.response.UserResponseDto; -import sopt.org.thirdSeminar.controller.exception.SuccessStatus; -import sopt.org.thirdSeminar.service.UserService; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -public class UserController { - - private final UserService userService; - - @PostMapping("/user/signup") - @ResponseStatus(HttpStatus.CREATED) - public ApiResponseDto create(@RequestBody @Valid final UserRequestDto request) { - return ApiResponseDto.success(SuccessStatus.SIGNUP_SUCCESS, userService.create(request)); - } -} diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/advice/ControllerExceptionAdvice.java b/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/advice/ControllerExceptionAdvice.java deleted file mode 100644 index 9aae6fc..0000000 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/advice/ControllerExceptionAdvice.java +++ /dev/null @@ -1,22 +0,0 @@ -package sopt.org.thirdSeminar.controller.common.advice; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import sopt.org.thirdSeminar.controller.common.dto.ApiResponseDto; -import sopt.org.thirdSeminar.controller.exception.ErrorStatus; - -@RestControllerAdvice -public class ControllerExceptionAdvice { - - /* - * 400 BAD_REQUEST - */ - @ResponseStatus(HttpStatus.BAD_REQUEST) - @ExceptionHandler(MethodArgumentNotValidException.class) - protected ApiResponseDto handleMethodArgumentNotValidException(final MethodArgumentNotValidException e) { - return ApiResponseDto.error(ErrorStatus.VALIDATION_REQUEST_MISSING_EXCEPTION); - } -} diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/dto/ApiResponseDto.java b/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/dto/ApiResponseDto.java deleted file mode 100644 index e64bda4..0000000 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/controller/common/dto/ApiResponseDto.java +++ /dev/null @@ -1,32 +0,0 @@ -package sopt.org.thirdSeminar.controller.common.dto; - - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import sopt.org.thirdSeminar.controller.exception.ErrorStatus; -import sopt.org.thirdSeminar.controller.exception.SuccessStatus; - -@Getter -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) -@AllArgsConstructor(access = AccessLevel.PRIVATE) -public class ApiResponseDto { - - private final int code; - private final String message; - private T data; - - public static ApiResponseDto success(SuccessStatus successStatus) { - return new ApiResponseDto<>(successStatus.getHttpStatus().value(), successStatus.getMessage()); - } - - public static ApiResponseDto success(SuccessStatus successStatus, T data) { - return new ApiResponseDto(successStatus.getHttpStatus().value(), successStatus.getMessage(), data); - } - - public static ApiResponseDto error(ErrorStatus errorStatus) { - return new ApiResponseDto<>(errorStatus.getHttpStatus().value(), errorStatus.getMessage()); - } -} - diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/infrastructure/UserRepository.java b/fourthSeminar/src/main/java/sopt/org/thirdSeminar/infrastructure/UserRepository.java deleted file mode 100644 index aebbbd2..0000000 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/infrastructure/UserRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package sopt.org.thirdSeminar.infrastructure; - -import org.springframework.data.repository.Repository; -import sopt.org.thirdSeminar.domain.User; - -public interface UserRepository extends Repository { - - void save(User user); -} diff --git a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/service/UserService.java b/fourthSeminar/src/main/java/sopt/org/thirdSeminar/service/UserService.java deleted file mode 100644 index 16f78a9..0000000 --- a/fourthSeminar/src/main/java/sopt/org/thirdSeminar/service/UserService.java +++ /dev/null @@ -1,31 +0,0 @@ -package sopt.org.thirdSeminar.service; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import sopt.org.thirdSeminar.controller.dto.request.UserRequestDto; -import sopt.org.thirdSeminar.controller.dto.response.UserResponseDto; -import sopt.org.thirdSeminar.domain.User; -import sopt.org.thirdSeminar.infrastructure.UserRepository; - -import javax.transaction.Transactional; - -@Service -@RequiredArgsConstructor -public class UserService { - - private final UserRepository userRepository; - - @Transactional - public UserResponseDto create(UserRequestDto request) { - User user = User.builder() - .email(request.getEmail()) - .nickname(request.getNickname()) - .password(request.getPassword()) - .build(); - - userRepository.save(user); - - return UserResponseDto.of(user.getId(), user.getNickname()); - } - -}