Skip to content

Commit

Permalink
4차 세미나 #10
Browse files Browse the repository at this point in the history
  • Loading branch information
PgmJun committed May 6, 2023
1 parent 280bf10 commit 461bdff
Show file tree
Hide file tree
Showing 27 changed files with 468 additions and 143 deletions.
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<UserResponseDto> create(@RequestBody @Valid final UserRequestDto request) {
return ApiResponse.success(Success.SIGNUP_SUCCESS, userService.create(request));
}
}
Original file line number Diff line number Diff line change
@@ -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<Object> handleException(final Exception e) {
return ApiResponse.error(Error.INTERNAL_SERVER_ERROR);
}

/**
* Sopt custom error
*/
@ExceptionHandler(SoptException.class)
protected ResponseEntity<ApiResponse> handleSoptException(SoptException e) {
return ResponseEntity.status(e.getHttpStatus())
.body(ApiResponse.error(e.getError(), e.getMessage()));
}
}
Original file line number Diff line number Diff line change
@@ -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<T> {

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 <T> ApiResponse<T> success(Success success, T data) {
return new ApiResponse<T>(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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
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;
import javax.validation.constraints.NotNull;
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;
}
Original file line number Diff line number Diff line change
@@ -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 {

Expand All @@ -14,4 +16,4 @@ public class UserResponseDto {
public static UserResponseDto of(Long userId, String nickname) {
return new UserResponseDto(userId, nickname);
}
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sopt.org.thirdSeminar.controller.exception;
package sopt.org.fourthSeminar.controller.exception;


import lombok.AccessLevel;
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sopt.org.thirdSeminar.controller.exception;
package sopt.org.fourthSeminar.controller.exception;

import lombok.AccessLevel;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading

0 comments on commit 461bdff

Please sign in to comment.