diff --git a/src/main/java/com/seniors/domain/resume/dto/ResumeDto.java b/src/main/java/com/seniors/domain/resume/dto/ResumeDto.java index 644434d..6ca125c 100644 --- a/src/main/java/com/seniors/domain/resume/dto/ResumeDto.java +++ b/src/main/java/com/seniors/domain/resume/dto/ResumeDto.java @@ -112,7 +112,7 @@ public static class GetResumeRes { @Builder - private GetResumeRes(Resume resume) { + public GetResumeRes(Resume resume) { this.id = resume.getId(); this.introduce = resume.getIntroduce(); this.photoUrl = resume.getPhotoUrl(); diff --git a/src/main/java/com/seniors/domain/users/controller/UsersController.java b/src/main/java/com/seniors/domain/users/controller/UsersController.java index 32c9e14..6a1c4f7 100644 --- a/src/main/java/com/seniors/domain/users/controller/UsersController.java +++ b/src/main/java/com/seniors/domain/users/controller/UsersController.java @@ -1,10 +1,15 @@ package com.seniors.domain.users.controller; import com.seniors.common.annotation.LoginUsers; -import com.seniors.common.constant.ResultCode; import com.seniors.common.dto.DataResponseDto; -import com.seniors.common.dto.ResponseDto; +import com.seniors.common.dto.ErrorResponse; +import com.seniors.common.exception.type.BadRequestException; +import com.seniors.common.exception.type.NotAuthorizedException; +import com.seniors.common.exception.type.NotFoundException; import com.seniors.config.security.CustomUserDetails; +import com.seniors.domain.post.dto.PostDto; +import com.seniors.domain.users.dto.UsersDto.GetUserDetailRes; +import com.seniors.domain.users.dto.UsersDto.SetUserDto; import com.seniors.domain.users.service.UsersService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -16,10 +21,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; @Tag(name = "사용자", description = "사용자 API 명세서") @Slf4j @@ -28,6 +33,8 @@ @RequestMapping("/api/users") public class UsersController { + private final UsersService usersService; + /** * 유저 검증 API * ex) 글쓰기 페이지 접속 시 검증 API를 사용하여 @@ -49,5 +56,46 @@ public ResponseEntity userValidate( : new ResponseEntity<>(userDetails, HttpStatus.OK); } + @Operation(summary = "유저 정보 조회") + @ApiResponse(responseCode = "200", description = "단건 조회 성공", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = GetUserDetailRes.class))) + @ApiResponse(responseCode = "401", description = "유효하지 않은 회원입니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = NotAuthorizedException.class))) + @ApiResponse(responseCode = "404", description = "사용자가 존재하지 않습니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = NotFoundException.class))) + @ApiResponse(responseCode = "500", description = "서버 에러.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))) + @GetMapping("") + public DataResponseDto usersDetails( + @Parameter(hidden = true) @LoginUsers CustomUserDetails userDetails + ) { + GetUserDetailRes getUserRes = usersService.findOneUsers(userDetails.getUserId(), userDetails.getUserSnsId(), + userDetails.getUserNickname(), userDetails.getProfileImageUrl(), + userDetails.getUserEmail(), userDetails.getGender()); + return DataResponseDto.of(getUserRes); + } + + @Operation(summary = "유저 정보 수정") + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "수정 요청 body", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = SetUserDto.class))) + @ApiResponse(responseCode = "200", description = "단건 수정 성공", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = DataResponseDto.class))) + @ApiResponse(responseCode = "400", description = "유효성 검증 실패", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = BadRequestException.class))) + @ApiResponse(responseCode = "401", description = "유효하지 않은 회원입니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = NotAuthorizedException.class))) + @ApiResponse(responseCode = "404", description = "사용자가 존재하지 않습니다.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = NotFoundException.class))) + @ApiResponse(responseCode = "500", description = "서버 에러.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))) + @PatchMapping("") + public DataResponseDto usersModify( + @Parameter(hidden = true) @LoginUsers CustomUserDetails userDetails, + @RequestPart(value = "data") SetUserDto setUserDto, + @RequestPart(value = "profileImage", required = false) MultipartFile profileImage + ) throws IOException { + usersService.modifyUsers(userDetails.getUserId(), userDetails.getProfileImageUrl(), setUserDto, profileImage); + return DataResponseDto.of("SUCCESS"); + } } diff --git a/src/main/java/com/seniors/domain/users/dto/UsersDto.java b/src/main/java/com/seniors/domain/users/dto/UsersDto.java index ec23c55..a4310cd 100644 --- a/src/main/java/com/seniors/domain/users/dto/UsersDto.java +++ b/src/main/java/com/seniors/domain/users/dto/UsersDto.java @@ -1,6 +1,8 @@ package com.seniors.domain.users.dto; import com.seniors.domain.chat.dto.ChatRoomMembersDto.GetChatRoomMembersRes; +import com.seniors.domain.resume.dto.ResumeDto.GetResumeRes; +import com.seniors.domain.resume.entity.Resume; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; @@ -59,4 +61,44 @@ public GetChatUserRes(Long userId, List chatRoomMembers) } + @Data + public static class GetUserDetailRes { + @Schema(description = "사용자 ID") + private Long userId; + + @Schema(description = "사용자 sns ID") + private String snsId; + + @Schema(description = "닉네임") + private String nickname; + + @Schema(description = "프로필 이미지 url") + private String profileImageUrl; + + @Schema(description = "이메일") + private String email; + + @Schema(description = "성별") + private String gender; + + @Schema(description = "사용자 이력서") + private GetResumeRes resume; + + public GetUserDetailRes(Resume resume, Long userId, String snsId, String nickname, String profileImageUrl, String email, String gender) { + this.userId = userId; + this.snsId = snsId; + this.nickname = nickname; + this.profileImageUrl = profileImageUrl; + this.email = email; + this.gender = gender; + this.resume = new GetResumeRes(resume); + } + } + + @Data + public static class SetUserDto { + @Schema(description = "닉네임") + private String nickname; + } + } diff --git a/src/main/java/com/seniors/domain/users/entity/Users.java b/src/main/java/com/seniors/domain/users/entity/Users.java index d7531d8..e8fd651 100644 --- a/src/main/java/com/seniors/domain/users/entity/Users.java +++ b/src/main/java/com/seniors/domain/users/entity/Users.java @@ -9,6 +9,7 @@ import com.seniors.domain.notification.entity.Notification; import com.seniors.domain.post.entity.Post; import com.seniors.domain.post.entity.PostLike; +import com.seniors.domain.resume.entity.Resume; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.BatchSize; diff --git a/src/main/java/com/seniors/domain/users/repository/UsersRepositoryCustom.java b/src/main/java/com/seniors/domain/users/repository/UsersRepositoryCustom.java index c2a7e19..57d0f26 100644 --- a/src/main/java/com/seniors/domain/users/repository/UsersRepositoryCustom.java +++ b/src/main/java/com/seniors/domain/users/repository/UsersRepositoryCustom.java @@ -1,6 +1,8 @@ package com.seniors.domain.users.repository; +import com.seniors.domain.users.dto.UsersDto.GetUserDetailRes; +import com.seniors.domain.users.dto.UsersDto.SetUserDto; import com.seniors.domain.users.entity.Users; @@ -8,4 +10,7 @@ public interface UsersRepositoryCustom { Users getOneUsers(Long userId); + GetUserDetailRes getUserDetails(Long userId, String snsId, String nickname, String profileImageUrl, String email, String gender); + + void modifyUser(Long userId, SetUserDto setUserDto, String profileImageUrl); } diff --git a/src/main/java/com/seniors/domain/users/repository/UsersRepositoryImpl.java b/src/main/java/com/seniors/domain/users/repository/UsersRepositoryImpl.java index a5e3733..8f89880 100644 --- a/src/main/java/com/seniors/domain/users/repository/UsersRepositoryImpl.java +++ b/src/main/java/com/seniors/domain/users/repository/UsersRepositoryImpl.java @@ -1,11 +1,17 @@ package com.seniors.domain.users.repository; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.seniors.common.exception.type.NotFoundException; import com.seniors.common.repository.BasicRepoSupport; +import com.seniors.domain.resume.entity.Resume; +import com.seniors.domain.users.dto.UsersDto.GetUserDetailRes; +import com.seniors.domain.users.dto.UsersDto.SetUserDto; import com.seniors.domain.users.entity.QUsers; import com.seniors.domain.users.entity.Users; import jakarta.persistence.EntityManager; +import static com.seniors.domain.resume.entity.QResume.resume; + public class UsersRepositoryImpl extends BasicRepoSupport implements UsersRepositoryCustom { protected UsersRepositoryImpl(JPAQueryFactory jpaQueryFactory, EntityManager em) { @@ -16,11 +22,33 @@ protected UsersRepositoryImpl(JPAQueryFactory jpaQueryFactory, EntityManager em) @Override public Users getOneUsers(Long userId) { - Users user = jpaQueryFactory + return jpaQueryFactory .selectFrom(QUsers.users) .where(QUsers.users.id.eq(userId)) .fetchOne(); - return user; + } + + @Override + public GetUserDetailRes getUserDetails(Long userId, String snsId, String nickname, String profileImageUrl, String email, String gender) { + Resume detailResume = jpaQueryFactory + .selectFrom(resume) + .where(resume.users.id.eq(userId).and(resume.users.snsId.eq(snsId))) + .fetchOne(); + + if (detailResume == null) { + throw new NotFoundException("Resume Not Found"); + } + + return new GetUserDetailRes(detailResume, userId, snsId, nickname, profileImageUrl, email, gender); + } + + @Override + public void modifyUser(Long userId, SetUserDto setUserDto, String profileImageUrl) { + jpaQueryFactory.update(users) + .set(users.nickname, setUserDto.getNickname()) + .set(users.profileImageUrl, profileImageUrl) + .where(users.id.eq(userId)) + .execute(); } } diff --git a/src/main/java/com/seniors/domain/users/service/UsersService.java b/src/main/java/com/seniors/domain/users/service/UsersService.java index 2655f98..4cc3d73 100644 --- a/src/main/java/com/seniors/domain/users/service/UsersService.java +++ b/src/main/java/com/seniors/domain/users/service/UsersService.java @@ -1,13 +1,43 @@ package com.seniors.domain.users.service; +import com.seniors.config.S3Uploader; +import com.seniors.domain.users.dto.UsersDto.GetUserDetailRes; +import com.seniors.domain.users.dto.UsersDto.SetUserDto; import com.seniors.domain.users.repository.UsersRepository; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; @Service @RequiredArgsConstructor public class UsersService { private final UsersRepository usersRepository; + private final S3Uploader s3Uploader; + + public GetUserDetailRes findOneUsers(Long userId, String snsId, String nickname, String profileImageUrl, String email, String gender) { + + return usersRepository.getUserDetails(userId, + snsId, + nickname, + profileImageUrl, + email, + gender); + } + + @Transactional + public void modifyUsers(Long userId, String curProfileImage, SetUserDto setUserDto, MultipartFile profileImage) throws IOException { + String dirName = "users/profileImage/" + userId.toString(); + String uploadImagePath = curProfileImage; + if (profileImage != null) { + // 기존 미디어 파일 삭제 + s3Uploader.deleteS3Object(dirName); + uploadImagePath = s3Uploader.upload(profileImage, dirName); + } + usersRepository.modifyUser(userId, setUserDto, uploadImagePath); + } }