diff --git a/cider-api/build.gradle b/cider-api/build.gradle index 879288d..44f2c92 100644 --- a/cider-api/build.gradle +++ b/cider-api/build.gradle @@ -18,7 +18,7 @@ dependencies { runtimeOnly 'com.mysql:mysql-connector-j' // swagger - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.3' // jasypt implementation "com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3" @@ -35,8 +35,11 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-api:0.11.2' implementation 'io.jsonwebtoken:jjwt-impl:0.11.2' - //modelMapper + // modelMapper implementation group: 'org.modelmapper', name: 'modelmapper', version: '3.1.0' + + // validate + implementation 'org.hibernate.validator:hibernate-validator:7.0.1.Final' } jar{ diff --git a/cider-api/src/main/java/com/cmc/domains/member/controller/MemberController.java b/cider-api/src/main/java/com/cmc/domains/member/controller/MemberController.java new file mode 100644 index 0000000..5a197fb --- /dev/null +++ b/cider-api/src/main/java/com/cmc/domains/member/controller/MemberController.java @@ -0,0 +1,38 @@ +package com.cmc.domains.member.controller; + +import com.cmc.domains.member.dto.request.MemberUpdateReqDto; +import com.cmc.domains.member.dto.response.MemberUpdateResDto; +import com.cmc.domains.member.service.MemberService; +import com.cmc.global.resolver.RequestMemberId; +import com.cmc.member.Member; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +@Slf4j +@RestController +@RequiredArgsConstructor +@Tag(name = "members", description = "멤버 API") +@RequestMapping("/api/member") +public class MemberController { + + private final MemberService memberService; + + @Tag(name = "members") + @Operation(summary = "멤버 업데이트") + @PatchMapping(value = "") + public ResponseEntity updateTeam(@Parameter(hidden = true) @RequestMemberId Long memberId, @Valid @RequestBody MemberUpdateReqDto request) { + + Member member = memberService.updateMember(memberId, request.getMemberGender(), request.getMemberBirth(), request.getInterestChallenge()); + return ResponseEntity.ok(MemberUpdateResDto.from(member)); + } +} diff --git a/cider-api/src/main/java/com/cmc/domains/member/dto/request/MemberUpdateReqDto.java b/cider-api/src/main/java/com/cmc/domains/member/dto/request/MemberUpdateReqDto.java new file mode 100644 index 0000000..7f27c5a --- /dev/null +++ b/cider-api/src/main/java/com/cmc/domains/member/dto/request/MemberUpdateReqDto.java @@ -0,0 +1,37 @@ +package com.cmc.domains.member.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.validation.annotation.Validated; + +import java.util.Date; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Validated +public class MemberUpdateReqDto { + + @NotNull + @Schema(description = "멤버 이름", example = "건조한모래의사막", required=true) + private String memberName; + + @NotNull + @Schema(description = "생년월일", example = "2023-07-09", required=true) + private String memberBirth; + + @NotNull + @Schema(description = "성별 - F: 여성, M: 남성", example = "F / M", required=true) + private String memberGender; + + @NotNull + @Schema(description = "원하는 챌린지 분야 - T: 재테크, M: 돈관리, L: 금융학습, C: 소비절약\n" + ",로 구분해서 보내주세요", example = "T, M, L, C", required=true) + private String interestChallenge; + +} \ No newline at end of file diff --git a/cider-api/src/main/java/com/cmc/domains/member/dto/response/MemberUpdateResDto.java b/cider-api/src/main/java/com/cmc/domains/member/dto/response/MemberUpdateResDto.java new file mode 100644 index 0000000..f56db89 --- /dev/null +++ b/cider-api/src/main/java/com/cmc/domains/member/dto/response/MemberUpdateResDto.java @@ -0,0 +1,41 @@ +package com.cmc.domains.member.dto.response; + +import com.cmc.member.Member; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MemberUpdateResDto { + + @Schema(description = "멤버 id", example = "13") + private Long memberId; + + @Schema(description = "멤버 이름", example = "건조한모래의사막") + private String memberName; + + @Schema(description = "생년월일", example = "2023-07-09") + private String memberBirth; + + @Schema(description = "성별", example = "F / M") + private String memberGender; + + @Schema(description = "원하는 챌린지 분야", example = "T, M, L, C" ) + private String interestChallenge; + + public static MemberUpdateResDto from(Member member){ + + return MemberUpdateResDto.builder() + .memberId(member.getMemberId()) + .memberName(member.getMemberName()) + .memberBirth(member.getMemberBirth()) + .memberGender(member.getMemberGender()) + .interestChallenge(member.getInterestChallenge()) + .build(); + } +} diff --git a/cider-api/src/main/java/com/cmc/domains/member/service/MemberService.java b/cider-api/src/main/java/com/cmc/domains/member/service/MemberService.java new file mode 100644 index 0000000..3e795f1 --- /dev/null +++ b/cider-api/src/main/java/com/cmc/domains/member/service/MemberService.java @@ -0,0 +1,30 @@ +package com.cmc.domains.member.service; + +import com.cmc.common.exception.BadRequestException; +import com.cmc.domains.member.repository.MemberRepository; +import com.cmc.member.Member; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MemberService { + + private final MemberRepository memberRepository; + + // 멤버 정보 업데이트 + public Member updateMember(Long memberId, String memberGender, String memberBirth, String interestChallenge) { + + Member member = findMemberOrThrow(memberId); + member.update(memberGender, memberBirth, interestChallenge); + return memberRepository.save(member); + } + + private Member findMemberOrThrow(Long memberId) { + return memberRepository.findById(memberId).orElseThrow(() -> { + throw new BadRequestException("요청한 멤버는 존재하지 않습니다."); + }); + } +} diff --git a/cider-api/src/main/java/com/cmc/global/resolver/RequestMemberId.java b/cider-api/src/main/java/com/cmc/global/resolver/RequestMemberId.java new file mode 100644 index 0000000..fe5f103 --- /dev/null +++ b/cider-api/src/main/java/com/cmc/global/resolver/RequestMemberId.java @@ -0,0 +1,11 @@ +package com.cmc.global.resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequestMemberId { +} diff --git a/cider-api/src/main/java/com/cmc/global/resolver/RequestMemberIdArgumentResolver.java b/cider-api/src/main/java/com/cmc/global/resolver/RequestMemberIdArgumentResolver.java new file mode 100644 index 0000000..ae672c3 --- /dev/null +++ b/cider-api/src/main/java/com/cmc/global/resolver/RequestMemberIdArgumentResolver.java @@ -0,0 +1,29 @@ +package com.cmc.global.resolver; + +import com.cmc.oauth.service.TokenProvider; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; +import jakarta.servlet.http.HttpServletRequest; + +@Slf4j +public class RequestMemberIdArgumentResolver implements HandlerMethodArgumentResolver { + @Override + public boolean supportsParameter(MethodParameter parameter) { + final boolean hasMemberAnnotation = parameter.hasParameterAnnotation(RequestMemberId.class); + final boolean hasLong = Long.class.isAssignableFrom(parameter.getParameterType()); + + return hasMemberAnnotation && hasLong; + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + final HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + final String token = request.getHeader(HttpHeaders.AUTHORIZATION); + return TokenProvider.getMemberId(token); + } +} diff --git a/cider-api/src/main/java/com/cmc/oauth/dto/response/ResponseJwtTokenDto.java b/cider-api/src/main/java/com/cmc/oauth/dto/response/ResponseJwtTokenDto.java index ed3090d..567264b 100644 --- a/cider-api/src/main/java/com/cmc/oauth/dto/response/ResponseJwtTokenDto.java +++ b/cider-api/src/main/java/com/cmc/oauth/dto/response/ResponseJwtTokenDto.java @@ -33,9 +33,16 @@ public class ResponseJwtTokenDto { @Builder.Default private Boolean isNewMember = false; + @Schema(description = "멤버 ID") + private Long memberId; + @Schema(description = "멤버 이름") private String memberName; - @Schema(description = "멤버 ID") - private Long memberId; + @Schema(description = "멤버 생일") + private String birthday; + + @Schema(description = "멤버 성별") + private String gender; + } \ No newline at end of file diff --git a/cider-api/src/main/java/com/cmc/oauth/service/OauthLoginService.java b/cider-api/src/main/java/com/cmc/oauth/service/OauthLoginService.java index f477eed..d4426f9 100644 --- a/cider-api/src/main/java/com/cmc/oauth/service/OauthLoginService.java +++ b/cider-api/src/main/java/com/cmc/oauth/service/OauthLoginService.java @@ -76,6 +76,8 @@ public ResponseJwtTokenDto createMemberAndJwt(KakaoUserInfoResDto memberInfo, So responseJwtTokenDto.setMemberName(requestMember.getMemberName()); } responseJwtTokenDto.setMemberId(requestMember.getMemberId()); + responseJwtTokenDto.setBirthday(requestMember.getMemberBirth()); + responseJwtTokenDto.setGender(requestMember.getMemberGender()); return responseJwtTokenDto; } @@ -140,6 +142,9 @@ public ResponseJwtTokenDto generateToken(Member member) { responseJwtTokenDto.setMemberName(member.getMemberName()); } responseJwtTokenDto.setMemberId(member.getMemberId()); + responseJwtTokenDto.setMemberName(""); + responseJwtTokenDto.setBirthday(""); + responseJwtTokenDto.setGender(""); return responseJwtTokenDto; } diff --git a/cider-domain/src/main/java/com/cmc/member/Member.java b/cider-domain/src/main/java/com/cmc/member/Member.java index b50eae7..62cbab5 100644 --- a/cider-domain/src/main/java/com/cmc/member/Member.java +++ b/cider-domain/src/main/java/com/cmc/member/Member.java @@ -72,4 +72,10 @@ public static Member createApple(String email, SocialType socialType) { .build(); } + public void update(String memberGender, String memberBirth, String interestChallenge) { + + this.memberGender = memberGender; + this.memberBirth = memberBirth; + this.interestChallenge = interestChallenge; + } }