Skip to content

Commit 2512ccd

Browse files
authored
[refactor/OPS-337] 요구사항 반영 및 일부 로직 수정. (#81)
* refactor/OPS-337 : 프론트 요구사항 반영 및 에러 수정. * refactor/OPS-337 : 테스트 케이스 수정.
1 parent 7e27e6d commit 2512ccd

File tree

10 files changed

+166
-12
lines changed

10 files changed

+166
-12
lines changed

src/main/java/org/tuna/zoopzoop/backend/domain/auth/controller/ApiV1AuthController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ public ResponseEntity<RsData<Void>> refreshToken(
122122
.body(new RsData<>("200", "액세스 토큰을 재발급 했습니다.", null));
123123
}
124124

125+
/**
126+
* 확장프로그램의 액세스 토큰 발급을 위한 백그라운드 풀링에 대응하는 API
127+
* @param state 확장프로그램 로그인 시 전달한 state 값.
128+
*/
129+
125130
@GetMapping("/result")
126131
@Operation(summary = "확장프로그램 백그라운드 풀링 대응 API")
127132
public ResponseEntity<RsData<AuthResultData>> pullingResult(

src/main/java/org/tuna/zoopzoop/backend/domain/member/controller/ApiV1MemberController.java

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
import org.springframework.http.ResponseEntity;
99
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1010
import org.springframework.web.bind.annotation.*;
11+
import org.tuna.zoopzoop.backend.domain.member.dto.req.ReqBodyForEditMember;
1112
import org.tuna.zoopzoop.backend.domain.member.dto.req.ReqBodyForEditMemberName;
12-
import org.tuna.zoopzoop.backend.domain.member.dto.res.ResBodyForEditMemberName;
13-
import org.tuna.zoopzoop.backend.domain.member.dto.res.ResBodyForGetMemberInfo;
14-
import org.tuna.zoopzoop.backend.domain.member.dto.res.ResBodyForGetMemberInfoV2;
13+
import org.tuna.zoopzoop.backend.domain.member.dto.req.ReqBodyForEditMemberProfileImage;
14+
import org.tuna.zoopzoop.backend.domain.member.dto.res.*;
1515
import org.tuna.zoopzoop.backend.domain.member.entity.Member;
1616
import org.tuna.zoopzoop.backend.domain.member.service.MemberService;
1717
import org.tuna.zoopzoop.backend.global.rsData.RsData;
@@ -62,14 +62,14 @@ public ResponseEntity<RsData<ResBodyForGetMemberInfoV2>> getMemberInfo(
6262
* @param userDetails @AuthenticationPrincipal로 받아오는 현재 사용자 정보
6363
* @param reqBodyForEditMemberName 수정할 닉네임을 받아오는 reqDto
6464
*/
65-
@PutMapping("/edit")
65+
@PutMapping("/edit/name")
6666
@Operation(summary = "사용자 닉네임 수정")
6767
public ResponseEntity<RsData<ResBodyForEditMemberName>> editMemberName(
6868
@AuthenticationPrincipal CustomUserDetails userDetails,
6969
@Valid @RequestBody ReqBodyForEditMemberName reqBodyForEditMemberName
7070
) {
7171
Member member = userDetails.getMember();
72-
member.updateName(reqBodyForEditMemberName.newName());
72+
memberService.updateMemberName(member, reqBodyForEditMemberName.newName());
7373
return ResponseEntity
7474
.status(HttpStatus.OK)
7575
.body(
@@ -81,12 +81,64 @@ public ResponseEntity<RsData<ResBodyForEditMemberName>> editMemberName(
8181
);
8282
}
8383

84+
/**
85+
* 현재 로그인한 사용자의 프로필 이미지를 변경하는 API
86+
* HTTP METHOD: PUT
87+
* @param userDetails @AuthenticationPrincipal로 받아오는 현재 사용자 정보
88+
* @param reqBodyForEditMemberProfileImage 수정할 프로필 이미지를 받아오는 dto
89+
*/
90+
@PutMapping("/edit/image")
91+
@Operation(summary = "사용자 닉네임 수정")
92+
public ResponseEntity<RsData<ResBodyForEditMemberProfileImage>> editMemberProfileImage(
93+
@AuthenticationPrincipal CustomUserDetails userDetails,
94+
@Valid @RequestBody ReqBodyForEditMemberProfileImage reqBodyForEditMemberProfileImage
95+
) {
96+
Member member = userDetails.getMember();
97+
memberService.updateMemberProfileUrl(member, reqBodyForEditMemberProfileImage.file());
98+
return ResponseEntity
99+
.status(HttpStatus.OK)
100+
.body(
101+
new RsData<>(
102+
"200",
103+
"사용자의 프로필 이미지를 변경했습니다.",
104+
new ResBodyForEditMemberProfileImage(member.getProfileImageUrl())
105+
)
106+
);
107+
}
108+
109+
/**
110+
* 현재 로그인한 사용자의 닉네임과 프로필 이미지를 변경하는 API
111+
* HTTP METHOD: PUT
112+
* @param userDetails @AuthenticationPrincipal로 받아오는 현재 사용자 정보
113+
* @param reqBodyForEditMember 수정할 프로필 정보를 받아오는 dto
114+
*/
115+
@PutMapping("/edit")
116+
@Operation(summary = "사용자 프로필 수정")
117+
public ResponseEntity<RsData<ResBodyForEditMember>> editMemberProfile(
118+
@AuthenticationPrincipal CustomUserDetails userDetails,
119+
@Valid @RequestBody ReqBodyForEditMember reqBodyForEditMember
120+
) {
121+
Member member = userDetails.getMember();
122+
memberService.updateMemberProfile(member, reqBodyForEditMember.newName(), reqBodyForEditMember.file());
123+
return ResponseEntity
124+
.status(HttpStatus.OK)
125+
.body(
126+
new RsData<>(
127+
"200",
128+
"사용자의 프로필을 변경했습니다.",
129+
new ResBodyForEditMember(member.getName(), member.getProfileImageUrl())
130+
)
131+
);
132+
}
133+
134+
84135
/**
85136
* 현재 로그인한 사용자를 삭제하는 API
86137
* 사용할 지 모르겠음.
87138
* HTTP METHOD: DELETE
88139
* @param userDetails @AuthenticationPrincipal로 받아오는 현재 사용자 정보
89140
*/
141+
90142
@DeleteMapping
91143
@Operation(summary = "사용자 삭제")
92144
public ResponseEntity<RsData<Void>> deleteMember(
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.tuna.zoopzoop.backend.domain.member.dto.req;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.NotNull;
5+
import org.springframework.web.multipart.MultipartFile;
6+
7+
public record ReqBodyForEditMember (
8+
@NotBlank(message = "잘못된 요청입니다.") //MethodArgumentException
9+
String newName,
10+
@NotNull(message = "파일을 선택해주세요.")
11+
MultipartFile file
12+
) {
13+
public ReqBodyForEditMember(String newName, MultipartFile file) {
14+
this.newName = newName;
15+
this.file = file;
16+
}
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.tuna.zoopzoop.backend.domain.member.dto.req;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
import org.springframework.web.multipart.MultipartFile;
5+
6+
public record ReqBodyForEditMemberProfileImage (
7+
@NotNull(message = "파일을 선택해주세요.")
8+
MultipartFile file
9+
) {
10+
public ReqBodyForEditMemberProfileImage(MultipartFile file) {
11+
this.file = file;
12+
}
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.tuna.zoopzoop.backend.domain.member.dto.res;
2+
3+
public record ResBodyForEditMember(
4+
String name,
5+
String profileUrl
6+
) {
7+
public ResBodyForEditMember(String name, String profileUrl) {
8+
this.name = name;
9+
this.profileUrl = profileUrl;
10+
}
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.tuna.zoopzoop.backend.domain.member.dto.res;
2+
3+
public record ResBodyForEditMemberProfileImage(
4+
String profileUrl
5+
) {
6+
public ResBodyForEditMemberProfileImage(String profileUrl) {
7+
this.profileUrl = profileUrl;
8+
}
9+
}

src/main/java/org/tuna/zoopzoop/backend/domain/member/dto/res/ResBodyForGetMemberInfoV2.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@
22

33
import org.tuna.zoopzoop.backend.domain.member.entity.Member;
44

5+
import java.time.LocalDateTime;
6+
57
public record ResBodyForGetMemberInfoV2(
68
Integer id,
79
String name,
810
String profileUrl,
9-
String provider
11+
String provider,
12+
LocalDateTime createAt
1013
) {
1114
public ResBodyForGetMemberInfoV2(Member member){
1215
this(
1316
member.getId(),
1417
member.getName(),
1518
member.getProfileImageUrl(),
16-
member.getProvider().name()
19+
member.getProvider().name(),
20+
member.getCreateDate()
1721
);
1822
}
1923
}

src/main/java/org/tuna/zoopzoop/backend/domain/member/entity/Member.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,14 @@ public Member(String name, String providerKey, Provider provider, String profile
5454

5555
//---------- 메소드 ----------//
5656
public boolean isActive() { return this.active; }
57-
public void updateName(String name) { //사용자 이름 수정
57+
public String updateName(String name) { //사용자 이름 수정
5858
this.name = name;
59+
return this.name;
5960
} //사용자 이름 변경
6061
public void deactivate() { this.active = false; } //soft-delete
6162
public void activate() { this.active = true; } //restore
63+
public String updateProfileUrl(String profileImageUrl) {
64+
this.profileImageUrl = profileImageUrl;
65+
return this.profileImageUrl;
66+
}
6267
}

src/main/java/org/tuna/zoopzoop/backend/domain/member/service/MemberService.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
import org.springframework.dao.DataIntegrityViolationException;
66
import org.springframework.stereotype.Service;
77
import org.springframework.transaction.annotation.Transactional;
8+
import org.springframework.util.StringUtils;
9+
import org.springframework.web.multipart.MultipartFile;
810
import org.tuna.zoopzoop.backend.domain.member.entity.Member;
911
import org.tuna.zoopzoop.backend.domain.member.enums.Provider;
1012
import org.tuna.zoopzoop.backend.domain.member.repository.MemberRepository;
13+
import org.tuna.zoopzoop.backend.global.aws.S3Service;
1114

15+
import java.io.IOException;
1216
import java.util.List;
1317
import java.util.Optional;
1418
import java.util.UUID;
@@ -17,6 +21,7 @@
1721
@RequiredArgsConstructor
1822
public class MemberService {
1923
private final MemberRepository memberRepository;
24+
private final S3Service s3Service;
2025

2126
//회원 조회 관련
2227
public Member findById(Integer id) {
@@ -84,8 +89,40 @@ public void updateMemberName(Member member, String newName){
8489
throw new DataIntegrityViolationException("이미 사용중인 이름입니다.");
8590
}
8691
member.updateName(generateUniqueUserNameTag(newName));
92+
memberRepository.save(member);
8793
}
8894

95+
@Transactional
96+
public void updateMemberProfileUrl(Member member, MultipartFile file){
97+
String extension = StringUtils.getFilenameExtension(file.getOriginalFilename());
98+
String fileName = "profile/" + member.getId() + "/profile." + extension;
99+
try {
100+
String newUrl = s3Service.upload(file, fileName);
101+
member.updateProfileUrl(newUrl);
102+
memberRepository.save(member);
103+
} catch (IOException e) {
104+
throw new IllegalArgumentException("잘못된 파일 입력입니다.");
105+
}
106+
}
107+
108+
@Transactional
109+
public void updateMemberProfile(Member member, String newName, MultipartFile file){
110+
if(memberRepository.findByName(newName).isPresent()) {
111+
throw new DataIntegrityViolationException("이미 사용중인 이름입니다.");
112+
}
113+
member.updateName(generateUniqueUserNameTag(newName));
114+
String extension = StringUtils.getFilenameExtension(file.getOriginalFilename());
115+
String fileName = "profile/" + member.getId() + "/profile." + extension;
116+
try {
117+
String newUrl = s3Service.upload(file, fileName);
118+
member.updateProfileUrl(newUrl);
119+
memberRepository.save(member);
120+
} catch (IOException e) {
121+
throw new IllegalArgumentException("잘못된 파일 입력입니다.");
122+
}
123+
}
124+
125+
89126
//회원 삭제/복구 관련
90127
public void softDeleteMember(Member member){ member.deactivate(); }
91128
public void hardDeleteMember(Member member){ memberRepository.delete(member); }

src/test/java/org/tuna/zoopzoop/backend/domain/member/controller/MemberControllerTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.tuna.zoopzoop.backend.domain.member.repository.MemberRepository;
1717
import org.tuna.zoopzoop.backend.domain.member.service.MemberService;
1818

19+
import static org.hamcrest.Matchers.containsString;
1920
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
2021
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
2122
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -158,21 +159,21 @@ void getMemberInfoByNameUnauthorized() throws Exception {
158159
@DisplayName("사용자 이름 수정 - 성공(200)")
159160
void editMemberNameSuccess() throws Exception {
160161
ReqBodyForEditMemberName reqBodyForEditMemberName = new ReqBodyForEditMemberName("test3");
161-
mockMvc.perform(put("/api/v1/member/edit")
162+
mockMvc.perform(put("/api/v1/member/edit/name")
162163
.contentType(MediaType.APPLICATION_JSON)
163164
.content(objectMapper.writeValueAsString(reqBodyForEditMemberName)))
164165
.andExpect(status().isOk())
165166
.andExpect(jsonPath("$.status").value(200))
166167
.andExpect(jsonPath("$.msg").value("사용자의 닉네임을 변경했습니다."))
167-
.andExpect(jsonPath("$.data.name").value("test3"));
168+
.andExpect(jsonPath("$.data.name").value(containsString("test")));
168169
}
169170

170171
@Test
171172
@WithUserDetails(value = "GOOGLE:2222", setupBefore = TestExecutionEvent.TEST_METHOD)
172173
@DisplayName("사용자 이름 수정 - 실패(400, Bad_Request)")
173174
void editMemberNameFailedByBadRequest() throws Exception {
174175
ReqBodyForEditMemberName reqBodyForEditMemberName = new ReqBodyForEditMemberName("");
175-
mockMvc.perform(put("/api/v1/member/edit")
176+
mockMvc.perform(put("/api/v1/member/edit/name")
176177
.contentType(MediaType.APPLICATION_JSON)
177178
.content(objectMapper.writeValueAsString(reqBodyForEditMemberName)))
178179
.andExpect(status().isBadRequest())
@@ -184,7 +185,7 @@ void editMemberNameFailedByBadRequest() throws Exception {
184185
@DisplayName("사용자 이름 수정 - 실패(401, Unauthorized)")
185186
void editMemberNameFailedByUnauthorized() throws Exception {
186187
ReqBodyForEditMemberName reqBodyForEditMemberName = new ReqBodyForEditMemberName("test3");
187-
mockMvc.perform(put("/api/v1/member/edit")
188+
mockMvc.perform(put("/api/v1/member/edit/name")
188189
.contentType(MediaType.APPLICATION_JSON)
189190
.content(objectMapper.writeValueAsString(reqBodyForEditMemberName)))
190191
.andExpect(status().isUnauthorized())

0 commit comments

Comments
 (0)