From 55cf6e29c7d1738802b18e0b42eb84fcf9101c4d Mon Sep 17 00:00:00 2001 From: mng990 Date: Fri, 1 Nov 2024 14:49:39 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20private-post=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=84=9C=EB=B2=84=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EC=A4=80=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 2 +- .../backend/common/config/SecurityConfig.java | 2 +- .../aimo/backend/common/dto/DataResponse.java | 10 +- .../backend/common/entity/BaseEntity.java | 11 +- .../java/aimo/backend/common/entity/Like.java | 3 +- .../backend/common/exception/ErrorCode.java | 1 - .../exception/GlobalExceptionHandler.java | 41 +++--- .../common/mapper/AudioRecordMapper.java | 11 +- .../backend/common/mapper/MemberMapper.java | 3 +- .../backend/common/mapper/PostMapper.java | 40 ++++++ .../common/mapper/PrivatePostMapper.java | 35 ++--- .../common/properties/AiServerProperties.java | 4 +- .../common/properties/JwtProperties.java | 49 +++---- .../common/properties/SecurityProperties.java | 6 +- .../backend/common/swagger/SwaggerConfig.java | 42 +++--- .../ExceptionHandlingFilter.java | 2 + .../jwtFilter/JwtAuthenticationFilter.java | 4 +- .../security/jwtFilter/JwtTokenProvider.java | 6 +- .../jwtFilter/JwtTokenProviderImpl.java | 15 ++- .../controller/ChildCommentController.java | 1 - .../comment/costants/CommentConstants.java | 1 + .../dto/request/SaveChildCommentRequest.java | 12 +- .../dto/request/SaveParentCommentRequest.java | 12 +- .../request/UpdateChildCommentRequest.java | 11 +- .../request/UpdateParentCommentRequest.java | 12 +- .../dto/response/ChildCommentResponse.java | 4 + .../comment/dto/response/CommentResponse.java | 17 +++ .../domains/comment/entity/ParentComment.java | 5 +- .../comment/mapper/ChildCommentMapper.java | 11 +- .../comment/mapper/ParentCommentMapper.java | 9 +- .../comment/service/ChildCommentService.java | 1 - .../domains/member/dto/DeleteRequest.java | 5 +- .../domains/member/dto/SignUpRequest.java | 3 +- .../backend/domains/member/entity/Member.java | 10 +- .../domains/member/entity/ProfileImage.java | 1 + .../domains/member/entity/RefreshToken.java | 1 + .../backend/domains/member/model/Gender.java | 5 +- .../domains/member/model/MemberRole.java | 1 + .../domains/member/model/Provider.java | 2 + .../member/repository/MemberRepository.java | 6 +- .../repository/RefreshTokenRepository.java | 2 + .../domains/member/service/MemberService.java | 123 +++++++++--------- .../member/service/RefreshTokenService.java | 5 +- .../post/controller/PostController.java | 32 +++++ .../domains/post/dto/GetPostResponse.java | 4 + .../domains/post/dto/PostListResponse.java | 6 + .../domains/post/dto/PostPreviewResponse.java | 24 ++++ .../domains/post/dto/SavePostRequest.java | 34 +++++ .../domains/post/dto/SinglePostResponse.java | 30 +++++ .../backend/domains/post/entity/Post.java | 85 +++++++++++- .../backend/domains/post/entity/PostLike.java | 2 +- .../backend/domains/post/entity/PostView.java | 48 +++++++ .../backend/domains/post/entity/Vote.java | 46 +++++++ .../aimo/backend/domains/post/model/Side.java | 14 ++ .../post/repository/PostLikeRepository.java | 11 ++ .../post/repository/PostRepository.java | 1 + .../post/repository/PostViewRepository.java | 9 ++ .../post/repository/VoteRepsoitory.java | 9 ++ .../domains/post/service/PostService.java | 12 +- .../controller/PrivatePostController.java | 54 +++----- .../dto/SaveAudioSuccessRequest.java | 18 +++ .../dto/SummaryAndJudgementRequest.java | 1 + .../dto/SummaryAndJudgementResponse.java | 12 -- .../privatePost/dto/TextRecordRequest.java | 4 +- .../dto/UploadAudioSuccessRequest.java | 18 --- .../privatePost/entity/AudioRecord.java | 3 +- .../privatePost/entity/ChatRecord.java | 3 +- .../privatePost/entity/PrivatePost.java | 6 +- .../privatePost/entity/TextRecord.java | 3 +- .../repository/ChatRecordRepository.java | 1 + .../service/AudioRecordService.java | 6 +- .../service/ChatRecordService.java | 9 +- .../service/PrivatePostService.java | 67 ++++++---- .../service/TextRecordService.java | 2 +- .../util/encoder/PasswordEncoderUtil.java | 2 +- .../util/memberLoader/MemberLoader.java | 1 - .../util/responseWriter/ResponseWriter.java | 42 +++--- 77 files changed, 794 insertions(+), 372 deletions(-) create mode 100644 backend/src/main/java/aimo/backend/common/mapper/PostMapper.java create mode 100644 backend/src/main/java/aimo/backend/domains/comment/dto/response/ChildCommentResponse.java create mode 100644 backend/src/main/java/aimo/backend/domains/comment/dto/response/CommentResponse.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/controller/PostController.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/dto/GetPostResponse.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/dto/PostListResponse.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/dto/PostPreviewResponse.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/dto/SavePostRequest.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/dto/SinglePostResponse.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/entity/PostView.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/entity/Vote.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/model/Side.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/repository/PostLikeRepository.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/repository/PostViewRepository.java create mode 100644 backend/src/main/java/aimo/backend/domains/post/repository/VoteRepsoitory.java create mode 100644 backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java delete mode 100644 backend/src/main/java/aimo/backend/domains/privatePost/dto/UploadAudioSuccessRequest.java diff --git a/backend/build.gradle b/backend/build.gradle index 74967bd..82a001b 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -35,7 +35,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'io.netty:netty-all:4.1.75.Final' // netty 버전에 맞게 설정 + implementation 'io.netty:netty-all:4.1.75.Final' implementation 'org.springframework.boot:spring-boot-starter-websocket' implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'javax.annotation:javax.annotation-api:1.3.2' diff --git a/backend/src/main/java/aimo/backend/common/config/SecurityConfig.java b/backend/src/main/java/aimo/backend/common/config/SecurityConfig.java index 9724a32..a4b7367 100644 --- a/backend/src/main/java/aimo/backend/common/config/SecurityConfig.java +++ b/backend/src/main/java/aimo/backend/common/config/SecurityConfig.java @@ -7,6 +7,7 @@ import aimo.backend.domains.auth.security.loginFilter.LoginFilter; import aimo.backend.domains.member.service.MemberService; import lombok.RequiredArgsConstructor; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -39,7 +40,6 @@ public class SecurityConfig { private final PasswordEncoder passwordEncoder; private final AntPathMatcher pathMatcher = new AntPathMatcher(); - @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // 비활성확 목록 diff --git a/backend/src/main/java/aimo/backend/common/dto/DataResponse.java b/backend/src/main/java/aimo/backend/common/dto/DataResponse.java index 6c05410..d2a49e4 100644 --- a/backend/src/main/java/aimo/backend/common/dto/DataResponse.java +++ b/backend/src/main/java/aimo/backend/common/dto/DataResponse.java @@ -24,6 +24,12 @@ public static DataResponse from(T data) { public static DataResponse ok() { return new DataResponse<>(HttpStatus.OK, null); } - public static DataResponse created() { return new DataResponse<>(HttpStatus.CREATED, null); } - public static DataResponse noContent() { return new DataResponse<>(HttpStatus.NO_CONTENT, null); } + + public static DataResponse created() { + return new DataResponse<>(HttpStatus.CREATED, null); + } + + public static DataResponse noContent() { + return new DataResponse<>(HttpStatus.NO_CONTENT, null); + } } diff --git a/backend/src/main/java/aimo/backend/common/entity/BaseEntity.java b/backend/src/main/java/aimo/backend/common/entity/BaseEntity.java index 6773c83..aadc5ec 100644 --- a/backend/src/main/java/aimo/backend/common/entity/BaseEntity.java +++ b/backend/src/main/java/aimo/backend/common/entity/BaseEntity.java @@ -5,6 +5,7 @@ import jakarta.persistence.MappedSuperclass; import lombok.Getter; import lombok.NoArgsConstructor; + import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -17,11 +18,11 @@ @EntityListeners(AuditingEntityListener.class) public abstract class BaseEntity { - @CreatedDate - @Column(updatable = false) - private LocalDateTime createdAt; + @CreatedDate + @Column(updatable = false) + private LocalDateTime createdAt; - @LastModifiedDate - private LocalDateTime updatedAt; + @LastModifiedDate + private LocalDateTime updatedAt; } diff --git a/backend/src/main/java/aimo/backend/common/entity/Like.java b/backend/src/main/java/aimo/backend/common/entity/Like.java index 2eb51db..5762aa0 100644 --- a/backend/src/main/java/aimo/backend/common/entity/Like.java +++ b/backend/src/main/java/aimo/backend/common/entity/Like.java @@ -20,7 +20,8 @@ @EntityListeners(AuditingEntityListener.class) public abstract class Like extends BaseEntity { - @Id @GeneratedValue + @Id + @GeneratedValue @Column(nullable = false) private Long like_id; diff --git a/backend/src/main/java/aimo/backend/common/exception/ErrorCode.java b/backend/src/main/java/aimo/backend/common/exception/ErrorCode.java index c20cf1f..ddec53f 100644 --- a/backend/src/main/java/aimo/backend/common/exception/ErrorCode.java +++ b/backend/src/main/java/aimo/backend/common/exception/ErrorCode.java @@ -35,7 +35,6 @@ public enum ErrorCode { INVALID_EMAIL(HttpStatus.BAD_REQUEST, "이메일 형식이 잘못 되었습니다.", "MEMBER-009"), EMAIL_NOT_MATCH(HttpStatus.BAD_REQUEST, "이메일이 일치하지 않습니다.", "MEMBER-010"), - //PrivatePost PRIVATE_POST_NOT_FOUND(HttpStatus.NOT_FOUND, "해당하는 대화록을 찾을 수 없습니다.", "DISPUTE-001"), PRIVATE_POST_CREATE_FAIL(HttpStatus.BAD_REQUEST, "대화록 생성에 실패하였습니다.", "DISPUTE-002"), diff --git a/backend/src/main/java/aimo/backend/common/exception/GlobalExceptionHandler.java b/backend/src/main/java/aimo/backend/common/exception/GlobalExceptionHandler.java index b8b1e32..04fc885 100644 --- a/backend/src/main/java/aimo/backend/common/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/aimo/backend/common/exception/GlobalExceptionHandler.java @@ -2,6 +2,7 @@ import java.io.IOException; +import org.apache.coyote.Response; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -13,37 +14,47 @@ public class GlobalExceptionHandler { @ExceptionHandler(ApiException.class) public ResponseEntity handleApiException(ApiException e) { - return ResponseEntity - .status(e.getHttpStatus()) - .body(ErrorResponse.of(e.getHttpStatus(), e.getMessage(), e.getCode())); + return makeResponseEntity(e); } - @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) { - return ResponseEntity - .status(HttpStatus.BAD_REQUEST) - .body(ErrorResponse.of(HttpStatus.BAD_REQUEST, e.getMessage(), ErrorCode.ILLEGAL_ARGUMENT.getCode())); + return makeResponseEntity400(e); } @ExceptionHandler(IOException.class) public ResponseEntity handleIOException(IOException e) { - return ResponseEntity - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(ErrorResponse.of(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage(), ErrorCode.IO_EXCEPTION.getCode())); + return makeResponseEntity5xx(e); } @ExceptionHandler(RuntimeException.class) public ResponseEntity handleRuntimeException(RuntimeException e) { - return ResponseEntity - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(ErrorResponse.of(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage(), ErrorCode.INTERNAL_SERVER_ERROR.getCode())); + return makeResponseEntity5xx(e); } @ExceptionHandler(Exception.class) public ResponseEntity handleException(Exception e) { + return makeResponseEntity5xx(e); + } + + public ResponseEntity makeResponseEntity(ApiException e) { + return ResponseEntity + .status(e.getHttpStatus()) + .body(ErrorResponse.of(e.getHttpStatus(), e.getMessage(), e.getCode())); + } + + public ResponseEntity makeResponseEntity400(Exception e) { + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body(ErrorResponse.of(HttpStatus.BAD_REQUEST, e.getMessage(), ErrorCode.ILLEGAL_ARGUMENT.getCode())); + } + + public ResponseEntity makeResponseEntity5xx(Exception e) { return ResponseEntity - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(ErrorResponse.of(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage(), ErrorCode.INTERNAL_SERVER_ERROR.getCode())); + .status(ErrorCode.INTERNAL_SERVER_ERROR.getHttpStatus()) + .body(ErrorResponse.of( + ErrorCode.INTERNAL_SERVER_ERROR.getHttpStatus(), + e.getMessage(), + ErrorCode.INTERNAL_SERVER_ERROR.getCode())); } } diff --git a/backend/src/main/java/aimo/backend/common/mapper/AudioRecordMapper.java b/backend/src/main/java/aimo/backend/common/mapper/AudioRecordMapper.java index 48572e1..fc57607 100644 --- a/backend/src/main/java/aimo/backend/common/mapper/AudioRecordMapper.java +++ b/backend/src/main/java/aimo/backend/common/mapper/AudioRecordMapper.java @@ -1,15 +1,16 @@ package aimo.backend.common.mapper; -import aimo.backend.domains.privatePost.dto.UploadAudioSuccessRequest; +import aimo.backend.domains.privatePost.dto.SaveAudioSuccessRequest; import aimo.backend.domains.privatePost.entity.AudioRecord; public class AudioRecordMapper { - public static AudioRecord toEntity(UploadAudioSuccessRequest uploadAudioSuccessRequest) { + + public static AudioRecord toEntity(SaveAudioSuccessRequest saveAudioSuccessRequest) { return AudioRecord .builder() - .url(uploadAudioSuccessRequest.url()) - .size(uploadAudioSuccessRequest.size()) - .filename(uploadAudioSuccessRequest.filename()) + .url(saveAudioSuccessRequest.url()) + .size(saveAudioSuccessRequest.size()) + .filename(saveAudioSuccessRequest.filename()) .build(); } } diff --git a/backend/src/main/java/aimo/backend/common/mapper/MemberMapper.java b/backend/src/main/java/aimo/backend/common/mapper/MemberMapper.java index 482db69..ea99dd7 100644 --- a/backend/src/main/java/aimo/backend/common/mapper/MemberMapper.java +++ b/backend/src/main/java/aimo/backend/common/mapper/MemberMapper.java @@ -12,9 +12,10 @@ @Component @RequiredArgsConstructor public class MemberMapper { + private final PasswordEncoder passwordEncoder; - public Member signUpMemberEntity(SignUpRequest signUpRequest){ + public Member signUpMemberEntity(SignUpRequest signUpRequest) { return Member .builder() .username(signUpRequest.username()) diff --git a/backend/src/main/java/aimo/backend/common/mapper/PostMapper.java b/backend/src/main/java/aimo/backend/common/mapper/PostMapper.java new file mode 100644 index 0000000..4954f01 --- /dev/null +++ b/backend/src/main/java/aimo/backend/common/mapper/PostMapper.java @@ -0,0 +1,40 @@ +package aimo.backend.common.mapper; + +import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.post.dto.PostPreviewResponse; +import aimo.backend.domains.post.dto.SavePostRequest; +import aimo.backend.domains.post.entity.Post; + +public class PostMapper { + + public static Post toEntity(SavePostRequest request, Member member) { + return Post + .builder() + .member(member) + .title(request.title()) + .summaryAi(request.summaryAi()) + .stancePlaintiff(request.stancePlaintiff()) + .stanceDefendant(request.stanceDefendant()) + .privatePostId(request.privatePostId()) + .originType(request.originType()) + .category(request.category()) + .build(); + } + + public static PostPreviewResponse toPreviewResponse(Post post) { + return new PostPreviewResponse( + post.getId(), + post.getTitle(), + getPreview(post.getSummaryAi(), 90), + post.getPostLikes().size(), + post.getPostViews().size(), + post.getCommentsCount(), + post.getCreatedAt() + ); + } + + public static String getPreview(String summaryAi, Integer length) { + return summaryAi.length() > length ? + summaryAi.substring(0, length) + "..." : summaryAi; + } +} \ No newline at end of file diff --git a/backend/src/main/java/aimo/backend/common/mapper/PrivatePostMapper.java b/backend/src/main/java/aimo/backend/common/mapper/PrivatePostMapper.java index 58d1e9b..7d4e234 100644 --- a/backend/src/main/java/aimo/backend/common/mapper/PrivatePostMapper.java +++ b/backend/src/main/java/aimo/backend/common/mapper/PrivatePostMapper.java @@ -8,8 +8,7 @@ public class PrivatePostMapper { public static PrivatePost toEntity(SummaryAndJudgementResponse summaryAndJudgementResponse) { - return PrivatePost - .builder() + return PrivatePost.builder() .title(summaryAndJudgementResponse.title()) .stancePlaintiff(summaryAndJudgementResponse.stancePlaintiff()) .stanceDefendant(summaryAndJudgementResponse.stanceDefendant()) @@ -20,31 +19,19 @@ public static PrivatePost toEntity(SummaryAndJudgementResponse summaryAndJudgeme .build(); } - public static PrivatePostPreviewResponse toPreviewResponse(PrivatePost privatePost){ - return new PrivatePostPreviewResponse( - privatePost.getId(), - privatePost.getTitle(), - getPreview(privatePost.getSummaryAi(), 21), - privatePost.getOriginType(), - privatePost.getCreatedAt(), - privatePost.getPublished() - ); + public static PrivatePostPreviewResponse toPreviewResponse(PrivatePost privatePost) { + return new PrivatePostPreviewResponse(privatePost.getId(), privatePost.getTitle(), + getPreview(privatePost.getSummaryAi(), 21), privatePost.getOriginType(), privatePost.getCreatedAt(), + privatePost.getPublished()); } - public static String getPreview(String summaryAi, Integer length){ - return summaryAi.length() > length ? - summaryAi.substring(0, length) + "..." : summaryAi; + public static String getPreview(String summaryAi, Integer length) { + return summaryAi.length() > length ? summaryAi.substring(0, length) + "..." : summaryAi; } - public static PrivatePostResponse toResponse(PrivatePost privatePost){ - return new PrivatePostResponse( - privatePost.getTitle(), - privatePost.getSummaryAi(), - privatePost.getStancePlaintiff(), - privatePost.getStanceDefendant(), - privatePost.getJudgement(), - privatePost.getFaultRate(), - privatePost.getPublished() - ); + public static PrivatePostResponse toResponse(PrivatePost privatePost) { + return new PrivatePostResponse(privatePost.getTitle(), privatePost.getSummaryAi(), + privatePost.getStancePlaintiff(), privatePost.getStanceDefendant(), privatePost.getJudgement(), + privatePost.getFaultRate(), privatePost.getPublished()); } } diff --git a/backend/src/main/java/aimo/backend/common/properties/AiServerProperties.java b/backend/src/main/java/aimo/backend/common/properties/AiServerProperties.java index 01e7321..f0e9c58 100644 --- a/backend/src/main/java/aimo/backend/common/properties/AiServerProperties.java +++ b/backend/src/main/java/aimo/backend/common/properties/AiServerProperties.java @@ -5,9 +5,11 @@ import lombok.Getter; import lombok.Setter; -@Getter @Setter +@Getter +@Setter @ConfigurationProperties(prefix = "ai.server") public class AiServerProperties { + private String domainUrl; private String judgementApi; } diff --git a/backend/src/main/java/aimo/backend/common/properties/JwtProperties.java b/backend/src/main/java/aimo/backend/common/properties/JwtProperties.java index adb0f2f..ae40ca6 100644 --- a/backend/src/main/java/aimo/backend/common/properties/JwtProperties.java +++ b/backend/src/main/java/aimo/backend/common/properties/JwtProperties.java @@ -2,6 +2,7 @@ import lombok.Getter; import lombok.Setter; + import org.springframework.boot.context.properties.ConfigurationProperties; @Getter @@ -9,27 +10,29 @@ @ConfigurationProperties(prefix = "jwt") public class JwtProperties { - private String issuer; - private String secret; - private Access access; - private Refresh refresh; - - private String ACCESS_TOKEN_SUBJECT = "AccessToken"; - private String REFRESH_TOKEN_SUBJECT = "RefreshToken"; - private String MEMBER_ID_CLAIM = "member_id"; - private String BEARER = "Bearer "; - - @Getter - @Setter - public static class Access { - private int expiration; - private String header; - } - - @Getter - @Setter - public static class Refresh { - private int expiration; - private String header; - } + private String issuer; + private String secret; + private Access access; + private Refresh refresh; + + private String ACCESS_TOKEN_SUBJECT = "AccessToken"; + private String REFRESH_TOKEN_SUBJECT = "RefreshToken"; + private String MEMBER_ID_CLAIM = "member_id"; + private String BEARER = "Bearer "; + + @Getter + @Setter + public static class Access { + + private int expiration; + private String header; + } + + @Getter + @Setter + public static class Refresh { + + private int expiration; + private String header; + } } diff --git a/backend/src/main/java/aimo/backend/common/properties/SecurityProperties.java b/backend/src/main/java/aimo/backend/common/properties/SecurityProperties.java index 3e3aa84..38a0abb 100644 --- a/backend/src/main/java/aimo/backend/common/properties/SecurityProperties.java +++ b/backend/src/main/java/aimo/backend/common/properties/SecurityProperties.java @@ -2,12 +2,14 @@ import lombok.Getter; import lombok.Setter; + import org.springframework.boot.context.properties.ConfigurationProperties; @Getter @Setter @ConfigurationProperties(prefix = "security") public class SecurityProperties { - private String[] permitUrls; - private String password; + + private String[] permitUrls; + private String password; } diff --git a/backend/src/main/java/aimo/backend/common/swagger/SwaggerConfig.java b/backend/src/main/java/aimo/backend/common/swagger/SwaggerConfig.java index d343d17..87be4ba 100644 --- a/backend/src/main/java/aimo/backend/common/swagger/SwaggerConfig.java +++ b/backend/src/main/java/aimo/backend/common/swagger/SwaggerConfig.java @@ -5,6 +5,7 @@ import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,24 +13,25 @@ @Configuration public class SwaggerConfig { - @Bean - public OpenAPI openAPI() { - - SecurityScheme securityScheme = new SecurityScheme() - .type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT") - .in(SecurityScheme.In.HEADER).name("Authorization"); - SecurityRequirement securityRequirement = new SecurityRequirement().addList("bearerAuth"); - - return new OpenAPI() - .components(new Components().addSecuritySchemes("bearerAuth", securityScheme)) - .security(Arrays.asList(securityRequirement)) - .info(apiInfo()); - } - - private Info apiInfo() { - return new Info() - .title("aimo api 명세서") - .description("aimo api 명세서입니다.") - .version("1.0.0"); - } + + @Bean + public OpenAPI openAPI() { + + SecurityScheme securityScheme = new SecurityScheme() + .type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT") + .in(SecurityScheme.In.HEADER).name("Authorization"); + SecurityRequirement securityRequirement = new SecurityRequirement().addList("bearerAuth"); + + return new OpenAPI() + .components(new Components().addSecuritySchemes("bearerAuth", securityScheme)) + .security(Arrays.asList(securityRequirement)) + .info(apiInfo()); + } + + private Info apiInfo() { + return new Info() + .title("aimo api 명세서") + .description("aimo api 명세서입니다.") + .version("1.0.0"); + } } diff --git a/backend/src/main/java/aimo/backend/domains/auth/security/exceptionHandlingFilter/ExceptionHandlingFilter.java b/backend/src/main/java/aimo/backend/domains/auth/security/exceptionHandlingFilter/ExceptionHandlingFilter.java index 3cee8e3..84b7f6a 100644 --- a/backend/src/main/java/aimo/backend/domains/auth/security/exceptionHandlingFilter/ExceptionHandlingFilter.java +++ b/backend/src/main/java/aimo/backend/domains/auth/security/exceptionHandlingFilter/ExceptionHandlingFilter.java @@ -9,6 +9,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; + import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @@ -16,6 +17,7 @@ @Slf4j public class ExceptionHandlingFilter extends OncePerRequestFilter { + @Override protected void doFilterInternal( HttpServletRequest request, diff --git a/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtAuthenticationFilter.java b/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtAuthenticationFilter.java index 4fb1017..b3df056 100644 --- a/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtAuthenticationFilter.java @@ -11,6 +11,7 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; @@ -55,7 +56,8 @@ protected void doFilterInternal( //4. access토큰이 존재하며, accesToken이 유효하지 않으면 에러 리턴 //5. 그 외 모든 경우는 에러 리턴 - if (refreshToken != null && jwtTokenProvider.isTokenValid(refreshToken) && request.getRequestURI().matches("^\\/reissue$")) { + if (refreshToken != null && jwtTokenProvider.isTokenValid(refreshToken) && request.getRequestURI() + .matches("^\\/reissue$")) { log.info("refresh토큰 인증 성공"); jwtTokenProvider.checkRefreshTokenAndReIssueAccessAndRefreshToken(response, accessToken, refreshToken); } else if (refreshToken != null && !jwtTokenProvider.isTokenValid(refreshToken)) { diff --git a/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProvider.java b/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProvider.java index 5ab7ce5..321b2be 100644 --- a/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProvider.java +++ b/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProvider.java @@ -3,6 +3,7 @@ import io.jsonwebtoken.Claims; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import org.springframework.security.core.Authentication; import java.util.Optional; @@ -35,9 +36,10 @@ public interface JwtTokenProvider { void expireRefreshToken(Long memberId, String accessToken, String refreshToken); - void checkRefreshTokenAndReIssueAccessAndRefreshToken(HttpServletResponse response, String accessToken, String refreshToken); + void checkRefreshTokenAndReIssueAccessAndRefreshToken(HttpServletResponse response, String accessToken, + String refreshToken); boolean isRefreshTokenValid(String refreshToken); - + boolean isLogout(String accessToken); } \ No newline at end of file diff --git a/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProviderImpl.java b/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProviderImpl.java index 80513f7..ac5a257 100644 --- a/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProviderImpl.java +++ b/backend/src/main/java/aimo/backend/domains/auth/security/jwtFilter/JwtTokenProviderImpl.java @@ -20,6 +20,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; + import org.springframework.http.HttpStatus; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -33,7 +34,6 @@ import java.util.List; import java.util.Optional; - @Transactional(readOnly = true) @Service @Slf4j @@ -104,7 +104,8 @@ public void sendAccessAndRefreshToken(HttpServletResponse response, String acces setAccessTokenHeader(response, accessToken); setRefreshTokenHeader(response, refreshToken); - JwtDTO.AccessAndRefreshTokenResponse accessAndRefreshTokenResponse = JwtDTO.AccessAndRefreshTokenResponse.from(accessToken, + JwtDTO.AccessAndRefreshTokenResponse accessAndRefreshTokenResponse = JwtDTO.AccessAndRefreshTokenResponse.from( + accessToken, refreshToken); ResponseWriter.writeResponse(response, DataResponse.from(accessAndRefreshTokenResponse), HttpStatus.OK); @@ -187,17 +188,17 @@ public boolean isTokenValid(String token) { return false; } - public void checkRefreshTokenAndReIssueAccessAndRefreshToken(HttpServletResponse response, String accessToken, String refreshToken) { + public void checkRefreshTokenAndReIssueAccessAndRefreshToken(HttpServletResponse response, String accessToken, + String refreshToken) { //refreshToken이 유효한지 확인 Long memberId = extractMemberId(refreshToken) - .orElseThrow(() -> ApiException.from(INVALID_REFRESH_TOKEN)); + .orElseThrow(() -> ApiException.from(INVALID_REFRESH_TOKEN)); - if(!isRefreshTokenValid(accessToken)){ + if (!isRefreshTokenValid(accessToken)) { throw ApiException.from(INVALID_REFRESH_TOKEN); } - String newAccessToken = createAccessToken(memberId); String newRefreshToken = createRefreshToken(memberId); @@ -206,7 +207,7 @@ public void checkRefreshTokenAndReIssueAccessAndRefreshToken(HttpServletResponse } @Override - public boolean isRefreshTokenValid(String accessToken){ + public boolean isRefreshTokenValid(String accessToken) { return !refreshTokenService.existsByAccessToken(accessToken); } diff --git a/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java b/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java index 258b2f0..c9e3da8 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java +++ b/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java @@ -11,7 +11,6 @@ import aimo.backend.common.dto.DataResponse; import aimo.backend.domains.comment.dto.request.SaveChildCommentRequest; -import aimo.backend.domains.comment.dto.request.UpdateChildCommentRequest; import aimo.backend.domains.comment.service.ChildCommentService; import aimo.backend.domains.member.entity.Member; import aimo.backend.util.memberLoader.MemberLoader; diff --git a/backend/src/main/java/aimo/backend/domains/comment/costants/CommentConstants.java b/backend/src/main/java/aimo/backend/domains/comment/costants/CommentConstants.java index c47ff0d..4aaef5d 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/costants/CommentConstants.java +++ b/backend/src/main/java/aimo/backend/domains/comment/costants/CommentConstants.java @@ -6,6 +6,7 @@ @Getter @RequiredArgsConstructor public enum CommentConstants { + DELETED_COMMENT("댓글이 삭제되었습니다."), DELETED_MEMBER("탈퇴한 회원"), ; diff --git a/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java b/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java index 4d49f88..8b6daac 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java +++ b/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java @@ -1,10 +1,8 @@ package aimo.backend.domains.comment.dto.request; -import lombok.Data; -import lombok.RequiredArgsConstructor; +import jakarta.validation.constraints.Size; -@Data -@RequiredArgsConstructor -public class SaveChildCommentRequest { - private final String content; -} +public record SaveChildCommentRequest( + @Size(max = 1500, message = "댓글은 한글 기준 최대 500자까지 입력할 수 있습니다.") + String content +) { } diff --git a/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveParentCommentRequest.java b/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveParentCommentRequest.java index ce6514c..20adb86 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveParentCommentRequest.java +++ b/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveParentCommentRequest.java @@ -1,10 +1,8 @@ package aimo.backend.domains.comment.dto.request; -import lombok.Data; -import lombok.RequiredArgsConstructor; +import jakarta.validation.constraints.Size; -@Data -@RequiredArgsConstructor -public class SaveParentCommentRequest { - private final String content; -} +public record SaveParentCommentRequest( + @Size(max = 1500, message = "댓글은 한글 기준 최대 500자까지 입력할 수 있습니다.") + String content +) { } diff --git a/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateChildCommentRequest.java b/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateChildCommentRequest.java index 55f771c..8bcb06a 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateChildCommentRequest.java +++ b/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateChildCommentRequest.java @@ -1,10 +1,9 @@ package aimo.backend.domains.comment.dto.request; -import lombok.Data; -import lombok.RequiredArgsConstructor; +import jakarta.validation.constraints.Size; -@Data -@RequiredArgsConstructor -public class UpdateChildCommentRequest { - private final String content; +public record UpdateChildCommentRequest( + @Size(max = 1500, message = "댓글은 한글 기준 최대 500자까지 입력할 수 있습니다.") + String content +) { } diff --git a/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateParentCommentRequest.java b/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateParentCommentRequest.java index ccde01e..257bb44 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateParentCommentRequest.java +++ b/backend/src/main/java/aimo/backend/domains/comment/dto/request/UpdateParentCommentRequest.java @@ -1,10 +1,8 @@ package aimo.backend.domains.comment.dto.request; -import lombok.Data; -import lombok.RequiredArgsConstructor; +import jakarta.validation.constraints.Size; -@Data -@RequiredArgsConstructor -public class UpdateParentCommentRequest { - private final String content; -} +public record UpdateParentCommentRequest( + @Size(max = 1500, message = "댓글은 한글 기준 최대 500자까지 입력할 수 있습니다.") + String content +) { } diff --git a/backend/src/main/java/aimo/backend/domains/comment/dto/response/ChildCommentResponse.java b/backend/src/main/java/aimo/backend/domains/comment/dto/response/ChildCommentResponse.java new file mode 100644 index 0000000..789f937 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/comment/dto/response/ChildCommentResponse.java @@ -0,0 +1,4 @@ +package aimo.backend.domains.comment.dto.response; + +public record ChildCommentResponse() { +} diff --git a/backend/src/main/java/aimo/backend/domains/comment/dto/response/CommentResponse.java b/backend/src/main/java/aimo/backend/domains/comment/dto/response/CommentResponse.java new file mode 100644 index 0000000..7d80cc9 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/comment/dto/response/CommentResponse.java @@ -0,0 +1,17 @@ +package aimo.backend.domains.comment.dto.response; + +import java.time.LocalDateTime; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; + +public record CommentResponse( + Long commentId, + String username, + String content, + Long likes, + ListchildComments, + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime createdAt +) { +} diff --git a/backend/src/main/java/aimo/backend/domains/comment/entity/ParentComment.java b/backend/src/main/java/aimo/backend/domains/comment/entity/ParentComment.java index 55ae297..60de2cb 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/entity/ParentComment.java +++ b/backend/src/main/java/aimo/backend/domains/comment/entity/ParentComment.java @@ -24,7 +24,6 @@ public class ParentComment extends BaseEntity { @Column(name = "parent_comment_id") private Long id; - @Column(nullable = false) private String memberName; @@ -45,6 +44,10 @@ public class ParentComment extends BaseEntity { @Column(nullable = false) private Boolean isDeleted; + public Integer getCommentsCount() { + return childComments.size() + 1; + } + @Builder private ParentComment( String memberName, diff --git a/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java b/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java index be23e89..15e1db9 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java +++ b/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java @@ -13,14 +13,9 @@ @RequiredArgsConstructor public class ChildCommentMapper { - public ChildComment from( - SaveChildCommentRequest request, - Member member, - ParentComment parentComment, - Post post - ) { - return ChildComment - .builder() + public ChildComment from(SaveChildCommentRequest request, + Member member, ParentComment parentComment, Post post) { + return ChildComment.builder() .memberName(member.getUsername()) .content(request.getContent()) .parentComment(parentComment) diff --git a/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java b/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java index 5192080..97c9285 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java +++ b/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java @@ -12,13 +12,8 @@ @RequiredArgsConstructor public class ParentCommentMapper { - public ParentComment from( - SaveParentCommentRequest request, - Member member, - Post post - ) { - return ParentComment - .builder() + public ParentComment from(SaveParentCommentRequest request, Member member, Post post) { + return ParentComment.builder() .memberName(member.getUsername()) .content(request.getContent()) .isDeleted(false) diff --git a/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java b/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java index 76341b7..b33e95a 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java +++ b/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java @@ -7,7 +7,6 @@ import aimo.backend.common.exception.ApiException; import aimo.backend.domains.comment.dto.request.SaveChildCommentRequest; -import aimo.backend.domains.comment.dto.request.UpdateChildCommentRequest; import aimo.backend.domains.comment.entity.ChildComment; import aimo.backend.domains.comment.entity.ParentComment; import aimo.backend.domains.comment.mapper.ChildCommentMapper; diff --git a/backend/src/main/java/aimo/backend/domains/member/dto/DeleteRequest.java b/backend/src/main/java/aimo/backend/domains/member/dto/DeleteRequest.java index 05bd749..c55c267 100644 --- a/backend/src/main/java/aimo/backend/domains/member/dto/DeleteRequest.java +++ b/backend/src/main/java/aimo/backend/domains/member/dto/DeleteRequest.java @@ -1,7 +1,4 @@ package aimo.backend.domains.member.dto; -public record DeleteRequest( - String password -) -{ +public record DeleteRequest(String password) { } diff --git a/backend/src/main/java/aimo/backend/domains/member/dto/SignUpRequest.java b/backend/src/main/java/aimo/backend/domains/member/dto/SignUpRequest.java index e00e275..04b3cd3 100644 --- a/backend/src/main/java/aimo/backend/domains/member/dto/SignUpRequest.java +++ b/backend/src/main/java/aimo/backend/domains/member/dto/SignUpRequest.java @@ -10,6 +10,5 @@ public record SignUpRequest( String password, Gender gender, String phoneNumber, - LocalDate birth) -{ + LocalDate birth) { } diff --git a/backend/src/main/java/aimo/backend/domains/member/entity/Member.java b/backend/src/main/java/aimo/backend/domains/member/entity/Member.java index 1541e23..9247ebd 100644 --- a/backend/src/main/java/aimo/backend/domains/member/entity/Member.java +++ b/backend/src/main/java/aimo/backend/domains/member/entity/Member.java @@ -79,7 +79,15 @@ public class Member extends BaseEntity { private List parentComments = new ArrayList<>(); @Builder - private Member(String username, String email, String password, MemberRole memberRole, Gender gender, Provider provider, LocalDate birthDate) { + private Member( + String username, + String email, + String password, + MemberRole memberRole, + Gender gender, + Provider provider, + LocalDate birthDate) { + this.username = username; this.email = email; this.password = password; diff --git a/backend/src/main/java/aimo/backend/domains/member/entity/ProfileImage.java b/backend/src/main/java/aimo/backend/domains/member/entity/ProfileImage.java index 0715b5f..81948a5 100644 --- a/backend/src/main/java/aimo/backend/domains/member/entity/ProfileImage.java +++ b/backend/src/main/java/aimo/backend/domains/member/entity/ProfileImage.java @@ -14,6 +14,7 @@ @Getter @Table(name = "profile_images") public class ProfileImage extends BaseEntity { + @Id @Column(name = "profile_id") @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/backend/src/main/java/aimo/backend/domains/member/entity/RefreshToken.java b/backend/src/main/java/aimo/backend/domains/member/entity/RefreshToken.java index d036294..c68a724 100644 --- a/backend/src/main/java/aimo/backend/domains/member/entity/RefreshToken.java +++ b/backend/src/main/java/aimo/backend/domains/member/entity/RefreshToken.java @@ -11,6 +11,7 @@ @AllArgsConstructor @RedisHash(value = "refreshToken", timeToLive = 1209600) public class RefreshToken { + @Id @Indexed private String accessToken; diff --git a/backend/src/main/java/aimo/backend/domains/member/model/Gender.java b/backend/src/main/java/aimo/backend/domains/member/model/Gender.java index 38cd864..fe29cc9 100644 --- a/backend/src/main/java/aimo/backend/domains/member/model/Gender.java +++ b/backend/src/main/java/aimo/backend/domains/member/model/Gender.java @@ -4,12 +4,15 @@ import com.fasterxml.jackson.annotation.JsonValue; public enum Gender { + MALE("male"), FEMALE("female"); private final String value; - Gender(String value) { this.value = value; } + Gender(String value) { + this.value = value; + } @JsonValue public String getValue() { diff --git a/backend/src/main/java/aimo/backend/domains/member/model/MemberRole.java b/backend/src/main/java/aimo/backend/domains/member/model/MemberRole.java index 93652f9..ee61a85 100644 --- a/backend/src/main/java/aimo/backend/domains/member/model/MemberRole.java +++ b/backend/src/main/java/aimo/backend/domains/member/model/MemberRole.java @@ -4,6 +4,7 @@ @Getter public enum MemberRole { + USER("USER"), ADMIN("ADMIN"); diff --git a/backend/src/main/java/aimo/backend/domains/member/model/Provider.java b/backend/src/main/java/aimo/backend/domains/member/model/Provider.java index 759ebd4..17fe2b2 100644 --- a/backend/src/main/java/aimo/backend/domains/member/model/Provider.java +++ b/backend/src/main/java/aimo/backend/domains/member/model/Provider.java @@ -1,10 +1,12 @@ package aimo.backend.domains.member.model; public enum Provider { + KAKAO("kakao"), AIMO("aimo"); private final String value; + Provider(String value) { this.value = value; } diff --git a/backend/src/main/java/aimo/backend/domains/member/repository/MemberRepository.java b/backend/src/main/java/aimo/backend/domains/member/repository/MemberRepository.java index d04773e..d49f089 100644 --- a/backend/src/main/java/aimo/backend/domains/member/repository/MemberRepository.java +++ b/backend/src/main/java/aimo/backend/domains/member/repository/MemberRepository.java @@ -7,6 +7,8 @@ import java.util.Optional; public interface MemberRepository extends JpaRepository { - Optional findByEmail(String email); - void deleteMemberByEmail(String email); + + Optional findByEmail(String email); + + void deleteMemberByEmail(String email); } diff --git a/backend/src/main/java/aimo/backend/domains/member/repository/RefreshTokenRepository.java b/backend/src/main/java/aimo/backend/domains/member/repository/RefreshTokenRepository.java index f2ae07e..b0d263e 100644 --- a/backend/src/main/java/aimo/backend/domains/member/repository/RefreshTokenRepository.java +++ b/backend/src/main/java/aimo/backend/domains/member/repository/RefreshTokenRepository.java @@ -11,6 +11,8 @@ public interface RefreshTokenRepository extends CrudRepository { Optional findByAccessToken(String accessToken); + boolean existsByAccessToken(String accessToken); + void deleteByAccessToken(String accessToken); } diff --git a/backend/src/main/java/aimo/backend/domains/member/service/MemberService.java b/backend/src/main/java/aimo/backend/domains/member/service/MemberService.java index ef75692..3416abb 100644 --- a/backend/src/main/java/aimo/backend/domains/member/service/MemberService.java +++ b/backend/src/main/java/aimo/backend/domains/member/service/MemberService.java @@ -24,66 +24,65 @@ @Transactional(readOnly = true) public class MemberService { - private final MemberRepository memberRepository; - private final RefreshTokenService refreshTokenService; - private final MemberMapper memberMapper; - private final JwtTokenProvider jwtTokenProvider; - private final PasswordEncoder passwordEncoder; - - // 이메일로 멤버 조회 - public Optional findByEmail(String email) { - return memberRepository.findByEmail(email); - } - - // 회원 가입 - @Transactional - public void signUp(SignUpRequest signUpRequest) { - if(isDuplicateEmail(signUpRequest.email())){ - throw ApiException.from(ErrorCode.EMAIL_DUPLICATE); - } - - Member member = memberMapper.signUpMemberEntity(signUpRequest); - memberRepository.save(member); - } - - - //로그아웃 - @Transactional - public void logoutMember(String accessToken, String refreshToken) { - // 회원의 refreshToken 만료 처리 - RefreshToken expiredToken = new RefreshToken(accessToken, refreshToken); - refreshTokenService.save(expiredToken); - log.info("Logout successful {}", refreshTokenService.existsByAccessToken(accessToken)); - } - - @Transactional - public void deleteMember(String accessToken, DeleteRequest deleteRequest) { - Long memberId = jwtTokenProvider - .extractMemberId(accessToken) - .orElseThrow(() -> ApiException.from(ErrorCode.INVALID_ACCESS_TOKEN)); - - Member member = memberRepository - .findById(memberId) - .orElseThrow(() -> ApiException.from(ErrorCode.MEMBER_NOT_FOUND)); - - if(!isValid(deleteRequest.password(), member.getPassword())){ - throw ApiException.from(ErrorCode.INVALID_PASSWORD); - } - - memberRepository.delete(member); - } - - public Member findById(Long memberId) { - return memberRepository - .findById(memberId) - .orElseThrow(() -> ApiException.from(ErrorCode.MEMBER_NOT_FOUND)); - } - - protected boolean isDuplicateEmail(String email) { - return memberRepository.findByEmail(email).isPresent(); - } - - protected boolean isValid(String password, String encodedPassword) { - return passwordEncoder.matches(password, encodedPassword); - } + private final MemberRepository memberRepository; + private final RefreshTokenService refreshTokenService; + private final MemberMapper memberMapper; + private final JwtTokenProvider jwtTokenProvider; + private final PasswordEncoder passwordEncoder; + + // 이메일로 멤버 조회 + public Optional findByEmail(String email) { + return memberRepository.findByEmail(email); + } + + // 회원 가입 + @Transactional + public void signUp(SignUpRequest signUpRequest) { + if (isDuplicateEmail(signUpRequest.email())) { + throw ApiException.from(ErrorCode.EMAIL_DUPLICATE); + } + + Member member = memberMapper.signUpMemberEntity(signUpRequest); + memberRepository.save(member); + } + + //로그아웃 + @Transactional + public void logoutMember(String accessToken, String refreshToken) { + // 회원의 refreshToken 만료 처리 + RefreshToken expiredToken = new RefreshToken(accessToken, refreshToken); + refreshTokenService.save(expiredToken); + log.info("Logout successful {}", refreshTokenService.existsByAccessToken(accessToken)); + } + + @Transactional + public void deleteMember(String accessToken, DeleteRequest deleteRequest) { + Long memberId = jwtTokenProvider + .extractMemberId(accessToken) + .orElseThrow(() -> ApiException.from(ErrorCode.INVALID_ACCESS_TOKEN)); + + Member member = memberRepository + .findById(memberId) + .orElseThrow(() -> ApiException.from(ErrorCode.MEMBER_NOT_FOUND)); + + if (!isValid(deleteRequest.password(), member.getPassword())) { + throw ApiException.from(ErrorCode.INVALID_PASSWORD); + } + + memberRepository.delete(member); + } + + public Member findById(Long memberId) { + return memberRepository + .findById(memberId) + .orElseThrow(() -> ApiException.from(ErrorCode.MEMBER_NOT_FOUND)); + } + + protected boolean isDuplicateEmail(String email) { + return memberRepository.findByEmail(email).isPresent(); + } + + protected boolean isValid(String password, String encodedPassword) { + return passwordEncoder.matches(password, encodedPassword); + } } diff --git a/backend/src/main/java/aimo/backend/domains/member/service/RefreshTokenService.java b/backend/src/main/java/aimo/backend/domains/member/service/RefreshTokenService.java index d20d6bd..8397df9 100644 --- a/backend/src/main/java/aimo/backend/domains/member/service/RefreshTokenService.java +++ b/backend/src/main/java/aimo/backend/domains/member/service/RefreshTokenService.java @@ -23,6 +23,7 @@ public Optional findByAccessToken(String accessToken) { public void save(RefreshToken refreshToken) { refreshTokenRepository.save(refreshToken); } + public Optional findByToken(String token) { return refreshTokenRepository.findById(token); } @@ -31,5 +32,7 @@ public void deleteByAccessToken(String accessToken) { refreshTokenRepository.deleteByAccessToken(accessToken); } - public boolean existsByAccessToken(String accessToken) { return refreshTokenRepository.existsByAccessToken(accessToken); } + public boolean existsByAccessToken(String accessToken) { + return refreshTokenRepository.existsByAccessToken(accessToken); + } } diff --git a/backend/src/main/java/aimo/backend/domains/post/controller/PostController.java b/backend/src/main/java/aimo/backend/domains/post/controller/PostController.java new file mode 100644 index 0000000..264395b --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/controller/PostController.java @@ -0,0 +1,32 @@ +package aimo.backend.domains.post.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import aimo.backend.common.dto.DataResponse; +import aimo.backend.domains.post.dto.SavePostRequest; +import aimo.backend.domains.post.service.PostService; +import aimo.backend.util.memberLoader.MemberLoader; +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/api/v1/posts") +@RequiredArgsConstructor +public class PostController { + + private final PostService postService; + private final MemberLoader memberLoader; + + @PostMapping("/{private_post_id}") + public ResponseEntity> publish(@RequestBody SavePostRequest publishPostRequest) { + postService.save(publishPostRequest, memberLoader.getMember()); + return ResponseEntity.status(HttpStatus.CREATED).body(DataResponse.created()); + } +} diff --git a/backend/src/main/java/aimo/backend/domains/post/dto/GetPostResponse.java b/backend/src/main/java/aimo/backend/domains/post/dto/GetPostResponse.java new file mode 100644 index 0000000..6a838e0 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/dto/GetPostResponse.java @@ -0,0 +1,4 @@ +package aimo.backend.domains.post.dto; + +public record GetPostResponse() { +} diff --git a/backend/src/main/java/aimo/backend/domains/post/dto/PostListResponse.java b/backend/src/main/java/aimo/backend/domains/post/dto/PostListResponse.java new file mode 100644 index 0000000..76edbb2 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/dto/PostListResponse.java @@ -0,0 +1,6 @@ +package aimo.backend.domains.post.dto; + +import java.util.List; + +public record PostListResponse(List postPreviews) { +} diff --git a/backend/src/main/java/aimo/backend/domains/post/dto/PostPreviewResponse.java b/backend/src/main/java/aimo/backend/domains/post/dto/PostPreviewResponse.java new file mode 100644 index 0000000..23ea505 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/dto/PostPreviewResponse.java @@ -0,0 +1,24 @@ +package aimo.backend.domains.post.dto; + +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; + +public record PostPreviewResponse( + @JsonProperty("post_id") + Long postId, + @JsonProperty("title") + String title, + @JsonProperty("content_preview") + String contentPreview, + @JsonProperty("likes_count") + Integer likesCount, + @JsonProperty("views_count") + Integer viewsCount, + @JsonProperty("comments_count") + Integer commentsCount, + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime createdAt +) { +} diff --git a/backend/src/main/java/aimo/backend/domains/post/dto/SavePostRequest.java b/backend/src/main/java/aimo/backend/domains/post/dto/SavePostRequest.java new file mode 100644 index 0000000..652c6ab --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/dto/SavePostRequest.java @@ -0,0 +1,34 @@ +package aimo.backend.domains.post.dto; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; + +import aimo.backend.domains.post.model.Category; +import aimo.backend.domains.privatePost.model.OriginType; +import jakarta.validation.constraints.NotNull; + +public record SavePostRequest( + @NotNull(message = "privatePostId is null") + Long privatePostId, + @NotNull(message = "categoryId is null") + String title, + @NotNull(message = "summaryAi is null") + String stancePlaintiff, + @NotNull(message = "stanceDefendant is null") + String stanceDefendant, + @NotNull(message = "summaryAi is null") + String summaryAi, + @NotNull(message = "judgement is null") + String judgement, + @NotNull(message = "originType is null") + OriginType originType, + @JsonSetter(nulls = Nulls.SKIP) + Category category +) { + + public SavePostRequest { + if (category == null) + category = Category.COMMON; + } + +} diff --git a/backend/src/main/java/aimo/backend/domains/post/dto/SinglePostResponse.java b/backend/src/main/java/aimo/backend/domains/post/dto/SinglePostResponse.java new file mode 100644 index 0000000..59625b7 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/dto/SinglePostResponse.java @@ -0,0 +1,30 @@ +package aimo.backend.domains.post.dto; + +import java.time.LocalDateTime; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; + +import aimo.backend.domains.comment.dto.response.CommentResponse; + +public record SinglePostResponse( + String title, + String username, + String content, + @JsonProperty("votes_plaintiff") + Long votesPlaintiff, + @JsonProperty("votes_defendant") + Long votesDefendant, + Long likes, + @JsonProperty("views_count") + Long viewsCount, + @JsonProperty("votes_count") + Long votesCount, + @JsonProperty("comments_count") + Long commentsCount, + @JsonProperty("comments") + List comments, + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime createdAt) { +} diff --git a/backend/src/main/java/aimo/backend/domains/post/entity/Post.java b/backend/src/main/java/aimo/backend/domains/post/entity/Post.java index 188d6aa..dbdfbf9 100644 --- a/backend/src/main/java/aimo/backend/domains/post/entity/Post.java +++ b/backend/src/main/java/aimo/backend/domains/post/entity/Post.java @@ -6,10 +6,12 @@ import java.util.List; import aimo.backend.common.entity.BaseEntity; +import aimo.backend.domains.post.model.Side; import aimo.backend.domains.privatePost.entity.PrivatePost; import aimo.backend.domains.member.entity.Member; import aimo.backend.domains.comment.entity.ParentComment; import aimo.backend.domains.post.model.Category; +import aimo.backend.domains.privatePost.model.OriginType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -22,6 +24,7 @@ import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -31,7 +34,8 @@ @NoArgsConstructor(access = PROTECTED) public class Post extends BaseEntity { - @Id @GeneratedValue + @Id + @GeneratedValue @Column(name = "post_id") private Long id; @@ -42,19 +46,90 @@ public class Post extends BaseEntity { @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, orphanRemoval = true, cascade = ALL) private List parentComments; - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "dispute_id") - private PrivatePost privatePost; + @JoinColumn(name = "origin_private_post_id") + private Long privatePostId; @Column(nullable = false) private String title; - @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 2500) + private String summaryAi; + + @Column(nullable = false, length = 2500) + private String stancePlaintiff; + + @Column(nullable = false, length = 2500) + private String stanceDefendant; + @Column(nullable = false) + private OriginType originType; + + @Column(nullable = false, length = 2500) + private String judgement; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, columnDefinition = "VARCHAR(100) DEFAULT 'COMMON'") private Category category; + @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, orphanRemoval = true, cascade = ALL) + private List postLikes; + + @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, orphanRemoval = true, cascade = ALL) + private List postViews; + + @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, orphanRemoval = true, cascade = ALL) + private List votes; + public void setAuthor(Member member) { this.member = member; member.getPosts().add(this); } + + public Integer getCommentsCount() { + return parentComments + .stream() + .map(ParentComment::getCommentsCount) + .reduce(1, Integer::sum); + } + + public void deletePost() { + this.member.getPosts().remove(this); + this.member = null; + } + + public Long getPlaintiffVotesCount() { + return votes + .stream() + .filter(vote -> vote.getSide() == Side.PLAINTIFF) + .count(); + } + + public Long getVotesCount() { + return votes + .stream() + .count(); + } + + @Builder + public Post( + Long privatePostId, + Member member, + String title, + String summaryAi, + String stancePlaintiff, + String stanceDefendant, + String judgement, + OriginType originType, + Category category) { + + this.privatePostId = privatePostId; + this.member = member; + this.title = title; + this.summaryAi = summaryAi; + this.judgement = judgement; + this.stancePlaintiff = stancePlaintiff; + this.stanceDefendant = stanceDefendant; + this.originType = originType; + this.category = category; + } } diff --git a/backend/src/main/java/aimo/backend/domains/post/entity/PostLike.java b/backend/src/main/java/aimo/backend/domains/post/entity/PostLike.java index 24daa3a..1dd4084 100644 --- a/backend/src/main/java/aimo/backend/domains/post/entity/PostLike.java +++ b/backend/src/main/java/aimo/backend/domains/post/entity/PostLike.java @@ -17,7 +17,7 @@ @Table( name = "post_likes", uniqueConstraints = { - @UniqueConstraint(columnNames = { "post_id", "member_id" }) + @UniqueConstraint(columnNames = {"post_id", "member_id"}) }) @NoArgsConstructor(access = PROTECTED) public class PostLike extends Like { diff --git a/backend/src/main/java/aimo/backend/domains/post/entity/PostView.java b/backend/src/main/java/aimo/backend/domains/post/entity/PostView.java new file mode 100644 index 0000000..b050a29 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/entity/PostView.java @@ -0,0 +1,48 @@ +package aimo.backend.domains.post.entity; + +import static lombok.AccessLevel.*; + +import aimo.backend.common.entity.BaseEntity; +import aimo.backend.domains.member.entity.Member; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table( + name = "post_views", + uniqueConstraints = { + @UniqueConstraint(columnNames = {"post_id", "member_id"}) + }) +@NoArgsConstructor(access = PROTECTED) +public class PostView extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "view_id") + private Long viewId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Builder + PostView(Post post, Member member) { + this.post = post; + this.member = member; + } +} diff --git a/backend/src/main/java/aimo/backend/domains/post/entity/Vote.java b/backend/src/main/java/aimo/backend/domains/post/entity/Vote.java new file mode 100644 index 0000000..7e8b563 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/entity/Vote.java @@ -0,0 +1,46 @@ +package aimo.backend.domains.post.entity; + +import static lombok.AccessLevel.*; + +import aimo.backend.common.entity.BaseEntity; +import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.post.model.Side; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table( + name = "votes", + uniqueConstraints = { + @UniqueConstraint(columnNames = {"post_id", "member_id"}) + }) +@NoArgsConstructor(access = PROTECTED) +public class Vote extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "vote_id") + private Long voteId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Column(nullable = false) + private Side side; +} diff --git a/backend/src/main/java/aimo/backend/domains/post/model/Side.java b/backend/src/main/java/aimo/backend/domains/post/model/Side.java new file mode 100644 index 0000000..e47c10f --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/model/Side.java @@ -0,0 +1,14 @@ +package aimo.backend.domains.post.model; + +import lombok.Getter; + +public enum Side { + PLAINTIFF("원고"), + DEFENDANT("피고"); + + private final String value; + + Side(String value) { + this.value = value; + } +} diff --git a/backend/src/main/java/aimo/backend/domains/post/repository/PostLikeRepository.java b/backend/src/main/java/aimo/backend/domains/post/repository/PostLikeRepository.java new file mode 100644 index 0000000..0e3d4f4 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/repository/PostLikeRepository.java @@ -0,0 +1,11 @@ +package aimo.backend.domains.post.repository; + +import java.beans.JavaBean; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import aimo.backend.domains.post.entity.PostLike; + +public interface PostLikeRepository extends JpaRepository { +} diff --git a/backend/src/main/java/aimo/backend/domains/post/repository/PostRepository.java b/backend/src/main/java/aimo/backend/domains/post/repository/PostRepository.java index d0dbaa1..c94f7a3 100644 --- a/backend/src/main/java/aimo/backend/domains/post/repository/PostRepository.java +++ b/backend/src/main/java/aimo/backend/domains/post/repository/PostRepository.java @@ -1,6 +1,7 @@ package aimo.backend.domains.post.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import aimo.backend.domains.post.entity.Post; diff --git a/backend/src/main/java/aimo/backend/domains/post/repository/PostViewRepository.java b/backend/src/main/java/aimo/backend/domains/post/repository/PostViewRepository.java new file mode 100644 index 0000000..27cc9d5 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/repository/PostViewRepository.java @@ -0,0 +1,9 @@ +package aimo.backend.domains.post.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import aimo.backend.domains.post.entity.PostView; + +public interface PostViewRepository extends JpaRepository { +} diff --git a/backend/src/main/java/aimo/backend/domains/post/repository/VoteRepsoitory.java b/backend/src/main/java/aimo/backend/domains/post/repository/VoteRepsoitory.java new file mode 100644 index 0000000..8807371 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/post/repository/VoteRepsoitory.java @@ -0,0 +1,9 @@ +package aimo.backend.domains.post.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import aimo.backend.domains.post.entity.Vote; + +public interface VoteRepsoitory extends JpaRepository { +} diff --git a/backend/src/main/java/aimo/backend/domains/post/service/PostService.java b/backend/src/main/java/aimo/backend/domains/post/service/PostService.java index 77545fe..b812e4f 100644 --- a/backend/src/main/java/aimo/backend/domains/post/service/PostService.java +++ b/backend/src/main/java/aimo/backend/domains/post/service/PostService.java @@ -1,12 +1,13 @@ package aimo.backend.domains.post.service; -import static aimo.backend.common.exception.ErrorCode.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import aimo.backend.common.exception.ApiException; -import aimo.backend.domains.post.entity.Post; +import aimo.backend.common.mapper.PostMapper; +import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.service.MemberService; +import aimo.backend.domains.post.dto.SavePostRequest; import aimo.backend.domains.post.repository.PostRepository; import lombok.RequiredArgsConstructor; @@ -17,8 +18,7 @@ public class PostService { private final PostRepository postRepository; - public Post findById(Long id) { - return postRepository.findById(id) - .orElseThrow(() -> ApiException.from(POST_NOT_FOUND)); + public void save(SavePostRequest savePostRequest, Member member) { + postRepository.save(PostMapper.toEntity(savePostRequest, member)); } } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java b/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java index 057060c..6f29ecb 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java @@ -6,10 +6,8 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.data.web.PageableDefault; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -23,26 +21,26 @@ import aimo.backend.common.dto.DataResponse; import aimo.backend.common.exception.ApiException; import aimo.backend.common.exception.ErrorCode; -import aimo.backend.common.mapper.PrivatePostMapper; import aimo.backend.domains.auth.security.jwtFilter.JwtTokenProviderImpl; import aimo.backend.domains.member.entity.Member; import aimo.backend.domains.member.service.MemberService; import aimo.backend.domains.privatePost.dto.PrivatePostPreviewResponse; import aimo.backend.domains.privatePost.dto.PrivatePostResponse; import aimo.backend.domains.privatePost.dto.SummaryAndJudgementRequest; +import aimo.backend.domains.privatePost.dto.SummaryAndJudgementResponse; import aimo.backend.domains.privatePost.dto.TextRecordRequest; -import aimo.backend.domains.privatePost.dto.UploadAudioSuccessRequest; -import aimo.backend.domains.privatePost.entity.PrivatePost; +import aimo.backend.domains.privatePost.dto.SaveAudioSuccessRequest; import aimo.backend.domains.privatePost.service.AudioRecordService; import aimo.backend.domains.privatePost.service.ChatRecordService; import aimo.backend.domains.privatePost.service.TextRecordService; import aimo.backend.domains.privatePost.service.PrivatePostService; +import aimo.backend.util.memberLoader.MemberLoader; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j @RestController -@RequestMapping("/api/private-post") +@RequestMapping("/api/private-posts") @RequiredArgsConstructor public class PrivatePostController { @@ -50,11 +48,10 @@ public class PrivatePostController { private final PrivatePostService privatePostService; private final TextRecordService textRecordService; private final ChatRecordService chatRecordService; - private final MemberService memberService; - private final JwtTokenProviderImpl jwtTokenProviderImpl; + private final MemberLoader memberLoader; @GetMapping("/upload/audio/presigned") - public ResponseEntity> getPresignedUrlTo(@RequestParam("file") MultipartFile file) { + public ResponseEntity> getPresignedUrlTo(@RequestParam("file") MultipartFile file) { return ResponseEntity .status(HttpStatus.CREATED) .body(DataResponse.created()); @@ -62,9 +59,9 @@ public ResponseEntity> getPresignedUrlTo(@RequestParam("file" @PostMapping("/upload/audio/success") public ResponseEntity> saveAudioRecord( - @RequestBody UploadAudioSuccessRequest uploadAudioSuccessRequest + @RequestBody SaveAudioSuccessRequest saveAudioSuccessRequest ) { - audioRecordService.save(uploadAudioSuccessRequest); + audioRecordService.save(saveAudioSuccessRequest); return ResponseEntity .status(HttpStatus.CREATED) .body(DataResponse.created()); @@ -72,29 +69,16 @@ public ResponseEntity> saveAudioRecord( @PostMapping("/judgement") public ResponseEntity> judgement( - @RequestHeader("Authorization") String accessToken, @RequestBody TextRecordRequest textRecordRequest ) { - Long memberId = jwtTokenProviderImpl - .extractMemberId(accessToken) - .orElseThrow(() -> ApiException.from(ErrorCode.INVALID_ACCESS_TOKEN)); - - Member member = memberService.findById(memberId); - - SummaryAndJudgementRequest summaryAndJudgementRequest = - new SummaryAndJudgementRequest( - textRecordRequest.title(), - textRecordRequest.script(), - member.getUsername(), - member.getGender(), - member.getBirthDate() - ); - - return privatePostService - .serveScriptToAi(summaryAndJudgementRequest) - .blockOptional() - .map(response -> ResponseEntity.status(HttpStatus.CREATED).body(DataResponse.created())) - .orElseThrow(() -> ApiException.from(ErrorCode.AI_BAD_GATEWAY)); + + SummaryAndJudgementResponse summaryAndJudgementResponse = + privatePostService.serveScriptToAi(textRecordRequest); + + privatePostService.save(summaryAndJudgementResponse); + + return ResponseEntity.status(HttpStatus.CREATED) + .body(DataResponse.created()); } @PostMapping("/upload/text") @@ -102,8 +86,7 @@ public ResponseEntity> uploadTextRecord( @RequestBody TextRecordRequest textRecordRequest ) { textRecordService.save(textRecordRequest); - return ResponseEntity - .status(HttpStatus.CREATED) + return ResponseEntity.status(HttpStatus.CREATED) .body(DataResponse.created()); } @@ -112,8 +95,7 @@ public ResponseEntity> uploadChatRecord( @RequestParam("chat_record") MultipartFile file ) throws IOException { chatRecordService.save(file); - return ResponseEntity - .status(HttpStatus.CREATED) + return ResponseEntity.status(HttpStatus.CREATED) .body(DataResponse.created()); } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java new file mode 100644 index 0000000..bcd3869 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java @@ -0,0 +1,18 @@ +package aimo.backend.domains.privatePost.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import jakarta.validation.constraints.NotNull; + +public record SaveAudioSuccessRequest( + @NotNull(message = "URL이 필요합니다.") + String url, + @NotNull(message = "파일 사이즈가 필요합니다.") + Long size, + @JsonProperty("filename") + @NotNull(message = "파일 이름이 필요합니다.") + String filename, + @JsonProperty("extension") + @NotNull(message = "파일 확장자가 필요합니다.") + String extension +) { } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java index 4a1df1c..912cbac 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java @@ -1,6 +1,7 @@ package aimo.backend.domains.privatePost.dto; import java.time.LocalDate; + import aimo.backend.domains.member.model.Gender; public record SummaryAndJudgementRequest( diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementResponse.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementResponse.java index 00e76a5..c343cca 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementResponse.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementResponse.java @@ -6,24 +6,12 @@ import jakarta.validation.constraints.NotNull; public record SummaryAndJudgementResponse( - @NotNull(message = "Title is required") String title, - @NotNull(message = "Stance of plaintiff is required") - @JsonProperty("stance_plaintiff") String stancePlaintiff, - @NotNull(message = "Stance of defendant is required") - @JsonProperty("stance_defendant") String stanceDefendant, - @NotNull(message = "Summary of AI is required") - @JsonProperty("summary_ai") String summaryAi, - @NotNull(message = "Judgement is required") String judgement, - @NotNull(message = "Origin type is required") - @JsonProperty("fault_rate") Double faultRate, - @NotNull(message = "Origin type is required") - @JsonProperty("origin_type") OriginType originType ) { } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/TextRecordRequest.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/TextRecordRequest.java index b37f34d..5ef4d76 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/dto/TextRecordRequest.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/dto/TextRecordRequest.java @@ -3,9 +3,9 @@ import jakarta.validation.constraints.NotNull; public record TextRecordRequest( - @NotNull(message = "Title is required") + @NotNull(message = "제목을 입력하세요.") String title, - @NotNull(message = "Stance of plaintiff is required") + @NotNull(message = "내용을 입력하세요.") String script ) { } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/UploadAudioSuccessRequest.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/UploadAudioSuccessRequest.java deleted file mode 100644 index 8529a52..0000000 --- a/backend/src/main/java/aimo/backend/domains/privatePost/dto/UploadAudioSuccessRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package aimo.backend.domains.privatePost.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import jakarta.validation.constraints.NotNull; - -public record UploadAudioSuccessRequest( - @NotNull(message = "Audio file url is required") - String url, - @NotNull(message = "Audio file size is required") - Long size, - @JsonProperty("filename") - @NotNull(message = "Audio file file name is required") - String filename, - @JsonProperty("extension") - String extension -) { -} diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/entity/AudioRecord.java b/backend/src/main/java/aimo/backend/domains/privatePost/entity/AudioRecord.java index 3dc4451..4f24ff3 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/entity/AudioRecord.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/entity/AudioRecord.java @@ -19,7 +19,8 @@ @NoArgsConstructor(access = PROTECTED) public class AudioRecord extends BaseEntity { - @Id @GeneratedValue + @Id + @GeneratedValue @Column(name = "audio_record_id") private Long id; diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/entity/ChatRecord.java b/backend/src/main/java/aimo/backend/domains/privatePost/entity/ChatRecord.java index f87e58e..42c22e6 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/entity/ChatRecord.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/entity/ChatRecord.java @@ -18,7 +18,8 @@ @Getter @NoArgsConstructor(access = PROTECTED) public class ChatRecord extends BaseEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "chat_record_id") private Long id; diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/entity/PrivatePost.java b/backend/src/main/java/aimo/backend/domains/privatePost/entity/PrivatePost.java index 783784e..90d80bc 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/entity/PrivatePost.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/entity/PrivatePost.java @@ -25,7 +25,8 @@ @Table(name = "disputes") @NoArgsConstructor(access = PROTECTED) public class PrivatePost extends BaseEntity { - @Id @GeneratedValue + @Id + @GeneratedValue @Column(name = "private_post_id") private Long id; @@ -78,8 +79,7 @@ private PrivatePost( TextRecord textRecord, OriginType originType, Double faultRate, - Boolean published) - { + Boolean published) { this.title = title; this.member = member; this.stancePlaintiff = stancePlaintiff; diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/entity/TextRecord.java b/backend/src/main/java/aimo/backend/domains/privatePost/entity/TextRecord.java index 698b365..e9f8a21 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/entity/TextRecord.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/entity/TextRecord.java @@ -16,7 +16,8 @@ @Table(name = "text_records") @NoArgsConstructor public class TextRecord extends BaseEntity { - @Id @GeneratedValue + @Id + @GeneratedValue @Column(name = "text_record_id") private Long id; diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/repository/ChatRecordRepository.java b/backend/src/main/java/aimo/backend/domains/privatePost/repository/ChatRecordRepository.java index de137d7..3c1a077 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/repository/ChatRecordRepository.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/repository/ChatRecordRepository.java @@ -1,6 +1,7 @@ package aimo.backend.domains.privatePost.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import aimo.backend.domains.privatePost.entity.ChatRecord; diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/service/AudioRecordService.java b/backend/src/main/java/aimo/backend/domains/privatePost/service/AudioRecordService.java index f4d2f25..c61796d 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/service/AudioRecordService.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/service/AudioRecordService.java @@ -5,7 +5,7 @@ import aimo.backend.common.exception.ApiException; import aimo.backend.common.mapper.AudioRecordMapper; -import aimo.backend.domains.privatePost.dto.UploadAudioSuccessRequest; +import aimo.backend.domains.privatePost.dto.SaveAudioSuccessRequest; import aimo.backend.domains.privatePost.repository.AudioRecordRepository; import lombok.RequiredArgsConstructor; @@ -17,7 +17,7 @@ public class AudioRecordService { private final AudioRecordRepository audioRecordRepository; @Transactional(rollbackFor = ApiException.class) - public void save(UploadAudioSuccessRequest uploadAudioSuccessRequest) { - audioRecordRepository.save(AudioRecordMapper.toEntity(uploadAudioSuccessRequest)); + public void save(SaveAudioSuccessRequest saveAudioSuccessRequest) { + audioRecordRepository.save(AudioRecordMapper.toEntity(saveAudioSuccessRequest)); } } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java b/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java index bf8b873..64d8e13 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java @@ -29,18 +29,21 @@ public class ChatRecordService { @Transactional(rollbackFor = ApiException.class) public Long save(MultipartFile file) throws IOException { String originalFilename = file.getOriginalFilename(); - if(originalFilename == null) throw ApiException.from(ErrorCode.INVALID_FILE_NAME); + if (originalFilename == null) + throw ApiException.from(ErrorCode.INVALID_FILE_NAME); List parts = Arrays .stream(originalFilename.split("\\.")) .toList(); - if(parts.size() <= 1) throw ApiException.from(ErrorCode.INVALID_FILE_NAME); + if (parts.size() <= 1) + throw ApiException.from(ErrorCode.INVALID_FILE_NAME); String filename = String.join(".", parts.subList(0, parts.size() - 1)); String extension = parts.get(parts.size() - 1); - if(!Objects.equals(extension, "txt")) throw ApiException.from(ErrorCode.INVALID_FILE_EXTENSION); + if (!Objects.equals(extension, "txt")) + throw ApiException.from(ErrorCode.INVALID_FILE_EXTENSION); String script = StreamUtils .copyToString(file.getInputStream(), StandardCharsets.UTF_8); diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java b/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java index 357db62..bddaabd 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java @@ -31,6 +31,7 @@ import aimo.backend.domains.privatePost.dto.TextRecordRequest; import aimo.backend.domains.privatePost.entity.PrivatePost; import aimo.backend.domains.privatePost.repository.PrivatePostRepository; +import aimo.backend.util.memberLoader.MemberLoader; import lombok.RequiredArgsConstructor; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; @@ -43,34 +44,43 @@ public class PrivatePostService { private final PrivatePostRepository privatePostRepository; private final WebClient webClient; private final AiServerProperties aiServerProperties; - private final JwtTokenProviderImpl jwtTokenProvider; - private final MemberService memberService; + private final MemberLoader memberLoader; @Transactional(rollbackFor = ApiException.class) - public Mono> serveScriptToAi( - SummaryAndJudgementRequest summaryAndJudgementRequest + public SummaryAndJudgementResponse serveScriptToAi( + TextRecordRequest textRecordRequest ) { + Member member = memberLoader.getMember(); + + SummaryAndJudgementRequest summaryAndJudgementRequest = + new SummaryAndJudgementRequest( + textRecordRequest.title(), + textRecordRequest.script(), + member.getUsername(), + member.getGender(), + member.getBirthDate() + ); + return webClient - .post() - .uri(aiServerProperties.getDomainUrl() + aiServerProperties.getJudgementApi()) - .bodyValue(summaryAndJudgementRequest) - .retrieve() - .onStatus(HttpStatusCode::is4xxClientError, clientResponse -> { - throw ApiException.from(ErrorCode.AI_BAD_GATEWAY); - }) - .onStatus(HttpStatusCode::is5xxServerError, clientResponse -> { - throw ApiException.from(ErrorCode.AI_SEVER_ERROR); - }) - .bodyToMono(new ParameterizedTypeReference>() {}) - .flatMap(response -> save(response.getData())) - .then(Mono.just(DataResponse.created())); + .post() + .uri(aiServerProperties.getDomainUrl() + aiServerProperties.getJudgementApi()) + .bodyValue(summaryAndJudgementRequest) + .retrieve() + .onStatus(HttpStatusCode::is4xxClientError, clientResponse -> { + throw ApiException.from(ErrorCode.AI_BAD_GATEWAY); + }) + .onStatus(HttpStatusCode::is5xxServerError, clientResponse -> { + throw ApiException.from(ErrorCode.AI_SEVER_ERROR); + }) + .bodyToMono(new ParameterizedTypeReference() { + }) + .block(); } @Transactional(rollbackFor = ApiException.class) - public Mono save(SummaryAndJudgementResponse summaryAndJudgementResponse) { + public PrivatePost save(SummaryAndJudgementResponse summaryAndJudgementResponse) { PrivatePost privatePost = PrivatePostMapper.toEntity(summaryAndJudgementResponse); - return Mono.fromCallable(() -> privatePostRepository.save(privatePost)) - .subscribeOn(Schedulers.boundedElastic()); + return privatePostRepository.save(privatePost); } public PrivatePostResponse getPrivatePost(Long id) { @@ -88,14 +98,19 @@ public Page getPrivatePostPreviews( Page privatePostPage = privatePostRepository .findAll(pageable); - return new PageImpl<> ( + return new PageImpl<>( privatePostPage - .getContent() - .stream() - .map(PrivatePostMapper::toPreviewResponse) - .collect(Collectors.toList()), + .getContent() + .stream() + .map(PrivatePostMapper::toPreviewResponse) + .collect(Collectors.toList()), pageable, privatePostPage.getTotalPages() - ); + ); + } + + public PrivatePost findById(Long id) { + return privatePostRepository.findById(id) + .orElseThrow(() -> ApiException.from(PRIVATE_POST_NOT_FOUND)); } } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java b/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java index 8f857dc..9b37e81 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java @@ -19,7 +19,7 @@ public class TextRecordService { private final TextRecordRepository textRecordRepository; @Transactional(rollbackFor = Exception.class) - public ResponseEntity> save(TextRecordRequest textRecordRequest){ + public ResponseEntity> save(TextRecordRequest textRecordRequest) { TextRecord textRecord = TextRecord .builder() .title(textRecordRequest.title()) diff --git a/backend/src/main/java/aimo/backend/util/encoder/PasswordEncoderUtil.java b/backend/src/main/java/aimo/backend/util/encoder/PasswordEncoderUtil.java index 4fa1ac2..1bdeadd 100644 --- a/backend/src/main/java/aimo/backend/util/encoder/PasswordEncoderUtil.java +++ b/backend/src/main/java/aimo/backend/util/encoder/PasswordEncoderUtil.java @@ -7,7 +7,7 @@ @Service @RequiredArgsConstructor -public class PasswordEncoderUtil { +public class PasswordEncoderUtil { private final PasswordEncoder passwordEncoder; diff --git a/backend/src/main/java/aimo/backend/util/memberLoader/MemberLoader.java b/backend/src/main/java/aimo/backend/util/memberLoader/MemberLoader.java index 8051948..cc8650d 100644 --- a/backend/src/main/java/aimo/backend/util/memberLoader/MemberLoader.java +++ b/backend/src/main/java/aimo/backend/util/memberLoader/MemberLoader.java @@ -1,6 +1,5 @@ package aimo.backend.util.memberLoader; - import static aimo.backend.common.exception.ErrorCode.*; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/backend/src/main/java/aimo/backend/util/responseWriter/ResponseWriter.java b/backend/src/main/java/aimo/backend/util/responseWriter/ResponseWriter.java index 5d3b555..2345008 100644 --- a/backend/src/main/java/aimo/backend/util/responseWriter/ResponseWriter.java +++ b/backend/src/main/java/aimo/backend/util/responseWriter/ResponseWriter.java @@ -12,26 +12,26 @@ public class ResponseWriter { - private static final String CONTENT_TYPE = "application/json"; - private static final String CHARACTER_ENCODING = "utf-8"; - private static final ObjectMapper objectMapper = new ObjectMapper(); - - public static void writeResponse( - HttpServletResponse response, - BaseResponse dataResponse, - HttpStatusCode statusCode - ) { - response.setContentType(CONTENT_TYPE); - response.setCharacterEncoding(CHARACTER_ENCODING); - objectMapper.registerModule(new JavaTimeModule()); - response.setStatus(statusCode.value()); - - try { - String result = objectMapper.writeValueAsString(dataResponse); - response.getWriter().write(result); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + private static final String CONTENT_TYPE = "application/json"; + private static final String CHARACTER_ENCODING = "utf-8"; + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static void writeResponse( + HttpServletResponse response, + BaseResponse dataResponse, + HttpStatusCode statusCode + ) { + response.setContentType(CONTENT_TYPE); + response.setCharacterEncoding(CHARACTER_ENCODING); + objectMapper.registerModule(new JavaTimeModule()); + response.setStatus(statusCode.value()); + + try { + String result = objectMapper.writeValueAsString(dataResponse); + response.getWriter().write(result); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } From 3e400dae89f725204859d207b7149b70708e984b Mon Sep 17 00:00:00 2001 From: mng990 Date: Fri, 1 Nov 2024 15:21:50 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20private-post=20git=20=EC=BB=A8?= =?UTF-8?q?=EB=B2=A4=EC=85=98=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChildCommentController.java | 2 +- .../dto/request/SaveChildCommentRequest.java | 2 +- .../comment/mapper/ChildCommentMapper.java | 2 +- .../comment/mapper/ParentCommentMapper.java | 2 +- .../comment/service/ChildCommentService.java | 4 ++-- .../comment/service/ParentCommentService.java | 2 +- .../domains/post/service/PostService.java | 10 +++++++++- .../controller/PrivatePostController.java | 9 ++++++--- .../dto/PrivatePostPreviewResponse.java | 16 ++++++---------- .../privatePost/dto/SaveAudioSuccessRequest.java | 2 -- .../dto/SummaryAndJudgementRequest.java | 1 - .../privatePost/service/ChatRecordService.java | 6 ++---- .../privatePost/service/PrivatePostService.java | 6 ------ .../privatePost/service/TextRecordService.java | 6 +----- 14 files changed, 31 insertions(+), 39 deletions(-) diff --git a/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java b/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java index c9e3da8..ad97fef 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java +++ b/backend/src/main/java/aimo/backend/domains/comment/controller/ChildCommentController.java @@ -39,7 +39,7 @@ public ResponseEntity> saveChildComment( @PutMapping("comments/child/{childCommentId}") public ResponseEntity> updateParentComment( @PathVariable Long childCommentId, - @RequestBody UpdateChildCommentRequest request + @RequestBody SaveChildCommentRequest request ) { Member member = memberLoader.getMember(); childCommentService.validateAndUpdateChildComment(member, childCommentId, request); diff --git a/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java b/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java index 8b6daac..030ca89 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java +++ b/backend/src/main/java/aimo/backend/domains/comment/dto/request/SaveChildCommentRequest.java @@ -3,6 +3,6 @@ import jakarta.validation.constraints.Size; public record SaveChildCommentRequest( - @Size(max = 1500, message = "댓글은 한글 기준 최대 500자까지 입력할 수 있습니다.") + @Size(max = 1500, message = "댓글은 최대 500자까지 입력할 수 있습니다.") String content ) { } diff --git a/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java b/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java index 15e1db9..b8dc3df 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java +++ b/backend/src/main/java/aimo/backend/domains/comment/mapper/ChildCommentMapper.java @@ -17,7 +17,7 @@ public ChildComment from(SaveChildCommentRequest request, Member member, ParentComment parentComment, Post post) { return ChildComment.builder() .memberName(member.getUsername()) - .content(request.getContent()) + .content(request.content()) .parentComment(parentComment) .isDeleted(false) .member(member) diff --git a/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java b/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java index 97c9285..f060300 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java +++ b/backend/src/main/java/aimo/backend/domains/comment/mapper/ParentCommentMapper.java @@ -15,7 +15,7 @@ public class ParentCommentMapper { public ParentComment from(SaveParentCommentRequest request, Member member, Post post) { return ParentComment.builder() .memberName(member.getUsername()) - .content(request.getContent()) + .content(request.content()) .isDeleted(false) .member(member) .post(post) diff --git a/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java b/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java index b33e95a..ca072a6 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java +++ b/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java @@ -48,13 +48,13 @@ public void saveChildComment(Member member, Long postId, Long parentCommentId, S //자식 댓글 수정 @Transactional(rollbackFor = ApiException.class) - public void validateAndUpdateChildComment(Member member, Long childCommentId, UpdateChildCommentRequest request) { + public void validateAndUpdateChildComment(Member member, Long childCommentId, SaveChildCommentRequest request) { validateChildCommentAuthority(member, childCommentId); ChildComment childComment = childCommentRepository.findById(childCommentId) .orElseThrow(() -> ApiException.from(UNAUTHORIZED_CHILD_COMMENT)); - childComment.updateChildComment(request.getContent()); + childComment.updateChildComment(request.content()); } //자식 댓글 삭제 diff --git a/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java b/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java index 7b3c475..dbfb0af 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java +++ b/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java @@ -51,7 +51,7 @@ public void validateAndUpdateParentComment(Member member, Long commentId, Update ParentComment parentComment = parentCommentRepository.findById(commentId) .orElseThrow(() -> ApiException.from(PARENT_COMMENT_NOT_FOUND)); - parentComment.updateContent(request.getContent()); + parentComment.updateContent(request.content()); } // 부모 댓글 삭제 diff --git a/backend/src/main/java/aimo/backend/domains/post/service/PostService.java b/backend/src/main/java/aimo/backend/domains/post/service/PostService.java index b812e4f..bd3d5ca 100644 --- a/backend/src/main/java/aimo/backend/domains/post/service/PostService.java +++ b/backend/src/main/java/aimo/backend/domains/post/service/PostService.java @@ -1,13 +1,16 @@ package aimo.backend.domains.post.service; +import static aimo.backend.common.exception.ErrorCode.*; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import aimo.backend.common.exception.ApiException; import aimo.backend.common.mapper.PostMapper; import aimo.backend.domains.member.entity.Member; -import aimo.backend.domains.member.service.MemberService; import aimo.backend.domains.post.dto.SavePostRequest; +import aimo.backend.domains.post.entity.Post; import aimo.backend.domains.post.repository.PostRepository; import lombok.RequiredArgsConstructor; @@ -21,4 +24,9 @@ public class PostService { public void save(SavePostRequest savePostRequest, Member member) { postRepository.save(PostMapper.toEntity(savePostRequest, member)); } + + public Post findById(Long postId) { + return postRepository.findById(postId) + .orElseThrow(() -> ApiException.from(POST_NOT_FOUND)); + } } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java b/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java index 6f29ecb..4b3aadc 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/controller/PrivatePostController.java @@ -77,7 +77,8 @@ public ResponseEntity> judgement( privatePostService.save(summaryAndJudgementResponse); - return ResponseEntity.status(HttpStatus.CREATED) + return ResponseEntity + .status(HttpStatus.CREATED) .body(DataResponse.created()); } @@ -86,7 +87,8 @@ public ResponseEntity> uploadTextRecord( @RequestBody TextRecordRequest textRecordRequest ) { textRecordService.save(textRecordRequest); - return ResponseEntity.status(HttpStatus.CREATED) + return ResponseEntity + .status(HttpStatus.CREATED) .body(DataResponse.created()); } @@ -95,7 +97,8 @@ public ResponseEntity> uploadChatRecord( @RequestParam("chat_record") MultipartFile file ) throws IOException { chatRecordService.save(file); - return ResponseEntity.status(HttpStatus.CREATED) + return ResponseEntity + .status(HttpStatus.CREATED) .body(DataResponse.created()); } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/PrivatePostPreviewResponse.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/PrivatePostPreviewResponse.java index 5a6910e..664b9eb 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/dto/PrivatePostPreviewResponse.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/dto/PrivatePostPreviewResponse.java @@ -10,27 +10,23 @@ import jakarta.validation.constraints.NotNull; public record PrivatePostPreviewResponse( - @NotNull(message = "privatePostId is null") - @JsonProperty("private_post_id") + @NotNull(message = "ID가 비었습니다.") Long privatePostId, - @NotNull(message = "title is null") + @NotNull(message = "제목이 비었습니다.") String title, - @NotNull(message = "privatePostPreview is null") - @JsonProperty("private_post_preview") + @NotNull(message = "preview가 비었습니다.") String privatePostPreview, - @NotNull(message = "privatePostPreviewType is null") - @JsonProperty("origin_type") + @NotNull(message = "원본 타입이 비었습니다.") OriginType originType, - @NotNull(message = "createdAt is null") - @JsonProperty("created_at") + @NotNull(message = "생성일자가 비었습니다.") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime createdAt, - @NotNull(message = "published is null") + @NotNull(message = "발행이 비었습니다.") Boolean published ) { } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java index bcd3869..bcb410e 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SaveAudioSuccessRequest.java @@ -9,10 +9,8 @@ public record SaveAudioSuccessRequest( String url, @NotNull(message = "파일 사이즈가 필요합니다.") Long size, - @JsonProperty("filename") @NotNull(message = "파일 이름이 필요합니다.") String filename, - @JsonProperty("extension") @NotNull(message = "파일 확장자가 필요합니다.") String extension ) { } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java index 912cbac..4a1df1c 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/dto/SummaryAndJudgementRequest.java @@ -1,7 +1,6 @@ package aimo.backend.domains.privatePost.dto; import java.time.LocalDate; - import aimo.backend.domains.member.model.Gender; public record SummaryAndJudgementRequest( diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java b/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java index 64d8e13..fb985b7 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/service/ChatRecordService.java @@ -27,7 +27,7 @@ public class ChatRecordService { private final ChatRecordRepository chatRecordRepository; @Transactional(rollbackFor = ApiException.class) - public Long save(MultipartFile file) throws IOException { + public void save(MultipartFile file) throws IOException { String originalFilename = file.getOriginalFilename(); if (originalFilename == null) throw ApiException.from(ErrorCode.INVALID_FILE_NAME); @@ -55,8 +55,6 @@ public Long save(MultipartFile file) throws IOException { .script(script) .build(); - return chatRecordRepository - .save(chatRecord) - .getId(); + chatRecordRepository.save(chatRecord); } } diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java b/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java index bddaabd..8171fdd 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/service/PrivatePostService.java @@ -13,17 +13,13 @@ import org.springframework.http.HttpStatusCode; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.reactive.function.client.WebClient; -import aimo.backend.common.dto.DataResponse; import aimo.backend.common.exception.ApiException; import aimo.backend.common.exception.ErrorCode; import aimo.backend.common.mapper.PrivatePostMapper; import aimo.backend.common.properties.AiServerProperties; -import aimo.backend.domains.auth.security.jwtFilter.JwtTokenProviderImpl; import aimo.backend.domains.member.entity.Member; -import aimo.backend.domains.member.service.MemberService; import aimo.backend.domains.privatePost.dto.PrivatePostPreviewResponse; import aimo.backend.domains.privatePost.dto.PrivatePostResponse; import aimo.backend.domains.privatePost.dto.SummaryAndJudgementRequest; @@ -33,8 +29,6 @@ import aimo.backend.domains.privatePost.repository.PrivatePostRepository; import aimo.backend.util.memberLoader.MemberLoader; import lombok.RequiredArgsConstructor; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; @Service @RequiredArgsConstructor diff --git a/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java b/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java index 9b37e81..8c09a31 100644 --- a/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java +++ b/backend/src/main/java/aimo/backend/domains/privatePost/service/TextRecordService.java @@ -19,7 +19,7 @@ public class TextRecordService { private final TextRecordRepository textRecordRepository; @Transactional(rollbackFor = Exception.class) - public ResponseEntity> save(TextRecordRequest textRecordRequest) { + public void save(TextRecordRequest textRecordRequest) { TextRecord textRecord = TextRecord .builder() .title(textRecordRequest.title()) @@ -27,9 +27,5 @@ public ResponseEntity> save(TextRecordRequest textRecordReque .build(); textRecordRepository.save(textRecord); - - return ResponseEntity - .status(HttpStatus.CREATED) - .body(DataResponse.created()); } }