From 342a00a48e120883ee89b0f39c1593c549323819 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 22 Apr 2025 00:27:08 +0900 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20Post=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=EC=97=90=20Image=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/post/dto/PostCreateRequest.java | 10 ++++++- .../domain/post/dto/PostCreateResponse.java | 12 +++++++-- .../domain/post/dto/PostReadResponse.java | 14 ++++++++-- .../domain/post/dto/PostUpdateRequest.java | 10 ++++++- .../domain/post/dto/PostUpdateResponse.java | 11 ++++++-- .../domain/post/service/PostServiceImpl.java | 27 ++++++++++++++++--- .../domain/postimage/entity/PostImage.java | 4 +++ .../repository/PostImageRepository.java | 4 +++ .../post/controller/PostControllerTest.java | 20 +++++++++++--- 9 files changed, 98 insertions(+), 14 deletions(-) diff --git a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateRequest.java b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateRequest.java index 7ffae19..a1eea6d 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateRequest.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateRequest.java @@ -1,9 +1,12 @@ package com.backendboard.domain.post.dto; +import java.util.List; + import com.backendboard.domain.post.entity.Post; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Builder; import lombok.Getter; @@ -21,10 +24,15 @@ public class PostCreateRequest { @NotBlank private final String content; + @Schema(description = "이미지 아이디", example = "[1, 2, 3]") + @NotNull + private final List imageIds; + @Builder - private PostCreateRequest(String title, String content) { + private PostCreateRequest(String title, String content, List imageIds) { this.title = title; this.content = content; + this.imageIds = imageIds; } public static Post toEntity(PostCreateRequest dto, Long userId) { diff --git a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateResponse.java b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateResponse.java index 2806f6f..6125211 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostCreateResponse.java @@ -1,5 +1,7 @@ package com.backendboard.domain.post.dto; +import java.util.List; + import com.backendboard.domain.post.entity.Post; import io.swagger.v3.oas.annotations.media.Schema; @@ -27,19 +29,24 @@ public class PostCreateResponse { @Schema(description = "조회수", example = "0") private final Long viewCount; + @Schema(description = "이미지 아이디", example = "[1, 2, 3]") + private final List imageIds; + @Builder - private PostCreateResponse(Long id, String author, String title, String content, Long likeCount, Long viewCount) { + private PostCreateResponse(Long id, String author, String title, String content, Long likeCount, Long viewCount, + List imageIds) { this.id = id; this.author = author; this.title = title; this.content = content; this.likeCount = likeCount; this.viewCount = viewCount; + this.imageIds = imageIds; } @Builder - public static PostCreateResponse toDto(Post post, String author) { + public static PostCreateResponse toDto(Post post, String author, List imageIds) { return PostCreateResponse.builder() .id(post.getId()) .author(author) @@ -47,6 +54,7 @@ public static PostCreateResponse toDto(Post post, String author) { .content(post.getContent()) .likeCount(post.getLikeCount()) .viewCount(post.getViewCount()) + .imageIds(imageIds) .build(); } } diff --git a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java index a255822..a393dc1 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java @@ -1,6 +1,10 @@ package com.backendboard.domain.post.dto; +import java.util.List; + import com.backendboard.domain.post.entity.Post; +import com.backendboard.domain.postimage.dto.PostImageReadResponse; +import com.backendboard.domain.postimage.entity.PostImage; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @@ -27,19 +31,24 @@ public class PostReadResponse { @Schema(description = "조회수", example = "0") private final Long viewCount; + @Schema(description = "이미지 아이디", example = "[1, 2, 3]") + private final List images; + @Builder - private PostReadResponse(Long id, String author, String title, String content, Long likeCount, Long viewCount) { + private PostReadResponse(Long id, String author, String title, String content, Long likeCount, Long viewCount, + List images) { this.id = id; this.author = author; this.title = title; this.content = content; this.likeCount = likeCount; this.viewCount = viewCount; + this.images = images; } @Builder - public static PostReadResponse toDto(Post post, String author) { + public static PostReadResponse toDto(Post post, String author, List images) { return PostReadResponse.builder() .id(post.getId()) .author(author) @@ -47,6 +56,7 @@ public static PostReadResponse toDto(Post post, String author) { .content(post.getContent()) .likeCount(post.getLikeCount()) .viewCount(post.getViewCount()) + .images(images.stream().map(PostImageReadResponse::toDto).toList()) .build(); } } diff --git a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateRequest.java b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateRequest.java index 515dcf3..2a55700 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateRequest.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateRequest.java @@ -1,7 +1,10 @@ package com.backendboard.domain.post.dto; +import java.util.List; + import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Builder; import lombok.Getter; @@ -18,9 +21,14 @@ public class PostUpdateRequest { @NotBlank private final String content; + @Schema(description = "이미지 아이디", example = "[1, 2, 3]") + @NotNull + private final List imageIds; + @Builder - private PostUpdateRequest(String title, String content) { + private PostUpdateRequest(String title, String content, List imageIds) { this.title = title; this.content = content; + this.imageIds = imageIds; } } diff --git a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateResponse.java b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateResponse.java index 49c7219..33a83a2 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostUpdateResponse.java @@ -1,5 +1,7 @@ package com.backendboard.domain.post.dto; +import java.util.List; + import com.backendboard.domain.post.entity.Post; import io.swagger.v3.oas.annotations.media.Schema; @@ -21,20 +23,25 @@ public class PostUpdateResponse { @Schema(description = "게시글 내용", example = "내용입니다.") private final String content; + @Schema(description = "이미지 아이디", example = "[1, 2, 3]") + private final List imageIds; + @Builder - private PostUpdateResponse(Long id, String author, String title, String content) { + private PostUpdateResponse(Long id, String author, String title, String content, List imageIds) { this.id = id; this.author = author; this.title = title; this.content = content; + this.imageIds = imageIds; } - public static PostUpdateResponse toDto(Post post, String author) { + public static PostUpdateResponse toDto(Post post, String author, List imageIds) { return PostUpdateResponse.builder() .id(post.getId()) .author(author) .title(post.getTitle()) .content(post.getContent()) + .imageIds(imageIds) .build(); } } diff --git a/backend-board/src/main/java/com/backendboard/domain/post/service/PostServiceImpl.java b/backend-board/src/main/java/com/backendboard/domain/post/service/PostServiceImpl.java index ecd0957..84ac2be 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/service/PostServiceImpl.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/service/PostServiceImpl.java @@ -1,5 +1,6 @@ package com.backendboard.domain.post.service; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -18,6 +19,8 @@ import com.backendboard.domain.post.dto.PostUpdateResponse; import com.backendboard.domain.post.entity.Post; import com.backendboard.domain.post.respository.PostRepository; +import com.backendboard.domain.postimage.entity.PostImage; +import com.backendboard.domain.postimage.repository.PostImageRepository; import com.backendboard.domain.user.entity.User; import com.backendboard.domain.user.repository.UserRepository; import com.backendboard.global.error.CustomError; @@ -31,14 +34,23 @@ public class PostServiceImpl implements PostService { private final PostRepository postRepository; private final UserRepository userRepository; + private final PostImageRepository postImageRepository; @Transactional @Override public PostCreateResponse createPost(PostCreateRequest request, Long authUserId) { User user = userRepository.getByAuthUserId(authUserId); Post post = PostCreateRequest.toEntity(request, user.getId()); + postRepository.save(post); - return PostCreateResponse.toDto(post, user.getNickname()); + + List imageIds = request.getImageIds(); + List images = postImageRepository.findAllById(imageIds); + + for (PostImage image : images) { + image.updatePostId(post.getId()); + } + return PostCreateResponse.toDto(post, user.getNickname(), imageIds); } @Transactional @@ -50,7 +62,14 @@ public PostUpdateResponse updatePost(PostUpdateRequest request, Long postId, Lon validateAuthor(post, user); post.update(request.getTitle(), request.getContent()); - return PostUpdateResponse.toDto(post, user.getNickname()); + + List imageIds = request.getImageIds(); + List images = postImageRepository.findAllById(imageIds); + + for (PostImage image : images) { + image.updatePostId(post.getId()); + } + return PostUpdateResponse.toDto(post, user.getNickname(), imageIds); } @Override @@ -58,7 +77,9 @@ public PostReadResponse getPost(Long postId) { Post post = postRepository.findById(postId).orElseThrow(() -> new CustomException(CustomError.POST_NOT_FOUND)); User user = userRepository.findById(post.getUserId()) .orElseThrow(() -> new CustomException(CustomError.USER_NOT_FOUND)); - return PostReadResponse.toDto(post, user.getNickname()); + + List images = postImageRepository.findByPostId(postId); + return PostReadResponse.toDto(post, user.getNickname(), images); } @Transactional diff --git a/backend-board/src/main/java/com/backendboard/domain/postimage/entity/PostImage.java b/backend-board/src/main/java/com/backendboard/domain/postimage/entity/PostImage.java index eda764e..771a2db 100644 --- a/backend-board/src/main/java/com/backendboard/domain/postimage/entity/PostImage.java +++ b/backend-board/src/main/java/com/backendboard/domain/postimage/entity/PostImage.java @@ -53,4 +53,8 @@ public void update(String originalFileName, String storedFileName, String imageT this.imageType = imageType; this.fileSize = fileSize; } + + public void updatePostId(Long postId) { + this.postId = postId; + } } diff --git a/backend-board/src/main/java/com/backendboard/domain/postimage/repository/PostImageRepository.java b/backend-board/src/main/java/com/backendboard/domain/postimage/repository/PostImageRepository.java index 5226600..f272a34 100644 --- a/backend-board/src/main/java/com/backendboard/domain/postimage/repository/PostImageRepository.java +++ b/backend-board/src/main/java/com/backendboard/domain/postimage/repository/PostImageRepository.java @@ -1,5 +1,7 @@ package com.backendboard.domain.postimage.repository; +import java.util.List; + import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; @@ -11,4 +13,6 @@ public interface PostImageRepository extends JpaRepository { Slice findByPostId(Long postId, Pageable pageable); + + List findByPostId(Long postId); } diff --git a/backend-board/src/test/java/com/backendboard/domain/post/controller/PostControllerTest.java b/backend-board/src/test/java/com/backendboard/domain/post/controller/PostControllerTest.java index f35372a..3e7f354 100644 --- a/backend-board/src/test/java/com/backendboard/domain/post/controller/PostControllerTest.java +++ b/backend-board/src/test/java/com/backendboard/domain/post/controller/PostControllerTest.java @@ -3,6 +3,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.util.ArrayList; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -66,7 +68,11 @@ class CreatePost { @DisplayName("성공 201") void success() throws Exception { // given - PostCreateRequest request = PostCreateRequest.builder().title("제목").content("내용").build(); + PostCreateRequest request = PostCreateRequest.builder() + .title("제목") + .content("내용") + .imageIds(new ArrayList<>()) + .build(); Post post = postMockData.createPost(user); // when & then @@ -89,7 +95,11 @@ class UpdatePost { @DisplayName("성공 200") void success() throws Exception { // given - PostUpdateRequest request = PostUpdateRequest.builder().title("제목 변경").content("내용 변경").build(); + PostUpdateRequest request = PostUpdateRequest.builder() + .title("제목 변경") + .content("내용 변경") + .imageIds(new ArrayList<>()) + .build(); Post post = postMockData.createPost(user); // when & then @@ -107,7 +117,11 @@ void success() throws Exception { @DisplayName("게시글을 찾을 수 없습니다. 404") void notFoundPost() throws Exception { // given - PostUpdateRequest request = PostUpdateRequest.builder().title("제목 변경").content("내용 변경").build(); + PostUpdateRequest request = PostUpdateRequest.builder() + .title("제목 변경") + .content("내용 변경") + .imageIds(new ArrayList<>()) + .build(); Post post = postMockData.createPost(user); // when & then From 058dfaf22512da8b21425b60e5ef37634f83dff6 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 22 Apr 2025 18:22:14 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20User=20=EB=B3=B4=EA=B8=B0=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 3 - .../user/controller/UserController.java | 66 +++++++++++++++++++ .../user/dto/UserNicknameUpdateRequest.java | 20 ++++++ .../user/dto/UserNicknameUpdateResponse.java | 10 +++ .../domain/user/dto/UserReadResponse.java | 40 +++++++++++ .../domain/user/service/UserService.java | 7 ++ .../domain/user/service/UserServiceImpl.java | 23 +++++++ .../global/config/SwaggerConfig.java | 10 ++- 8 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/dto/UserReadResponse.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java create mode 100644 backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java diff --git a/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java b/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java index 2efd958..aafcafc 100644 --- a/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java +++ b/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java @@ -1,7 +1,5 @@ package com.backendboard.domain.auth.controller; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; @@ -33,7 +31,6 @@ @RestController @RequiredArgsConstructor public class AuthController { - private static final Logger log = LoggerFactory.getLogger(AuthController.class); private final AuthService authService; private final JwtUtil jwtUtil; diff --git a/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java new file mode 100644 index 0000000..a7b9d37 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java @@ -0,0 +1,66 @@ +package com.backendboard.domain.user.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.backendboard.domain.user.dto.UserReadResponse; +import com.backendboard.domain.user.service.UserService; +import com.backendboard.global.error.dto.ErrorResponse; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + +@Tag(name = "유저", description = "유저 관련 API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/users") +public class UserController { + private final UserService userService; + + @Operation( + summary = "유저 보기 API", + description = "유저의 정보를 보여줍니다.", + security = {@SecurityRequirement(name = "bearerAuth")} + ) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "200 성공", + content = @Content( + mediaType = "application/json", schema = @Schema(implementation = UserReadResponse.class))), + @ApiResponse(responseCode = "404", description = "유저를 찾을 수 없습니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), + }) + @GetMapping("/{userId}") + public ResponseEntity readUser(@PathVariable Long userId) { + UserReadResponse response = userService.getUser(userId); + return ResponseEntity.status(HttpStatus.OK).body(response); + } + + @Operation( + summary = "유저 닉네임 변경 API", + description = "유저의 닉네임을 변경합니다.", + security = {@SecurityRequirement(name = "bearerAuth")} + ) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "200 성공", + content = @Content( + mediaType = "application/json", schema = @Schema(implementation = UserReadResponse.class))), + @ApiResponse(responseCode = "404", description = "유저를 찾을 수 없습니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), + }) + @PatchMapping("/{userId}") + public ResponseEntity updateNickname(@PathVariable Long userId) { + UserReadResponse response = userService.getUser(userId); + return ResponseEntity.status(HttpStatus.OK).body(response); + } +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java new file mode 100644 index 0000000..1031866 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java @@ -0,0 +1,20 @@ +package com.backendboard.domain.user.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Builder; +import lombok.Getter; + +@Schema(description = "유저 닉네임 변경 요청 DTO") +@Getter +public class UserNicknameUpdateRequest { + @NotBlank + @Size(max = 100) + private final String nickname; + + @Builder + private UserNicknameUpdateRequest(String nickname) { + this.nickname = nickname; + } +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java new file mode 100644 index 0000000..6618ae3 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java @@ -0,0 +1,10 @@ +package com.backendboard.domain.user.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Schema(description = "유저 닉네임 변경 응답 DTO") +@Getter +public class UserNicknameUpdateResponse { + +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/UserReadResponse.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserReadResponse.java new file mode 100644 index 0000000..b9122c7 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserReadResponse.java @@ -0,0 +1,40 @@ +package com.backendboard.domain.user.dto; + +import com.backendboard.domain.user.entity.User; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Schema(description = "유저 보기 응답 DTO") +@Getter +public class UserReadResponse { + @Schema(description = "회원 고유 번호", example = "1") + private final Long id; + + @Schema(description = "로그인 아이디", example = "user") + private final String loginId; + + @Schema(description = "유저의 이름", example = "감자") + private final String username; + + @Schema(description = "닉네임", example = "배고픈감자") + private final String nickname; + + @Builder + private UserReadResponse(Long id, String loginId, String username, String nickname) { + this.id = id; + this.loginId = loginId; + this.username = username; + this.nickname = nickname; + } + + public static UserReadResponse toDto(User user) { + return builder() + .id(user.getId()) + .loginId(user.getAuthUser().getUsername()) + .username(user.getUsername()) + .nickname(user.getNickname()) + .build(); + } +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java new file mode 100644 index 0000000..6de933c --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java @@ -0,0 +1,7 @@ +package com.backendboard.domain.user.service; + +import com.backendboard.domain.user.dto.UserReadResponse; + +public interface UserService { + UserReadResponse getUser(Long userId); +} diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java new file mode 100644 index 0000000..b3b8f78 --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java @@ -0,0 +1,23 @@ +package com.backendboard.domain.user.service; + +import org.springframework.stereotype.Service; + +import com.backendboard.domain.user.dto.UserReadResponse; +import com.backendboard.domain.user.entity.User; +import com.backendboard.domain.user.repository.UserRepository; +import com.backendboard.global.error.CustomError; +import com.backendboard.global.error.CustomException; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { + private final UserRepository userRepository; + + @Override + public UserReadResponse getUser(Long userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new CustomException(CustomError.USER_NOT_FOUND)); + return UserReadResponse.toDto(user); + } +} diff --git a/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java b/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java index b535fe1..8ecf498 100644 --- a/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java +++ b/backend-board/src/main/java/com/backendboard/global/config/SwaggerConfig.java @@ -44,11 +44,19 @@ public GroupedOpenApi comment() { .build(); } + @Bean + public GroupedOpenApi user() { + return GroupedOpenApi.builder() + .group("유저 관련 API") + .pathsToMatch("/users/**") + .build(); + } + @Bean public GroupedOpenApi auth() { return GroupedOpenApi.builder() .group("인증 관련 API") - .pathsToMatch("/join", "reissue") + .pathsToMatch("/join", "/reissue") .build(); } From 59d51e3dc3d63b5c71f461487c3f5d486f0e6543 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 22 Apr 2025 18:46:14 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20User=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 13 ++++++-- .../user/dto/UserNicknameUpdateRequest.java | 1 + .../user/dto/UserNicknameUpdateResponse.java | 15 +++++++++ .../backendboard/domain/user/entity/User.java | 4 +++ .../domain/user/service/UserService.java | 4 +++ .../domain/user/service/UserServiceImpl.java | 31 +++++++++++++++++++ .../global/error/CustomError.java | 1 + 7 files changed, 66 insertions(+), 3 deletions(-) diff --git a/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java index a7b9d37..1502239 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java @@ -2,15 +2,19 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.backendboard.domain.user.dto.UserNicknameUpdateRequest; +import com.backendboard.domain.user.dto.UserNicknameUpdateResponse; import com.backendboard.domain.user.dto.UserReadResponse; import com.backendboard.domain.user.service.UserService; import com.backendboard.global.error.dto.ErrorResponse; +import com.backendboard.global.security.dto.CustomUserDetails; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -54,13 +58,16 @@ public ResponseEntity readUser(@PathVariable Long userId) { @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", content = @Content( - mediaType = "application/json", schema = @Schema(implementation = UserReadResponse.class))), + mediaType = "application/json", schema = @Schema(implementation = UserNicknameUpdateResponse.class))), + @ApiResponse(responseCode = "403", description = "중복된 닉네임입니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), @ApiResponse(responseCode = "404", description = "유저를 찾을 수 없습니다.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), }) @PatchMapping("/{userId}") - public ResponseEntity updateNickname(@PathVariable Long userId) { - UserReadResponse response = userService.getUser(userId); + public ResponseEntity updateNickname(@PathVariable Long userId, + @AuthenticationPrincipal CustomUserDetails customUserDetails, UserNicknameUpdateRequest request) { + UserNicknameUpdateResponse response = userService.updateNickname(request, userId, customUserDetails.getId()); return ResponseEntity.status(HttpStatus.OK).body(response); } } diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java index 1031866..81ffd3f 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateRequest.java @@ -9,6 +9,7 @@ @Schema(description = "유저 닉네임 변경 요청 DTO") @Getter public class UserNicknameUpdateRequest { + @Schema(description = "유저 닉네임", example = "감자") @NotBlank @Size(max = 100) private final String nickname; diff --git a/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java index 6618ae3..c2bc520 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/dto/UserNicknameUpdateResponse.java @@ -1,10 +1,25 @@ package com.backendboard.domain.user.dto; +import com.backendboard.domain.user.entity.User; + import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; import lombok.Getter; @Schema(description = "유저 닉네임 변경 응답 DTO") @Getter public class UserNicknameUpdateResponse { + @Schema(description = "유저 닉네임", example = "감자") + private final String nickname; + + @Builder + private UserNicknameUpdateResponse(String nickname) { + this.nickname = nickname; + } + public static UserNicknameUpdateResponse toDto(User user) { + return builder() + .nickname(user.getNickname()) + .build(); + } } diff --git a/backend-board/src/main/java/com/backendboard/domain/user/entity/User.java b/backend-board/src/main/java/com/backendboard/domain/user/entity/User.java index 28119f0..61f996e 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/entity/User.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/entity/User.java @@ -40,4 +40,8 @@ private User(String username, String nickname, AuthUser authUser) { this.nickname = nickname; this.authUser = authUser; } + + public void updateNickname(String nickname) { + this.nickname = nickname; + } } diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java index 6de933c..213824d 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserService.java @@ -1,7 +1,11 @@ package com.backendboard.domain.user.service; +import com.backendboard.domain.user.dto.UserNicknameUpdateRequest; +import com.backendboard.domain.user.dto.UserNicknameUpdateResponse; import com.backendboard.domain.user.dto.UserReadResponse; public interface UserService { UserReadResponse getUser(Long userId); + + UserNicknameUpdateResponse updateNickname(UserNicknameUpdateRequest request, Long userId, Long authUserId); } diff --git a/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java index b3b8f78..84e7a93 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/service/UserServiceImpl.java @@ -1,7 +1,10 @@ package com.backendboard.domain.user.service; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.backendboard.domain.user.dto.UserNicknameUpdateRequest; +import com.backendboard.domain.user.dto.UserNicknameUpdateResponse; import com.backendboard.domain.user.dto.UserReadResponse; import com.backendboard.domain.user.entity.User; import com.backendboard.domain.user.repository.UserRepository; @@ -10,6 +13,7 @@ import lombok.RequiredArgsConstructor; +@Transactional(readOnly = true) @Service @RequiredArgsConstructor public class UserServiceImpl implements UserService { @@ -20,4 +24,31 @@ public UserReadResponse getUser(Long userId) { User user = userRepository.findById(userId).orElseThrow(() -> new CustomException(CustomError.USER_NOT_FOUND)); return UserReadResponse.toDto(user); } + + @Transactional + @Override + public UserNicknameUpdateResponse updateNickname(UserNicknameUpdateRequest request, Long userId, Long authUserId) { + validateUser(userId, authUserId); + + //공백 제거 + String updateNickname = request.getNickname().replaceAll("\\p{Z}", ""); + + validateDuplicationNickname(updateNickname); + + User user = userRepository.findById(userId).orElseThrow(() -> new CustomException(CustomError.USER_NOT_FOUND)); + user.updateNickname(updateNickname); + return UserNicknameUpdateResponse.toDto(user); + } + + private void validateDuplicationNickname(String nickname) { + if (userRepository.existsByNickname(nickname)) { + throw new CustomException(CustomError.USER_DUPLICATION_NICKNAME); + } + } + + public void validateUser(Long userId, Long authUserId) { + if (userId != authUserId) { + throw new CustomException(CustomError.AUTH_INVALID_USER); + } + } } diff --git a/backend-board/src/main/java/com/backendboard/global/error/CustomError.java b/backend-board/src/main/java/com/backendboard/global/error/CustomError.java index d7bae4f..be1dbe0 100644 --- a/backend-board/src/main/java/com/backendboard/global/error/CustomError.java +++ b/backend-board/src/main/java/com/backendboard/global/error/CustomError.java @@ -14,6 +14,7 @@ public enum CustomError { AUTH_INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "AU102", "토큰이 유효하지 않습니다."), AUTH_EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "AU103", "토큰이 만료되었습니다."), AUTH_INVALID_TOKEN_FORM(HttpStatus.UNAUTHORIZED, "AU104", "토큰폼이 맞지않습니다.."), + AUTH_INVALID_USER(HttpStatus.FORBIDDEN, "AU105", "본인이 아닙니다."), //유저 에러 USER_DUPLICATION_ID(HttpStatus.FORBIDDEN, "UR100", "중복된 아이디 입니다."), From 634129863e1cc8e3d873cc32c6f0f615ec217482 Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 22 Apr 2025 19:00:18 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20Post,=20Comment=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=EC=97=90=20=EC=88=98=EC=A0=95=EC=8B=9C=EA=B0=84,=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=8B=9C=EA=B0=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/dto/CommentReadResponse.java | 16 +++++++++++++++- .../domain/comment/dto/CommentSliceResponse.java | 15 ++++++++++++++- .../domain/post/dto/PostReadResponse.java | 13 ++++++++++++- .../domain/post/dto/PostSliceResponse.java | 15 ++++++++++++++- .../backendboard/domain/post/entity/Post.java | 4 +++- .../backendboard/global/entity/BaseEntity.java | 2 ++ 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentReadResponse.java b/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentReadResponse.java index 488e6b8..702d8da 100644 --- a/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentReadResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentReadResponse.java @@ -1,5 +1,7 @@ package com.backendboard.domain.comment.dto; +import java.time.LocalDateTime; + import com.backendboard.domain.comment.entity.Comment; import io.swagger.v3.oas.annotations.media.Schema; @@ -21,12 +23,22 @@ public class CommentReadResponse { @Schema(description = "댓글 내용", example = "안녕하세요.") private final String content; + @Schema(description = "생성 시간") + private final LocalDateTime createdDate; + + @Schema(description = "최근 수정 시간") + private final LocalDateTime lastModifiedDate; + @Builder - private CommentReadResponse(Long id, Long postId, String author, String content) { + private CommentReadResponse(Long id, Long postId, String author, String content, LocalDateTime createdDate, + LocalDateTime lastModifiedDate + ) { this.id = id; this.postId = postId; this.author = author; this.content = content; + this.createdDate = createdDate; + this.lastModifiedDate = lastModifiedDate; } public static CommentReadResponse toDto(Comment comment, String author) { @@ -34,6 +46,8 @@ public static CommentReadResponse toDto(Comment comment, String author) { .id(comment.getId()) .postId(comment.getPostId()) .content(comment.getContent()) + .createdDate(comment.getCreatedDate()) + .lastModifiedDate(comment.getLastModifiedDate()) .author(author) .build(); } diff --git a/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentSliceResponse.java b/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentSliceResponse.java index 62d6a1d..23650c9 100644 --- a/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentSliceResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/comment/dto/CommentSliceResponse.java @@ -1,5 +1,7 @@ package com.backendboard.domain.comment.dto; +import java.time.LocalDateTime; + import com.backendboard.domain.comment.entity.Comment; import io.swagger.v3.oas.annotations.media.Schema; @@ -21,12 +23,21 @@ public class CommentSliceResponse { @Schema(description = "댓글 내용", example = "안녕하세요.") private final String content; + @Schema(description = "생성 시간") + private final LocalDateTime createdDate; + + @Schema(description = "최근 수정 시간") + private final LocalDateTime lastModifiedDate; + @Builder - private CommentSliceResponse(Long id, Long postId, String author, String content) { + private CommentSliceResponse(Long id, Long postId, String author, String content, LocalDateTime createdDate, + LocalDateTime lastModifiedDate) { this.id = id; this.postId = postId; this.author = author; this.content = content; + this.createdDate = createdDate; + this.lastModifiedDate = lastModifiedDate; } public static CommentSliceResponse toDto(Comment comment, String author) { @@ -34,6 +45,8 @@ public static CommentSliceResponse toDto(Comment comment, String author) { .id(comment.getId()) .postId(comment.getPostId()) .content(comment.getContent()) + .createdDate(comment.getCreatedDate()) + .lastModifiedDate(comment.getLastModifiedDate()) .author(author) .build(); } diff --git a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java index a393dc1..7dfb3ec 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostReadResponse.java @@ -1,5 +1,6 @@ package com.backendboard.domain.post.dto; +import java.time.LocalDateTime; import java.util.List; import com.backendboard.domain.post.entity.Post; @@ -34,9 +35,15 @@ public class PostReadResponse { @Schema(description = "이미지 아이디", example = "[1, 2, 3]") private final List images; + @Schema(description = "생성 시간") + private final LocalDateTime createdDate; + + @Schema(description = "최근 수정 시간") + private final LocalDateTime lastModifiedDate; + @Builder private PostReadResponse(Long id, String author, String title, String content, Long likeCount, Long viewCount, - List images) { + List images, LocalDateTime createdDate, LocalDateTime lastModifiedDate) { this.id = id; this.author = author; this.title = title; @@ -44,6 +51,8 @@ private PostReadResponse(Long id, String author, String title, String content, L this.likeCount = likeCount; this.viewCount = viewCount; this.images = images; + this.createdDate = createdDate; + this.lastModifiedDate = lastModifiedDate; } @Builder @@ -57,6 +66,8 @@ public static PostReadResponse toDto(Post post, String author, List i .likeCount(post.getLikeCount()) .viewCount(post.getViewCount()) .images(images.stream().map(PostImageReadResponse::toDto).toList()) + .createdDate(post.getCreatedDate()) + .lastModifiedDate(post.getLastModifiedDate()) .build(); } } diff --git a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostSliceResponse.java b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostSliceResponse.java index a735eff..90ed87d 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/dto/PostSliceResponse.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/dto/PostSliceResponse.java @@ -1,5 +1,7 @@ package com.backendboard.domain.post.dto; +import java.time.LocalDateTime; + import com.backendboard.domain.post.entity.Post; import io.swagger.v3.oas.annotations.media.Schema; @@ -27,14 +29,23 @@ public class PostSliceResponse { @Schema(description = "조회수", example = "0") private final Long viewCount; + @Schema(description = "생성 시간") + private final LocalDateTime createdDate; + + @Schema(description = "최근 수정 시간") + private final LocalDateTime lastModifiedDate; + @Builder - private PostSliceResponse(Long id, String author, String title, String content, Long likeCount, Long viewCount) { + private PostSliceResponse(Long id, String author, String title, String content, Long likeCount, Long viewCount, + LocalDateTime createdDate, LocalDateTime lastModifiedDate) { this.id = id; this.author = author; this.title = title; this.content = content; this.likeCount = likeCount; this.viewCount = viewCount; + this.createdDate = createdDate; + this.lastModifiedDate = lastModifiedDate; } @Builder @@ -46,6 +57,8 @@ public static PostSliceResponse toDto(Post post, String author) { .content(post.getContent()) .likeCount(post.getLikeCount()) .viewCount(post.getViewCount()) + .createdDate(post.getCreatedDate()) + .lastModifiedDate(post.getLastModifiedDate()) .build(); } } diff --git a/backend-board/src/main/java/com/backendboard/domain/post/entity/Post.java b/backend-board/src/main/java/com/backendboard/domain/post/entity/Post.java index bfc2247..f1d72f5 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/entity/Post.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/entity/Post.java @@ -1,5 +1,7 @@ package com.backendboard.domain.post.entity; +import com.backendboard.global.entity.BaseEntity; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -14,7 +16,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Post { +public class Post extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java b/backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java index ec35b96..7b4b6fd 100644 --- a/backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java +++ b/backend-board/src/main/java/com/backendboard/global/entity/BaseEntity.java @@ -8,7 +8,9 @@ import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +@Getter @MappedSuperclass @EntityListeners(AuditingEntityListener.class) public class BaseEntity { From 41acaaaeb1ebc228940d5739d429b68574e7784b Mon Sep 17 00:00:00 2001 From: taehyeon Date: Tue, 22 Apr 2025 19:27:36 +0900 Subject: [PATCH 5/5] =?UTF-8?q?feat:=20User=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B3=80=EA=B2=BD=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 21 +++++++++++++++++++ .../auth/dto/PasswordUpdateRequest.java | 21 +++++++++++++++++++ .../domain/auth/entity/AuthUser.java | 4 ++++ .../domain/auth/service/AuthService.java | 3 +++ .../domain/auth/service/AuthServiceImpl.java | 8 +++++++ .../comment/controller/CommentController.java | 4 ++-- .../post/controller/PostController.java | 4 ++-- .../controller/PostImageController.java | 2 +- .../controller/PostLikeController.java | 2 +- .../user/controller/UserController.java | 4 ++-- 10 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 backend-board/src/main/java/com/backendboard/domain/auth/dto/PasswordUpdateRequest.java diff --git a/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java b/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java index aafcafc..551a17e 100644 --- a/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java +++ b/backend-board/src/main/java/com/backendboard/domain/auth/controller/AuthController.java @@ -2,17 +2,21 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.backendboard.domain.auth.dto.JoinRequest; import com.backendboard.domain.auth.dto.JoinResponse; +import com.backendboard.domain.auth.dto.PasswordUpdateRequest; import com.backendboard.domain.auth.dto.RefreshTokenDto; import com.backendboard.domain.auth.service.AuthService; import com.backendboard.global.error.CustomError; import com.backendboard.global.error.CustomException; import com.backendboard.global.error.dto.ErrorResponse; +import com.backendboard.global.security.dto.CustomUserDetails; import com.backendboard.global.util.JwtUtil; import io.swagger.v3.oas.annotations.Operation; @@ -53,6 +57,23 @@ public ResponseEntity join(@RequestBody @Valid JoinRequest request return ResponseEntity.status(HttpStatus.CREATED).body(response); } + @Operation( + summary = "비밀번호 변경 API", + description = "비밀번호를 변경합니다.", + security = {@SecurityRequirement(name = "bearerAuth")} + ) + @ApiResponses({ + @ApiResponse(responseCode = "204", description = "204 성공", content = @Content()), + @ApiResponse(responseCode = "403", description = "본인이 아닙니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), + }) + @PatchMapping("/users/password") + public ResponseEntity updatePassword(PasswordUpdateRequest request, + @AuthenticationPrincipal CustomUserDetails customUserDetails) { + authService.updatePassword(request, customUserDetails.getId()); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + @Operation( summary = "토큰 재발급 API - Swagger ui 에서 테스트 X", description = "새로운 토큰을 발급합니다.", diff --git a/backend-board/src/main/java/com/backendboard/domain/auth/dto/PasswordUpdateRequest.java b/backend-board/src/main/java/com/backendboard/domain/auth/dto/PasswordUpdateRequest.java new file mode 100644 index 0000000..ef0c24f --- /dev/null +++ b/backend-board/src/main/java/com/backendboard/domain/auth/dto/PasswordUpdateRequest.java @@ -0,0 +1,21 @@ +package com.backendboard.domain.auth.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Builder; +import lombok.Getter; + +@Schema(description = "비밀번호 변경 요청 DTO") +@Getter +public class PasswordUpdateRequest { + @Schema(description = "비밀번호", example = "1234") + @NotBlank + @Size(max = 30) + private final String password; + + @Builder + private PasswordUpdateRequest(String password) { + this.password = password; + } +} diff --git a/backend-board/src/main/java/com/backendboard/domain/auth/entity/AuthUser.java b/backend-board/src/main/java/com/backendboard/domain/auth/entity/AuthUser.java index 424de95..cdd2efa 100644 --- a/backend-board/src/main/java/com/backendboard/domain/auth/entity/AuthUser.java +++ b/backend-board/src/main/java/com/backendboard/domain/auth/entity/AuthUser.java @@ -60,6 +60,10 @@ public User createUser(String username, String nickname) { .build(); } + public void updatePassword(String password) { + this.password = password; + } + public void deactivate() { this.status = false; } diff --git a/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthService.java b/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthService.java index d68db25..2c404bf 100644 --- a/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthService.java +++ b/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthService.java @@ -2,6 +2,7 @@ import com.backendboard.domain.auth.dto.JoinRequest; import com.backendboard.domain.auth.dto.JoinResponse; +import com.backendboard.domain.auth.dto.PasswordUpdateRequest; import com.backendboard.domain.auth.dto.RefreshTokenDto; public interface AuthService { @@ -12,4 +13,6 @@ public interface AuthService { void deleteRefreshToken(String refreshToken); boolean isValidRefreshToken(String refreshToken); + + void updatePassword(PasswordUpdateRequest request, Long authUserId); } diff --git a/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthServiceImpl.java b/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthServiceImpl.java index 604f09b..3873433 100644 --- a/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthServiceImpl.java +++ b/backend-board/src/main/java/com/backendboard/domain/auth/service/AuthServiceImpl.java @@ -6,6 +6,7 @@ import com.backendboard.domain.auth.dto.JoinRequest; import com.backendboard.domain.auth.dto.JoinResponse; +import com.backendboard.domain.auth.dto.PasswordUpdateRequest; import com.backendboard.domain.auth.dto.RefreshTokenDto; import com.backendboard.domain.auth.entity.AuthUser; import com.backendboard.domain.auth.entity.RefreshToken; @@ -58,6 +59,13 @@ public JoinResponse joinProcess(JoinRequest request) { return JoinResponse.toDto(user); } + @Transactional + @Override + public void updatePassword(PasswordUpdateRequest request, Long authUserId) { + AuthUser user = authUserRepository.getReferenceById(authUserId); + user.updatePassword(bCryptPasswordEncoder.encode(request.getPassword())); + } + public void validateDuplicationNickname(String nickname) { if (userRepository.existsByNickname(nickname)) { throw new CustomException(CustomError.USER_DUPLICATION_NICKNAME); diff --git a/backend-board/src/main/java/com/backendboard/domain/comment/controller/CommentController.java b/backend-board/src/main/java/com/backendboard/domain/comment/controller/CommentController.java index 2fd357e..a8319ad 100644 --- a/backend-board/src/main/java/com/backendboard/domain/comment/controller/CommentController.java +++ b/backend-board/src/main/java/com/backendboard/domain/comment/controller/CommentController.java @@ -88,7 +88,7 @@ public ResponseEntity updateComment( @Operation( summary = "댓글 보기 API", description = "댓글을 보여줍니다.", - security = {@SecurityRequirement(name = "bearerAuth")} + security = {} ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", @@ -123,7 +123,7 @@ public ResponseEntity deleteComment( @Operation( summary = "댓글 슬라이스 보기 API", description = "댓글을 슬라이스로 보여줍니다.", - security = {@SecurityRequirement(name = "bearerAuth")} + security = {} ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", diff --git a/backend-board/src/main/java/com/backendboard/domain/post/controller/PostController.java b/backend-board/src/main/java/com/backendboard/domain/post/controller/PostController.java index 706ab14..ad17270 100644 --- a/backend-board/src/main/java/com/backendboard/domain/post/controller/PostController.java +++ b/backend-board/src/main/java/com/backendboard/domain/post/controller/PostController.java @@ -88,7 +88,7 @@ public ResponseEntity updatePost( @Operation( summary = "게시글 보기 API", description = "게시글을 보여줍니다.", - security = {@SecurityRequirement(name = "bearerAuth")} + security = {} ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", @@ -123,7 +123,7 @@ public ResponseEntity deletePost( @Operation( summary = "게시글 슬라이스 API", description = "게시글을 슬라이스로 보여줍니다.", - security = {@SecurityRequirement(name = "bearerAuth")} + security = {} ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", diff --git a/backend-board/src/main/java/com/backendboard/domain/postimage/controller/PostImageController.java b/backend-board/src/main/java/com/backendboard/domain/postimage/controller/PostImageController.java index a2be24a..83be7de 100644 --- a/backend-board/src/main/java/com/backendboard/domain/postimage/controller/PostImageController.java +++ b/backend-board/src/main/java/com/backendboard/domain/postimage/controller/PostImageController.java @@ -62,7 +62,7 @@ public ResponseEntity createImage(@RequestParam("image" @Operation( summary = "이미지 보기 API", description = "이미지를 보여줍니다.", - security = {@SecurityRequirement(name = "bearerAuth")} + security = {} ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", diff --git a/backend-board/src/main/java/com/backendboard/domain/postlike/controller/PostLikeController.java b/backend-board/src/main/java/com/backendboard/domain/postlike/controller/PostLikeController.java index 7ea2fa4..2ae0c24 100644 --- a/backend-board/src/main/java/com/backendboard/domain/postlike/controller/PostLikeController.java +++ b/backend-board/src/main/java/com/backendboard/domain/postlike/controller/PostLikeController.java @@ -68,7 +68,7 @@ public ResponseEntity readLikeStatus( @Operation( summary = "게시판 좋아요 수 API", description = "게시판 좋아요 수를 보는 기능입니다.", - security = {@SecurityRequirement(name = "bearerAuth")} + security = {} ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", diff --git a/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java index 1502239..06ae6ac 100644 --- a/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java +++ b/backend-board/src/main/java/com/backendboard/domain/user/controller/UserController.java @@ -35,7 +35,7 @@ public class UserController { @Operation( summary = "유저 보기 API", description = "유저의 정보를 보여줍니다.", - security = {@SecurityRequirement(name = "bearerAuth")} + security = {} ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "200 성공", @@ -64,7 +64,7 @@ public ResponseEntity readUser(@PathVariable Long userId) { @ApiResponse(responseCode = "404", description = "유저를 찾을 수 없습니다.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))), }) - @PatchMapping("/{userId}") + @PatchMapping("/{userId}/nickname") public ResponseEntity updateNickname(@PathVariable Long userId, @AuthenticationPrincipal CustomUserDetails customUserDetails, UserNicknameUpdateRequest request) { UserNicknameUpdateResponse response = userService.updateNickname(request, userId, customUserDetails.getId());