Skip to content

Commit 8594f3c

Browse files
authored
Merge pull request #172 from TaskFlow-CLAP/CLAP-172
CLAP-172 회원 상세 정보 조회 & 회원 정보 수정 API 구현
2 parents 3b46d6f + a5d081f commit 8594f3c

39 files changed

Lines changed: 315 additions & 182 deletions

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ dependencies {
101101
implementation 'software.amazon.awssdk:s3'
102102
implementation 'ch.qos.logback:logback-classic:1.4.12'
103103

104+
// Apache Tika
105+
implementation 'org.apache.tika:tika-core:2.9.0'
106+
implementation 'org.apache.tika:tika-parsers:2.9.0'
107+
104108
}
105109

106110
tasks.named('test') {

src/main/java/clap/server/adapter/inbound/web/admin/ManageMemberController.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package clap.server.adapter.inbound.web.admin;
22

33
import clap.server.adapter.inbound.security.SecurityUserDetails;
4-
import clap.server.adapter.inbound.web.dto.admin.UpdateMemberInfoRequest;
5-
import clap.server.application.port.inbound.admin.ManageMemberUsecase;
4+
import clap.server.adapter.inbound.web.dto.admin.UpdateMemberRequest;
5+
import clap.server.application.port.inbound.admin.UpdateMemberUsecase;
66
import clap.server.common.annotation.architecture.WebAdapter;
77
import io.swagger.v3.oas.annotations.Operation;
88
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -20,14 +20,14 @@
2020
@RequiredArgsConstructor
2121
@RequestMapping("/api/managements/members")
2222
public class ManageMemberController {
23-
private final ManageMemberUsecase manageMemberUsecase;
23+
private final UpdateMemberUsecase updateMemberUsecase;
2424

2525
@Operation(summary = "회원 정보 수정 API")
2626
@PostMapping("/{memberId}")
2727
@Secured("ROLE_ADMIN")
2828
public void registerMember(@AuthenticationPrincipal SecurityUserDetails userInfo,
2929
@PathVariable Long memberId,
30-
@RequestBody @Valid UpdateMemberInfoRequest request){
31-
manageMemberUsecase.updateMemberInfo(memberId, request);
30+
@RequestBody @Valid UpdateMemberRequest request){
31+
updateMemberUsecase.updateMemberInfo(userInfo.getUserId(), memberId, request);
3232
}
3333
}

src/main/java/clap/server/adapter/inbound/web/auth/AuthController.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import clap.server.adapter.inbound.security.SecurityUserDetails;
44
import clap.server.adapter.inbound.web.dto.auth.LoginRequest;
55
import clap.server.adapter.inbound.web.dto.auth.LoginResponse;
6-
import clap.server.application.port.inbound.auth.AuthUsecase;
6+
import clap.server.application.port.inbound.auth.LoginUsecase;
7+
import clap.server.application.port.inbound.auth.LogoutUsecase;
78
import clap.server.common.annotation.architecture.WebAdapter;
89
import io.swagger.v3.oas.annotations.Operation;
910
import io.swagger.v3.oas.annotations.Parameter;
@@ -23,15 +24,16 @@
2324
@RequiredArgsConstructor
2425
@RequestMapping("/api/auths")
2526
public class AuthController {
26-
private final AuthUsecase authUsecase;
27+
private final LoginUsecase loginUsecase;
28+
private final LogoutUsecase logoutUsecase;
2729

2830
@Operation(summary = "로그인 API")
2931
@PostMapping("/login")
3032
public ResponseEntity<LoginResponse> login(@RequestHeader(name = "sessionId") String sessionId,
3133
@RequestBody LoginRequest request,
3234
HttpServletRequest httpRequest) {
3335
String clientIp = getClientIp(httpRequest);
34-
LoginResponse response = authUsecase.login(request.nickname(), request.password(), sessionId, clientIp);
36+
LoginResponse response = loginUsecase.login(request.nickname(), request.password(), sessionId, clientIp);
3537
return ResponseEntity.ok(response);
3638
}
3739

@@ -41,7 +43,7 @@ public void logout(@AuthenticationPrincipal SecurityUserDetails userInfo,
4143
@Parameter(hidden = true) @RequestHeader(value = "Authorization") String authHeader,
4244
@RequestHeader(value = "refreshToken") String refreshToken) {
4345
String accessToken = authHeader.split(" ")[1];
44-
authUsecase.logout(userInfo.getUserId(), accessToken, refreshToken);
46+
logoutUsecase.logout(userInfo.getUserId(), accessToken, refreshToken);
4547
}
4648

4749
}

src/main/java/clap/server/adapter/inbound/web/dto/admin/UpdateMemberInfoRequest.java renamed to src/main/java/clap/server/adapter/inbound/web/dto/admin/UpdateMemberRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import jakarta.validation.constraints.NotNull;
77
import jakarta.validation.constraints.Pattern;
88

9-
public record UpdateMemberInfoRequest(
9+
public record UpdateMemberRequest(
1010
@NotBlank @Schema(description = "회원 이름", example = "서주원")
1111
String name,
1212
@NotBlank
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package clap.server.adapter.inbound.web.dto.member;
2+
3+
import clap.server.adapter.outbound.persistense.entity.member.constant.MemberRole;
4+
import io.swagger.v3.oas.annotations.media.Schema;
5+
6+
public record MemberDetailInfoResponse(
7+
String profileImageUrl,
8+
@Schema(description = "회원 이름", example = "서주원")
9+
String name,
10+
@Schema(description = "회원 아이디", example = "siena.it")
11+
String nicknanme,
12+
@Schema(description = "회원 이메일", example = "siena.it@gmail.com")
13+
String email,
14+
@Schema(description = "승인 권한 여부")
15+
Boolean isReviewer,
16+
@Schema(description = "회원 역할")
17+
MemberRole role,
18+
@Schema(description = "부서")
19+
String departmentName,
20+
@Schema(description = "직책")
21+
String departmentRole,
22+
@Schema(description = "알림 수신 여부")
23+
NotificationSettingInfoResponse notificationSettingInfo
24+
) {
25+
public static record NotificationSettingInfoResponse(
26+
@Schema(description = "아지트 알림 수신 여부")
27+
boolean agit,
28+
@Schema(description = "이메일 알림 수신 여부")
29+
boolean email,
30+
@Schema(description = "카카오 워크 알림 수신 여부")
31+
boolean kakaoWork
32+
) {
33+
}
34+
}
35+
36+
37+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package clap.server.adapter.inbound.web.dto.member;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.NotBlank;
5+
6+
public record UpdateMemberInfoRequest(
7+
@NotBlank @Schema(description = "이름")
8+
String name,
9+
@Schema(description = "아지트 알림 수신 여부")
10+
boolean agitNotification,
11+
@Schema(description = "이메일 알림 수신 여부")
12+
boolean emailNotification,
13+
@Schema(description = "카카오 워크 알림 수신 여부")
14+
boolean kakaoWorkNotification
15+
) {
16+
}
17+
18+
19+
Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,54 @@
11
package clap.server.adapter.inbound.web.member;
22

33
import clap.server.adapter.inbound.security.SecurityUserDetails;
4+
import clap.server.adapter.inbound.web.dto.member.MemberDetailInfoResponse;
45
import clap.server.adapter.inbound.web.dto.member.MemberProfileResponse;
5-
import clap.server.application.port.inbound.member.MemberInfoUsecase;
6+
import clap.server.adapter.inbound.web.dto.member.UpdateMemberInfoRequest;
7+
import clap.server.application.port.inbound.member.UpdateMemberInfoUsecase;
8+
import clap.server.application.port.inbound.member.MemberDetailInfoUsecase;
9+
import clap.server.application.port.inbound.member.MemberProfileUsecase;
610
import clap.server.common.annotation.architecture.WebAdapter;
711
import io.swagger.v3.oas.annotations.Operation;
812
import io.swagger.v3.oas.annotations.tags.Tag;
913
import lombok.RequiredArgsConstructor;
14+
import org.springframework.http.MediaType;
1015
import org.springframework.http.ResponseEntity;
1116
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1217
import org.springframework.web.bind.annotation.GetMapping;
18+
import org.springframework.web.bind.annotation.PatchMapping;
1319
import org.springframework.web.bind.annotation.RequestMapping;
20+
import org.springframework.web.bind.annotation.RequestPart;
21+
import org.springframework.web.multipart.MultipartFile;
22+
23+
import java.io.IOException;
1424

1525
@Tag(name = "01. Member", description = "회원 정보 조회 및 수정 API")
1626
@WebAdapter
1727
@RequiredArgsConstructor
1828
@RequestMapping("/api/members")
1929
public class MemberInfoController {
20-
private final MemberInfoUsecase memberInfoUsecase;
30+
private final MemberProfileUsecase memberProfileUsecase;
31+
private final MemberDetailInfoUsecase memberDetailInfoUsecase;
32+
private final UpdateMemberInfoUsecase updateMemberInfoUsecase;
2133

22-
@Operation(summary = "회원 프로필을 조회합니다. 활성화된 회원만 조회 가능합니다.")
34+
@Operation(summary = "회원 프로필 조회 API")
2335
@GetMapping("/profile")
2436
public ResponseEntity<MemberProfileResponse> getMemberProfile(@AuthenticationPrincipal SecurityUserDetails userInfo) {
25-
return ResponseEntity.ok(memberInfoUsecase.getMemberProfile(userInfo.getUserId()));
37+
return ResponseEntity.ok(memberProfileUsecase.getMemberProfile(userInfo.getUserId()));
38+
}
39+
40+
@Operation(summary = "회원 상세 정보 조회 API")
41+
@GetMapping("/info")
42+
public ResponseEntity<MemberDetailInfoResponse> getMemberDetailInfo(@AuthenticationPrincipal SecurityUserDetails userInfo) {
43+
return ResponseEntity.ok(memberDetailInfoUsecase.getMemberInfo(userInfo.getUserId()));
2644
}
2745

46+
@Operation(summary = "회원 정보 수정 API", description = "이미지 수정이 없을 시에는 profileImage를 보내지 않습니다.")
47+
@PatchMapping(value = "/info", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE})
48+
public void updateMemberDetailInfo(
49+
@RequestPart(name = "memberInfo") UpdateMemberInfoRequest request,
50+
@RequestPart(name = "profileImage", required = false) MultipartFile profileImage,
51+
@AuthenticationPrincipal SecurityUserDetails userInfo) throws IOException {
52+
updateMemberInfoUsecase.updateMemberInfo(userInfo.getUserId(), request, profileImage);
53+
}
2854
}

src/main/java/clap/server/adapter/inbound/web/member/ResetPasswordController.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package clap.server.adapter.inbound.web.member;
22

33
import clap.server.adapter.inbound.security.SecurityUserDetails;
4+
import clap.server.application.port.inbound.member.ResetInitialPasswordUsecase;
45
import clap.server.application.port.inbound.member.ResetPasswordUsecase;
56
import clap.server.common.annotation.architecture.WebAdapter;
67
import clap.server.common.annotation.validation.password.ValidPassword;
@@ -19,12 +20,13 @@
1920
@RequestMapping("/api")
2021
public class ResetPasswordController {
2122
private final ResetPasswordUsecase resetPasswordUsecase;
23+
private final ResetInitialPasswordUsecase resetInitialPasswordUsecase;
2224

2325
@Operation(summary = "초기 로그인 후 비밀번호 재설정 API", description = "swagger에서 따옴표를 포함하지 않고 요청합니다.")
2426
@PatchMapping("/members/initial-password")
2527
public void resetPasswordAndActivateMember(@AuthenticationPrincipal SecurityUserDetails userInfo,
2628
@RequestBody @NotBlank @ValidPassword String password) {
27-
resetPasswordUsecase.resetPasswordAndActivateMember(userInfo.getUserId(), password);
29+
resetInitialPasswordUsecase.resetPasswordAndActivateMember(userInfo.getUserId(), password);
2830
}
2931

3032
@Operation(summary = "비밀번호 재설정 API", description = "swagger에서 따옴표를 포함하지 않고 요청합니다.")

src/main/java/clap/server/adapter/inbound/web/task/ManagementTaskController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class ManagementTaskController {
3434
@Secured({"ROLE_MANAGER", "ROLE_USER"})
3535
public ResponseEntity<CreateTaskResponse> createTask(
3636
@RequestPart(name = "taskInfo") @Valid CreateTaskRequest createTaskRequest,
37-
@RequestPart(name = "attachment") @NotNull List<MultipartFile> attachments,
37+
@RequestPart(name = "attachment", required = false) @NotNull List<MultipartFile> attachments,
3838
@AuthenticationPrincipal SecurityUserDetails userInfo
3939
){
4040
return ResponseEntity.ok(createTaskUsecase.createTask(userInfo.getUserId(), createTaskRequest, attachments));
@@ -46,7 +46,7 @@ public ResponseEntity<CreateTaskResponse> createTask(
4646
public ResponseEntity<UpdateTaskResponse> updateTask(
4747
@PathVariable @NotNull Long taskId,
4848
@RequestPart(name = "taskInfo") @Valid UpdateTaskRequest updateTaskRequest,
49-
@RequestPart(name = "attachment") @NotNull List<MultipartFile> attachments,
49+
@RequestPart(name = "attachment", required = false) @NotNull List<MultipartFile> attachments,
5050
@AuthenticationPrincipal SecurityUserDetails userInfo){
5151
return ResponseEntity.ok(updateTaskUsecase.updateTask(userInfo.getUserId(), taskId, updateTaskRequest, attachments));
5252
}

src/main/java/clap/server/adapter/outbound/infrastructure/s3/S3UploadAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import clap.server.config.s3.KakaoS3Config;
66
import clap.server.common.constants.FilePathConstants;
77
import clap.server.exception.S3Exception;
8-
import clap.server.exception.code.S3Errorcode;
8+
import clap.server.exception.code.AttachmentErrorcode;
99
import lombok.RequiredArgsConstructor;
1010
import lombok.extern.slf4j.Slf4j;
1111
import org.springframework.web.multipart.MultipartFile;
@@ -34,11 +34,12 @@ public String uploadSingleFile(FilePathConstants filePrefix, MultipartFile file)
3434
try {
3535
Path filePath = getFilePath(file);
3636
String objectKey = createObjectKey(filePrefix.getPath(), file.getOriginalFilename());
37+
3738
uploadToS3(objectKey, filePath);
3839
Files.delete(filePath);
3940
return getFileUrl(objectKey);
4041
} catch (IOException e) {
41-
throw new S3Exception(S3Errorcode.FILE_UPLOAD_REQUEST_FAILED);
42+
throw new S3Exception(AttachmentErrorcode.FILE_UPLOAD_REQUEST_FAILED);
4243
}
4344
}
4445

0 commit comments

Comments
 (0)