Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

7주차 기본과제 #7

Open
wants to merge 1 commit into
base: #6
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions fourthSeminar/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ dependencies {
implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2'
implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2'

// S3 AWS
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-aws', version: '2.2.6.RELEASE'
// swagger
implementation 'org.springdoc:springdoc-openapi-ui:1.7.0'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public boolean supportsParameter(MethodParameter parameter) {
@Override
public Object resolveArgument(@NotNull MethodParameter parameter, ModelAndViewContainer mavContainer, @NotNull NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
final HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
final String token = request.getHeader("Authorization");
final String token = request.getHeader("Authorization").split(" ")[1]; //swagger Authorization에 Bearer를 붙이기 때문

//토큰 검증
if (!jwtService.verifyToken(token)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package sopt.org.fourthSeminar.config.swagger;

import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@SecurityScheme(
name = "JWT Auth",
type = SecuritySchemeType.HTTP,
bearerFormat = "JWT",
scheme = "bearer"
)
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
Info info = new Info()
.title("SOPT32nd Seminar project")
.description("SOPT32nd Seminar project API Document")
.version("1.0.0");

return new OpenAPI()
.components(new Components())
.info(info);

}
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,45 @@
package sopt.org.fourthSeminar.controller;

import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import sopt.org.fourthSeminar.common.dto.ApiResponse;
import sopt.org.fourthSeminar.config.jwt.JwtService;
import sopt.org.fourthSeminar.config.resolver.UserId;
import sopt.org.fourthSeminar.controller.request.dto.BoardImageListRequestDto;
import sopt.org.fourthSeminar.controller.request.dto.BoardRequestDto;
import sopt.org.fourthSeminar.exception.Success;
import sopt.org.fourthSeminar.external.client.aws.S3Service;
import sopt.org.fourthSeminar.service.BoardService;

import javax.validation.Valid;
import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/board")
@SecurityRequirement(name = "JWT Auth")
public class BoardController {

private final BoardService boardService;
private final JwtService jwtService;
private final S3Service s3Service;

// @PostMapping("/create")
// @ResponseStatus(HttpStatus.CREATED)
// public ApiResponse create(
// @RequestHeader("Authorization") String accessToken,
// @RequestBody @Valid final BoardRequestDto request) {
// boardService.create(Long.parseLong(jwtService.getJwtContents(accessToken)), request);
// return ApiResponse.success(Success.CREATE_BOARD_SUCCESS);
// }

@PostMapping("/create")
@PostMapping(value = "/create/{userId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.CREATED)
public ApiResponse create(
@UserId Long userId,
@RequestBody @Valid final BoardRequestDto request) {
boardService.create(userId, request);
//ModelAttri -> 적합한 생성자 만들어줌? -> 데이터 바인딩이 setter를 하지 않으면 -> allArgs
public ApiResponse create(@UserId Long userId, @ModelAttribute @Valid final BoardRequestDto request) {
String boardThumbnailImageUrl = s3Service.uploadImage(request.getThumbnail(), "board");
boardService.create(userId, boardThumbnailImageUrl, request);
return ApiResponse.success(Success.CREATE_BOARD_SUCCESS);
}

@PostMapping(value = "/create/images/{userId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.CREATED)
//ModelAttri -> List는 데이터바인딩 안됨..
public ApiResponse create(@UserId Long userId, @ModelAttribute @Valid final BoardImageListRequestDto request) {
List<String> boardThumbnailImageUrlList = s3Service.uploadsImages(request.getBoardImages(), "board");
boardService.create(userId, boardThumbnailImageUrlList, request);
return ApiResponse.success(Success.CREATE_BOARD_SUCCESS);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package sopt.org.fourthSeminar.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
Expand All @@ -17,12 +19,14 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
@Tag(name = "User", description = "유저 API Document")
public class UserController {
private final UserService userService;
private final JwtService jwtService;

@PostMapping("/signup")
@ResponseStatus(HttpStatus.CREATED)
@Operation(summary = "유저 생성 API", description = "유저를 서버에 등록합니다.")
public ApiResponse<UserResponseDto> create(@RequestBody @Valid final UserRequestDto request) {
return ApiResponse.success(Success.SIGNUP_SUCCESS, userService.create(request));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package sopt.org.fourthSeminar.controller.request.dto;


import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BoardImageListRequestDto {
private List<MultipartFile> boardImages;

@NotBlank
private String title;

@NotBlank
private String content;

@NotNull
private Boolean isPublic;

// public void setBoardImages(List<MultipartFile> boardImages) {
// this.boardImages = boardImages;
// }


}
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package sopt.org.fourthSeminar.controller.request.dto;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BoardRequestDto {

// @Email(message = "이메일 형식에 맞지 않습니다")
// private String email;
@NotNull
private MultipartFile thumbnail;

@NotBlank
private String title;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package sopt.org.fourthSeminar.controller.request.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -11,9 +12,11 @@

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Schema(description = "유저 생성 DTO")
public class UserRequestDto {
@NotBlank
@Pattern(regexp = "^[가-힣a-zA-Z]{2,10}$", message = "닉네임 형식에 맞지 않습니다")
@Schema(description = "유저 닉네임")
private String nickname;

@Email(message = "이메일 형식에 맞지 않습니다")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public class Board extends AuditingTimeEntity {
@JoinColumn(name = "user_id", nullable = false, foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT))
private User user;

@Column
private String thumbnail;

@Column(nullable = false)
private String title;

Expand All @@ -36,7 +39,19 @@ private Board(User user, String title, String content, Boolean isPublic) {
this.isPublic = isPublic;
}

private Board(User user, String thumbnail, String title, String content, Boolean isPublic) {
this.user = user;
this.thumbnail = thumbnail;
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);
}

public static Board newInstance(User user, String thumbnail, String title, String content, Boolean isPublic) {
return new Board(user, thumbnail, title, content, isPublic);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package sopt.org.fourthSeminar.domain;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Image extends AuditingTimeEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_id", nullable = false, foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT))
private Board board;

@Column(nullable = false)
private String imageUrl;

private Image(Board board, String imageUrl) {
this.board = board;
this.imageUrl = imageUrl;
}

public static Image newInstance(Board board, String imageUrl) {
return new Image(board, imageUrl);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public enum Error {
VALIDATION_WRONG_TYPE_EXCEPTION(HttpStatus.BAD_REQUEST, "잘못된 타입이 입력되었습니다"),
PARAMETER_TYPE_MISMATCH_EXCEPTION(HttpStatus.BAD_REQUEST, "파라미터의 타입이 잘못됐습니다"),
INVALID_PASSWORD_EXCEPTION(HttpStatus.BAD_REQUEST, "잘못된 비밀번호가 입력됐습니다."),
INVALID_MULTIPART_EXTENSION_EXCEPTION(HttpStatus.BAD_REQUEST, "잘못된 이미지 확장자입니다"),

/**
* 401 UNAUTHORIZED
Expand All @@ -29,7 +30,8 @@ public enum Error {
*/
NOT_FOUND_USER_EXCEPTION(HttpStatus.NOT_FOUND, "존재하지 않는 유저입니다"),
NOT_FOUND_POST_EXCEPTION(HttpStatus.NOT_FOUND, "존재하지 않는 게시물입니다"),
NOT_FOUND_EMOTION_EXCEPTION(HttpStatus.NOT_FOUND, "존재하지 않는 감정 기록입니다"),
NOT_FOUND_SAVE_IMAGE_EXCEPTION(HttpStatus.NOT_FOUND, "이미지를 저장하는데 실패했습니다"),
NOT_FOUND_IMAGE_EXCEPTION(HttpStatus.NOT_FOUND, "이미지를 찾을 수 없습니다"),

/**
* 409 CONFLICT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import sopt.org.fourthSeminar.exception.Error;

//@ResponseStatus(HttpStatus.BAD_REQUEST)
public class BadRequestException extends SoptException{
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class BadRequestException extends SoptException {
public BadRequestException(Error error, String message) {
super(error, message);
}
Expand Down
Loading